How to get a Face or a FaceProxy object's true Normal?

How to get a Face or a FaceProxy object's true Normal?

bjhuxq
Participant Participant
929 Views
3 Replies
Message 1 of 4

How to get a Face or a FaceProxy object's true Normal?

bjhuxq
Participant
Participant

Hi,

Inventor 2021

API,C# VisualStudio

 

I try to get a kPlaneSurface FaceProxy's Normal by faceProxy.Geometry.Normal property,but I found the normal property is related to Face.IsParamReversed property. In normal ipt,face's normal is reversed when IsParamReversed property is true,but in ipt which is created by mirrored ReferenceFeature,face's normal is reversed when IsParamReversed property is false.So,how can I conveniently and efficiently get the normal?

Normal ipt IsParamReversed is falseNormal ipt IsParamReversed is falsemirrored ipt IsParamReversed is truemirrored ipt IsParamReversed is trueNormal ipt IsParamReversed is trueNormal ipt IsParamReversed is truemirrored ipt IsParamReversed is falsemirrored ipt IsParamReversed is false

my purpose is make AssemblyConstraint(Flush or Mate),if there is no way to get true normal of face,how can I get referrencefeature's mirror infomation by API?

 

0 Likes
Accepted solutions (1)
930 Views
3 Replies
Replies (3)
Message 2 of 4

earl_cody
Contributor
Contributor
Accepted solution

@bjhuxq

 

Try using the Face.Evaluator object. It is a SurfaceEvaluator type that has a GetNormal method for getting the surface normal.

 

https://help.autodesk.com/view/INVNTOR/2021/ENU/?guid=GUID-4DC35278-D6AC-41F0-9D12-68E95EA07A89 

https://help.autodesk.com/view/INVNTOR/2021/ENU/?guid=GUID-11A3E5CD-A40B-4D3D-93C9-A60F094BD784 

 

Inventor.PartDocument doc = invApp.ActiveDocument as Inventor.PartDocument;
Inventor.Face f = invApp.CommandManager.Pick(Inventor.SelectionFilterEnum.kPartFaceFilter, "pick face") as Inventor.Face;

Inventor.SurfaceEvaluator surfEval = f.Evaluator;
Inventor.Box2d box2DParamRange = surfEval.ParamRangeRect;

double u;
double v;

double[] pars = new double[2];
double[] normals = new double[3];

u = box2DParamRange.MinPoint.X;
v = box2DParamRange.MaxPoint.X;
pars[0] = (u + v) / 2;

u = box2DParamRange.MinPoint.X;
v = box2DParamRange.MaxPoint.X;
pars[1] = (u + v) / 2;

surfEval.GetNormal(ref pars, ref normals);
Message 3 of 4

bjhuxq
Participant
Participant

That's exactly what I want,thank you very much.

 

0 Likes
Message 4 of 4

maxim.teleguz
Advocate
Advocate

here is my code that gets it closer without selecting a face, now i wish that someone can help me get it all the way:


Sub Main()
    ' iLogic rule to set view orientation to the closest face normal in a part or assembly document

    Dim oDoc As Document = ThisDoc.Document
    Dim oCompDef As ComponentDefinition
    Dim oCamera As Camera = ThisApplication.ActiveView.Camera

    ' Determine the document type and get the ComponentDefinition
    If TypeOf oDoc Is PartDocument Then
        oCompDef = oDoc.ComponentDefinition
    ElseIf TypeOf oDoc Is AssemblyDocument Then
        oCompDef = oDoc.ComponentDefinition
    Else
        MsgBox("This script only works in Part or Assembly environment.")
        Exit Sub
    End If

    Dim maxDotProduct As Double = -1
    Dim closestFace As Face = Nothing

    ' Get the current view direction
    Dim currentViewVector As UnitVector = oCamera.Eye.VectorTo(oCamera.Target).AsUnitVector

    ' Collect faces
    Dim allFaces As New List(Of Face)()
    If TypeOf oCompDef Is PartComponentDefinition Then
        For Each oFace As Face In oCompDef.SurfaceBodies(1).Faces
            allFaces.Add(oFace)
        Next
    ElseIf TypeOf oCompDef Is AssemblyComponentDefinition Then
        allFaces.AddRange(GetAllFaces(oCompDef))
    Else
        MsgBox("Unsupported ComponentDefinition.")
        Exit Sub
    End If

    For Each oFace As Face In allFaces
        ' Get a point on the face
        Dim pointOnFace As Point = oFace.PointOnFace

        ' Get the normal vector of the face at the point
        Dim pointCoords(2) As Double
        pointCoords(0) = pointOnFace.X
        pointCoords(1) = pointOnFace.Y
        pointCoords(2) = pointOnFace.Z

        Dim normals(2) As Double
        Call oFace.Evaluator.GetNormalAtPoint(pointCoords, normals)

        ' Create a UnitVector from the normals array
        Dim faceNormal As UnitVector = ThisApplication.TransientGeometry.CreateUnitVector(normals(0), normals(1), normals(2))

        ' Calculate the dot product between the face normal and the current view direction
        Dim dotProduct As Double = Abs(currentViewVector.DotProduct(faceNormal))

        ' Find the face with the largest dot product (closest to being perpendicular to the view direction)
        If dotProduct > maxDotProduct Then
            maxDotProduct = dotProduct
            closestFace = oFace
        End If
    Next

    If Not closestFace Is Nothing Then
        ' Get a point on the closest face
        Dim closestPointOnFace As Point = closestFace.PointOnFace

        ' Get the normal vector of the closest face at the point
        Dim closestPointCoords(2) As Double
        closestPointCoords(0) = closestPointOnFace.X
        closestPointCoords(1) = closestPointOnFace.Y
        closestPointCoords(2) = closestPointOnFace.Z

        Dim closestNormals(2) As Double
        Call closestFace.Evaluator.GetNormalAtPoint(closestPointCoords, closestNormals)

        ' Create a UnitVector from the closestNormals array
        Dim closestFaceNormal As UnitVector = ThisApplication.TransientGeometry.CreateUnitVector(closestNormals(0), closestNormals(1), closestNormals(2))

        ' Set the camera to look along the closest face normal
        oCamera.Eye = ThisApplication.TransientGeometry.CreatePoint(closestPointOnFace.X - 100 * closestFaceNormal.X, closestPointOnFace.Y - 100 * closestFaceNormal.Y, closestPointOnFace.Z - 100 * closestFaceNormal.Z)
        
		oCamera.Target = closestPointOnFace
        oCamera.UpVector = ThisApplication.TransientGeometry.CreateUnitVector(0, 1, 0) ' Y-axis as the up direction
        oCamera.Fit

        ' Refresh the view
        oCamera.Apply()
        ThisApplication.ActiveView.Update()
    Else
        MsgBox("No faces found.")
    End If
End Sub

' Function to get all faces in an assembly
Function GetAllFaces(oCompDef As AssemblyComponentDefinition) As List(Of Face)
    Dim allFaces As New List(Of Face)()

    ' Iterate through all occurrences in the assembly
    For Each oOccurrence As ComponentOccurrence In oCompDef.Occurrences
        Dim occurrenceCompDef As ComponentDefinition = oOccurrence.Definition
        For Each oSurfaceBody As SurfaceBody In occurrenceCompDef.SurfaceBodies
            For Each oFace As Face In oSurfaceBody.Faces
                allFaces.Add(oFace)
            Next
        Next
    Next

    Return allFaces
End Function
0 Likes