Get face to face measurement

Get face to face measurement

blandb
Mentor Mentor
1,584 Views
12 Replies
Message 1 of 13

Get face to face measurement

blandb
Mentor
Mentor

I found the code below, and if I have used an insert constrain and set 2 parts 100 in apart, this code does not give the correct value. I need something to where I can choose the 2 faces and then get the actual face to face measurements. Thanks in advanced!

 

Dim Face1 As Object
Dim Face2 As Object
Dim oDoc As AssemblyDocument
oDoc = ThisApplication.ActiveDocument
Face1 = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFaceFilter,"Select Start Face1 to measure distance:")
'MsgBox("Face area1: " & Face1.Evaluator.Area & " cm^2")
Face2 = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFaceFilter,"Select End Face2 to measure distance:")
'MsgBox("Face area: " & Face2.Evaluator.Area & " cm^2")
Dim Distance As Double
'Distance = Face1.PointOnFace.DistanceTo(Face2.PointOnFace)
Distance = ThisApplication.MeasureTools.GetMinimumDistance(Face1.PointOnFace, Face2.PointOnFace)
MsgBox( Distance & " cm")
Distance = oDoc.UnitsOfMeasure.ConvertUnits(Distance, "cm", "in")
MsgBox (Distance & " in")

 

Autodesk Certified Professional
0 Likes
Accepted solutions (2)
1,585 Views
12 Replies
Replies (12)
Message 2 of 13

WCrihfield
Mentor
Mentor

Hi @blandb.  This example may not be exactly what you were looking for, but is similar and does basically the same task, with Angle also thrown in there.  Only it does so using API code and geometry properties, rather than a measure command.  It also takes into account if the two selected faces are not perfectly parallel.  And it was designed for use in an assembly environment too, so it kind of fits the scenario.

Sub Main
	Dim Face1 As FaceProxy = PickPlanarFaceProxy
	If IsNothing(Face1) Then Exit Sub
	Dim Face2 As FaceProxy = PickPlanarFaceProxy
	If IsNothing(Face2) Then Exit Sub
	Dim Plane1 As Plane = Face1.Geometry
	Dim Plane2 As Plane = Face2.Geometry
	Dim Distance, Angle As Double
	If Plane1.IsParallelTo(Plane2) Then
		If Plane1.IsCoplanarTo(Plane2, 0.0001) Then
			Distance = 0.0 : Angle = 0.0
		Else
			Distance = Plane1.DistanceTo(Plane2.RootPoint) : Angle = 0.0
		End If
	ElseIf Plane1.IsPerpendicularTo(Plane2, 0.0001) Then
		MsgBox("Selected Faces Are Perpendicular.", , "")
		Exit Sub
	Else
		Distance = 0.0 : Angle = Plane1.Normal.AngleTo(Plane2.Normal)
	End If
	MsgBox("Distance = " & Distance & " cm" & vbCrLf & _
	"Angle = " & Angle & " rad", , "")
	Dim oDoc As Document = Face1.ContainingOccurrence.Parent.Document
	Distance = oDoc.UnitsOfMeasure.ConvertUnits(Distance, "cm", "in")
	Angle = oDoc.UnitsOfMeasure.ConvertUnits(Angle, "rad", "deg")
	MsgBox("Distance = " & Distance & " in" & vbCrLf & _
	"Angle = " & Angle & " deg",,"")
End Sub

Function PickPlanarFaceProxy As FaceProxy
	oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select a flat face.")
	If IsNothing(oObj) OrElse (TypeOf oObj Is FaceProxy = False) Then Return Nothing
	Dim oFace As FaceProxy = oObj
	If oFace.SurfaceType <> SurfaceTypeEnum.kPlaneSurface Then Return Nothing
	Return oFace
End Function

I left the two different feedback message, showing centimeters & radians in one, and inches and degrees in the other, because I wasn't sure if that was part of the goal or not.  You could also simply select the two faces, then execute the normal measure command too ("AppMeasureDistanceCmd"), but then what's the use of doing it by code, because you've pretty much done more work this way, than doing it with the normal measure tool on the screen, and still don't have a value stored in a variable.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 13

blandb
Mentor
Mentor

Thanks, you are on to something there. Luckily most everything I will be using this for is parallel faces. All I am needing is just an inch measurement, the other was there from the code prior. I'm grabbing this to store that measured distance to do math from later. Is there a way to not have it display say a negative number? Seems no matter the first picked face, I get a negative number. Just return the ABS Value of the faces?

Autodesk Certified Professional
0 Likes
Message 4 of 13

WCrihfield
Mentor
Mentor
Accepted solution

Sure.  Here you go.  I got rid of all the angle stuff, and metric stuff.  I left the perpendicular message in there, just so you know that it did something, instead of just not returning any message at all, when that is the case.  But you can get rid of that too, if you are just going to turn this into its own Function.  The key to not getting a negative number is the Math.Abs() function.

Sub Main
	Dim Face1 As FaceProxy = PickPlanarFaceProxy
	If IsNothing(Face1) Then Exit Sub
	Dim Face2 As FaceProxy = PickPlanarFaceProxy
	If IsNothing(Face2) Then Exit Sub
	Dim Plane1 As Plane = Face1.Geometry
	Dim Plane2 As Plane = Face2.Geometry
	Dim Distance As Double
	If Plane1.IsParallelTo(Plane2) Then
		If Plane1.IsCoplanarTo(Plane2, 0.0001) Then
			Distance = 0.0
		Else
			Distance = Plane1.DistanceTo(Plane2.RootPoint)
		End If
	ElseIf Plane1.IsPerpendicularTo(Plane2, 0.0001) Then
		MsgBox("Selected Faces Are Perpendicular.", , "") : Exit Sub
	End If
	UOM = ThisApplication.UnitsOfMeasure
	Distance = UOM.ConvertUnits(Distance, "cm", "in")
	Distance = Math.Abs(Distance)
	MsgBox("Distance = " & Distance & " in",,"")
End Sub

Function PickPlanarFaceProxy As FaceProxy
	oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFacePlanarFilter, "Select a flat face.")
	If IsNothing(oObj) OrElse (TypeOf oObj Is FaceProxy = False) Then Return Nothing
	Dim oFace As FaceProxy = oObj
	If oFace.SurfaceType <> SurfaceTypeEnum.kPlaneSurface Then Return Nothing
	Return oFace
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 13

blandb
Mentor
Mentor

Thanks, that works. So basically, I am using this to get a gap, then see how many I can fit in this gap, placing the components that need to be patterned and then doing the pattern. The issue I see is, I don't know how many times I might run this rule in an assembly, could be 1 time, could be 5 times. So I cant give the names of the components I want to add a "stagnant" name such as "clamp 1" because the next time this is ran, it will want to place "clamp 1" again. What is the best way to do that?

Autodesk Certified Professional
0 Likes
Message 6 of 13

WCrihfield
Mentor
Mentor

Hi @blandb.  I'm not sure I fully understand the overall process and your question, but if you need to be able to specify a component name within your code, but do not want to hard code the name into the code, there are usually a few options for that situation.  You could use an InputBox to prompt the user to enter the component name.  You could use a SharedVariable to temporarily store the component name within Inventor's 'session memory', then retrieve that SharedVariable's value within your followup code somewhere so that it can be shared multiple times by multiple rules.  You could record the value/data to something like an Attribute, iProperty, or Parameter, but that will 'dirty' your document.  You could write the value out to a temporary text file in your temp folder, then retrieve it as needed.  Are any of these thoughts pointing in the right direction?

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 7 of 13

blandb
Mentor
Mentor

Below is an image with 2 faces highlighted. Obviously these would be much further apart. So, I have some components that need to fit between those faces. I'm working on the quantity that is needed to fit the space. This situation can happen multiple different times on an assembly, this is just a single instance. There could be many of the same size components highlighted with the blue faces that I need to auto fill the spacing. So that is where the issue of the names of adding components. Since I could only run this once on this run, or many different times on different runs. I cant use tube and pipe for this. I currently place the components and then pattern, but my boss is wanting to try and automate this.

 

FACES.png

 

I am also trying to figure out how to capture the edge names of the highlighted faces. I have named the entities, but when I choose face 1, how to extract the edge name I assigned when selecting that instances face, same for face 2.

 

hope that helps.

Autodesk Certified Professional
0 Likes
Message 8 of 13

WCrihfield
Mentor
Mentor

Hi @blandb.  Concerning the last two sentences of your last post...Did you assign the names to those two faces within the Part environment, using the built-in user interface tool...select face, right-click, choose 'Assign Name' from right-click menu, type in name, then OK?  Or did you use some other automation tool?  If you used some other automation tool, are you using the same naming conventions as the built-in tool for naming entities?  In an assembly environment, faces, edges, & vertex objects that were assigned names in part environment, will not be immediately available.  You will have to do a little digging to identify them, or extract any possibly existing name from their 'native' object.  All that type of geometry in an assembly is a proxy of the original, instead of the original directly.  For instance, a face we select in an assembly environment will be a FaceProxy object, instead of a regular Face.  So we would have to dig back to the original Face that this Proxy represents, then either dig down into its Face.AttributeSets for the Attribute, or get the document object that the component represents, then get the NamedEntities interface for that document, then use its tools to check if the entity has been given a name.  I don't recall what version of Inventor you are using, but the user interface tool, and the NameEntities interface became available around Inventor 2019.1 I believe.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 9 of 13

blandb
Mentor
Mentor

I did name the edge entities with the "assign name". I used edges because I use Insert Constraints. Oh....I think I am in over my head on this one lol

Autodesk Certified Professional
0 Likes
Message 10 of 13

WCrihfield
Mentor
Mentor
Accepted solution

It can definitely be intimidating to tackle when you are new to the idea.  Here is one way of doing it with a fairly simple iLogic rule.  This example is just for Edges though, as a quickie example to suit the specific need right now.  This example will also only work when the selected edge is on a top level part type component.

oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartEdgeFilter, "Select part edge.")
If IsNothing(oObj) OrElse (TypeOf oObj Is EdgeProxy = False) Then Exit Sub
Dim oEdgeProxy As EdgeProxy = oObj
Dim oEdge As Edge = oEdgeProxy.NativeObject
Dim oPDoc As PartDocument = oEdge.Parent.ComponentDefinition.Document
oNEs = iLogicVb.Automation.GetNamedEntities(oPDoc)
Dim oName As String = oNEs.GetName(oEdge)
If oName = "" Then
	MsgBox("No name found for selected edge.", , "")
Else
	MsgBox("The Name assigned to the selected edge is:  " & oName, , "")
End If

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.

If you want and have time, I would appreciate your Vote(s) for My IDEAS :bulb: or you can Explore My CONTRIBUTIONS

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 11 of 13

blandb
Mentor
Mentor

So I have tried to get the distance between my 2 edges, but I guess it is not a simple as just measuring the minimum distance between the named edges?

 

Sub Main
	
	Dim InletEdge As EdgeProxy = PickInletEdgeProxy
	Dim OutletEdge As EdgeProxy = PickOutletEdgeProxy

	Dim Distance As Double
		Distance = Measure.MinimumDistance(InletEdge, OutletEdge)


	UOM = ThisApplication.UnitsOfMeasure
	Distance = UOM.ConvertUnits(Distance, "cm", "in")
	Distance = Math.Abs(Distance)
	MsgBox("Distance = " & Distance & " in", , "")

End Sub

Function PickInletEdgeProxy As EdgeProxy
oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartEdgeFilter, "Select Inlet edge.")
If IsNothing(oObj) OrElse (TypeOf oObj Is EdgeProxy = False) Then Return Nothing
Dim oEdgeProxy As EdgeProxy = oObj
Dim oEdge As Edge = oEdgeProxy.NativeObject
Dim oPDoc As PartDocument = oEdge.Parent.ComponentDefinition.Document
oNEs = iLogicVb.Automation.GetNamedEntities(oPDoc)
Dim oName As String = oNEs.GetName(oEdge)
	If oName = "" Then
	MsgBox("No name found for selected edge.", , "")
Else
	MsgBox("The Name assigned to the selected edge is:  " & oName, , "")
End If
End Function

Function PickOutletEdgeProxy As EdgeProxy
oObj = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartEdgeFilter, "Select Outlet edge.")
If IsNothing(oObj) OrElse (TypeOf oObj Is EdgeProxy = False) Then Return Nothing
Dim oEdgeProxy As EdgeProxy = oObj
Dim oEdge As Edge = oEdgeProxy.NativeObject
Dim oPDoc As PartDocument = oEdge.Parent.ComponentDefinition.Document
oNEs = iLogicVb.Automation.GetNamedEntities(oPDoc)
Dim oName As String = oNEs.GetName(oEdge)
	If oName = "" Then
	MsgBox("No name found for selected edge.", , "")
Else
	MsgBox("The Name assigned to the selected edge is:  " & oName, , "")
End If
End Function
Autodesk Certified Professional
0 Likes
Message 12 of 13

Maximilian.Prasser
Participant
Participant

Is there any option to get the max distance between to edges / named geometries / surfaces?

MaximilianPrasser_1-1737040106910.png

 

 

0 Likes
Message 13 of 13

WCrihfield
Mentor
Mentor

Hi @Maximilian.Prasser.  I do not believe there is a 'built-in' method for finding 'maximum distance'.

There are 3 methods for finding minimum distance:

MeasureTools.GetMinimumDistance

ICadMeasure.MinimumDistance Method (Object, Object)

ICadMeasure.MinimumDistance Method (Object, Object, Object, Object)

...but none of those have any option for getting maximum distance.

There is very likely a way to get that data, if it is important enough, but it will likely require a 'custom' method.  There can be a great many things involved in creating custom measuring tools, depending on how complex the scenarios that it is expected to manage.  Flat faces and straight edges are relatively simple to deal with, but the geometry of the bottom face in that image, and its edges appear to be curved in all 3 coordinate directions, so it will be much more complex to measure to/from accurately.  Since the measurement you want in this specific situation could be found by an 'oriented bounding box', there may be an easier route to finding that size, but that size would be one value among 3 values, and you would need to be able to determine which of those 3 values is the correct one.

SurfaceBody.OrientedMinimumRangeBox (a Property of the SurfaceBody object, which returns an OrientedBox transient mathematical object)

OrientedBox (that returned object Type)

DirectionOneDirectionTwo, & DirectionThree (three properties of that object, which give us 'Vector' objects)

Vector (transient mathematical object representing direction and distance)

Vector.Length (a property of the Vector object, which gives us its length)

You can collect that data from all 3 of its directions, then use known sizes to eliminate the ones you are not looking for.  Just one plan, among multiple possible plans.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes