[SOLVED] Get coordinate on the arc

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
arun
Active Member
Posts: 34
Joined: Tue May 09, 2023 9:04 am

[SOLVED] Get coordinate on the arc

Post by arun » Sat Jan 13, 2024 1:56 am

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
Attachments
Untitled.png
Untitled.png (143.81 KiB) Viewed 1304 times
Last edited by arun on Mon Feb 05, 2024 2:29 am, edited 1 time in total.

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

Re: Get coordinate on the arc

Post by CVH » Sat Jan 13, 2024 4:45 am

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

arun
Active Member
Posts: 34
Joined: Tue May 09, 2023 9:04 am

Re: Get coordinate on the arc

Post by arun » Sat Jan 13, 2024 7:38 am

Thanks CVH, much appreciated for the detailed explanation. This works well
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'm also keen to understand this relationship between bulge and middlePoint.
I do get the following as the output

Code: Select all

pl.getSegmentAt(1).getMiddlePoint()
"RVector(-57.656854, 182.656854, 0.000000, 1)"
and

Code: Select all

pl.getSegmentAt(1).getBulge()
0.41421356237309503
Could you also share on how can I derive the MiddlePoint from Bulge factor

Thanks again,
Arun

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

Re: Get coordinate on the arc

Post by CVH » Sun Jan 14, 2024 10:27 am

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.
arun wrote:
Sat Jan 13, 2024 7:38 am
I'm also keen to understand this relationship between bulge and middlePoint.
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);
    }
}
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

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”