[Solved] Spline Knot Vector Problem

Discussion forum for C++ and script developers who are using the QCAD development platform or who are looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files, scripts and screenshots.

Post one question per topic.

Post Reply
333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

[Solved] Spline Knot Vector Problem

Post by 333onlyhalfevil » Wed Dec 04, 2024 2:06 pm

Hello everyone.

I'm trying to use a spline in one of my scripts and I seem to be having a problem getting the knot vector to work. I've tried the following:

Code: Select all

var controlPoints = [];
controlPoints.push(new RVector(0.96802918, 4.09554303));
controlPoints.push(new RVector(0.97387637, 4.09519903));
controlPoints.push(new RVector(0.98155731, 4.09536022));
controlPoints.push(new RVector(0.99014236, 4.09546301));
controlPoints.push(new RVector(1.00816138, 4.09567873));
controlPoints.push(new RVector(1.02929573, 4.09482100));
controlPoints.push(new RVector(1.04156829, 4.09554303));
var spline = new RSpline(controlPoints, 3);
var splineData = new RSplineData(spline);
var splineEntity = new RSplineEntity(doc, splineData);
var op = new RAddObjectsOperation();
op.addObject(splineEntity);
The above code works to create a spline and add it to the drawing with the add objects operation. But if I try to add the knot vector with any of the following it doesn't work as expected.

Code: Select all

spline.appendKnot(3.55926049);
spline.appendKnot(3.55926049);
spline.appendKnot(3.55926049);
spline.appendKnot(3.28970036);
spline.appendKnot(3.28970036);
spline.appendKnot(3.28970036);
spline.appendKnot(2.72392481);
spline.appendKnot(2.72392481);
spline.appendKnot(2.72392481);

Code: Select all

var knots = [];
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(2.72392481);
knots.push(2.72392481);
knots.push(2.72392481);
spline.setKnotVector(knots);
The above two code block attempts to add the knot vector, if added to the first code block, cause the spline (that was working) to not be drawn anymore. The following code block below, if added to the first code block, allows the spline to still be drawn, but there appears to be no knot vector when inspecting the properties.

Code: Select all

var knots = [];
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(2.72392481);
knots.push(2.72392481);
knots.push(2.72392481);
spline.knotVector = knots;
Any ideas on how to add the knot vector to a spline?
Last edited by 333onlyhalfevil on Fri Dec 06, 2024 11:10 pm, edited 1 time in total.

CVH
Premier Member
Posts: 4919
Joined: Wed Sep 27, 2017 4:17 pm

Re: Spline Knot Vector Problem

Post by CVH » Wed Dec 04, 2024 4:07 pm

Hi,

Remind that it is a Spline with Control Points or with Fit Points (QCAD Pro).
We don't actually set the Knotvectors.

Further Control Points are simply added to the controlPoints array before creation with new RSpline(controlPoints, 3).
Or afterwards with setControlPoints(), appendControlPoint(...) or appendControlPoints(...)

appendKnot(..) would append to the existent set.
Setting Control Points updates the knotvector list internally.

Setting the Knotvectors in direct would be similar as setting the points: spline.setKnotVector(..)

Regards,
CVH

333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

Re: Spline Knot Vector Problem

Post by 333onlyhalfevil » Wed Dec 04, 2024 7:57 pm

See attached dxf files. The one with a 1 in the name is downloaded off the internet (note that I deleted everything but a single spline that is located in the model space). The other one (with a 2 in the name) is the one produced by my script (it is intended to be the exact same spline with the exact same control points / knot vector only the spline is in a block instead of the model space) that doesn't do anything with the knot vector. What's going on with these? Why are they different? and does the knot vector not matter that much? Also, is there a difference between control points and fit points?
Attachments
spline2.dxf
(33.32 KiB) Downloaded 796 times
spline1.dxf
(37.98 KiB) Downloaded 699 times

333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

Re: Spline Knot Vector Problem

Post by 333onlyhalfevil » Wed Dec 04, 2024 8:05 pm

Now that I'm looking at these two files again, you're right in that it did add in a knot vector. The knot vector isn't shown under properties when the script runs to create the spline. I guess it has to be saved/opened to show? If knot vectors are created automatically, could different softwares be the reason for the difference? I could imagine the one from the internet was created with autocad.

CVH
Premier Member
Posts: 4919
Joined: Wed Sep 27, 2017 4:17 pm

Re: Spline Knot Vector Problem

Post by CVH » Thu Dec 05, 2024 11:07 am

Hi,
I a metric guy and use a comma as separator, the semicolon is then my option to express a coordinate.
The Command Line is geared to and accepts a list of coordinates.

New Control Point Spline (SP), open, degree 3 with the next points and 'Done' afterwards draws the intended spline.
(I am about sure that originally these coordinate values are not limited to 8 decimals)
  • 0,96802918; 4,09554303
    0,97387637; 4,09519903
    0,98155731; 4,09536022
    0,99014236; 4,09546301
    1,00816138; 4,09567873
    1,02929573; 4,09482100
    1,04156829; 4,09554303
When selected the Property Editor does not list Knot Vectors.

Save (Ctrl+S) and Revert reloads the file.
That reminds me of this topic (Unanswered, not fixed, bug report FS#2453 unattended :!: )

I now have a list of 9 Knot Vectors: 0 ; 0 ; 0 ; 1 ; 2 ; 3 ; 4 ; 4 ; 4
All are integer values like in spline2.dxf.


Then I tried the next code in the Script Shell (GE):

Code: Select all

var doc = EAction.getDocument();
var di = EAction.getDocumentInterface();

var controlPoints = [];
controlPoints.push(new RVector(0.96802918, 4.09554303));
controlPoints.push(new RVector(0.97387637, 4.09519903));
controlPoints.push(new RVector(0.98155731, 4.09536022));
controlPoints.push(new RVector(0.99014236, 4.09546301));
controlPoints.push(new RVector(1.00816138, 4.09567873));
controlPoints.push(new RVector(1.02929573, 4.09482100));
controlPoints.push(new RVector(1.04156829, 4.09554303));
var spline = new RSpline(controlPoints, 3);

var knots = spline.getKnotVector();
debugger;

var knots = [];
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.55926049);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(3.28970036);
knots.push(2.72392481);
knots.push(2.72392481);
knots.push(2.72392481);
//spline.setKnotVector(knots);    // # Ruled out CVH #

var splineData = new RSplineData(spline);
var splineEntity = new RSplineEntity(doc, splineData);
var op = new RAddObjectsOperation();
op.addObject(splineEntity);

di.applyOperation(op);
With ruling out the spline.setKnotVector(knots) line I get the same Spline as in spline2.dxf.

When not ruled out the transaction also reports a newly created ... Affected object besides object 5 (Model_Space Block).
But there is seemingly nothing in the drawing.

Except when you box select all inclusive around where it is expected AND including the origin.
A method to reveal Null-entities.
What is selected is not visible but it is a Spline with the intended Knot Vectors.

Save and Revert reloads the file, but the mysterious Spline was not saved and that without an error message in the nature of "Object not saved".
Nor does AutoSave complains when we leave the file unsaved with the invisible Spline.

:arrow: We are definitely missing something ... :? :?:
For that I included reading out the Knot Vectors and halt in Debugger mode. (No idea why this is not in plural)

Not functional in the Script Shell (GE) >>> Instruction lines are handled line by line.
Not functional when using Run Script (XC) with the code saved as a JS script >>> Execution is not halted.
... So I needed to merge the code in some QCAD script at hand ...

The knot list is empty at that point ...
In debugger mode pointing to the spline we see that it reports "Internal used Knots: 0 ; 0 ; 0 ; 1 ; 2 ; 3 ; 4 ; 4 ; 4"
Executing the next lines, with setting the knots list, we see that the intended knots are there but also that there is 1 more line ....
SettingSplineKnot.png
SettingSplineKnot.png (39.37 KiB) Viewed 57484 times

Aargl! Including var text = spline.toString(); then :roll: It simplifies copy/paste too :

Code: Select all

"RSpline(RShape(address: \"0xd64c8f0\"), degree: 3, dirty: true, order: 4, closed: false, periodic: false, start point: \"RVector(0.018694, 3.048743, 0.000000, 1)\", end point: \"RVector(0.018694, 3.048743, 0.000000, 1)\", start tan: \"RVector(0.000000, 0.000000, 0.000000, 1)\", end tan: \"RVector(0.000000, 0.000000, 0.000000, 1)\", t_min: 0, t_max: 0,
controlPoints (7): 0: \"RVector(0.968029, 4.095543, 0.000000, 1)\", 1: \"RVector(0.973876, 4.095199, 0.000000, 1)\", 2: \"RVector(0.981557, 4.095360, 0.000000, 1)\", 3: \"RVector(0.990142, 4.095463, 0.000000, 1)\", 4: \"RVector(1.008161, 4.095679, 0.000000, 1)\", 5: \"RVector(1.029296, 4.094821, 0.000000, 1)\", 6: \"RVector(1.041568, 4.095543, 0.000000, 1)\", ,
weights (0): ,
fitPoints (0): ,
knots (9): 0: 3.55926, 1: 3.55926, 2: 3.55926, 3: 3.2897, 4: 3.2897, 5: 3.2897, 6: 2.72392, 7: 2.72392, 8: 2.72392, ,
internally used knots (9): 0: 3.55926, 1: 3.55926, 2: 3.55926, 3: 3.2897, 4: 3.2897, 5: 3.2897, 6: 2.72392, 7: 2.72392, 8: 2.72392, "
The internally used knots are set as required :!:

Now let us grab the spline in spline1.dxf and list its details with the following code executed in the Script Shell (GE):

Code: Select all

var doc = EAction.getDocument();
var ids = doc.queryAllEntities(false, false, RS.EntitySpline);
var entity = doc.queryEntityDirect(ids[0]);
var spline = entity.castToShape();
spline.toString()

Code: Select all

RSpline(RShape(address: "0xd267268"), degree: 3, dirty: false, order: 4, closed: false, periodic: false, start point: "RVector(1.041568, 4.095543, 0.000000, 1)", end point: "RVector(0.968029, 4.095543, 0.000000, 1)", start tan: "RVector(0.000000, 0.000000, 0.000000, 1)", end tan: "RVector(0.000000, 0.000000, 0.000000, 1)", t_min: 2.72392, t_max: 3.55926, 
controlPoints (7): 0: "RVector(1.041568, 4.095543, 0.000000, 1)", 1: "RVector(1.029296, 4.094821, 0.000000, 1)", 2: "RVector(1.008161, 4.095679, 0.000000, 1)", 3: "RVector(0.990142, 4.095463, 0.000000, 1)", 4: "RVector(0.981557, 4.095360, 0.000000, 1)", 5: "RVector(0.973876, 4.095199, 0.000000, 1)", 6: "RVector(0.968029, 4.095543, 0.000000, 1)", , 
weights (0): , 
fitPoints (0): , 
knots (9): 0: 2.72392, 1: 2.72392, 2: 2.72392, 3: 3.2897, 4: 3.2897, 5: 3.2897, 6: 3.55926, 7: 3.55926, 8: 3.55926, , 
internally used knots (9): 0: 2.72392, 1: 2.72392, 2: 2.72392, 3: 3.2897, 4: 3.2897, 5: 3.2897, 6: 3.55926, 7: 3.55926, 8: 3.55926, 
Closing in on the issue ... Can you spot the difference apart from being reversed?


Besides that dirty is true, t_min and t_max of our Spline shape are both zero.
Hence a Spline rendered from t=0 to t=0.
Hence a Null-entity ... With reference points and thus with selection markers.

Setting TMin and TMax is not an option.
The method update() is already called for with setting the knots list.
The method updateInternal() is not an option (Protected).

I found another method that calls updateInternal() ... Including var test = spline.getActualKnotVector(); after the knot list is set.
dirty is now false, actual knots are fine but t_min and t_max remain zero.

Wait a minute .... t min/max :idea: ... Your knots are listed from large to small :!:

:arrow: Reverse both the Control Point list and the Knot Vector list and all is fine.


All for the time being ....
I could not have solved this WITHOUT THE DEBUGGER.
Then scripting under QCAD, support and much more ends.


And thank you very much.
This opens up routes for approximations of a hyperbola or an involute with splines.
If I ever want (and/or still can) update the gear generator exploiting a given modulus with splines as tooth profile.
A hyperbola is the line of equal distance between Arcs/Circles of different sizes, required to form a skeleton of an enclosed area.
A skeleton is the base for a Pocketing path by CAM.

Regards
CVH

333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

Re: Spline Knot Vector Problem

Post by 333onlyhalfevil » Fri Dec 06, 2024 9:00 am

Thank you very much for this lengthly/detailed reply.

Including var test = spline.getActualKnotVector() seems to work in getting the intended knot vector included within the spline.

It is interesting to note that using spline.setKnotVector(knots) creates the null-spline but using spline.getActualKnotVector() makes the spline work with the intended knot vector whereas using spline.knotVector = knots (see the solutions on some of my other threads) makes the spline work (albeit without the intended knot vector) but if you try to use spline.getActualKnotVector() it'll break and make the null-spline again.

I did have the control points reversed from the spline1.dxf. I've been trying to code everything similarly and one of the standards is to generally draw things from left to right, top to bottom, and/or clockwise, so I switched the order and also switched the order of the knot vector. It seems to work regardless of the order of control points as long as the order of the knot vector remains unchanged. Do you know if this matters and/or if it is safe to use the knot vector produced by qcad?
CVH wrote:
Thu Dec 05, 2024 11:07 am
Except when you box select all inclusive around where it is expected AND including the origin.
A method to reveal Null-entities.
What is selected is not visible but it is a Spline with the intended Knot Vectors.
This is very interesting. I'll have to remember this little technique in the future.

CVH
Premier Member
Posts: 4919
Joined: Wed Sep 27, 2017 4:17 pm

Re: Spline Knot Vector Problem

Post by CVH » Fri Dec 06, 2024 1:33 pm

333onlyhalfevil wrote:
Fri Dec 06, 2024 9:00 am
Thank you very much for this lengthly/detailed reply.
I am merely recording what I tried and how I came to certain conclusions that led to the solution.
With the words this, that, there, such and so it would become unreadable.
It is already a tricky subject in itself.
333onlyhalfevil wrote:
Fri Dec 06, 2024 9:00 am
It seems to work regardless of the order of control points as long as the order of the knot vector remains unchanged.
Probably ... Seemingly ... Perhaps because your Knot Vectors are 3 triplets and symmetric.
Where the middle 3 Knot Vectors generated by QCAD are: 1 ; 2 ; 3

I agree that I can not detect any difference using these Knot Vectors together with these Control Points.
Unsure if that is valid for any arbitrary list and combination ... Very doubtful.
333onlyhalfevil wrote:
Fri Dec 06, 2024 9:00 am
Do you know if this matters and/or if it is safe to use the knot vector produced by qcad?
Save? why not?
It matters, it is a different shape with: 0 ; 0 ; 0 ; 1 ; 2 ; 3 ; 4 ; 4 ; 4
Although that the example is very flat. :wink:

I also tested reversing the QCAD spline.
Obviously, Control Points are in reversed order.
Knots Vectors go from -4 to 0 ... Hence, t_min < t_max

Reversing your Spline would then require to negate the Knots Vectors, a list from -3.55926049 to -2.72392481
333onlyhalfevil wrote:
Fri Dec 06, 2024 9:00 am
whereas using spline.knotVector = knots (see the solutions on some of my other threads) makes the spline work (albeit without the intended knot vector)
spline.setKnotVector(knots) see reference.
Setting the spline.knotVector in direct does not call for an update as on line 510.
Hence, they are not used as you pointed out, and an update by other means will fail because 3.55926049 > 2.72392481

Regards,
CVH

333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

Re: Spline Knot Vector Problem

Post by 333onlyhalfevil » Fri Dec 06, 2024 11:09 pm

Ah, negate the values in the knot vector, ok.

This thread seems solved now. Thanks again for your help.

333onlyhalfevil
Full Member
Posts: 92
Joined: Fri Apr 28, 2023 12:39 pm

Re: [Solved] Spline Knot Vector Problem

Post by 333onlyhalfevil » Sat Dec 07, 2024 1:54 am

One last thing. To reverse the order of the control points, you have to both negate and also reverse the order of the knot vector values. Only negating them (and not also reversing) yields the null spline.

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”