I realise that this is of rather limited interest, but please forgive
me the few kB of inbox space.
Years ago I published a YouTube video showing slicing to an SVG file
from inside AutoDesk Inventor, and a link to the .ivb binary file.
Chatting on IRC it became evident that a plain-text version might be
more useful, so I am attaching it here, partly as a way to have it
archived and available.
--------------------SVGFile----------------------
Dim ts As Scripting.TextStream
Dim fs As New Scripting.FileSystemObject
Dim indent As Integer
Dim path As Long, layer As Long
Dim CurrentLayer As String
Dim CurrentPath As String
Const PI As Double = 3.14159265358979
Const rad2deg As Double = 180 / 3.14159265358979
Const height As Double = 21
Const width As Double = 29.7
Const scalefac As Double = 1
Sub OpenFile(originX As Double, originY As Double)
Set ts = fs.CreateTextFile("C:/temp/newfile.svg")
writelineTS "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
writelineTS "<svg"
writelineTS "xmlns='http://www.w3.org/2000/svg'"
writelineTS "xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'"
writelineTS "xmlns:slicer='http://www.bodgesoc.org'"
writelineTS "width='{1}cm'", width
writelineTS "height='{1}cm'", height
writelineTS "viewBox='{1} {2} {3} {4}'", -(width / 2), -height / 2,
width, height
writelineTS "version='1.1'"
writelineTS
"style='fill:#ffffff;fill-rule:evenodd;stroke-width:0px;fill-opacity:1'
>"
writelineTS "<rect style='fill:#000000;fill-opacity:1;stroke:none'
width='100%' height='100%' x='{1}' y='{2}' />", -width / 2, -height /
2
writelineTS "<g transform='translate({1},{2}) scale({3}, {4})'>",
-originX, originY, scalefac, -scalefac
End Sub
Sub Add_Layer(offset As Double)
If CurrentLayer <> "" Then
writelineTS "</g>"
CurrentLayer = ""
End If
layer = layer + 1
CurrentLayer = "layer_" & layer
writelineTS "<g inkscape:groupmode='layer' inkscape:label='{1}' ",
CurrentLayer
writelineTS "id='{1}' slicer:Z='{2}' >", CurrentLayer, Abs(offset * 10)
End Sub
Sub Add_Profile(profile As ProfilePath)
Dim s As String
Dim start As Point2d
Dim P1 As Point2d, P2 As Point2d
Dim i As Integer, j As Long
Dim C As Object
Dim cs As Double, sn As Double, rx As Double, ry As Double, an As Double
'2D curves can be:
'kBSplineCurve2d 5256
'kCircleCurve2d 5252
'kCircularArcCurve2d 5253
'kEllipseFullCurve2d 5254
'kEllipticalArcCurve2d 5255
'kLineCurve2d 5250
'kLineSegmentCurve2d 5251
'kPolylineCurve2d 5257
'kUnknownCurve2d 5249
For i = 1 To profile.count
Set C = profile.Item(i).Curve
Select Case profile.Item(i).CurveType
Case kBSplineCurve2d
Dim m As Double, n As Double, count As Long
Dim k() As Double, w() As Double, P() As Double
C.Evaluator.GetEndPoints k(), w()
openpath k(0), k(1)
C.Evaluator.GetParamExtents m, n
C.Evaluator.GetStrokes m, n, 0.001, count, k()
writeTS " L "
For j = 0 To count * 2 - 1 Step 2
writeTS " {1} {2} ", k(j), k(j + 1)
Next
Erase k, w, P ' This memory leak is hard to spot
Case kCircleCurve2d
closepath profile
writeTS "<circle cx='{1}' cy='{2}' r='{3}' ", C.Center.X,
C.Center.Y, C.Radius
If profile.AddsMaterial = False Then writeTS "style='fill:#000000' "
writelineTS "/>"
Case kCircularArcCurve2d
openpath C.StartPoint.X, C.StartPoint.Y
writeTS " A {1},{1} 0 ", C.Radius
If C.SweepAngle < 0 Then
If C.SweepAngle < -PI Then
writeTS "1,0 "
Else
writeTS "0,0 "
End If
Else
If C.SweepAngle > PI Then
writeTS "1,1 "
Else
writeTS "0,1 "
End If
End If
writeTS "{1},{2} ", C.EndPoint.X, C.EndPoint.Y
Case kEllipseFullCurve2d
closepath profile
rx = C.MajorAxisVector.Length
ry = C.MajorAxisVector.Length * C.MinorMajorRatio
cs = C.MajorAxisVector.X / C.MajorAxisVector.Length
sn = C.MajorAxisVector.Y / C.MajorAxisVector.Length
writeTS "<ellipse cx='{1}' cy='{2}' rx='{3}' ry='{4}' ",
C.Center.X, C.Center.Y, rx, ry
'writeTS "transform='matrix({1},{2},{3},{4},0,0)'", cs, sn, -sn, cs
writeTS "transform='rotate({1},{2},{3})'", rad2deg *
ArcTan2(C.MajorAxisVector.X, C.MajorAxisVector.Y), C.Center.X,
C.Center.Y
If profile.AddsMaterial = False Then writeTS "style='fill:#000000' "
writelineTS "/>"
Case kEllipticalArcCurve2d ' CHECK ME
'the elliptical arc has something funny about the start and end points
Set C = profile.Item(i)
openpath C.StartSketchPoint.Geometry.X, C.StartSketchPoint.Geometry.Y
rx = C.Curve.MajorRadius
ry = C.Curve.MinorRadius
an = rad2deg * ArcTan2(C.Curve.MajorAxis.X, C.Curve.MajorAxis.Y)
writeTS " A {1},{2} {3} ", rx, ry, an
an = C.Curve.SweepAngle
'The curve sweep angle is wrong for negative angles, the API
returns 2pi - angle
If an < 0 Then
If an > -PI Then
writeTS "1,0 "
Else
writeTS "0,0 "
End If
Else
If an > PI Then
writeTS "1,1 "
Else
writeTS "0,1 "
End If
End If
writeTS "{1},{2} ", C.EndSketchPoint.Geometry.X,
C.EndSketchPoint.Geometry.Y
'Case kLineCurve2d ' START ME
Case kLineSegmentCurve2d
openpath C.StartPoint.X, C.StartPoint.Y
writeTS "L {1} {2} ", C.EndPoint.X, C.EndPoint.Y
'Case kPolylineCurve2d 'START ME
Case Else
MsgBox "You need to add " & TypeName(C)
Debug.Print TypeName(C)
End
End Select
'Try to avoid leaking memory
Set C = Nothing
Next
closepath profile
Set profile = Nothing
End Sub
Sub finish()
Dim oFileDlg As FileDialog
Dim fname As String
If CurrentLayer <> "" Then
writelineTS "</g>"
CurrentLayer = ""
End If
writelineTS "</g>" ' Close the transform group
ts.WriteLine "</svg>"
ts.Close
Call ThisApplication.CreateFileDialog(oFileDlg)
oFileDlg.Filter = "SVG File (*.svg)"
oFileDlg.DialogTitle = "Choose a filename"
oFileDlg.InitialDirectory = "C:\Temp"
oFileDlg.CancelError = True
On Error Resume Next
oFileDlg.ShowSave
If Not Err Then
fname = oFileDlg.FileName
If fs.GetExtensionName(fname) <> "svg" Then fname = fname & ".svg"
fs.CopyFile "C:\temp\newfile.svg", fname, True
fs.DeleteFile "C:\temp\newfile.svg"
End If
On Error GoTo 0
bStop = True
End Sub
Private Sub openpath(startx As Double, starty As Double)
If CurrentPath <> "" Then Exit Sub
path = path + 1
CurrentPath = "path_" & path
writelineTS "<path id='{1}'", CurrentPath
writeTS "d='M {1} {2} ", startx, starty
End Sub
Private Sub closepath(profile As ProfilePath)
If CurrentPath = "" Then Exit Sub
CurrentPath = ""
writeTS " Z'"
If profile.AddsMaterial = False Then writeTS " style='fill:#000000' "
writelineTS " />"
End Sub
Private Function writeTS(f As String, ParamArray t())
' A simple version of printf for putting numbers into strings
' also replaces ' by "" to keep things legible
Dim i As Integer
For i = 0 To UBound(t)
f = Replace$(f, "{" & i + 1 & "}", t(i))
Next
f = Replace$(f, "'", """")
If InStr(f, "</g>") Then
indent = indent - 3
End If
ts.Write f
If ts.Column > 120 Then
ts.WriteLine
ts.Write Space(indent)
End If
If InStr(f, "<g") Or InStr(f, "<svg") Then
indent = indent + 3
End If
End Function
Private Function writelineTS(f As String, ParamArray t())
' A simple version of printf for putting numbers into strings
' also replaces ' by "" to keep things legible
Dim i As Integer
For i = 0 To UBound(t)
f = Replace$(f, "{" & i + 1 & "}", t(i))
Next
f = Replace$(f, "'", """")
If InStr(f, "</g>") Then
indent = indent - 3
End If
ts.WriteLine f
If InStr(f, "<g") Or InStr(f, "<svg") Then
indent = indent + 3
End If
ts.Write Space(indent)
End Function
Function ArcTan2(X As Double, Y As Double) As Double
Select Case X
Case Is > 0
ArcTan2 = Atn(Y / X)
Case Is < 0
ArcTan2 = Atn(Y / X) + PI * Sgn(Y)
If Y = 0 Then ArcTan2 = ArcTan2 + PI
Case Is = 0
ArcTan2 = PI / 2 * Sgn(Y)
End Select
End Function
--------------------Module1-----------------
Public Sub SliceToSVG()
Dim oActiveEnv As Environment
Set oActiveEnv = ThisApplication.UserInterfaceManager.ActiveEnvironment
If oActiveEnv.InternalName <> "PMxPartEnvironment" Then
MsgBox "This command can only run in an isolated part context
(at the moment at least)"
Exit Sub
End If
Dim oMiniToolbar As MiniToolbar
Set oMiniToolbar = ThisApplication.CommandManager.CreateMiniToolbar
oMiniToolbar.ShowOK = True
oMiniToolbar.ShowApply = False
oMiniToolbar.ShowCancel = True
Dim oControls As MiniToolbarControls
Set oControls = oMiniToolbar.Controls
oControls.Item("MTB_Options").Visible = False
Dim oDescriptionLabel As MiniToolbarControl
Set oDescriptionLabel = oControls.AddLabel("Description", "Slice
the part to SVG", "The intention is to drive a DLP")
oControls.AddNewLine
Dim oPlaneChooser As MiniToolbarButton
Set oPlaneChooser = oControls.AddButton("btnBasePlane", "Base
Plane:", "Pick the base plane to slice parallel to")
Dim oPlaneName As MiniToolbarControl
Set PlaneName = oControls.AddLabel("lblBasePlane", "
", "Press the button on the left to choose a plane")
oControls.AddNewLine
Dim oSliceThickness As MiniToolbarValueEditor
Set oSliceThickness = oControls.AddValueEditor("Thickness", "Enter
slice thickness (microns)", kLengthUnits, "microns")
oSliceThickness.Expression = "50"
' Set the position of mini-toolbar
Dim oPosition As Point2d
Set oPosition =
ThisApplication.TransientGeometry.CreatePoint2d(ThisApplication.ActiveView.Left,
ThisApplication.ActiveView.Top)
oMiniToolbar.Position = oPosition
oMiniToolbar.Visible = True
Dim oMiniToolbarEvents As New ClsToolbarEvents
Call oMiniToolbarEvents.Init(oMiniToolbar)
End Sub
-----------------ClsToolbarEvents----------------------------------
Public BasePlane As Object
Private WithEvents m_BasePlane As MiniToolbarButton
Private WithEvents m_Thickness As MiniToolbarValueEditor
Private m_BasePlaneName As MiniToolbarControl
Private WithEvents m_MiniToolbar As MiniToolbar
Private bStop As Boolean
Public Sub Init(oMiniToolbar As MiniToolbar)
Set m_MiniToolbar = oMiniToolbar
Set m_BasePlane = m_MiniToolbar.Controls.Item("btnBasePlane")
Set m_Thickness = m_MiniToolbar.Controls.Item("Thickness")
Set m_BasePlaneName = m_MiniToolbar.Controls.Item("lblBasePlane")
m_MiniToolbar.EnableOK = False
bStop = False
Do
ThisApplication.UserInterfaceManager.DoEvents
Loop Until bStop
End Sub
Private Sub m_BasePlane_OnClick()
Set BasePlane =
ThisApplication.CommandManager.Pick(kAllPlanarEntities, "Select start
plane or face")
If BasePlane Is Nothing Then Exit Sub
If TypeName(BasePlane) = "WorkPlane" Then
m_BasePlaneName.DisplayName = BasePlane.Name
Else
m_BasePlaneName.DisplayName = BasePlane.Parent.Name & ".Face"
End If
m_MiniToolbar.EnableOK = True
End Sub
Private Sub m_MiniToolbar_OnCancel()
bStop = True
End Sub
Private Sub m_MiniToolbar_OnOK()
SliceIt
End Sub
Private Sub SliceIt()
Dim oDoc As PartDocument
Set oDoc = ThisApplication.ActiveDocument
Dim oDef As PartComponentDefinition
Set oDef = oDoc.ComponentDefinition
Dim oSketch As PlanarSketch
Dim P As profile
Dim PP As ProfilePath
Dim nWP As WorkPlane
Dim i As Long
Dim SVG As New SVGFile
Dim ErrCount As Integer
Dim originX As Double, originY As Double
Dim P1 As Point2d, P2 As Point2d
Dim offset As Double, delta As Double
offset = 0
delta = m_Thickness.Expression / 10000
Set nWP = oDef.WorkPlanes.AddByPlaneAndOffset(BasePlane, delta)
Set oSketch = oDef.Sketches.Add(nWP, False)
'find model exxtents in the slice plane
Set P1 = oSketch.ModelToSketchSpace(oDef.RangeBox.MaxPoint)
Set P2 = oSketch.ModelToSketchSpace(oDef.RangeBox.MinPoint)
SVG.OpenFile (P1.X + P2.X) / 2, (P1.Y + P2.Y) / 2
'check the extrude direction
On Error Resume Next
oSketch.ProjectedCuts.Add
If Err <> 0 Then
delta = -delta
End If
'And now extrude
ErrCount = 0
While Not bStop
nWP.SetByPlaneAndOffset BasePlane, offset
Set oSketch = oDef.Sketches.Add(nWP, False)
On Error Resume Next
oSketch.ProjectedCuts.Add
oSketch.Profiles.AddForSolid
On Error GoTo 0
If oSketch.Profiles.count = 0 Then
ErrCount = ErrCount + 1
If ErrCount > 3 Then
nWP.Delete
bStop = True
SVG.finish
Exit Sub
End If
Else
DoEvents
SVG.Add_Layer (offset)
For Each P In oSketch.Profiles
For Each PP In P
SVG.Add_Profile PP
Set PP = Nothing
Next
Set P = Nothing
Next
End If
oSketch.Delete
Set oSketch = Nothing
offset = offset + delta
Wend
bStop = True
SVG.finish
End Sub
--
atp
"A motorcycle is a bicycle with a pandemonium attachment and is
designed for the especial use of mechanical geniuses, daredevils and
lunatics."
— George Fitch, Atlanta Constitution Newspaper, 1912
_______________________________________________
Emc-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-users