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: 

Transform 2D global XY coordinates to local XY coordinates

1 REPLY 1
SOLVED
Reply
Message 1 of 2
william
246 Views, 1 Reply

Transform 2D global XY coordinates to local XY coordinates

Hello
Some context to this issue.
I was having issues with the built in command below to export face to DXF.

ThisApplication.CommandManager.ControlDefinitions.Item("GeomToDXFCommand")

 There is no way to specify the export version (See related posts on this below). This meant that the exported dxf would export with splines and would fail on import by other programs requiring the splines to be linearized. 
iLogic/API: Provide an API for exporting a face to DXF (with options) - Autodesk Community
Setting the ACAD Version for Export Surface from Part to dxf File with the API - Autodesk Community

So, I have this rule that creates a dxf file from a selected face. It linearizes all the edges on a face and writes to a dxf file. 
The problem I have is that it only works on horizontal faces, because the XY coordinates of the edge vertices are global and not transformed to the normal of the face selected. 

How would I transform these points to give me the local XY coordinates from the face selected? 

 

Sub Main()
Dim oDoc As PartDocument = ThisDoc.Document
Dim oCompDef = oDoc.ComponentDefinition

Dim entity = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFaceFilter, "Select a Face")
oDoc.SelectSet.Select(entity)

Dim oFace As Face
Dim oTG As TransientGeometry = ThisApplication.TransientGeometry
Dim oPointCol As New List(Of Double())

Try
    oFace = ThisApplication.ActiveDocument.SelectSet.Item(1)
Catch
    MsgBox("A face must be selected.")
End Try

oDoc.SelectSet.Clear

'Dim oSketch As PlanarSketch
'oSketch = oCompDef.Sketches.Add(oFace)
'oSketch.OriginPoint = oCompDef.WorkPoints.Item(1)

' Create a new file
Dim strUserProfile As String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile)
'MessageBox.Show(strUserProfile, "Title")

Dim fileName As String = strUserProfile & "\Downloads\FaceToDXFExample.dxf"
Dim file As New System.IO.StreamWriter(fileName)
SharedVariable("DXF_Data_Exists") = False

' Write DXF header
file.WriteLine("0")
file.WriteLine("SECTION")
file.WriteLine("2")
file.WriteLine("ENTITIES")

For Each oEL As EdgeLoop In oFace.EdgeLoops
	For k = 1 To oEL.Edges.Count 'Each oEdge As Edge In oEL.Edges
		oEdge = oEL.Edges(k)
		oEdge_StopVertex = oEdge.StopVertex
		oEdge_StartVertex = oEdge.StartVertex
		oEdge_StopVertex_Coordinates = "X" & oEdge.StopVertex.Point.X & "Y" & oEdge.StopVertex.Point.Y
		oEdge_StartVertex_Coordinates = "X" & oEdge.StartVertex.Point.X & "Y" & oEdge.StartVertex.Point.Y
		
'				Dim oHSet As HighlightSet = oDoc.CreateHighlightSet()
'				oHSet.Color = ThisApplication.TransientObjects.CreateColor(185, 0, 0) 'Red
'				oHSet.AddItem(oEdge)
'					MessageBox.Show("Edge type is " & oEdge.GeometryType)
'				oHSet.Clear()

		If k = 1 Then 'first line in loop
			If oEdge.GeometryType = CurveTypeEnum.kLineCurve Or oEdge.GeometryType = CurveTypeEnum.kLineSegmentCurve Then
				PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y,oTG,oSketch)
				PointCollection(oPointCol,oEdge_StopVertex.Point.X,oEdge_StopVertex.Point.Y,oTG,oSketch)
			Else
				CalculateEdgeStrokes(oEdge,oPointCol,oTG,oSketch)
			End If
		Else	'Line is not first line in loop

			If oEdge.GeometryType = CurveTypeEnum.kLineCurve Or oEdge.GeometryType = CurveTypeEnum.kLineSegmentCurve Then
				oPreviousEdge = oEL.Edges(k - 1)
				oPreviousEdge_StopVertex_Coordinates = "X" & oPreviousEdge.StopVertex.Point.X & "Y" & oPreviousEdge.StopVertex.Point.Y
				oPreviousEdge_StartVertex_Coordinates = "X" & oPreviousEdge.StartVertex.Point.X & "Y" & oPreviousEdge.StartVertex.Point.Y
				
				If oEdge_StartVertex_Coordinates = oPreviousEdge_StopVertex_Coordinates Or oEdge_StartVertex_Coordinates = oPreviousEdge_StartVertex_Coordinates 'Good the start of the current line shares the start or stop of the previous line
					PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y,oTG,oSketch)
					PointCollection(oPointCol,oEdge_StopVertex.Point.X,oEdge_StopVertex.Point.Y,oTG,oSketch)						
				Else 'switch current line start/stop positions
					PointCollection(oPointCol,oEdge_StopVertex.Point.X,oEdge_StopVertex.Point.Y,oTG,oSketch)	
					PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y,oTG,oSketch)
				End If
				

			Else
				CalculateEdgeStrokes(oEdge,oPointCol,oTG,oSketch)
			End If				
		End If
	Next
	WritePointsToDXF(file, oPointCol)
	oPointCol.Clear
Next

'MessageBox.Show("Point collection contains " & oPointCol.Count, "Title")

'For i As Integer = 0 To oPointCol.Count - 1
'	oPoint = oTG.CreatePoint2d(oPointCol(i)(0), oPointCol(i)(1))
'	oSketch.SketchPoints.Add(oPoint)
'	MessageBox.Show("Point Added", "Title")
'Next


' Write DXF footer
file.WriteLine("0")
file.WriteLine("ENDSEC")
file.WriteLine("0")
file.WriteLine("EOF")

' Close the file
file.Close()

If SharedVariable("DXF_Data_Exists") = False Then
	System.IO.File.Delete(fileName)
End If

End Sub


Sub PointCollection(oPointCol As List(Of Double()), X As Double, Y As Double, oTG As TransientGeometry,oSketch As PlanarSketch)
	If oPointCol.Count = 0 Then
		oPointCol.Add({X, Y })
'			oPoint = oTG.CreatePoint2d(X, Y)
'			oSketch.SketchPoints.Add(oPoint)
'			MessageBox.Show("Point Added", "Title")
	Else
		intLastIndex = oPointCol.Count - 1
		If oPointCol(intLastIndex)(0) = X And oPointCol(intLastIndex)(1) = Y Then
'			MessageBox.Show("Points are equal - will skip")
			oPointCol.Add({X, Y })
		Else
			oPointCol.Add({X, Y })
'			oPoint = oTG.CreatePoint2d(X, Y)
'			oSketch.SketchPoints.Add(oPoint)
'			MessageBox.Show("Point Added", "Title")
		End If
		
	End If
	Logger.Debug("X: " & X & ", Y: " & Y)
		
End Sub

Sub CalculateEdgeStrokes(oEdge As Edge,oPointCol As List(Of Double()),oTG As TransientGeometry,oSketch As PlanarSketch)
Dim lVertexCount As Long
Dim lSegmentCount As Long
Dim adVertexCoords() As Double = {}
Dim alVertexIndices() As Integer = {}
oEdge.CalculateStrokes(0.01, lVertexCount, lSegmentCount, adVertexCoords, alVertexIndices)

j = 1
For i = 0 To adVertexCoords.Length -1
	If j = 1 Then 
		strCoord_X = adVertexCoords(i)
	Else If j = 2 Then
		strCoord_Y = adVertexCoords(i)
	Else If j = 3 Then
		strCoord_Z = adVertexCoords(i)
		PointCollection(oPointCol,strCoord_X,strCoord_Y,oTG,oSketch)
		j = 0	'reset the counter
	End If
	j = j + 1
	
Next
End Sub

Sub WritePointsToDXF(file As System.IO.StreamWriter, oPointCol As List(Of Double()))
SharedVariable("DXF_Data_Exists") = True
' Write lines to file
For i = 0 To oPointCol.Count - 2
    file.WriteLine("0")
    file.WriteLine("LINE")
    file.WriteLine("8")
    file.WriteLine("0")
    file.WriteLine("10")
    file.WriteLine(oPointCol(i)(0))
    file.WriteLine("20")
    file.WriteLine(oPointCol(i)(1))
    file.WriteLine("11")
    file.WriteLine(oPointCol(i+1)(0))
    file.WriteLine("21")
    file.WriteLine(oPointCol(i+1)(1))
Next

' Add the last line to close the shape
file.WriteLine("0")
file.WriteLine("LINE")
file.WriteLine("8")
file.WriteLine("0")
file.WriteLine("10")
file.WriteLine(oPointCol((oPointCol.Count - 1))(0))
file.WriteLine("20")
file.WriteLine(oPointCol((oPointCol.Count - 1))(1))
file.WriteLine("11")
file.WriteLine(oPointCol(0)(0))
file.WriteLine("21")
File.WriteLine(oPointCol(0)(1))

End Sub
Labels (4)
1 REPLY 1
Message 2 of 2
william
in reply to: william

Ok, I have it now. 
I used the Face.Evaluator.GetParamAtPoint() method. 
Full working code below, might help someone else. 

 

 

Sub Main()
Dim oDoc As PartDocument = ThisDoc.Document
Dim oCompDef = oDoc.ComponentDefinition

Dim entity = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartFaceFilter, "Select a Face")
oDoc.SelectSet.Select(entity)

Dim oFace As Face
Dim oTG As TransientGeometry = ThisApplication.TransientGeometry
Dim oPointCol As New List(Of Double())

Try
    oFace = ThisApplication.ActiveDocument.SelectSet.Item(1)
Catch
    MsgBox("A face must be selected.")
	Exit Sub
End Try

oDoc.SelectSet.Clear

' Create a new file
Dim strUserProfile As String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile)
'MessageBox.Show(strUserProfile, "Title")

Dim fileName As String = strUserProfile & "\Downloads\FaceToDXFExample.dxf"
Dim file As New System.IO.StreamWriter(fileName)
SharedVariable("DXF_Data_Exists") = False
SharedVariable("PosX") = 0	'Placeholder value
SharedVariable("PosY") = 0	'Placeholder value

	DXFHeader(file)												
	ExportFace(oFace, file)
	
	'Add Text to the DXF file
	Call DXFAddText(file, "Text to add, line 1", SharedVariable("PosX"), SharedVariable("PosY"))
	Call DXFAddText(file, "Text to add, line 2", SharedVariable("PosX"), SharedVariable("PosY") - 5)
	
	DXFFooter(file,fileName)

End Sub


Sub CalculatePosX_PosY(oPointCol As List(Of Double())) 'Calculates the centroid of the dxf face by looking at all the vertices in the dxf

Dim Array_X As New ArrayList
Dim Array_Y As New ArrayList

For i = 0 To oPointCol.Count - 1
    Array_X.Add(oPointCol(i)(0))
	Array_Y.Add(oPointCol(i)(1))
Next

Array_X.Sort()
Array_Y.Sort()

minX = Array_X(0)
maxX = Array_X(Array_X.Count-1)
minY = Array_Y(0)
maxY = Array_Y(Array_X.Count - 1)

SharedVariable("PosX") = ((maxX - minX) / 2) + minX
SharedVariable("PosY") = ((maxY - minY) / 2) + minY

Array_X.Clear
Array_Y.Clear


End Sub

Sub DXFHeader(file As System.IO.StreamWriter) 
' Write DXF header
file.WriteLine("0")
file.WriteLine("SECTION")
file.WriteLine("2")
file.WriteLine("ENTITIES")

End Sub

Sub DXFFooter(file As System.IO.StreamWriter,fileName As String)
' Write DXF footer
file.WriteLine("0")
file.WriteLine("ENDSEC")
file.WriteLine("0")
file.WriteLine("EOF")

' Close the file
file.Close()

If SharedVariable("DXF_Data_Exists") = False Then 'dxf file was created but no line entities were written to it. Dispose of it
	System.IO.File.Delete(fileName)
End If

End Sub

Sub DXFAddText(file As System.IO.StreamWriter, TextToAdd As String, PosX As Double, PosY As Double)
file.WriteLine("  0")
file.WriteLine("TEXT")	'ENTITY TYPE
file.WriteLine("  8")
file.WriteLine("0") 'LAYERNAME
file.WriteLine("100")
file.WriteLine("AcDbText")
file.WriteLine("10")
file.WriteLine(PosX) 'X COORDINATE
file.WriteLine("20")
file.WriteLine(PosY) 'Y COORDINATE
file.WriteLine("30")
file.WriteLine("0.0") ' Z COORDINATE
file.WriteLine("40")
file.WriteLine("3.55") 'TEXT HEIGHT
file.WriteLine("  1")
file.WriteLine(TextToAdd) 'TEXT STRING
file.WriteLine("100")
file.WriteLine("AcDbText") 'TEXT STRING

End Sub



Sub ExportFace(oFace As Face, file As System.IO.StreamWriter)

Dim oTG As TransientGeometry = ThisApplication.TransientGeometry
Dim oPointCol As New List(Of Double())

For Each oEL As EdgeLoop In oFace.EdgeLoops
	For k = 1 To oEL.Edges.Count 
		oEdge = oEL.Edges(k)
		oEdge_StopVertex = oEdge.StopVertex
		oEdge_StartVertex = oEdge.StartVertex
		oEdge_StopVertex_Coordinates = "X" & oEdge.StopVertex.Point.X & "Y" & oEdge.StopVertex.Point.Y & "Z" & oEdge.StopVertex.Point.Z
		oEdge_StartVertex_Coordinates = "X" & oEdge.StartVertex.Point.X & "Y" & oEdge.StartVertex.Point.Y & "Z" & oEdge.StartVertex.Point.Z
		
		If k = 1 Then 'first line in loop
			If oEdge.GeometryType = CurveTypeEnum.kLineCurve Or oEdge.GeometryType = CurveTypeEnum.kLineSegmentCurve Then 'edge is straight
				PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y, oEdge_StartVertex.Point.Z, oTG,oSketch,oFace)
				PointCollection(oPointCol,oEdge_StopVertex.Point.X,oEdge_StopVertex.Point.Y, oEdge_StopVertex.Point.Z, oTG,oSketch,oFace)
			Else 'Edge is curved, or spline, polyline, eclipse, ect
				CalculateEdgeStrokes(oEdge,oPointCol,oTG,oSketch,k,"","",oFace)
			End If
		Else 'Line is not first line in loop
			oPreviousEdge = oEL.Edges(k - 1)
			oPreviousEdge_StopVertex_Coordinates = "X" & oPreviousEdge.StopVertex.Point.X & "Y" & oPreviousEdge.StopVertex.Point.Y & "Z" & oPreviousEdge.StopVertex.Point.Z
			oPreviousEdge_StartVertex_Coordinates = "X" & oPreviousEdge.StartVertex.Point.X & "Y" & oPreviousEdge.StartVertex.Point.Y & "Z" & oPreviousEdge.StartVertex.Point.Z
				
			If oEdge.GeometryType = CurveTypeEnum.kLineCurve Or oEdge.GeometryType = CurveTypeEnum.kLineSegmentCurve Then 'edge is straight

				If oEdge_StartVertex_Coordinates = oPreviousEdge_StopVertex_Coordinates Or oEdge_StartVertex_Coordinates = oPreviousEdge_StartVertex_Coordinates 'Good the start of the current line shares the start or stop of the previous line
					PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y, oEdge_StartVertex.Point.Z, oTG,oSketch,oFace)
					PointCollection(oPointCol,oEdge_StopVertex.Point.X, oEdge_StopVertex.Point.Y, oEdge_StopVertex.Point.Z, oTG,oSketch,oFace)						
				Else 'switch current line start/stop positions
					PointCollection(oPointCol,oEdge_StopVertex.Point.X, oEdge_StopVertex.Point.Y, oEdge_StopVertex.Point.Z, oTG,oSketch,oFace)	
					PointCollection(oPointCol, oEdge_StartVertex.Point.X, oEdge_StartVertex.Point.Y, oEdge_StartVertex.Point.Z, oTG,oSketch,oFace)
				End If
				

			Else 'Edge is curved, or spline, polyline, eclipse, ect
				CalculateEdgeStrokes(oEdge,oPointCol,oTG,oSketch,k,oPreviousEdge_StartVertex_Coordinates,oPreviousEdge_StopVertex_Coordinates,oFace)
				
			End If					
		End If
	Next

	If oEL.IsOuterEdgeLoop = True Then
		CalculatePosX_PosY(oPointCol)
	End If
	WritePointsToDXF(file, oPointCol)
	oPointCol.Clear
Next

End Sub


Sub PointCollection(oPointCol As List(Of Double()), X As Double, Y As Double, Z As Double, oTG As TransientGeometry, oSketch As PlanarSketch,oFace As Face)
	Dim oEval As SurfaceEvaluator
	oEval = oFace.Evaluator
	
	' Set the coordinate point where you want to get the corresponding
	' parametric point on the face. This point should lie on the face.
	Dim adPoints(2) As Double
	adPoints(0) = X
	adPoints(1) = Y
	adPoints(2) = Z
	
	Dim adGuessParams() As Double = {}
	Dim adMaxDeviations() As Double = {}
	Dim adParams() As Double = {}
	Dim alngSolutionNatures() As SolutionNatureEnum = {}
	Call oEval.GetParamAtPoint(adPoints, adGuessParams, adMaxDeviations,adParams, alngSolutionNatures)

	'MessageBox.Show("X: " & adParams(0) & ", Y: " & adParams(1))

	oPointCol.Add({adParams(0) * 10, adParams(1) * 10})
	'Logger.Debug("X: " & adParams(0) * 10 & ", adParams(1) * 10: " & Y)
		
End Sub

Sub CalculateEdgeStrokes(oEdge As Edge, oPointCol As List(Of Double()), oTG As TransientGeometry, oSketch As PlanarSketch, k As Integer, oPreviousEdge_StartVertex_Coordinates As String, oPreviousEdge_StopVertex_Coordinates As String,oFace As Face)
Dim oTempPointCol As New List(Of Double())

Dim lVertexCount As Long
Dim lSegmentCount As Long
Dim adVertexCoords() As Double = {}
Dim alVertexIndices() As Integer = {}
oEdge.CalculateStrokes(0.01, lVertexCount, lSegmentCount, adVertexCoords, alVertexIndices)


j = 1
For i = 0 To adVertexCoords.Length -1
	If j = 1 Then 
		strCoord_X = adVertexCoords(i)
	Else If j = 2 Then
		strCoord_Y = adVertexCoords(i)
	Else If j = 3 Then
		strCoord_Z = adVertexCoords(i)
		oTempPointCol.Add({strCoord_X, strCoord_Y, strCoord_Z})
		j = 0	'reset the counter
	End If
	j = j + 1
Next

If k = 1 Then
    For i = 0 To oTempPointCol.Count - 1
        PointCollection(oPointCol, oTempPointCol(i)(0), oTempPointCol(i)(1), oTempPointCol(i)(2), oTG, oSketch,oFace)
    Next
Else
    strCurrentEdgeStartVertex = "X" & oTempPointCol(0)(0) & "Y" & oTempPointCol(0)(1) & "Z" & oTempPointCol(0)(2)
    If strCurrentEdgeStartVertex = oPreviousEdge_StartVertex_Coordinates Or strCurrentEdgeStartVertex = oPreviousEdge_StopVertex_Coordinates Then 'Good, the starting point of the current line is equal to either the start/end vertex of the previous line
        For i = 0 To oTempPointCol.Count - 1
            PointCollection(oPointCol, oTempPointCol(i)(0), oTempPointCol(i)(1), oTempPointCol(i)(2), oTG, oSketch,oFace)
        Next
    Else
        For i = oTempPointCol.Count - 1 To 0 Step -1
            PointCollection(oPointCol, oTempPointCol(i)(0), oTempPointCol(i)(1), oTempPointCol(i)(2), oTG, oSketch,oFace)
        Next	
    End If
End If

oTempPointCol.Clear

End Sub

Sub WritePointsToDXF(file As System.IO.StreamWriter, oPointCol As List(Of Double()))
SharedVariable("DXF_Data_Exists") = True
' Write lines to file
For i = 0 To oPointCol.Count - 2
    file.WriteLine("0")
    file.WriteLine("LINE")
    file.WriteLine("8")
    file.WriteLine("0")
    file.WriteLine("10")
    file.WriteLine(oPointCol(i)(0))
    file.WriteLine("20")
    file.WriteLine(oPointCol(i)(1))
    file.WriteLine("11")
    file.WriteLine(oPointCol(i+1)(0))
    file.WriteLine("21")
    file.WriteLine(oPointCol(i+1)(1))
Next

' Add the last line to close the shape
file.WriteLine("0")
file.WriteLine("LINE")
file.WriteLine("8")
file.WriteLine("0")
file.WriteLine("10")
file.WriteLine(oPointCol((oPointCol.Count - 1))(0))
file.WriteLine("20")
file.WriteLine(oPointCol((oPointCol.Count - 1))(1))
file.WriteLine("11")
file.WriteLine(oPointCol(0)(0))
file.WriteLine("21")
file.WriteLine(oPointCol(0)(1))

End Sub

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

Post to forums  

Technology Administrators


Autodesk Design & Make Report