What's new

Guru Help Please - IInstance ??

albie0803

Alibre Super User
My script is giving an error
TypeError: expected IInstance, got Part
on line 36

The script is to place a bolt assembly into non patternable holes using the fastener constraint.
It will constrain the bolt assembly into the selected hole and constrain a copy of the assembly into all the holes on the face that are the same size.

1668393962169.png

Python:
win = Windows()
ca = CurrentAssembly()

def NearZero(value):
    if abs(value) < 0.00000001:
        return 1
    return 0

options = []
values = []
own_face = None
options.append(['Select bolt set edge' , WindowsInputTypes.Edge , None])
options.append(['Select a hole edge' , WindowsInputTypes.Edge , None])
values = win.OptionsDialog( 'Select Faces to Mate', options , 180 )

# get edges
blt_edge = values[0]
own_edge = values[1]

# get the sub assembly blt_edge is part of
blt_part = blt_edge.GetPart()
blt_ass = blt_part.GetAssembly() # <=== Problem starts here?
blt_Sub = ca.GetSubAssembly(blt_ass.Name + '<1>')

# determine the face and part that the hole is on
Sel_Edge = values[1].SelectableObject()
EdgeFaces =  Sel_Edge.Faces
for x in range(EdgeFaces.Count):
  edge_count = Face(EdgeFaces.Item(x)).GetEdges()
  if len(edge_count) > 2:
    own_face = Face(EdgeFaces.Item(x))
P1 = own_face.GetPart()
dia = own_edge.Diameter

# constrain original fastener
ca.AddFastenerConstraint(0,0,blt_Sub,blt_edge,P1, own_edge,False,'bolted')

if win.QuestionDialog('Does the Fastener Constraint need to Flipped?', 'Flip Constraint') == True:
  flip = True

# get the other matching holes and put a bolt assembly in them
holelist = []
holelist = own_face.GetEdges()
for i in range(len(holelist)):
  if NearZero(holelist[i].Diameter - dia):
    if holelist[i].Name != own_edge.Name:
      sub_assy1 = ca.DuplicateSubAssembly(blt_Sub,0,0,0)
      ca.AddMateConstraint(0, sub_assy1, sub_assy1.YZPlane, P1, own_face)
      ca.AddAlignConstraint(0, sub_assy1, sub_assy1.XAxis, P1, holelist[i])

if flip == True:
  win.InfoDialog('Remember to flip the first constraint!','Attention')

sys.exit('Script Complete')
 

Attachments

  • Bolt Assemblies.AD_PKG
    911.8 KB · Views: 8
Last edited:

NateLiquidGravity

Alibre Super User
I believe the problem is that
P1 = own_face.GetPart()
might be returning the part in a part context and not the specific instance of the part in the assembly context. I'm not able to test at the moment but what happens if you change that line to
P1 = own_edge.GetPart()
 

albie0803

Alibre Super User
No, still get TypeError: expected IInstance, got Part
for this line
# constrain original fastener
==> ca.AddFastenerConstraint(0,0,blt_Sub,blt_edge,P1, own_edge,False,'bolted')
 

bolsover

Senior Member
Try this.

P1 = own_edge.GetPart()
# constrain original fastener
#change blt_Sub to blt_part
ca.AddFastenerConstraint(0,0,blt_part,blt_edge,P1, own_edge,False,'bolted')
# initialise flip
flip = False
 

albie0803

Alibre Super User
Still no,
TypeError: expected IInstance, got Part

The basic question now is what is an IInstance?
 

idslk

Alibre Super User
Python:
win = Windows()
ca = CurrentAssembly()
flip = False

def NearZero(value):
    if abs(value) < 0.00000001:
        return 1
    return 0

options = []
values = []
own_face = None
options.append(['Select bolt set edge' , WindowsInputTypes.Edge , None])
options.append(['Select a hole edge' , WindowsInputTypes.Edge , None])
values = win.OptionsDialog( 'Select Faces to Mate', options , 180 )

# get edges
blt_edge = values[0]
own_edge = values[1]

# get the sub assembly blt_edge is part of
blt_part = blt_edge.GetPart()
blt_ass = blt_part.GetAssembly() # <=== Problem starts here?
blt_Sub = ca.GetSubAssembly(blt_ass.Name + '<1>')

# determine the face and part that the hole is on
Sel_Edge = values[1].SelectableObject()
#+++++++++++++++++++++++
P1 = values[1].GetPart()
#+++++++++++++++++++++++
EdgeFaces =  Sel_Edge.Faces
for x in range(EdgeFaces.Count):
  edge_count = Face(EdgeFaces.Item(x)).GetEdges()
  if len(edge_count) > 2:
    own_face = Face(EdgeFaces.Item(x))
#P1 = own_face.GetPart()
dia = own_edge.Diameter

# constrain original fastener
ca.AddFastenerConstraint(0,0,blt_part,blt_edge,P1, own_edge,False,'bolted')

Regards
Stefan
 

albie0803

Alibre Super User
Thankyou, oh wise one. May your coding ability never diminish and your generosity continue to abound!
 

albie0803

Alibre Super User
Well, I'm ambitious at least :rolleyes:

I'm having trouble with line 54 (& 56&58)

I have another version that works with a single part. Define a new copy of the part and insert
blt_edge = values[0]
be = blt_edge.Name
bolt = ca.DuplicatePart(blt,0,0,0)
ben = bolt.GetEdge(be)
ca.AddFastenerConstraint(0,0,bolt,ben,P1, holelist,True,'bolted')

I think the problem is with the name of the edge ben
I tried
ben = sub_assy1.GetEdge(be) but got 'AssembledSubAssembly' object has no attribute 'GetEdge'
ben = sub_assy1.part.GetEdge(be) but got 'AssembledSubAssembly' object has no attribute 'part'

ca.AddFastenerConstraint(0,0,sub_assy1,ben,P1, holelist,True,'bolted')

Help :confused: How do I tell it to pick the same edge but on the new subassembly?

Python:
win = Windows()
ca = CurrentAssembly()
flip = False

def NearZero(value):
    if abs(value) < 0.00000001:
        return 1
    return 0

options = []
values = []
own_face = None
options.append(['Select bolt set edge' , WindowsInputTypes.Edge , None])
options.append(['Select a hole edge' , WindowsInputTypes.Edge , None])
values = win.OptionsDialog( 'Select Faces to Mate', options , 180 )
if values == None:
  sys.exit('Script Aborted')

# get edges
blt_edge = values[0]
own_edge = values[1]
be = blt_edge.Name

# get the sub assembly blt_edge is part of
blt_part = blt_edge.GetPart()
blt_ass = blt_part.GetAssembly()
blt_Sub = ca.GetSubAssembly(blt_ass.Name + '<1>')

# determine the face and part that the hole is on
Sel_Edge = values[1].SelectableObject()

P1 = values[1].GetPart()
EdgeFaces =  Sel_Edge.Faces
for x in range(EdgeFaces.Count):
  edge_count = Face(EdgeFaces.Item(x)).GetEdges()
  if len(edge_count) > 2:
    own_face = Face(EdgeFaces.Item(x))
dia = own_edge.Diameter

# constrain original fastener
ca.AddFastenerConstraint(0,0,blt_part,blt_edge,P1, own_edge,False,'bolted')

if win.QuestionDialog('Does the Fastener Constraint need to Flipped?', 'Flip Constraint') == True:
  flip = True

# get the other matching holes and put a bolt assembly in them
holelist = []
holelist = own_face.GetEdges()
for i in range(len(holelist)):
  print holelist[i].Diameter
  if NearZero(holelist[i].Diameter - dia):
    if holelist[i].Name != own_edge.Name:
      sub_assy1 = ca.DuplicateSubAssembly(blt_Sub,0,0,0)
      ben = sub_assy1.part.GetEdge(be)
      if flip == True:
        ca.AddFastenerConstraint(0,0,sub_assy1,ben,P1, holelist[i],True,'bolted')
      else:
        ca.AddFastenerConstraint(0,0,sub_assy1,ben,P1, holelist[i],False,'bolted')
if flip == True:
  win.InfoDialog('Remember to flip the first constraint!','Attention')

sys.exit('Script Complete')
 
Last edited:

GIOV

Alibre Super User

albie0803,​

You are very ambitious!, like create an entire model with only script and storage this with a little kb... and share this fast without Gb restrictions.!
 

albie0803

Alibre Super User
Not that ambitious GIOV, What I am trying to create is a script to put fastener assemblies into hole sets that can't be patterned using the fastener constraint.

The user will need to create a bolt, nut, washer sub assembly with the correct gap spacing in it and then run the script.
You select an edge from the bolt sub assembly and the edge of the hole that it goes in and it constrains the bolt assembly,
then it auto constrains a new copy of the bolt set to all the other holes of the same size on the same face as the original hole.

I have this working for a single bolt but can't yet do it with the sub assemblies

I tried looping the single bolt version so you could put a washer first and then a bolt on top of it but we cant measure the distance between 2 faces of different parts in an assembly using code and I have also determined that the Fastener constraint command is broken for offsets. Support has acknowledged this and when(if) it gets fixed it may then be workable.

I'm beginning to wonder if what I am trying is even possible.
 

bolsover

Senior Member
Still no,
TypeError: expected IInstance, got Part

The basic question now is what is an IInstance?
Sticking my neck out here in the hope I don't give you a bum steer.
The best answer I can give is that it is an 'interface'. An interface in C# is essentially a contract that concrete classes like AssembledPart promise to implement.

The basic code for IInstance is as follows - note that the method signatures (like GetSelectionAssembly()) are NOT implemented.

C#:
using AlibreX;

namespace AlibreScript.API
{
  public interface IInstance
  {
    Assembly GetSelectionAssembly();

    void SetOccurrence(IADOccurrence Occurrence);

    IADOccurrence GetOccurrence();
  }
}

AssembledPart makes reference to both Part and IInstance:

The line 'public class AssembledPart : Part, IInstance' below could be read as 'public class AssembledPart extends Part implements IInstance'.
The key takeaway is that a Part is not an IInstance but an AssembledPart is both a Part and an IInstance and can access all the Part methods as well as those from IInstance and any new methods unique to AssembledPart.
There is no need for AssembledPart to re-implement the Part methods. But it MUST implement the IInstance methods.

C#:
namespace AlibreScript.API
{
  public class AssembledPart : Part, IInstance
  {....
 
   public new Assembly GetSelectionAssembly() => !(this._SelectionSession is IADAssemblySession) ? (Assembly) null : new Assembly(this._SelectionSession as IADAssemblySession);

    public void SetOccurrence(IADOccurrence Occurrence) => this._Occurrence = Occurrence;

    public IADOccurrence GetOccurrence() => this._Occurrence != null ? this._Occurrence : throw new Exception(\u0023cf.\u0023qWb("Part is not in an assembly. Use Assembly.GetPart to get the part."));
...

The real benefit of interfaces comes when you have several different classes that need to share common code.
One of the classic examples is shapes such as Circle, Square, Triangle. Each of these can be a separate class that implements an interface Shape.
Shape will define signatures for common methods such as 'double getArea()'.
Circle, Square and Triangle will each have their own concrete implementation of 'double getArea()'.
The benefit for the user is that he does not need to be concerned with the detail of 'how', he just needs to remember 'getArea()'

Hope this helps.

David
 

albie0803

Alibre Super User
So, the script does the following

Gets selected edges
edge1 = edge of washer in existing sub assembly
edge2 = edge of hole in plate/flange that bolt assembly is going in to.

determine the name of edge1 = Edge<4> = ass_edge
determine the part that edge1 is on = M8 Flat Washer<1> = ass_part
determine the assembly the part is in = Fasteners
define the assembly as a subassembly : ass_sub = ca.GetSubAssembly(ass_ass.Name + '<1>')
determine the name of the part = bpn :

determine the face that edge2 is on
determine the part that the face is on

constrain edge1 to edge 2 using AddFastenerConstraint(0,0,ass_part,ass_edge,P1, own_edge,False,'bolted')

THIS WORKS TO HERE - Thanks to Stefan

get a list of all edges on the face edge2 is on = holelist

work through the list of edges and if the edge is the same OD as edge2 but excluding edge2

create a duplicate of the subassembly = dup_sub = ca.DuplicateSubAssembly(ass_sub,0,0,0)
assign a part from the new subassembly using the part name : dup_ass_part = dup_sub.GetPart(bpn)
assign an edge from the part using the edge1 partname : dup_ass_edge = dup_ass_part.GetEdge(be)


constrain dup_ass_edge to edge 2 using AddFastenerConstraint(0,0, dup_ass_part, dup_ass_edge, P1, holelist,False,'bolted')

This doesn't work correctly as it correctly selects the correct edges (holes) to be filled but selects the original edge (edge1) of the washer from the original sub assembly, not the edge from the new sub assembly.

Where am I going wrong or is what I am trying just not possible?

Latest version of script
Python:
win = Windows()
ca = CurrentAssembly()
flip = False

def NearZero(value):
    if abs(value) < 0.00000001:
        return 1
    return 0

options = []
values = []
own_face = None
options.append(['Select bolt set edge' , WindowsInputTypes.Edge , None])
options.append(['Select a hole edge' , WindowsInputTypes.Edge , None])
values = win.OptionsDialog( 'Select Faces to Mate', options , 180 )
if values == None:
  sys.exit('Script Aborted')

# get edges
ass_edge = values[0]
own_edge = values[1]
be = ass_edge.Name

# get the sub assembly blt_edge is part of
ass_part = ass_edge.GetPart()
ass_ass = ass_part.GetAssembly()
ass_sub = ca.GetSubAssembly(ass_ass.Name + '<1>')
bpn = ass_part.Name

# determine the face and part that the hole is on
Sel_Edge = values[1].SelectableObject()
P1 = values[1].GetPart()
EdgeFaces =  Sel_Edge.Faces
for x in range(EdgeFaces.Count):
  edge_count = Face(EdgeFaces.Item(x)).GetEdges()
  if len(edge_count) > 2:
    own_face = Face(EdgeFaces.Item(x))
dia = own_edge.Diameter

print 'original'
print 'sub assembly part=',ass_part
print 'sub assembly part edge=',ass_edge

# constrain original fastener
ca.AddFastenerConstraint(0,0,ass_part,ass_edge,P1, own_edge,False,'bolted')

if win.QuestionDialog('Does the Fastener Constraint need to Flipped?', 'Flip Constraint') == True:
  flip = True

# get the other matching holes and put a bolt assembly in them
holelist = []
holelist = own_face.GetEdges()

for i in range(len(holelist)):
  if NearZero(holelist[i].Diameter - dia):
    if holelist[i].Name != own_edge.Name:
      # add a duplicate of blt_Sub as dup_sub
      dup_sub = ca.DuplicateSubAssembly(ass_sub,0,0,0)
      # define the part the edge will belong to as assp
      dup_ass_part = dup_sub.GetPart(bpn)
      # define the edge of the part to be used as asse
      dup_ass_edge = dup_ass_part.GetEdge(be)
      print'duplicate'
      print 'dup sub assembly=', dup_sub
      print 'dup sub assembly part=', dup_ass_part
      print 'dup sub assembly part edge=', dup_ass_edge
      if flip == True:
        ca.AddFastenerConstraint(0, 0, dup_ass_part, dup_ass_edge, P1, holelist[i],True,'bolted')
      else:
        ca.AddFastenerConstraint(0, 0, dup_ass_part, dup_ass_edge, P1, holelist[i],False,'bolted')

if flip == True:
  win.InfoDialog('Remember to flip the first constraint!','Attention')

sys.exit('Script Complete')
 

NateLiquidGravity

Alibre Super User
IDK I'm at a loss here. I tried everything I could thing of and even jumped into the AD API and tried it. Nothing worked. Perhaps it would be best to send to support.
 

albie0803

Alibre Super User
I know you can make it work with assembly planes, but I was trying to make it so that building the fastener sub assembly didn't have to be correctly anchored to a certain plane.
 

idslk

Alibre Super User
This doesn't work correctly as it correctly selects the correct edges (holes) to be filled but selects the original edge (edge1) of the washer from the original sub assembly, not the edge from the new sub assembly.
interesting...haven't looked at it yet...

Regards
Stefan
 

albie0803

Alibre Super User
I have sent this to support as per Nate's suggestion. They have passed it up to the Alibre Script developer to have a look at.
 

GIOV

Alibre Super User
I'm beginning to wonder if what I am trying is even possible.
Hi Albie0803.. No so much beginning..
 

GIOV

Alibre Super User
Yes Bolsover,
We are in a way to make a part, assembles and more complex model via only with script. that will allow share a lot of complex design with a little kb...
 
Top