Author Topic: Bug with Second Derivative of Scaled Spline  (Read 3892 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Bug with Second Derivative of Scaled Spline
« on: June 11, 2013, 10:40:04 AM »
Whilst working on a function to approximate a spline, I believe I have found a bug pertaining to the calculation of the second derivative at points along the spline (as calculated by the vlax-curve-getsecondderiv function) after the spline has been scaled.



Steps to reproduce the problem:

1. Construct a spline in the drawing with spline method set to 'Fit'.

2. Run the following program on the spline created:
Code: [Select]
(defun c:test ( / der di1 di2 ent inc )
    (if (setq ent (car (entsel)))
        (progn
            (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent))
                  di2 (vlax-curve-getdistatparam ent (vlax-curve-getendparam   ent))
                  inc (/ di2 20.0)
            )
            (while (< di1 di2)
                (setq der (cons (distance '(0.0 0.0 0.0) (vlax-curve-getsecondderiv ent (vlax-curve-getparamatdist ent di1))) der)
                      di1 (+ di1 inc)
                )
            )
            (print di2)
            (princ (/ (apply '+ der) (length der)))
        )
    )
    (princ)
)
(vl-load-com) (princ)

The above program will print the length of the spline, along with the average magnitude of the second derivative at 20 points along the spline.

3. Using the SCALE command, scale the spline by any scale factor, using any base point.

4. Run the above program again on the scaled spline.

If the spline has been scaled up, the average second derivative would be expected to decrease; if scaled down, this average would be expected to increase (since the spline will have tighter curves).

5. Use the COPY command to copy the scaled spline.

6. Run the above program on the copied spline.

One would expect the results of running the program on the copied spline to be identical to those reported by the program before the spline was copied (since the spline geometry has not changed).



Here are my results:

Original Spline:
Code: [Select]
Length     Ave. 2nd Deriv
32.6029    0.108747

Spline Scaled by 2:
Code: [Select]
Length     Ave. 2nd Deriv
65.2059    0.217493 <--- this should be half, not double :-(

Copy of Scaled Spline:
Code: [Select]
Length     Ave. 2nd Deriv
65.2059    0.051784 <--- value is now correct for copied spline



Observe that scaling the spline causes the average magnitude of the second derivative to increase by the scale factor, rather than decrease by a reciprocal of the scale factor.

Hence, in my example above,

Original Average 2nd Deriv is 0.108747
After scaling the spline by 2, this average is also doubled to 0.217493 (rather than halved)
After copying, the correct (halved) average is returned: 0.051784



Can anyone else replicate these results?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #1 on: June 11, 2013, 11:35:06 AM »
This bug can also be reproduced by performing the scaling and copying operations programmatically:

Code: [Select]
(defun c:test2 ( / ent )
    (if (setq ent (car (entsel)))
        (progn
            (calc2der ent)
            (vla-scaleentity (vlax-ename->vla-object ent) (vlax-3D-point 0 0) 2.0)
            (calc2der ent)
            (calc2der (vlax-vla-object->ename (vla-copy (vlax-ename->vla-object ent))))
        )
    )
    (princ)
)

(defun calc2der ( ent / der di1 di2 inc )
    (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent))
          di2 (vlax-curve-getdistatparam ent (vlax-curve-getendparam   ent))
          inc (/ di2 20.0)
    )
    (while (< di1 di2)
        (setq der (cons (distance '(0.0 0.0 0.0) (vlax-curve-getsecondderiv ent (vlax-curve-getparamatdist ent di1))) der)
              di1 (+ di1 inc)
        )
    )
    (print di2)
    (princ (/ (apply '+ der) (length der)))
)
(vl-load-com) (princ)

My results:

Code: [Select]
Length     2nd Deriv
8.33154    0.434966  ;; Original Spline
16.6631    0.913428  ;; Spline Scaled 2x
16.6631    0.217483  ;; Copy of Scaled Spline

This of course presents a solution of temporarily copying the spline before performing these calculations, and then deleting the temporary copy after all calculations have been performed.

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #2 on: June 11, 2013, 02:34:43 PM »
Update: copying the Spline does not appear to resolve this issue with 3D Splines  :-(

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Bug with Second Derivative of Scaled Spline
« Reply #3 on: June 11, 2013, 06:21:05 PM »
Select object:
789.486 0.00505354

Select object:
789.486 0.0048129

Select object:
789.486 0.0048129

Select object:
394.743 0.00240645

Select object:
394.743 0.00240645

Select object:
394.743 0.00252677

Select object:
394.743 0.00962581
Select object:
394.743 0.00962581
Select object:
394.743 0.00240645

Select object:
394.743 0.00962581
Select object:
394.743 0.00240645
Select object:
394.743 0.00252677
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

SEANT

  • Bull Frog
  • Posts: 345
Re: Bug with Second Derivative of Scaled Spline
« Reply #4 on: June 12, 2013, 06:05:08 AM »
Interesting, it appears that a SCALE operation does not modify the Parametric Range of a spline.   

Copying the spline, though, does reset the range equal to OriginalRange * ScaleFactor (if Knots = Chord).  Knots = Uniform does not require a reset.  Knots = Square Root would reset the range to OriginalRange * (SQRT(ScaleFactor).  IOW, COPYing modifies values as expected.
Sean Tessier
AutoCAD 2016 Mechanical

VovKa

  • Water Moccasin
  • Posts: 1629
  • Ukraine
Re: Bug with Second Derivative of Scaled Spline
« Reply #5 on: June 12, 2013, 08:05:00 AM »
add
Code: [Select]
(entmod (entget ent))right after scaling

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #6 on: June 12, 2013, 08:13:15 AM »
Interesting, it appears that a SCALE operation does not modify the Parametric Range of a spline.   

Copying the spline, though, does reset the range equal to OriginalRange * ScaleFactor (if Knots = Chord).  Knots = Uniform does not require a reset.  Knots = Square Root would reset the range to OriginalRange * (SQRT(ScaleFactor).  IOW, COPYing modifies values as expected.

Thank you for your investigation Sean, I appreciate it; so far, I've only been experimenting with splines created using Chord parameterisation, and mostly using the Fit method to construct the spline. I shall certainly need to spend some more time experimenting with the other parameterisation methods.

add
Code: [Select]
(entmod (entget ent))right after scaling

Fantastic suggestion VovKa, thanks!  :-)

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #7 on: June 12, 2013, 08:23:22 AM »
After running some tests with splines created using the Fit method, and splines created using the CV (Control Vertex) method, I have now discovered that the average magnitude of the second derivative is substantially greater for CV Splines than it is for Fit Splines with almost identical geometry:
Code: [Select]
Fit Spline
Length     2nd Deriv
118.988    0.0379314
Code: [Select]
CV Spline
Length     2nd Deriv
118.605    122.595 ;; <-- Why is this so much larger?

I'm no expert when it comes to Splines, so could anyone offer any explanation as to why there is such as significant difference in these results?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #8 on: June 12, 2013, 09:37:56 AM »
I have now discovered that the average magnitude of the second derivative is substantially greater for CV Splines than it is for Fit Splines with almost identical geometry

On further investigation, it seems that this difference varies for every spline method and parameterisation, even though the spline has the same basic geometry in each case:



Surely the second derivative is a property of the geometry of the curve and should be independent of the parameterisation?
Or am I overlooking something simple?

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Bug with Second Derivative of Scaled Spline
« Reply #9 on: June 12, 2013, 09:49:56 AM »
Have you looked the values for the first derivatives?

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #10 on: June 12, 2013, 10:59:48 AM »
Have you looked the values for the first derivatives?

Not as yet, though since you mention it I shall investigate the 1st derivative vectors when I get some time.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Bug with Second Derivative of Scaled Spline
« Reply #11 on: June 12, 2013, 12:01:46 PM »
*****************EDIT*****************
Doh! I see Seant already pointed that out.
*****************EDIT*****************
 
Hi Lee,
 
GetSecondDerivative is a virtual method of the curve class.
 
I am not sure if this helps, but I see if you scale a spline the end parameter is the same, and once you copy it then it will double.
 
I have command called GetProps that you can select a entity and it prints all of its properties to command line.
I will Print the name of the class and list it properties defined in class then will print the name of the class that it derives from listing its properties until it reaches System Object.
 
For example if you select a line it prints
Line
-Line Properties
-....
-....
Curve
-Curve properties
-....
-....
Entity
-Entity properties
-...
-...
....
 
Here is the command line output and I run
-GetProps on a spline
-Scale it by 2
-GetProps on spline(the end parameter is same but the end point changes, etc..)
-Copy the spline
-GetProps on copy of spline and the end parameter is now doubled.
 
Quote

Command: GETPROPS
Select Entity: Spline
-Type = FitPoints
-IsPlanar = True
-NurbsData = Autodesk.AutoCAD.DatabaseServices.NurbsData
-FitData = Autodesk.AutoCAD.DatabaseServices.FitData
-HasFitData = True
-EndFitTangent = (0,0,0)
-StartFitTangent = (0,0,0)
-FitTolerance = 1E-10
-NumFitPoints = 5
-NumControlPoints = 7
-Degree = 3
-IsRational = False
-IsNull = False
Curve
-Area = 2.17354186542976
-Spline = Spline
-EndPoint = (22.1068952946368,10.1146416101536,0)
-StartPoint = (4.45563506922117,5.95178398434367,0)
-EndParam = 20.0846275850912
-StartParam = 0
-IsPeriodic = False
-Closed = False
Entity
-EdgeStyleId = (0)
-FaceStyleId = (0)
-VisualStyleId = (0)
-ForceAnnoAllVisible = True
-BlockName = String
-MaterialMapper = null
-MaterialId = (8796083600864)
-Material = String
-ReceiveShadows = False
-CastShadows = False
-Hyperlinks = HyperLinkCollection
-CloneMeForDragging = True
-CompoundObjectTransform != NotAvailable
-GeometricExtents = ((4.45563506922117,5.91015538808557,0),(22.1068952946368,10.1146416101536,0))
-Ecs = ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
-CollisionType = Solid
-LineWeight = ByLayer
-Visible = True
-LinetypeScale = 1
-LinetypeId = (8796083599696)
-Linetype = String
-LayerId = (8796083599616)
-Layer = String
-PlotStyleNameId = ((0),PlotStyleNameByLayer)
-PlotStyleName = String
-Transparency = (0)
-EntityColor = Autodesk.AutoCAD.Colors.EntityColor
-ColorIndex = 256
-Color = Color
-BlockId = (8796083599856)
DBObject
-PaperOrientation = NotApplicable
-Annotative = NotApplicable
-HasFields = False
-AcadObject = __ComObject
-ClassID = f5642c17-04bd-461b-bb44-b43fb191fbab
-ObjectBirthVersion = AC1012,Release0
-HasSaveVersionOverride = False
-IsObjectIdsInFlux = False
-UndoFiler = null
-IsAProxy = False
-IsTransactionResident = True
-IsReallyClosing = False
-IsCancelling = False
-IsUndoing = False
-IsNotifying = False
-IsNewObject = False
-IsModifiedGraphics = False
-IsModifiedXData = False
-IsModified = False
-IsNotifyEnabled = False
-IsWriteEnabled = False
-IsReadEnabled = True
-IsErased = False
-IsEraseStatusToggled = False
-XData = null
-MergeStyle = Ignore
-ExtensionDictionary = (0)
-Drawable = Spline
-Database = Database
-Handle = 2EE
-OwnerId = (8796083599856)
-ObjectId = (8796083609440)
-Id = (8796083609440)
-IsPersistent = True
Drawable
-DrawStream = null
-Bounds = ((4.45563506922117,5.91015538808557,0),(22.1068952946368,10.1146416101536,0))
-DrawableType = Geometry
DisposableWrapper
-AutoDelete = False
-IsDisposed = False
-UnmanagedObject = 779125408

Command: sc SCALE
Select objects: 1 found
Select objects:
Specify base point:
Specify scale factor or [Copy/Reference]: 2

Command: GETPROPS
Select Entity: Spline
-Type = FitPoints
-IsPlanar = True
-NurbsData = Autodesk.AutoCAD.DatabaseServices.NurbsData
-FitData = Autodesk.AutoCAD.DatabaseServices.FitData
-HasFitData = True
-EndFitTangent = (0,0,0)
-StartFitTangent = (0,0,0)
-FitTolerance = 1E-10
-NumFitPoints = 5
-NumControlPoints = 7
-Degree = 3
-IsRational = False
-IsNull = False
Curve
-Area = 8.69416746171903
-Spline = Spline
-EndPoint = (39.7581555200524,14.2774992359635,0)
-StartPoint = (4.45563506922117,5.95178398434367,0)
-EndParam = 20.0846275850912
-StartParam = 0
-IsPeriodic = False
-Closed = False
Entity
-EdgeStyleId = (0)
-FaceStyleId = (0)
-VisualStyleId = (0)
-ForceAnnoAllVisible = True
-BlockName = String
-MaterialMapper = null
-MaterialId = (8796083600864)
-Material = String
-ReceiveShadows = False
-CastShadows = False
-Hyperlinks = HyperLinkCollection
-CloneMeForDragging = True
-CompoundObjectTransform != NotAvailable
-GeometricExtents = ((4.45563506922117,5.86852681182747,0),(39.7581555200524,14.2774992359635,0))
-Ecs = ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
-CollisionType = Solid
-LineWeight = ByLayer
-Visible = True
-LinetypeScale = 1
-LinetypeId = (8796083599696)
-Linetype = String
-LayerId = (8796083599616)
-Layer = String
-PlotStyleNameId = ((0),PlotStyleNameByLayer)
-PlotStyleName = String
-Transparency = (0)
-EntityColor = Autodesk.AutoCAD.Colors.EntityColor
-ColorIndex = 256
-Color = Color
-BlockId = (8796083599856)
DBObject
-PaperOrientation = NotApplicable
-Annotative = NotApplicable
-HasFields = False
-AcadObject = __ComObject
-ClassID = f5642c17-04bd-461b-bb44-b43fb191fbab
-ObjectBirthVersion = AC1012,Release0
-HasSaveVersionOverride = False
-IsObjectIdsInFlux = False
-UndoFiler = null
-IsAProxy = False
-IsTransactionResident = True
-IsReallyClosing = False
-IsCancelling = False
-IsUndoing = False
-IsNotifying = False
-IsNewObject = False
-IsModifiedGraphics = False
-IsModifiedXData = False
-IsModified = False
-IsNotifyEnabled = False
-IsWriteEnabled = False
-IsReadEnabled = True
-IsErased = False
-IsEraseStatusToggled = False
-XData = null
-MergeStyle = Ignore
-ExtensionDictionary = (0)
-Drawable = Spline
-Database = Database
-Handle = 2EE
-OwnerId = (8796083599856)
-ObjectId = (8796083609440)
-Id = (8796083609440)
-IsPersistent = True
Drawable
-DrawStream = null
-Bounds = ((4.45563506922117,5.86852681182747,0),(39.7581555200524,14.2774992359635,0))
-DrawableType = Geometry
DisposableWrapper
-AutoDelete = False
-IsDisposed = False
-UnmanagedObject = 779125408

Command: Co COPY
Select objects: 1 found
Select objects:
Current settings:  Copy mode = Multiple
Specify base point or [Displacement/mOde] <Displacement>:
Specify second point or [Array] <use first point as displacement>:
Specify second point or [Array/Exit/Undo] <Exit>:

Command:
Command: GETPROPS
Select Entity: Spline
-Type = FitPoints
-IsPlanar = True
-NurbsData = Autodesk.AutoCAD.DatabaseServices.NurbsData
-FitData = Autodesk.AutoCAD.DatabaseServices.FitData
-HasFitData = True
-EndFitTangent = (0,0,0)
-StartFitTangent = (0,0,0)
-FitTolerance = 1E-10
-NumFitPoints = 5
-NumControlPoints = 7
-Degree = 3
-IsRational = False
-IsNull = False
Curve
-Area = 8.69416746171895
-Spline = Spline
-EndPoint = (39.7581555200523,23.3803335558762,0)
-StartPoint = (4.45563506922117,15.0546183042563,0)
-EndParam = 40.1692551701825
-StartParam = 0
-IsPeriodic = False
-Closed = False
Entity
-EdgeStyleId = (0)
-FaceStyleId = (0)
-VisualStyleId = (0)
-ForceAnnoAllVisible = True
-BlockName = String
-MaterialMapper = null
-MaterialId = (8796083600864)
-Material = String
-ReceiveShadows = False
-CastShadows = False
-Hyperlinks = HyperLinkCollection
-CloneMeForDragging = True
-CompoundObjectTransform != NotAvailable
-GeometricExtents = ((4.45563506922117,14.9713611317401,0),(39.7581555200524,23.3803335558762,0))
-Ecs = ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
-CollisionType = Solid
-LineWeight = ByLayer
-Visible = True
-LinetypeScale = 1
-LinetypeId = (8796083599696)
-Linetype = String
-LayerId = (8796083599616)
-Layer = String
-PlotStyleNameId = ((0),PlotStyleNameByLayer)
-PlotStyleName = String
-Transparency = (0)
-EntityColor = Autodesk.AutoCAD.Colors.EntityColor
-ColorIndex = 256
-Color = Color
-BlockId = (8796083599856)
DBObject
-PaperOrientation = NotApplicable
-Annotative = NotApplicable
-HasFields = False
-AcadObject = __ComObject
-ClassID = f5642c17-04bd-461b-bb44-b43fb191fbab
-ObjectBirthVersion = AC1012,Release0
-HasSaveVersionOverride = False
-IsObjectIdsInFlux = False
-UndoFiler = null
-IsAProxy = False
-IsTransactionResident = True
-IsReallyClosing = False
-IsCancelling = False
-IsUndoing = False
-IsNotifying = False
-IsNewObject = False
-IsModifiedGraphics = False
-IsModifiedXData = False
-IsModified = False
-IsNotifyEnabled = False
-IsWriteEnabled = False
-IsReadEnabled = True
-IsErased = False
-IsEraseStatusToggled = False
-XData = null
-MergeStyle = Ignore
-ExtensionDictionary = (0)
-Drawable = Spline
-Database = Database
-Handle = 2F0
-OwnerId = (8796083599856)
-ObjectId = (8796083650560)
-Id = (8796083650560)
-IsPersistent = True
Drawable
-DrawStream = null
-Bounds = ((4.45563506922117,14.9713611317401,0),(39.7581555200524,23.3803335558762,0))
-DrawableType = Geometry
DisposableWrapper
-AutoDelete = False
-IsDisposed = False
-UnmanagedObject = 780409488
« Last Edit: June 12, 2013, 12:10:09 PM by Jeff H »

SEANT

  • Bull Frog
  • Posts: 345
Re: Bug with Second Derivative of Scaled Spline
« Reply #12 on: June 12, 2013, 01:40:55 PM »
The magnitude of the second derivative (acceleration vector) is based on the curves  rate of change through space per displacement through the parametric range.  A Uniform Knot Param tends to have small parametric range.  The Chord will have the largest range, so the ratio mentioned above will be smaller.

The included file has the geometry I’ve illustrated, as well as two splines created  via the CV method.  On the left the spline was created by tracing over the FIT spline Knots = Uniform, using 3DOsnap – Vertex.  Notice how closely it matches the FitPoint version (Actually, I’m not exactly sure why it isn’t a perfect match). 
The spline on the right is a reparameterized (0 to 100) copy of the spline on the left;  try you routine on that one.
Sean Tessier
AutoCAD 2016 Mechanical

Lee Mac

  • Seagull
  • Posts: 12913
  • London, England
Re: Bug with Second Derivative of Scaled Spline
« Reply #13 on: June 13, 2013, 07:44:00 AM »
Jeff / Sean,

I can't thank you enough for your time & explanations, the penny finally dropped after reading Sean's statement:

The magnitude of the second derivative (acceleration vector) is based on the curves rate of change through space per displacement through the parametric range.

I had overlooked the fact that since the splines are parametric curves, the parametric derivative will also be dependent on the rate of change of the parameter. Hence, for a small parametric range, the derivative will be much larger since the curve is deviating more in a shorter space of 'time'. With this information I can easily 'normalise' the second derivative vectors using the parametric range of the spline.

Many thanks once again, I appreciate the time you have donated to assist me.

Lee

SEANT

  • Bull Frog
  • Posts: 345
Re: Bug with Second Derivative of Scaled Spline
« Reply #14 on: June 13, 2013, 05:07:36 PM »
I am happy I could help. :-)
Sean Tessier
AutoCAD 2016 Mechanical