Hi,
I have a polyline which has line as well as arc segments. I'm trying to get the vertex and coordinates of this polyline entity through qcad script.
I know that I can get the vertex coordinates through `pl.getVertexAt`. However, how do I get the coordinates of this (shown in the screenshot) point in the arc segment?
Version:QCAD Pro 3.28.2 on Linux
[SOLVED] Get coordinate on the arc
Moderator: andrew
Forum rules
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
[SOLVED] Get coordinate on the arc
- Attachments
-
- Untitled.png (143.81 KiB) Viewed 1303 times
Last edited by arun on Mon Feb 05, 2024 2:29 am, edited 1 time in total.
Re: Get coordinate on the arc
Hi,
The marker you indicate is the middle point of the polyline segment.
Vertices and segments are both zero based lists.
Vertex00 - Segment00 - Vertex01 - Segment01 - Vertex02 - ...
The bulging character of a segment is stored in the bulge factor of the preceding vertex.
Logically closed polylines have the same amount of vertices and segments.
Open or geometrically closed polylines have one extra end-vertex.
For geometrically closed polylines the end-vertex coincides with the start-vertex.
One can query segments with the same ease as vertices:
https://qcad.org/doc/qcad/3.0/developer ... 4c56c9a1ea
That should return an RLine shape (bulge = zero) or an RArc shape (bulge <> zero).
Only, sequential vertices may coincide on the same spot with no real segment in between.
The middle points of these two types can be retrieved in identical ways:
https://qcad.org/doc/qcad/3.0/developer ... 128769e6b2
https://qcad.org/doc/qcad/3.0/developer ... 4b7cb2478b
var point = pl.getSegmentAt(n).getMiddlePoint();
Where n is the segment in question is a valid method if the segment is something meaningful.
In a way the middle between two coinciding vertices is again the same spot and could be valid too.
But it is impossible to re-create an RArc from 3 identical points.
In a mathematical way it is possible to retrieve the marker position from vertices and bulge without the arc conversion.
Remind that arc -> bulge -> arc -> bulge -> ... may introduce (minute) errors on each conversion.
Regards,
CVH
The marker you indicate is the middle point of the polyline segment.
Vertices and segments are both zero based lists.
Vertex00 - Segment00 - Vertex01 - Segment01 - Vertex02 - ...
The bulging character of a segment is stored in the bulge factor of the preceding vertex.
Logically closed polylines have the same amount of vertices and segments.
Open or geometrically closed polylines have one extra end-vertex.
For geometrically closed polylines the end-vertex coincides with the start-vertex.
One can query segments with the same ease as vertices:
https://qcad.org/doc/qcad/3.0/developer ... 4c56c9a1ea
That should return an RLine shape (bulge = zero) or an RArc shape (bulge <> zero).
Only, sequential vertices may coincide on the same spot with no real segment in between.
The middle points of these two types can be retrieved in identical ways:
https://qcad.org/doc/qcad/3.0/developer ... 128769e6b2
https://qcad.org/doc/qcad/3.0/developer ... 4b7cb2478b
var point = pl.getSegmentAt(n).getMiddlePoint();
Where n is the segment in question is a valid method if the segment is something meaningful.
In a way the middle between two coinciding vertices is again the same spot and could be valid too.
But it is impossible to re-create an RArc from 3 identical points.
In a mathematical way it is possible to retrieve the marker position from vertices and bulge without the arc conversion.
Remind that arc -> bulge -> arc -> bulge -> ... may introduce (minute) errors on each conversion.
Regards,
CVH
Re: Get coordinate on the arc
Thanks CVH, much appreciated for the detailed explanation. This works well
I do get the following as the output
and
Could you also share on how can I derive the MiddlePoint from Bulge factor
Thanks again,
Arun
I'm also keen to understand this relationship between bulge and middlePoint.In a mathematical way it is possible to retrieve the marker position from vertices and bulge without the arc conversion.
Remind that arc -> bulge -> arc -> bulge -> ... may introduce (minute) errors on each conversion.
I do get the following as the output
Code: Select all
pl.getSegmentAt(1).getMiddlePoint()
"RVector(-57.656854, 182.656854, 0.000000, 1)"
Code: Select all
pl.getSegmentAt(1).getBulge()
0.41421356237309503
Thanks again,
Arun
Re: Get coordinate on the arc
A bulge factor of 0.41421356237309503 is related to a 90 degree arc.
Almost, 4*atan(0.41421...) is nearly 90°, in Floating Point, in radians it can not be more accurately.
"RVector(-57.656854, 182.656854, 0.000000, 1)" is noway near the marker in the image.
I would expect 340 < X < 350 and 150 < Y < 160 for the arc segment in question looking at the example.
https://en.wikipedia.org/wiki/Sagitta_(geometry)
A trigonometric feature is than that the bulge factor also equals to tan(sweep/4) with a signed sweep of an identical arc shape.
Remark that this would fail for a division by zero and then also for a sweep angle of +/-360°.
For no or a null sagitta and for a zero sweep the bulge factor is zero what is not curved and thus a straight line segment.
What we do is basically summing the sagitta and the chord middle point vector-wise.
The following code first validates given parameters and handles straight and bulging segments.
What to do with null-length segments depends on the application.
It is possible that you don't require all the included conditioning.
I did not include a test for a full circular arc segment: tan(360°/4) = error.
But in Floating Point tan(PI/2) returns a ridiculous large value not necessarily +/-infinite.
Since some time QCAD handles these as two distinct semi circular segments to avoid the mathematical error.
I have to add that not all QCAD resources agree on how to determine edge cases and on how they are handled.
> For almost circular segments poly.getSegmentAt(index) will return a very short line segment:
https://github.com/qcad/qcad/blob/maste ... 1216-L1219
> RArc.getLength() for example does not allow for (almost) zero sweep and reverts to 2PI.
https://github.com/qcad/qcad/blob/maste ... c.cpp#L360
And RArc.getAngleLength(false): https://github.com/qcad/qcad/blob/maste ... #L434-L439
> RPolyline.isStraight(bulge) defines (where used) an absolute bulge less than 1e-6 or a sweep less than 2.292e-4 degrees as straight:
https://github.com/qcad/qcad/blob/maste ... 1126-L1131
...
..
.
Regards,
CVH
Almost, 4*atan(0.41421...) is nearly 90°, in Floating Point, in radians it can not be more accurately.
"RVector(-57.656854, 182.656854, 0.000000, 1)" is noway near the marker in the image.
I would expect 340 < X < 350 and 150 < Y < 160 for the arc segment in question looking at the example.
The bulge factor is defined as the sagitta length divide by half the chord length and signed where bulging out to the right is positive.
https://en.wikipedia.org/wiki/Sagitta_(geometry)
A trigonometric feature is than that the bulge factor also equals to tan(sweep/4) with a signed sweep of an identical arc shape.
Remark that this would fail for a division by zero and then also for a sweep angle of +/-360°.
For no or a null sagitta and for a zero sweep the bulge factor is zero what is not curved and thus a straight line segment.
What we do is basically summing the sagitta and the chord middle point vector-wise.
The following code first validates given parameters and handles straight and bulging segments.
What to do with null-length segments depends on the application.
It is possible that you don't require all the included conditioning.
Code: Select all
var pl; // An RPolylineEntity or RPolyline shape or pointers
var n; // Any integer index value
// Reject and/or report not a polyline entity/shape or that the index is out of range:
if (!isPolylineEntity || !isPolylineShape(pl) || !isNumber(n) || Math.floor(n) < 0 || Math.floor(n) > pl.countVertices()) {
var segmentMid = RVector.invalid;
}
else {
n = Math.floor(n);
var m = (n + 1) % pl.countVertices();
var bulge = pl.getBulgeAt(n);
var chordMid = RVector.getAverage(pl.getVertexAt(n), pl.getVertexAt(m);
// Use the average of endpoints for a straight line segment:
if (bulge === 0.0) {
var segmentMid = chordMid;
}
// Reject and/or report null-length segments ...
// Or use the average of endpoints when they (almost) coincides:
else if (pl.getVertexAt(n).equalsFuzzy(pl.getVertexAt(m)) { // Within RS.PointTolerance
var segmentMid = chordMid;
}
// Construct the middle point of the bulging segment:
else {
var v = pl.getVertexAt(n).getVectorTo(pl.getVertexAt(m));
var sagitta = bulge * v.getMagnitude2D() / 2; // Signed
v.set(v.y, -v.x); // Rotate 90° CW
v.setMagnitude2D(sagitta);
var segmentMid = chordMid.operator_add(v);
}
}
But in Floating Point tan(PI/2) returns a ridiculous large value not necessarily +/-infinite.
Since some time QCAD handles these as two distinct semi circular segments to avoid the mathematical error.
I have to add that not all QCAD resources agree on how to determine edge cases and on how they are handled.
> For almost circular segments poly.getSegmentAt(index) will return a very short line segment:
https://github.com/qcad/qcad/blob/maste ... 1216-L1219
> RArc.getLength() for example does not allow for (almost) zero sweep and reverts to 2PI.
https://github.com/qcad/qcad/blob/maste ... c.cpp#L360
And RArc.getAngleLength(false): https://github.com/qcad/qcad/blob/maste ... #L434-L439
> RPolyline.isStraight(bulge) defines (where used) an absolute bulge less than 1e-6 or a sweep less than 2.292e-4 degrees as straight:
https://github.com/qcad/qcad/blob/maste ... 1126-L1131
...
..
.
Regards,
CVH