Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to Improve iLogic Code?

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
Anonymous
1025 Views, 17 Replies

How to Improve iLogic Code?

Hi,

 

I recently got help with writing iLogic code for a part file that takes user input and calculates Area, Ix, and Iy values,
and modifies an existing iProperty. To begin, the user has to run the code, pick a planar face, and then the calculations are made and the values are saved as custom iProperties. Then, in my drawing file template, I specified the custom iProperties as text parameters in the Format Text dialog box so that the values automatically appear once a view of the part is loaded.

 

My question is, what I can do to improve my iLogic code and make it more robust? Is there anything that might make it stop working or "crash"? Are there any potential issues with my code that anyone sees? I am new to iLogic, so I'm not sure what I can do to make sure my code runs well without issues. I've posted a view of my code below.

 

Thanks.

 

My Code:

Code for forum post.PNG

17 REPLIES 17
Message 2 of 18
Frederick_Law
in reply to: Anonymous

Try crash it yourself.

ie try select non-plane.  Try a part with non-flat surface.

Run iLogic without part in file.

Message 3 of 18
philip1009
in reply to: Anonymous

If the code keeps running consistently without issues, then there's really no reason to change it.  There are conditions that you can put in to make sure that:

 

1) The code is run in a part file, although really only necessary if it's an external rule.

2) Make sure there is a solid body in the part file.

3) Make sure there is a flat face available for selection.

4) Make sure that selected face is part of the solid body instead of something else like a work plane.

 

If ThisApplication.ActiveDocument.DocumentType <> DocumentTypeEnum.kPartDocumentObject Then
	MsgBox("Part File must be Active.")
	Exit Sub
End If

If ThisApplication.ActiveDocument.ComponentDefinition.SurfaceBodies.Count = 0 Then
	MsgBox("Part File must contain a body.")
	Exit Sub
End If

blnPlanarFaceCheck = False
For Each objSurfaceBody As SurfaceBody In ThisApplication.ActiveDocument.ComponentDefinition.SurfaceBodies
	For Each objFace As Face In objSurfaceBody.Faces
		If objFace.SurfaceType = SurfaceTypeEnum.kPlaneSurface Then
			blnPlanarFaceCheck = True
			GoTo jmpFaceCheck
		End If
	Next
Next
jmpFaceCheck : If blnPlanarFaceCheck = False Then
	MsgBox("There must be a flat face for selection.")
	Exit Sub
End If

jmpFaceSelection : objFaceSelection = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select Planer Face to Calculate Area, Ix, and Iy Properties.")
If objFaceSelection.ObjectType <> Inventor.ObjectTypeEnum.kFaceObject Then
	MsgBox("A surface face must be selected.")
	GoTo jmpFaceSelection
End If

 

I left the full code threads in so you can make your own shorthands or use ones you've already made.  ThisApplication.ActiveDocument is meant more for running in an external rule, if your code is going to be a rule attached to your part file template then ThisDoc.Document will work just fine and there'll be no need for the first part of the code to make sure it's running from a part document.

 

One other thing I noticed is your method of undoing the face sketch for calculation, it assumes it takes 4 undo methods every time to get back to where you were at the beginning of the code.  I suggest you implement code that controls the Transaction Manager so that the number of undo methods is irrelevant.

 

oTransaction = ThisApplication.TransactionManager.StartTransaction(doc, "Inertia Calculation")

oSK = oCD.Sketches.Add(oFace)
oSK.Edit
oCommandMgr.ControlDefinitions("SketchProjectCutEdgesCmd").Execute
oProfile = oSK.Profiles.AddForSolid
dArea = oProfile.RegionProperties.Area
Dim adPrincipalMoments(2) As Double
oProfile.RegionProperties.PrincipalMomentsofInertia(adPrincipalMoments(0), adPrincipalMoments(1), adPrincipalMoments(2))

oTransaction.Abort

This will undo your sketch operations but the adPrincipalMoments will still be in code memory to calculate and copy to your iProperties.

 

The last thing I recommend is to turn off screen updating, as it currently is, your computer is spending time updating the screen to show exactly what's happening during the sketch operations.  Before you do the sketch operations, just put in the line ThisApplication.ScreenUpdating = False, then turn that back to True at the end of your code.  This isn't necessary but it may speed your code up a bit.

Message 4 of 18
Anonymous
in reply to: philip1009

Thank you for your suggestions. I made changes to my code based on what you had, and I have a couple of questions.

 

1. In the fifth line of my original code, I define "oFace = ...", which is used later in the code you wrote. This line has the text "Select Planar Face to...", and so does the last chunk of code from the first snapshot you gave me: 

 

jmpFaceSelection : objFaceSelection = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select Planer Face to Calculate Area, Ix, and Iy Properties.")
If objFaceSelection.ObjectType <> Inventor.ObjectTypeEnum.kFaceObject Then
MsgBox("A surface face must be selected.")
GoTo jmpFaceSelection
End If

 

How could I change my code? When I run it I have to choose the planar face twice, which doesn't seem right.

 

2. Also, I get the error "Public member 'ObjectType' on type 'Face' not found." I'm still looking into figuring out what this means so I can find out how to fix this error.

 

Thank you for your help.

 

Message 5 of 18
philip1009
in reply to: Anonymous

Sorry, that chunk was meant to check the face after it's been selected, and if the selection isn't a face from a surface it jumps back into the selection method for the user to try again.  Change my objFaceSelection to the oFace you're using and remove the first "oFace = oCommandMgr.Pick" line.  As for the error, I simply forgot the correct way to check object types.  The fixed code example is below

 

Dim doc = ThisDoc.Document

oCD = doc.ComponentDefinition

'Implement the first checks to make sure it's a part document with a solid body that has planar faces available for selection.

Dim oCommandMgr As CommandManager =ThisApplication.CommandManager

jmpFaceSelection : oFace = oCommandMgr.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select Planar Face to Calculate Area, Ix, and Iy Properties")

If oFace.Type <> ObjectTypeEnum.kFaceObject Then

MsgBox("A surface face must be selected.")

Goto jmpFaceSelection

End If

'Then continue with the rest of your code.

Message 6 of 18
Anonymous
in reply to: philip1009

Thank you for your help with this, I appreciate it. I understand what you're saying. Now the only issue with my code seems to be that I defined "jmpFaceSelection" twice in my code, once in the beginning, and once later in my code:

 

jmpFaceSelection : oFace = oCommandMgr.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select planar face to calculate area, Ix, and Iy properties")

 

jmpFaceSelection : oFace = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select planar face to calculate area, Ix, and Iy properties")

 

A view of my current code is below:

Code for forum post updated.PNGCode for forum post updated (2).PNG

 

 

Message 7 of 18
philip1009
in reply to: Anonymous

Remove the face selection on top since we don't want to select a face until we get past the other checks.  Is this going to be for an External Rule or a rule attached to a part file?  Once I know that I can go through your code and clean it up.

Message 8 of 18
Anonymous
in reply to: philip1009

This is for a rule attached to a part file.

Message 9 of 18
philip1009
in reply to: Anonymous

Alright, here's the code cleaned up a bit, I also divided the code into different sections using brackets, it also allows you to collapse and expand those sections, you can remove them if you don't like it.

 

'['Objects
App = ThisApplication
doc = ThisDoc.Document
oCD = doc.ComponentDefinition
oBodies = oCD.SurfaceBodies
oCommandMgr = App.CommandManager
Dim oFace As Face']
'['Check for Bodies
If oBodies.Count = 0 Then
	MsgBox("Part File must containt a body.")
	Exit Sub
End If']
'['Check for Planar Faces
blnPlanarFaceCheck = False
For Each oSurfaceBody As SurfaceBody In oBodies
	For Each oFace In oSurfaceBody.Faces
		If oFace.SurfaceType = SurfaceTypeEnum.kPlaneSurface Then
			blnPlanarFaceCheck = True
			GoTo jmpFaceCheck
		End If
	Next
Next
jmpFaceCheck : If blnPlanarFaceCheck = False Then
	MsgBox("There must be a flat face for selection.")
	Exit Sub
End If']
'['Select Face
jmpFaceSelection : oFace = oCommandMgr.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select planar face to calculate area, Ix, and Iy properties.")
If oFace.Type <> ObjectTypeEnum.kFaceObject Then
	MsgBox("A surface face must be selected.")
	GoTo jmpFaceSelection
End If']
'['Calculate Intertia
oTransaction = App.TransactionManager.StartTransaction(doc, "Inertia Calculation")
App.ScreenUpdating = False
oSK = oCD.Sketches.Add(oFace)
oSK.Edit
oCommandMgr.ControlDefinitions("SketchProjectCutEdgesCmd").Execute
oProfile = oSK.Profiles.AddForSolid
oRegProps = oProfile.RegionProperties
dArea = oRegProps.Area
Dim adPrincipalMoments(2) As Double
oRegProps.PrincipalMomentsofInertia(adPrincipalMoments(0), adPrincipalMoments(1), adPrincipalMoments(2))
App.ScreenUpdating = True
oTransaction.Abort']
'['Copy to iProperties
iProperties.Value("Custom", "Area") = Format(dArea / 6.542, ".000")
iProperties.Value("Custom", "Ix") = Format(adPrincipalMoments(0) / 41.623, ".000")
iProperties.Value("Custom", "Iy") = Format(adPrincipalMoments(1) / 41.623, ".000")
iProperties.Value("Custom", "Mass") = Format(iProperties.Mass, ".000")']
InventorVb.DocumentUpdate
Message 10 of 18
Anonymous
in reply to: philip1009

The code works great, although after running the rule, the part file is in sketch mode. What code should I add to exit sketch mode?

 

Thank you.

Issue.PNG

Message 11 of 18
philip1009
in reply to: Anonymous

That is strange that the transaction abort doesn't undo the sketch edit line.  In between the "oRegProps.PrincipalMomentsofIntertia" and the "App.ScreenUpdating = True" lines add "oSK.ExitEdit" like below:

 

oRegProps.PrincipalMomentsofInertia(adPrincipalMoments(0), adPrincipalMoments(1), adPrincipalMoments(2))
oSK.ExitEdit App.ScreenUpdating = True

 

Message 12 of 18
Anonymous
in reply to: philip1009

Hi,

 

Adding the extra line of code worked. Thank you so much for your help with this.

Message 13 of 18
Anonymous
in reply to: philip1009

I have a question about this code. How exactly are the area, Ix, and Iy properties calculated? 

 

To test my code, I made a part in Inventor with two separate components (see a view of that part below). Based on the values it calculates, it seems like you can pick either of the faces of those components, and it will calculate values for the entire cross section, including both profiles. It seems like you just have to pick a surface, and Inventor will take into account all the profiles in the entire plane you select, and then make calculations. Am I on the right track? Can you explain more about how that part of the code works?

 

Thanks.

 

Inventor part:

Die View.PNG

 

 

 

Message 14 of 18
philip1009
in reply to: Anonymous

Is it possible for you to attach that part sample or something similar for me to test the code with?  Is it only extruded profiles you're dealing with?

Message 15 of 18
Anonymous
in reply to: philip1009

Hi,

 

I've attached a sample part to test with, and it has the updated iLogic code. I'm only dealing with extruded profiles.

 

Thanks.

Message 16 of 18
philip1009
in reply to: Anonymous

The code is doing what it's been asked to do so far, it makes a sketch on the plane you selected and then this line:

oCommandMgr.ControlDefinitions("SketchProjectCutEdgesCmd").Execute

It projects every single solid edge that it finds, if you remove one of the sketch profiles from the extrusion the numbers do change.  I'll see if I can find a way that it only projects the edges of the selected face or I recommend that only there only be a single extrusion per part file and you use assemblies to make arrangements of multiple separate extrusions.

 

edges_edited.jpg

Message 17 of 18
Anonymous
in reply to: philip1009

Ok, sounds good. Thank you for the clarification.

Message 18 of 18
philip1009
in reply to: Anonymous

I'm about to leave for the day so I'll give you what I have so far:

 

Replace this line:

oCommandMgr.ControlDefinitions("SketchProjectCutEdgesCmd").Execute

 

With these lines:

For Each oEdge As Edge In oFace.Edges
	oSK.AddByProjectingEntity(oEdge)
Next

 

That will only project the edges of the selected face in the planar sketch.  That seems to get you the correct Area, Ix, and Iy.  However, Mass is currently getting pulled from iProperties and it measures every solid no matter what face is selected.

 

I noticed that you're checking to make sure the extruded length is always 12 inches, if you know for sure that the length is always 12, and assuming it's completely solid the whole way, then you can just multiply with the area to give you the volume and then multiply with the material density to give you the mass:

 

iProperties.Value("Custom", "Mass") = Format(iProperties.Value("Custom", "Area") * 12 * (iProperties.Mass / iProperties.Volume), ".000")

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report