OrientedMinimumRangeBox not always returning the exact dimension

OrientedMinimumRangeBox not always returning the exact dimension

dominiek_vanwest
Advocate Advocate
394 Views
7 Replies
Message 1 of 8

OrientedMinimumRangeBox not always returning the exact dimension

dominiek_vanwest
Advocate
Advocate

Hi,

 

I'm using the following code to check if the thickness of the Flat Pattern is the same as the thickness set by the sheet metal definition (just to make sure the part is drawn correctly as you could easily input a value for Face or Thicken instead of using Thickness).

 

If Math.Round(oRefDoc.ComponentDefinition.FlatPattern.Body.OrientedMinimumRangeBox.DirectionThree.Length, 3) <> Math.Round(oRefDoc.ComponentDefinition.thickness.Value, 3) Then
    MsgBox Math.Round(oRefDoc.ComponentDefinition.FlatPattern.Body.OrientedMinimumRangeBox.DirectionThree.Length * 10, 10)
End If

 

But this mostly returns values which are a little bit off.

In my example the thickness is 4 mm, but the OrientedMinimumRangeBox value is 4.0276439458 mm. So if I compare them, they give me the messagebox. But in reality the part is drawn correctly (if I measure the Flat Pattern myself I measure 4.000 mm).

 

What is causing these (wrong) numbers?

I could easily round it to 1 decimal but I'd like to know if there is another way.

 

Thanks in advance!

 

0 Likes
Accepted solutions (1)
395 Views
7 Replies
Replies (7)
Message 2 of 8

WCrihfield
Mentor
Mentor

Hi @dominiek_vanwest.  Have you tried using the SurfaceBody.PreciseRangeBox property, instead of the SurfaceBody.OrientedMinimumRangeBox property.  From what I have seen over the years on this forum and in other related 'blog' posts, using these types of resources to get the absolute tightest fit bounding boxes has always been pretty challenging, for multiple reasons.  I believe the original properties & methods, like the SurfaceBody.RangeBox and probably even the 'oriented' variation, sometimes included things like sketch geometry, work features, and the bounding boxes of such things within the overall bounding box, which was not always wanted.  Some make sure to always turn visibility of such things off before getting bounding boxes, or similar tactics, but I don't recall if that always worked.  For some reason, I think that newer one with 'Precise' in its name attempts to bypass those types of things, to get more accurate results, but I rarely need to use those tools, so have not done a ton of comparison testing with the newer tools yet.  One good property to check is the SheetMetalComponentDefinition.UseSheetMetalStyleThickness property, but as you said, even if everything else is done right, the user could have still used other means to modify the thickness.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 8

dominiek_vanwest
Advocate
Advocate

Thank you for the reply @WCrihfield 

 

I have tried your code like this:

Debug.Print "Z_max: " & oRefDoc.ComponentDefinition.FlatPattern.SurfaceBodies(1).PreciseRangeBox.Maxpoint.Z
Debug.Print "Z_min: " & oRefDoc.ComponentDefinition.FlatPattern.SurfaceBodies(1).PreciseRangeBox.MinPoint.Z
Debug.Print "Z: " & oRefDoc.ComponentDefinition.FlatPattern.SurfaceBodies(1).PreciseRangeBox.Maxpoint.Z - oRefDoc.ComponentDefinition.FlatPattern.SurfaceBodies(1).PreciseRangeBox.MinPoint.Z

But I get the following result. It's better but not perfect yet (it should be 0,4)

Z_max: 5,10774755824173E-12
Z_min: -0,399999999994898
Z: 0,400000000000006

 

But with rounding it I should get less errors than before.

0 Likes
Message 4 of 8

WCrihfield
Mentor
Mentor
Accepted solution

Hi @dominiek_vanwest.  It is unfortunate that we can't get the exact values we are looking for using 'bounding box' methods, but those are not our only options.  If exact measurements are needed, then we can simulate measuring that thickness by code instead.  There are likely multiple routes to do that, but below is one example of an iLogic rule designed with just that task in mind.  All it does is dig down to the existing FlatPattern object (does nothing if it does not already exist), then gets its 'top face' and 'bottom face', then gets the 'Plane' that their geometry represents, then uses a built-in geometry measurement method to get the value we are looking for.  Then, it takes the extra step of converting the units of the measurement to 'document units', if those are different from the 'database units' (centimeters), for convenience.  Then I just included 2 different ways to provide that raw, un-rounded value as feedback (show it in a MsgBox, or write it to the iLogic Log window).  I hope this helps.  I have seen a few situations over the years where one of those two Properties of the FlatPattern did not return a valid value, so if needed, you could always include a few more checks and/or use a Try...Catch...End Try statement (or few) in there to help.

Sub Main
	Dim oPDoc As Inventor.PartDocument = TryCast(ThisDoc.Document, Inventor.PartDocument)
	If oPDoc Is Nothing Then Return
	If Not TypeOf oPDoc.ComponentDefinition Is Inventor.SheetMetalComponentDefinition Then Return
	Dim oSMDef As Inventor.SheetMetalComponentDefinition = oPDoc.ComponentDefinition
	If oSMDef.HasFlatPattern Then
		Dim oFP As Inventor.FlatPattern = oSMDef.FlatPattern
		Dim dMeasuredThickness As Double = 0.0
		Dim oTopPlane As Inventor.Plane = oFP.TopFace.Geometry
		Dim oBottomPlane As Inventor.Plane = oFP.BottomFace.Geometry
		dMeasuredThickness = Math.Abs(oTopPlane.DistanceTo(oBottomPlane.RootPoint))
		Dim UOM As Inventor.UnitsOfMeasure = oPDoc.UnitsOfMeasure
		If Not UOM.LengthUnits = UnitsTypeEnum.kDatabaseLengthUnits Then
			dMeasuredThickness = UOM.ConvertUnits(dMeasuredThickness, UnitsTypeEnum.kDatabaseLengthUnits, UOM.LengthUnits)
		End If
		MsgBox("The FlatPattern's Measured Thickness Is:" & _
		vbCrLf & dMeasuredThickness.ToString(), vbInformation, "FlatPattern Thickness Measurement")
		Logger.Info("The FlatPattern's Measured Thickness Is:" & _
		vbCrLf & dMeasuredThickness.ToString())
	End If
End Sub

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

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 8

dominiek_vanwest
Advocate
Advocate

Thanks a lot! This is a very good solution.

 

There is an issue with rounding though. Here my code:

Dim dMeasuredThickness As Double
Dim oTopPlane As Inventor.Plane
Set oTopPlane = oRefDoc.ComponentDefinition.FlatPattern.TopFace.Geometry
Dim oBottomPlane As Inventor.Plane
Set oBottomPlane = oRefDoc.ComponentDefinition.FlatPattern.BottomFace.Geometry
dMeasuredThickness = Math.Abs(oTopPlane.DistanceTo(oBottomPlane.RootPoint))

If dMeasuredThickness <> oRefDoc.ComponentDefinition.thickness.Value Then
    Debug.Print " " & dMeasuredThickness
    Debug.Print " " & oRefDoc.ComponentDefinition.thickness.Value
End If

The output:

0,4
0,4

 

I actually shouldn't get an output as they are the same. But for some reason it does see it as different values. I can use rounding of both to make it work.

I know a similar issue exists in Excel. Sometimes when you compare two identical values it sees it as different values.

0 Likes
Message 6 of 8

WCrihfield
Mentor
Mentor

There are several tools available to help with Double type value comparisons.  The issue is that those values can go all the way out to about 15 decimal places, so 1.0000000000001 is not equal to 1.0000000000000000.  A couple of the tools I use most often are the uniquely iLogic EqualWithinTolerance Method (Double, Double, Double), where the first 2 inputs are the two values you want to compare, then the optional third input is the 'tolerance' amount that the two values are allowed to be different and still evaluate to being equal.  That method is readily available in our iLogic rules, because the 'Autodesk.iLogic.Runtime' DLL file is already referenced and 'Imported' into our rules automatically, and that tool is under the Autodesk.iLogic.Runtime.LmiMath Class.  I also have this little custom Function in one or two external iLogic resources, which works essentially the same, but has a built-in 'default' tolerance value that suits my needs most of the time.  But you can see the simplicity of the actual working code within that Function, and could just use that instead.  I'm sure there are others too.

'Compare Two Double Type Values For Equality, Within A Tolerance
Function CloseEnough(ByVal val1 As Double, ByVal val2 As Double, _
	Optional ByVal acceptableDifference As Double = 0.000001) As Boolean
	If Math.Abs(val1 - val2) <= acceptableDifference Then Return True
	Return False
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 8

jnowel
Collaborator
Collaborator

I encountered before some codes declaring as DoubleForEquals Structure instead of Double.
I got used to rounding off before comparing so I don't know much what issues it can make down the line
Have you also used that before @WCrihfield ?

0 Likes
Message 8 of 8

WCrihfield
Mentor
Mentor

Hi @jnowel.  I'm guessing we all have, whether we knew it or not, because that DoubleForEquals Structure is what iLogic uses behind the scenes for its 'blue' (by default), unquoted 'iLogic Parameters' within internal iLogic rules, when the parameter's value is a Double.  You may have noticed that if you type a dot (.) right after one of those blue, unquoted parameter names, it shows that whole list of methods shown in the DoubleForEquals Structure, and when you hover your mouse over any of those 'suggestions' provided by the 'Intellisense' system, you will see the Type it assumes the original parameter is, which gives it away.  Using that system cuts the number of decimal places way down (only about 6) just for comparison methods, to make them more forgiving.  It also offers a TON of methods and Operators.  I don't really use it much in my external rules, but I certainly would not discourage its use.  It is defined within the iLogic add-in though, so that can be slightly challenging if your codes are for add-ins or standalone exe's.  There is also the uniquely iLogic DoubleUtil Class, which offers two methods for comparing equality or inequality, while limiting precision to just 6 decimal digits.  Those methods can be used with regular Double values (no type conversion needed).  I don't use those much in my external rules either, but do not discourage it.  The simple methods mentioned before have met my needs in most cases, and are easy enough to understand for me.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)