iLogic "copy object"

iLogic "copy object"

robertast
Collaborator Collaborator
2,548 Views
21 Replies
Message 1 of 22

iLogic "copy object"

robertast
Collaborator
Collaborator

When using the code for "copy object"

  ' Copy objekt
    oFeatureDef2.BRepEntities = oCollection2
    oFeatureDef2.OutputType = kSurfaceOutputType
    oFeatureDef2.TargetOccurrence = oOccurrence1          
    oFeatureDef2.IsAssociative = True  
	
    Dim oBaseFeature1 As NonParametricBaseFeature
    oBaseFeature1 = oPartDef1.Features.NonParametricBaseFeatures.AddByDefinition(oFeatureDef2)

 

Although an associative link is indicated, the element does not fall into place. It can be replaced by using the command

oAssemblyDoc.Update10(True)

 

But after that, it will not be possible to continue writing illogics. Tell me which team to put them in place in this place so that I can continue to work with this rule

0 Likes
2,549 Views
21 Replies
Replies (21)
Message 2 of 22

JhoelForshav
Mentor
Mentor

Hi @robertast 

I don't know if I understand the question.

Does the NonParametricBaseFeature not appear until you update the document?

I assume you mean oAssemblyDoc.Update2(True)?

What do you mean with "it will not be possible to continue writing illogics"?

0 Likes
Message 3 of 22

robertast
Collaborator
Collaborator

@JhoelForshav 

 

Yes, I spent all night trying to figure out why your code works every other time. It turned out that after executing this part of the code, the "body surface" does not fall into place and, after checking for intersection, is deleted. Sometimes it happens that they are lucky and they get up not far from their place. But as I understood, the update should be used at the end of the whole code too, and it is not allowed to do it twice. So I ask good people for advice on how else to place these bodies at the center of the program.

0 Likes
Message 4 of 22

robertast
Collaborator
Collaborator

And can someone else explain to me a fool what this numeral is responsible for

 

Skaicius.jpg

0 Likes
Message 5 of 22

robertast
Collaborator
Collaborator

I was wrong to use "oAssemblyDoc.Update1 (True)" twice inappropriate. It is enough to put right after "copy object". I'm filming my first question.
The question remains for the "fool" that is me 😉

This is a question about those numbers in update

0 Likes
Message 6 of 22

JhoelForshav
Mentor
Mentor
Accepted solution

Hi @robertast 

There is no function called Update1

Update2 is pretty much the same as Update but it takes an argument wether or not to accept errors and continue.

You can use Update multiple times in a rule.

 

I don't think updating was ever the problem in you rule. Since I've helped you write it I could investigate and the problem is that the body is deleted if it doesn't intersect with the face as per your request. If the body has already been used to create a hole it no longer intersects. There were also some big issues with the parameters as the rule didn't keep track of which ones belonged to which hole etc.

 

I have rewritten the rule a bit for you, hope it helps 🙂

Dim asmDoc As AssemblyDocument
asmDoc = ThisApplication.ActiveDocument
Dim asmDef As AssemblyComponentDefinition
asmDef = asmDoc.ComponentDefinition


Dim targetOcc As ComponentOccurrence
targetOcc = ThisApplication.CommandManager.Pick( _
kAssemblyLeafOccurrenceFilter, _
"Select Part to copy the Body into.")
Dim targetDef As PartComponentDefinition
targetDef = targetOcc.Definition


Dim nonPrmFeatures As NonParametricBaseFeatures
nonPrmFeatures = targetDef.Features.NonParametricBaseFeatures

Dim transObjs As TransientObjects
transObjs = ThisApplication.TransientObjects
Dim col As ObjectCollection


col = transObjs.CreateObjectCollection

Dim SourceOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick( _
kAssemblyLeafOccurrenceFilter, _
"Select Part to copy bodies from")

Dim oFace As FaceProxy = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Pick face.")
If oFace.ContainingOccurrence IsNot (targetOcc) Then
	MsgBox("Face must be on the occurrence to copy bodies into")
	Exit Sub
End If
'Dim oDef As PartComponentDefinition = oFace.ContainingOccurrence.Definition
Dim oParams As UserParameters = targetDef.Parameters.UserParameters
Dim i As Integer = 0
For Each oBod As SurfaceBody In SourceOcc.Definition.SurfaceBodies
	If oBod.Name.StartsWith("Hole")
		Dim oProx As SurfaceBodyProxy = Nothing
		Call SourceOcc.CreateGeometryProxy(oBod, oProx)
		col.Add(oProx)


		Dim featureDef As NonParametricBaseFeatureDefinition
		featureDef = nonPrmFeatures.CreateDefinition


		featureDef.BRepEntities = col
		featureDef.OutputType = kSurfaceOutputType
		featureDef.TargetOccurrence = targetOcc
		featureDef.IsAssociative = True

		Dim baseFeature As NonParametricBaseFeature
		baseFeature = nonPrmFeatures.AddByDefinition(featureDef)
		On Error Resume Next
		baseFeature.Name = oBod.Name
		col.Clear
		Dim intersects As Boolean = False
		For Each NPFface As Face In baseFeature.Faces
			If ThisApplication.MeasureTools.GetMinimumDistance(oFace.NativeObject, NPFface) = 0 Then
				intersects = True
				Exit For
			End If
		Next
		If intersects = False
			baseFeature.Delete
		Else
			Dim oVals As String() = oBod.Name.Split(New String() {"(", ")" }, StringSplitOptions.None)(1).Split(";")
			If i = 0
				Dim PokParams As IEnumerable(Of Inventor.Parameter) = oParams.OfType(Of Inventor.Parameter)().Where(Function(x) x.Name.Contains("Hi_"))
				If PokParams.Count = 0
					i = 1
				Else
					i = PokParams.Max(Function(x) CInt(x.Name.Split("_")(1))) + 1
				End If
			End If
			Dim Di As Inventor.Parameter = oParams.AddByExpression("Di_" & i, oVals(0), UnitsTypeEnum.kMillimeterLengthUnits)
			Dim Hi As Inventor.Parameter = oParams.AddByExpression("Hi_" & i, oVals(1), UnitsTypeEnum.kMillimeterLengthUnits)
			i += 1

			Dim oCol As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
			Dim oSketch As PlanarSketch = targetDef.Sketches.Add(oFace.NativeObject)
			Dim oProjEnt As SketchEntity
			For Each NPFface As Face In baseFeature.Faces
				If NPFface.SurfaceType = SurfaceTypeEnum.kCylinderSurface
					oProjEnt = oSketch.AddByProjectingEntity(NPFface.Edges(1))
					oProjEnt.Construction = True
					Dim oPt As SketchPoint = oProjEnt.CenterSketchPoint
					oPt.HoleCenter = True
					oCol.Add(oPt)
				End If
			Next
			Dim oHole As HoleFeature = targetDef.Features.HoleFeatures.AddDrilledByDistanceExtent(oCol, Di.Name, Hi.Name, PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
			If oHole.RangeBox Is Nothing
				oHole.Delete
				oSketch.Delete
				baseFeature.Delete
				Di.Delete
				Hi.Delete
			End If
		End If
	End If
Next

ThisDoc.Document.Update
Message 7 of 22

robertast
Collaborator
Collaborator

@JhoelForshav 

 

It doesn't even work now, okay. To understand where the error is happening. I am in the morning because the best ideas come in the morning (it doesn't matter that I stayed up all night). I started to stop the rule piece by piece to see what it does on each line of code. It turned out that at this moment a "copy object" is created from the code, it does not always fall into place. And if he does not get up, after the next cycle (checking for intersections, this is before getting holes) he is removed. This is what we get when we stop after mine before checking. This is the best case, but we can get it outside the part.
So I'm trying to figure out how to get around these troubles. After all, the world is not without kind people, so somebody can help.

 

Klaida.jpg

0 Likes
Message 8 of 22

robertast
Collaborator
Collaborator

If it's "ThisDoc.Document.Update" move to this place in the code and delete it at the end - it works.

 

	featureDef.BRepEntities = col
	featureDef.OutputType = kSurfaceOutputType
	featureDef.TargetOccurrence = targetOcc
	featureDef.IsAssociative = True

	Dim baseFeature As NonParametricBaseFeature
	baseFeature = nonPrmFeatures.AddByDefinition(featureDef)
	
	ThisDoc.Document.Update

 

If we leave it at the end, we get an error.  Whether it is necessary at the end of the code or not, I still could not understand...

0 Likes
Message 9 of 22

JhoelForshav
Mentor
Mentor

I honestly have no idea what you're talking about, but that doesn't really matter as long as you have a code that you're happy with 😉

 

Since the code are making changes in the assembly's components the document will be left in a state where its not up to date if you don't update it once it's all done.

 

Are you saying that the code I posted earlier here doesn't work? In which way?

0 Likes
Message 10 of 22

robertast
Collaborator
Collaborator

@JhoelForshav 

 

As I said, it works, but it doesn't always work. I have shown where the error occurs in the code. After "copying the object", if the update is not applied, the object may appear outside the part. In this case, the next line of code, which checks this object for intersections, removes it, even if it should stay alive as planned. Therefore, I am looking for "kind people" who would help me solve my problem.
Yes, you have helped me a lot, and for that I will feel that I owe you the rest of my life. I've already said thank you many times.
But as you said, here's an example, but I have to make it work myself. My knowledge is not enough, so I am looking for good people to whom I have not yet owed. I hope these will find and help ...

0 Likes
Message 11 of 22

JhoelForshav
Mentor
Mentor
Accepted solution

I understand... But I'm very curious now as to why it doesn't work.

I remember though that I've had problems with copied bodies before where Inventor doesn't process these properly before the code continues.

 

The way I've solved this previously has been to use DoEvents, which allows Inventor to process all messages in the queue.

 

I think this will work for you 🙂

Dim asmDoc As AssemblyDocument
asmDoc = ThisApplication.ActiveDocument
Dim asmDef As AssemblyComponentDefinition
asmDef = asmDoc.ComponentDefinition


Dim targetOcc As ComponentOccurrence
targetOcc = ThisApplication.CommandManager.Pick( _
kAssemblyLeafOccurrenceFilter, _
"Select Part to copy the Body into.")
Dim targetDef As PartComponentDefinition
targetDef = targetOcc.Definition


Dim nonPrmFeatures As NonParametricBaseFeatures
nonPrmFeatures = targetDef.Features.NonParametricBaseFeatures

Dim transObjs As TransientObjects
transObjs = ThisApplication.TransientObjects
Dim col As ObjectCollection


col = transObjs.CreateObjectCollection

Dim SourceOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick( _
kAssemblyLeafOccurrenceFilter, _
"Select Part to copy bodies from")

Dim oFace As FaceProxy = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Pick face.")
If oFace.ContainingOccurrence IsNot (targetOcc) Then
	MsgBox("Face must be on the occurrence to copy bodies into")
	Exit Sub
End If

Dim oParams As UserParameters = targetDef.Parameters.UserParameters
Dim i As Integer = 0
For Each oBod As SurfaceBody In SourceOcc.Definition.SurfaceBodies
	If oBod.Name.StartsWith("Hole")
		Dim oProx As SurfaceBodyProxy = Nothing
		Call SourceOcc.CreateGeometryProxy(oBod, oProx)
		col.Add(oProx)


		Dim featureDef As NonParametricBaseFeatureDefinition
		featureDef = nonPrmFeatures.CreateDefinition


		featureDef.BRepEntities = col
		featureDef.OutputType = kSurfaceOutputType
		featureDef.TargetOccurrence = targetOcc
		featureDef.IsAssociative = True

		Dim baseFeature As NonParametricBaseFeature
		baseFeature = nonPrmFeatures.AddByDefinition(featureDef)
		Try
		baseFeature.Name = oBod.Name
		Catch
		End Try
		col.Clear
		
		ThisApplication.UserInterfaceManager.DoEvents()
		
		Dim intersects As Boolean = False
		
		For Each NPFface As Face In baseFeature.Faces
			If ThisApplication.MeasureTools.GetMinimumDistance(oFace.NativeObject, NPFface) = 0 Then
				intersects = True
				Exit For
			End If
		Next
		If intersects = False
			baseFeature.Delete
		Else
			Dim oVals As String() = oBod.Name.Split(New String() {"(", ")" }, StringSplitOptions.None)(1).Split(";")
			If i = 0
				Dim PokParams As IEnumerable(Of Inventor.Parameter) = oParams.OfType(Of Inventor.Parameter)().Where(Function(x) x.Name.Contains("Hi_"))
				If PokParams.Count = 0
					i = 1
				Else
					i = PokParams.Max(Function(x) CInt(x.Name.Split("_")(1))) + 1
				End If
			End If
			Dim Di As Inventor.Parameter = oParams.AddByExpression("Di_" & i, oVals(0), UnitsTypeEnum.kMillimeterLengthUnits)
			Dim Hi As Inventor.Parameter = oParams.AddByExpression("Hi_" & i, oVals(1), UnitsTypeEnum.kMillimeterLengthUnits)
			i += 1

			Dim oCol As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
			Dim oSketch As PlanarSketch = targetDef.Sketches.Add(oFace.NativeObject)
			Dim oProjEnt As SketchEntity
			
			
			
			For Each NPFface As Face In baseFeature.Faces
				If NPFface.SurfaceType = SurfaceTypeEnum.kCylinderSurface
					oProjEnt = oSketch.AddByProjectingEntity(NPFface.Edges(1))
					oProjEnt.Construction = True
					Dim oPt As SketchPoint = oProjEnt.CenterSketchPoint
					oPt.HoleCenter = True
					oCol.Add(oPt)
				End If
			Next
			Dim oHole As HoleFeature = targetDef.Features.HoleFeatures.AddDrilledByDistanceExtent(oCol, Di.Name, Hi.Name, PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
			If oHole.RangeBox Is Nothing
				oHole.Delete
				baseFeature.Delete
				Di.Delete
				Hi.Delete
			End If
		End If
	End If
Next

ThisDoc.Document.Update
Message 12 of 22

robertast
Collaborator
Collaborator

Yes, there are good people on the forum, but there are probably no good people with your level of knowledge besides you.
This "ThisApplication.UserInterfaceManager.DoEvents ()" corrected the situation, this particular rule was not enough to make it work without errors.
It remains only now, instead of parameters, to assign values ​​to variables. And position the loop so that it works - copy the first body named "Hole" and immediately check the intersections, depending on whether we are deleting it or moving on. Then we move on to the next one, create a sketch and make a hole using the values ​​obtained from the variables.
Anything I go to sleep, a day without sleep, affects my ability to think. But even after that I will not be able to complete my task without the help of "good people", most likely ...

0 Likes
Message 13 of 22

JhoelForshav
Mentor
Mentor
Accepted solution

@robertast 

Did you copy the entire code or just the line "ThisApplication.UserInterfaceManager.DoEvents ()" ?

Because I have changed the code do do it all in one loop now...

 

Are you saying that you want model parameters instead of user parameters? That's actually easier.

Try this entire code:

Dim asmDoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim asmDef As AssemblyComponentDefinition = asmDoc.ComponentDefinition

Dim targetOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick(kAssemblyLeafOccurrenceFilter, "Select Part to copy the Body into.")
Dim targetDef As PartComponentDefinition = targetOcc.Definition
Dim nonPrmFeatures As NonParametricBaseFeatures = targetDef.Features.NonParametricBaseFeatures

Dim transObjs As TransientObjects = ThisApplication.TransientObjects
Dim col As ObjectCollection = transObjs.CreateObjectCollection

Dim SourceOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick(kAssemblyLeafOccurrenceFilter, "Select Part to copy bodies from")

Dim oFace As FaceProxy = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Pick face.")
If oFace.ContainingOccurrence IsNot (targetOcc) Then
	MsgBox("Face must be on the occurrence to copy bodies into")
	Exit Sub
End If

For Each oBod As SurfaceBody In SourceOcc.Definition.SurfaceBodies
	If oBod.Name.StartsWith("Hole")
		Dim oProx As SurfaceBodyProxy = Nothing
		Call SourceOcc.CreateGeometryProxy(oBod, oProx)
		col.Add(oProx)
		Dim featureDef As NonParametricBaseFeatureDefinition = nonPrmFeatures.CreateDefinition
		featureDef.BRepEntities = col
		featureDef.OutputType = kSurfaceOutputType
		featureDef.TargetOccurrence = targetOcc
		featureDef.IsAssociative = True

		Dim baseFeature As NonParametricBaseFeature = nonPrmFeatures.AddByDefinition(featureDef)
		Try
			baseFeature.Name = oBod.Name
		Catch
		End Try
		col.Clear

		ThisApplication.UserInterfaceManager.DoEvents()

		Dim intersects As Boolean = False

		For Each NPFface As Face In baseFeature.Faces
			If ThisApplication.MeasureTools.GetMinimumDistance(oFace.NativeObject, NPFface) = 0 Then
				intersects = True
				Exit For
			End If
		Next
		If intersects = False
			baseFeature.Delete
		Else
			Dim oVals As String() = oBod.Name.Split(New String() {"(", ")" }, StringSplitOptions.None)(1).Split(";")
			Dim oCol As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection
			Dim oSketch As PlanarSketch = targetDef.Sketches.Add(oFace.NativeObject)
			Dim oProjEnt As SketchEntity

			For Each NPFface As Face In baseFeature.Faces
				If NPFface.SurfaceType = SurfaceTypeEnum.kCylinderSurface
					oProjEnt = oSketch.AddByProjectingEntity(NPFface.Edges(1))
					oProjEnt.Construction = True
					Dim oPt As SketchPoint = oProjEnt.CenterSketchPoint
					oPt.HoleCenter = True
					oCol.Add(oPt)
				End If
			Next
			Dim oHole As HoleFeature = targetDef.Features.HoleFeatures.AddDrilledByDistanceExtent(oCol, oVals(0), oVals(1), PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
			If oHole.RangeBox Is Nothing
				oHole.Delete
				baseFeature.Delete
			End If
		End If
	End If
Next

ThisDoc.Document.Update

If the bodies are named correctly and are made of cylindrical  surfaces I can't see any reason for it to fail🤔

Sleep well and let me know if it works when you have the time to try it!

Message 14 of 22

WCrihfield
Mentor
Mentor

@robertast @JhoelForshav 

Since you are trying to do this by copying bodies between two part type components of an assembly, to create new features within the second part component, perhaps you could get some pointers from this Sample VBA code that was provided within the online help section, that is dealing with a very similar issue.

It uses a method called ImprintBodies, which is found under ThisApplication.TransientBRep.

Please note too though, that they also mentioned (within the comments of the code) having trouble while attempting to use SurfaceBodyProxy objects, so they chose to show a workaround way to do it.

Perhaps this method will work for your situation, if the other options aren't working.


I had been trying to go at this whole issue from a slightly different perspective, to avoid as much set-up work as possible, such as creating a bunch of invisible solid/surface bodies ahead of time, avoid all the manual selections, by fully automating the task, using NamedEntities to identify the source & target items (faces, edges, etc.), then using something like attributes and/or NameValueMaps to convey their data from one part to the other, to then create the features needed within the target part. (Since naming an entity is essentially adding an Attribute to it, that helps you to uniquely identify it later, it seemed like a logical data storage medium.) Unfortunately, I never got the chance to finish it, so I thought I would just post one variation of the starting portion of this code here, so others can contemplate this idea too.

 

The initial rather simplistic idea was to name the source and target faces within the part files, then retrieve the source face within the assembly file, transfer the hole center points over to the target face, while also gathering the necessary data about the holes (from attributes or similar), then create the hole features within the target part file using the transferred hole center points and the gathered data (diameters & depths).

Here's the unfinished code I had started.

 

Sub Main
	If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
		MsgBox("This rule '" & iLogicVb.RuleName & "' only works for Assembly Documents.",vbOK, "WRONG DOCUMENT TYPE")
		Return
	End If

	Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim oAuto As IiLogicAutomation = iLogicVb.Automation
	Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
	Dim oOccs As ComponentOccurrences = oADef.Occurrences
	Dim oOcc As ComponentOccurrence
	
	'Get the Source & Target faces, occs, & definitions
	Dim oTOcc,oSOcc As ComponentOccurrence 'Target & Source Occurrences
	Dim oTDef,oSDef As PartComponentDefinition 'Target & Source PartComponentDefinitions
	Dim oTDoc, oSDoc As PartDocument 'Target & Source PartDocuments
	Dim oNE As NamedEntities
	Dim oTFace, oSFace As Face 'Target & Source mating Faces (within the parts)
	Dim oSDowelHoleFace1, oSScrewHoleFace1 As Face 'Source cylindrical hole named faces
	Dim oSDowelHoleFeat, oSScrewHoleFeat As PartFeature
	Dim oSDowelHoleDims, oSScrewHoleDims As FeatureDimensions
	Dim oTFProxy, oSFProxy As FaceProxy  'Target & Source FaceProxies (within the assembly)
	'Could also create variables for hole cylinder named faces here
	For Each oOcc In oOccs
		If oOcc.Name.Contains("Part 1") Then
			oTOcc = oOcc
			oTDef = oTOcc.Definition
			oTDoc = oTOcc.Definition.Document
			'The following face is the one on the target document, where the new hole features will be created.
			oTFace = oAuto.GetNamedEntities(oTargetDoc).TryGetEntity("Target Face")
			oTOcc.CreateGeometryProxy(oTFace,oTFProxy)
		ElseIf oOcc.Name.Contains("Part 2") Then
			oSOcc = oOcc
			oSDef = oSOcc.Definition
			oSDoc = oOcc.Definition.Document
			oNE = oAuto.GetNamedEntities(oSourceDoc)
			'The following face is the one on the Source document, where the existing holes are.
			oSFace = oNE.TryGetEntity("Source Face")
			oSScrewHoleFace1 = oNE.TryGetEntity("Screw Hole 1 Cylinder")
			oSScrewHoleFeat = oSScrewHoleFace1.CreatedByFeature
'			oSScrewHoleDims = oSScrewHoleFeat.FeatureDimensions
			oSDowelHoleFace1 = oNE.TryGetEntity("Dowel Hole 1 Cylinder")
			oSDowelHoleFeat = oSScrewHoleFace1.CreatedByFeature
'			oSDowelHoleDims = oSDowelHoleFeat.FeatureDimensions
			oSOcc.CreateGeometryProxy(oSFace,oSFProxy)
		End If
	Next
	
	'Collect geometry data from the source face holes
	Dim oCCount As Integer = 0
	Dim oCircle As Circle2d
	Dim oDia As Double
	Dim oCP As Point2d
	For Each oEL As EdgeLoop In oSFProxy.EdgeLoops
		If oEL.IsOuterEdgeLoop = False Then
			If oEL.Edges.Item(1).GeometryType = CurveTypeEnum.kCircleCurve Then
				oCCount = oCCount + 1  'found a circular edge
				oCircle = oEL.Edges.Item(1).Geometry
				oDia = oCircle.Radius * 2
				oCP = oCircle.Center
			End If
		End If
	Next
	
'	'Collect data about the source cylinder faces
'	Dim oScHoleCyl As Cylinder = oSScrewHoleFace1.Geometry
'	Dim oScHoleDia As Double = oScHoleCyl.Radius * 2
'	Dim oScHoleBPoint As Point = oScHoleCyl.BasePoint
'	Dim oDwlHoleCyl As Cylinder = oSDowelHoleFace1.Geometry
'	Dim oDwlHoleDia As Double = oDwlHoleCyl.Radius * 2
'	Dim oDwlHoleBPoint As Point = oDwlHoleCyl.BasePoint
	
	'Transfer hole center points to sketch on Target face while in-place editing the target part.
'	oTOcc.Edit     'not sure if I want to use this, because it will take focus away from the code running
	Dim oSketch As PlanarSketch = oTDef.Sketches.Add(oTFace, False)
	Dim oScHoleCPoint As SketchPoint = oSketch.AddByProjectingEntity(oScHoleBPoint)
	Dim oDwlHoleCPoint As SketchPoint = oSketch.AddByProjectingEntity(oDwlHoleBPoint)
'	oTOcc.ExitEdit(ExitTypeEnum.kExitToPrevious)
	
	'Create the HoleFeatures within the Target part
	Dim oTHoleFeats As HoleFeatures = oTDef.Features.HoleFeatures
	'Create the screw hole feature placement definition
	'Need to translate cylinder base point data to define oScHolePoint
	Dim oScHolePoint = ThisApplication.TransientGeometry.CreatePoint()
	Dim oTScHoleDef As HolePlacementDefinition = oTHoleFeats.CreatePointPlacementDefinition(oScHolePoint,oTFace)
'	oTHoleFeats.AddDrilledByDistanceExtent()
				
End Sub


 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 15 of 22

WCrihfield
Mentor
Mentor

Is the goal for the resulting new hole features to only exist within the assembly environment, leaving the target part unchanged (as if it were a master part), or is the goal to create the new hole features within the target part only?  Do you need the new hole features diameters & depths to be dependent on (linked to) the source part, and their positions being dictated by the assembly?

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 16 of 22

robertast
Collaborator
Collaborator

The crux of my problem is that I need to punch holes from one part to another. And the location of these holes depends on the position of the part from which they were taken.

 

 

 

Surinkimas.jpg

In other words, these holes are adapted for another part. I started the problem with "copy object" because if I do it with a responsive sketch they are lost when the assembly is resized. The Inventor developers explained to me that in my situation I can only achieve stability through a "copy object".
The code written by @JhoelForshav  works pretty well, especially the latter. It only fails in one place.
This is when checking for intersection and deletion if there is none.
I will try to find this place, although I do not have enough knowledge. @WCrihfield If you can help with this, I will be grateful to you.

 

 

0 Likes
Message 17 of 22

robertast
Collaborator
Collaborator

@JhoelForshav 

 

If I'm not tired of you with my problem yet. And you decide to help me to the end. I feel with my heart that in this code I will face another problem, this is the name of the objects. Before leaving them as in the standard. Dimensions in variables should be written earlier from solid bodies and used for holes

 

Pavirsiai.jpg

0 Likes
Message 18 of 22

JhoelForshav
Mentor
Mentor

@robertast 

I'm sorry but i didn't understand any of that... Could you try to express the same thing in different words? Maybe the translation will be better then 🙂

 

Also, I looked at the video you sent me. It seems that the first time you run the code, It should result in holes but none are created. Am i right?

 

As I see it there are two possible explainations to that.

1. The check for intersection fails and therefore the copied object is deleted.

2. The hole has no effect and therefore everything is deleted.

 

Maybe you can investigate a litte to see where the object gets deleted?

 

Do you have any sample files in 2020-version? 🙂

 

0 Likes
Message 19 of 22

JhoelForshav
Mentor
Mentor
Accepted solution

Hi @robertast 

I hope you'll feel better soon!

@ernissent me a private message with the sample files and I see the problem now.

 

The thing is that we need to update the assembly in order to make sure the copied surfaces are in their correct positions. When we update however, the faceobject will be changed, so even though our variable oFace still contains information, it doesn't refer to an actual face anymore. The same goes for trying to store oFace.NativeObject in a variable.

This makes the rule crash if we're trying to analyze intersection with oFace or create a sketch on oFace after the asssembly has been updated.

 

My workaround is this:

1. I use the SurfaceBodyProxy instead of the copied surface to analyze intersection. This is accurate even without an assembly update and lets me exclude bodies before the "copy-stage".

If a body has already been used to create a hole though, so the resulting hole will have no effect, the body will still be copied with the method we use to analyze intersection. This I've added a different check for later in the code.

 

2. I create and store all NonParametricBaseFeatures that hasn't been excluded by the intersection check and their dimension values in a dictionary. After that I update the assembly to get everything in position.

To be able to find the face on which to sketch on I create a "dummy sketch" that I can use to get the face again by its PlanarEntity-property.

I then traverse the dictionary creating holes. If the hole has no effect (it's rangebox is nothing) I delete the hole and the NonParametricBaseFeature.

 

Finally I delete this "dummy sketch" and update the Assembly one last time.

 

Maybe it's not the most sophisticated solution, but it works! Copying objects through the api really is a mess unfortunatley.

Here's the final code:

 

Dim asmDoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim asmDef As AssemblyComponentDefinition = asmDoc.ComponentDefinition

Dim targetOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick(kAssemblyLeafOccurrenceFilter, "Select Part to copy the Body into.")
Dim targetDef As PartComponentDefinition = targetOcc.Definition
Dim nonPrmFeatures As NonParametricBaseFeatures = targetDef.Features.NonParametricBaseFeatures

Dim transObjs As TransientObjects = ThisApplication.TransientObjects
Dim col As ObjectCollection = transObjs.CreateObjectCollection
Dim oHoles As New Dictionary(Of String(), NonParametricBaseFeature)

Dim SourceOcc As ComponentOccurrence = ThisApplication.CommandManager.Pick(kAssemblyLeafOccurrenceFilter, "Select Part to copy bodies from")

Dim oFace As FaceProxy = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Pick face.")
If oFace.ContainingOccurrence IsNot (targetOcc) Then
	MsgBox("Face must be on the occurrence to copy bodies into")
	Exit Sub
End If
Dim oFirstSketch As PlanarSketch = targetDef.Sketches.Add(oFace.NativeObject) 'Something to find the face with after update
For Each oBod As SurfaceBody In SourceOcc.Definition.SurfaceBodies
	If oBod.Name.StartsWith("Hole")
		Dim oProx As SurfaceBodyProxy = Nothing
		Call SourceOcc.CreateGeometryProxy(oBod, oProx)
		Dim intersects As Boolean = False
		For Each oFprox As FaceProxy In oProx.Faces
			If ThisApplication.MeasureTools.GetMinimumDistance(oFprox, oFace) = 0
				intersects = True
				Exit For
			End If
		Next
		If intersects = True
			col.Add(oProx)
			Dim featureDef As NonParametricBaseFeatureDefinition = nonPrmFeatures.CreateDefinition
			featureDef.BRepEntities = col
			featureDef.OutputType = kSurfaceOutputType
			featureDef.TargetOccurrence = targetOcc
			featureDef.IsAssociative = True

			Dim baseFeature As NonParametricBaseFeature = nonPrmFeatures.AddByDefinition(featureDef)
			ThisApplication.UserInterfaceManager.DoEvents()
			Try
				baseFeature.Name = oBod.Name & " [" & SourceOcc.Name & "]"
			Catch
			End Try
			col.Clear
			Dim oVals As String() = oBod.Name.Split(New String() {"(", ")" }, StringSplitOptions.None)(1).Split(";")
			oHoles.Add(oVals, baseFeature)
		End If
	End If
Next
asmDoc.Update
For Each oPair As KeyValuePair(Of String(), NonParametricBaseFeature) In oHoles
	Dim oSketch As PlanarSketch = targetDef.Sketches.Add(oFirstSketch.PlanarEntity)
	Dim oCol As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection

	Dim oProjEnt As SketchEntity
	For Each NPFface As Face In oPair.Value.Faces
		If NPFface.SurfaceType = SurfaceTypeEnum.kCylinderSurface
			oProjEnt = oSketch.AddByProjectingEntity(NPFface.Edges(1))
			oProjEnt.Construction = True
			Dim oPt As SketchPoint = oProjEnt.CenterSketchPoint
			oPt.HoleCenter = True
			oCol.Add(oPt)
		End If
	Next
	Dim oHole As HoleFeature = targetDef.Features.HoleFeatures.AddDrilledByDistanceExtent(oCol, oPair.Key(0), oPair.Key(1), PartFeatureExtentDirectionEnum.kPositiveExtentDirection)
	If oHole.RangeBox Is Nothing
		oHole.Delete
		oPair.Value.Delete
	End If
Next
oFirstSketch.Delete
asmDoc.Update
Message 20 of 22

robertast
Collaborator
Collaborator
Accepted solution

It looks like everything will work fine now. Thank you very much for your help. As you can see from the reviews, there is a lot of interest in this topic. But no one decided to join the discussion. I have said more than once that you are the best.

_ZENKLAS.png

Since all of your examples have invaluable information for other solutions, I will mark them all as a solution