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: 

Inventor sketchspline to svg Bezier

12 REPLIES 12
Reply
Message 1 of 13
andypugh
1352 Views, 12 Replies

Inventor sketchspline to svg Bezier

I am trying to write a little utility to export slices of an iPart to a multi-layer SVG file. 

This is to drive a friend's DLP printer, the idea being to bypass the lossy export to STL which introduces faceting that he does not like. 

 

So far moving a plane through the part, creating cutlines and exporting element-by-element to SVG paths is looking like it ought to work. 

The problem is that some cutlines are created as sketchspline, and I don't _think_ that there is a direct mapping between sketchspline properties and the quadratic and cubic Bezier curves of STL. 

 

The STL curves take a start and an end and either 1 or two "control points" whereas the Inventor sketchspline seems to have a much larger set of knots, weights, etc. 

 

Does anyone know of any sort of equivalance between these terms? Perhaps I need to split the sketchspline into short curves? It seems that this is possible. It is also apparently possible to split the spline into a polyline aproximation, but that seems like missing the point, as that is effectively the same as STL. 

 

So far I have not had much luck at interrogating the sketchpline objects. There are several examples out there that create them, but not a lot of info (that I have found) about poking abot inside pre-existing ones. 

 

I am rather new to Inventor VBA and the Inventor Object Model, but I have very extensive experience in Excel VBA. 

 

12 REPLIES 12
Message 2 of 13
ekinsb
in reply to: andypugh

I don't know of an easy way to accomplish what you want.  The splines in Inventor are NURBS curves.  NURBS introduces the additional concepts of weights and knots to a bezier curve.  For a non-rational NURBS curve (which is the most common) I believe it should be possible to break up the NURBS curve into multiple bezier segments but it's not a trivial problem.  If you have a way to fit a bezier curve through some points you might be able to approximate the curve by fitting a series of bezier curves through points on the NURBS curve.

 

The easiest thing will be to approximate the curve with a polyine.  You can determine the tolerance for this approximation so it can be very close to the original spline.  To do this, from the SketchSpline you can use the Geometry or Geometry3d properties.  The Geometry property will return a BSplineCurve2d that represent the spline in sketch space and the BSplineCurve3d property will return a BSplineCurve object that represents the spline in 3D model space.  From the BSplineCurve or BSplineCurve2d object you can call the Evaluator property which will return CurveEvaluator or CurveEvaluator2d object.  These object support the GetStrokes method.  This will approximate the spline by a series of points where the result is within a given tolerance.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 13
andypugh
in reply to: ekinsb

I have found references to Boehm's Algorithm as a way of converting a B-Spline into a poly-Bezier, though no actual implementation details.

http://web.archive.org/web/20120227050519/http://tom.cs.byu.edu/~455/bs.pdf

I am wondering if I can split the B-spline into sucessively shorter segments until each segment is simple enough to represent by a cubic Bezier segment, there are methods in the API to split the curve.

I need to read more aound this subject, none of the articles and papers I have seen so far bother to explain how a bezier or a spline actually defines points in (x,y) space, they all seem to assume that that is obvious.

 

I had seen the straight-line approximation method, but the whole point of this excercise was to not facet the curves.

Having said that, if the faceting is less than the pixel resolution of the end-point display then it shouldn't matter.

 

However at this point I am more interested  in understanding the maths than solving the problem.

Message 4 of 13
ekinsb
in reply to: andypugh

I thought that if I broke up a curve along the knots so I ended up with multiple curves with no internal knots that would be easy to convert to a Bezier equivalent.  A problem is that it appears that you're limited to cubic Bezier curves.  In my few tests, Inventor is creating curves with an order of 5.  To go to four will require an approximation.  The math could be interesting but it's not trivial and would take some time to work out.  There are quite a few books on curve math and also some programming libraries.  Good luck.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 5 of 13
andypugh
in reply to: ekinsb

I have seen some articles that say that you can ignore the first and last control points. And others that insist that conversion of a low-knot-count B-spline to Bezier is trivial (without actually indicating how to do it). 

 

I do now have the macro creating the multi-layer .SVG file from the .IPT parts using the straight-line approximation (.getstrokes) method and that might be OK. It would be nice to do it with no lost detail, though. 

 

I think I need to try some sample routines where I can see the effect in sample sketches. 

Message 6 of 13
ekinsb
in reply to: andypugh

You definitely can't ignore the first and last control points because those are the first and last points of the curve.

 

I did some playing around before I responded last time.  Here's the code if it helps at all.  It breaks the curve up at the knot locations along the curve so that the result is a series of curves without any internal knots.  Assuming the original curve is not rational, these curves are essentially bezier curves but Inventor is creating order 5 curves and you need order 4.  I'm not sure how to do that convesion and believe it will be an approximation.

 

This code works the best if the sketch containing the curve was created on the base x-y work plane.  It creates a new sketch and draws the result and that way the two will line up.

 

 

Public Sub BreakCurve()
    Dim skSpline As Object
    Set skSpline = ThisApplication.CommandManager.Pick(kSketchCurveSplineFilter, "Select a spline")
    
    Dim sk As PlanarSketch
    Set sk = skSpline.Parent
    
    Dim spline As BSplineCurve2d
    Set spline = skSpline.Geometry
    
    Dim order As Long
    Dim numPoles As Long
    Dim numKnots As Long
    Dim isRational As Boolean
    Dim isPeriodic As Boolean
    Dim isClosed As Boolean
    Call spline.GetBSplineInfo(order, numPoles, numKnots, isRational, isPeriodic, isClosed)
    
    Dim poles() As Double
    Dim knots() As Double
    Dim weights() As Double
    Call spline.GetBSplineData(poles, knots, weights)
    
    Dim eval As Curve2dEvaluator
    Set eval = spline.Evaluator
    Dim min As Double
    Dim max As Double
    Call eval.GetParamExtents(min, max)
    
    Dim knotList() As Double
    ReDim knotList(numKnots - (order * 2 - 2) - 1)
    Dim i As Integer
    Dim cnt As Integer
    cnt = 0
    For i = order - 1 To numKnots - order
        knotList(cnt) = knots(i)
        cnt = cnt + 1
    Next
    
    Dim newSketch As PlanarSketch
    Dim partDoc As PartDocument
    Set partDoc = ThisApplication.ActiveDocument
    Set newSketch = partDoc.ComponentDefinition.Sketches.Add(partDoc.ComponentDefinition.WorkPlanes.Item(3))
    
    For i = 0 To UBound(knotList) - 1
        Dim newSpline As BSplineCurve2d
        Set newSpline = spline.ExtractPartial(knotList(i), knotList(i + 1))
        Call newSketch.SketchFixedSplines.Add(newSpline)
    Next
End Sub

 


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 7 of 13
andypugh
in reply to: ekinsb

Thanks, I will try your code, though it can't happen now until Sunday. 

 

Re-reading the article I was going by, it isn't the points that it says can be ignored, but the first and last entries in the "knot vector". 

Message 8 of 13
andypugh
in reply to: andypugh

I have tried the code, and I see what you mean. The sub-spline always has 2 ends and 3 control points no matter how short you make it. 

 

I suspect that the pragmatic solution in this case will be to use the "strokes" command to get a series of points of a known deviation, then fit arcs by three points between those points. 

 

I will carry on reading round the subject, though. There seem to be ways to do this, I just don't understand the explanations. 

Message 9 of 13
ekinsb
in reply to: andypugh

The splines in Inventor are apparently all order 5 and you need order 4 for a quadric.  I believe to reduce the order of the curve it will mean creating an approximation.  Increasing the order can be done without losing precision, but reducing is an approximation.

 

Arc fitting isn't as easy as it first appears because ideally you're fitting to a certain tolerance to minimize the number of arcs and you also need to worry about tangency between the arcs.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 10 of 13
andypugh
in reply to: ekinsb

I think I might have found a recipe. 

http://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf

Pages DD7 and DD8 

This does assume that the input B-spline is relaxed, which remains to be seen. 

Message 11 of 13
andypugh
in reply to: andypugh

It also seems to assume that the b-spline is cubic, which I think gives a problem.  Certainly the first stab at it seems to be only a partial success. 

 

The attached .svg file contains the curve approximated by straight line segements (red) , and the polybezier conversion. (green)

 

Very much a "partial success". The next stage will be to try to split the B-spline into shorter curves of lower order. 

 

 (The attachment is a .svg but has been renamed to .xml to allow it to be posted)

Message 12 of 13
ekinsb
in reply to: andypugh

Splitting the curves into smaller segments won't reduce the order.  Inventor will just keep creating order 5 curves.  There's nothing in Inventor that will allow you to convert an existing curve into a new curve with a different order.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 13 of 13
andypugh
in reply to: ekinsb

The curve I tried to fit was order 6. I am wondering if for shorter segments the fit improves even if it is inexact. 

 

The straight-line "strokes" is borderline acceptable. I think that fitting arcs to triads of points would be closer, and maybe a generic fit to points might be better still. 

I have largerly given up on finding an exact solution, I just don't have the time to learn enough maths, much as I would like to. 

 

 

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

Post to forums  

Autodesk Design & Make Report