Selecting an object within a script

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.

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

Re: Selecting an object within a script

Post by CVH » Mon Jun 19, 2023 6:00 pm

CVH wrote:
Sat Jun 17, 2023 6:40 am
For some reason the polylines have 1 extra duplicated node at the end.
Shutterstock wrote:
Mon Jun 19, 2023 8:44 am
Where do you the a duplicated node? Can you give me what you are testing so I can reproduce?
Without the latest fix: When we select 10 points >> 9 segments the resulting polyline may have 11 vertices.
Stepping through such a polyline with the vertex index, we discover that the last vertex is identical to the previous one.
Probably just nearly, taken that the rounded X/Y values match even with 8 decimal digits.

The fixed DiscretizeArc.discretizeArc verifies the last segment length.
The comparison is made relative so this should work for every size of arc and any number of points.
When that segment is less than 1% of the intended length it is removed but the polyline is forced to end at the arc end ... :wink:

queryAllEntities() can be slow ... Read:
https://qcad.org/doc/qcad/3.0/developer ... 3c488b7f9d
Why not query all arcs: var entitiesIds = doc.queryAllEntities(false, false, RS.EntityArc);
The filtering is then done in C++?

Remind that if you put all arcs on a dedicated layer then:
- You don't have a reference to where they came from.
- The approximation by polylines is casted on that layer too.
Shutterstock wrote:
Mon Jun 19, 2023 8:44 am
CVH wrote:
Sat Jun 17, 2023 6:40 am
Still I think it is not a good idea to chop up an arc based on the number of segments ... A segment length would be more appropriate.
Each arc don't hold the same importance, so simply discretizing all arcs by the same length is not optimal. And chosing a length instead of a number of points is less intuitive for the user
Then you might want to consider the maximum deviation between the arc and the segments.
The given tolerance would then dictate the largest length of the sagitta, and that relates to the largest arc-segment sweep.
Chopping the arc in segments with a adapted partial sweep that sums to the total sweep.

You now have a QCAD tool that acts on the selected arc ... Implementing more/all arcs is yet another way, another script.

Regards,
CVH

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Tue Jun 20, 2023 11:20 am

I'm kinda stuck on moving arcs to the new layer.
Currently, I have this:

Code: Select all

DiscretizeArc.prototype.beginEvent = function() {
    Modify.prototype.beginEvent.call(this);

    this.di = this.getDocumentInterface();
    this.doc = this.getDocument();

    this.currentLayer = this.doc.queryCurrentLayer();
    // Create layer to highlight arcs
    var linetypeId = this.doc.getLinetypeId("CONTINUOUS");
    this.arcLayer = new RLayer(this.doc, "Arcs", false, false, new RColor("red"), linetypeId, RLineweight.Weight035);
    // Store the arc layer
    var op = new RModifyObjectsOperation();
    op.addObject(this.arcLayer);
    this.di.applyOperation(op);
    // Grab all arc entities
    var arcEntitiesIds = this.doc.queryAllEntities(false, false, RS.EntityArc);
    for (var i = 0; i < arcEntitiesIds.length; i++) {
        var arcEntityId = arcEntitiesIds[i];
        var arcEntity = this.doc.queryEntity(arcEntityId);
        // Store arcs in the layer
        arcEntity.setLayerId(this.arcLayer.getId());
    //     op.addObject(arcEntity); <---- crash
	}
    // this.di.applyOperation(op); <---- crash
    this.setState(DiscretizeArc.State.ChoosingEntity);
};
It creates the layer as I want, but it doesn't move any object. And when I try to uncomment "op.addObject(arcEntity);" or "this.di.applyOperation(op);", it provokes the crash of QCAD.
I've used the syntax of https://qcad.org/rsforum/viewtopic.php? ... yer#p15519, and I don't find any other example of something like that to help me on that :/

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Tue Jun 20, 2023 1:23 pm

edit:
I've found how not to make it crash, the op was applied a bit above, and then I retried to use that op. I guess it make it crash.
So now I have this:

Code: Select all

DiscretizeArc.prototype.beginEvent = function() {
    Modify.prototype.beginEvent.call(this);

    this.di = this.getDocumentInterface();
    this.doc = this.getDocument();

    this.currentLayer = this.doc.queryCurrentLayer();
    // Create layer to highlight arcs
    var linetypeId = this.doc.getLinetypeId("CONTINUOUS");
    this.arcLayer = new RLayer(this.doc, "Arcs", false, false, new RColor("red"), linetypeId, RLineweight.Weight035);
    // Store the arc layer
    var op = new RModifyObjectsOperation();
    op.addObject(this.arcLayer);
    // Grab all arc entities
    var arcEntitiesIds = this.doc.queryAllEntities(false, false, RS.EntityArc);
    for (var i = 0; i < arcEntitiesIds.length; i++) {
        var arcEntityId = arcEntitiesIds[i];
        var arcEntity = this.doc.queryEntity(arcEntityId);
        // Store arcs in the layer
        arcEntity.setLayerId(this.arcLayer.getId());
        op.addObject(arcEntity);
	}
    this.di.applyOperation(op);

    this.setState(DiscretizeArc.State.ChoosingEntity);
};
So it doesn't crash, but the arcs are not still note moved at all :/

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Tue Jun 20, 2023 2:20 pm

Oh I'm dumb, I needed that apply. I instead had to create a new op after :roll:

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Mon Jun 26, 2023 9:38 am

CVH wrote:
Mon Jun 19, 2023 6:00 pm
Then you might want to consider the maximum deviation between the arc and the segments.
The given tolerance would then dictate the largest length of the sagitta, and that relates to the largest arc-segment sweep.
Chopping the arc in segments with a adapted partial sweep that sums to the total sweep.
Are you talking about these red sagittas?
Capture d’écran 2023-06-26 103559.jpg
Capture d’écran 2023-06-26 103559.jpg (324.39 KiB) Viewed 79994 times

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

Re: Selecting an object within a script

Post by CVH » Mon Jun 26, 2023 8:55 pm

Shutterstock wrote:
Mon Jun 26, 2023 9:38 am
Are you talking about these red sagittas?
Yep, that is the sagitta of an arc.
The math is simple:
The ideal arc length given the maximum tolerance epsilon:
idealArcLength = 2 * acos(1.0 - (epsilon / radius))

But that may chop your arc up in N equal pieces plus the remaining as a shorter segment.

Chopping the arc in N (rounded up) equal pieces is then:
segmentCount = ceil(arcAngleLength / idealArcLength)

And there is a catch ... As always ... epsilon / radius can be more than 2.00
In that case the acos() will be invalid because it is less than -1.00.
'epsilon' and 'radius' are lengths and thus always positive, the acos() can not exceed 1.00

The next limit situation is segmentCount = 1 ... Short arc or small radii.
You might set a minimum segmentCount to at least mimic the curved nature.

BTW: Segments are your 'points' minus one. :wink:

Regards,
CVH
Last edited by CVH on Tue Jun 27, 2023 7:53 am, edited 1 time in total.

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

Re: Selecting an object within a script

Post by CVH » Mon Jun 26, 2023 9:15 pm

In arcEntity.setLayerId(this.arcLayer.getId()); you refer to this.arcLayer that you added to an operation.
That operation is not yet applied and the object id will still be invalid.
You must first apply the layer op and retrieve the layer back from the document to know its id ... :wink:

Why not use REntity.setLayerName(<name as string>); instead?
https://qcad.org/doc/qcad/3.0/developer ... c7a19c7039
Where REntity is your is your queried arcEntity.

Regards,
CVH

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Mon Jun 26, 2023 9:19 pm

CVH wrote:
Mon Jun 26, 2023 9:15 pm
In arcEntity.setLayerId(this.arcLayer.getId()); you refer to this.arcLayer that you added to an operation.
That operation is not yet applied and the object id will still be invalid.
You must first apply the layer op and retrieve the layer back from the document to know its id ... :wink:
Yeah, that's why I said:
Shutterstock wrote:
Tue Jun 20, 2023 2:20 pm
Oh I'm dumb, I needed that apply. I instead had to create a new op after :roll:
Also, I've found how to change the color of an object without using layer params, so I've used that instead, it's better and doesn't crash by nature lol

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Mon Jun 26, 2023 9:20 pm

CVH wrote:
Mon Jun 26, 2023 8:55 pm
Shutterstock wrote:
Mon Jun 26, 2023 9:38 am
Are you talking about these red sagittas?
Yep, that is the sagitta of an arc.
The math is simple:
The ideal arc length given the maximum tolerance epsilon:
idealArcLength = 2 * acos(1.0 - (epsilon / radius))

But that may chop your arc up in N equal pieces plus the remaining as a shorter segment.

Chopping the arc in N (rounded up) equal pieces is then:
segmentCount = ceil(arcAngleLength / idealArcLength)

And there is a catch ... As always ... epsilon / radius can be more then 2.00
In that case the acos() will be invalid because it is less than -1.00.
'epsilon' and 'radius' are lengths and thus always positive, the acos() can not exceed 1.00

The next limit situation is segmentCount = 1 ... Short arc or small radii.
You might set a minimum segmentCount to at least mimic the curved nature.

BTW: Segments are your 'points' minus one. :wink:

Regards,
CVH
I will still take a look, but people that will use my script told me the N number was totally enoughly good for what they are doing

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

Re: Selecting an object within a script

Post by CVH » Mon Jun 26, 2023 9:28 pm

Shutterstock wrote:
Mon Jun 26, 2023 9:20 pm
but people that will use my script told me
That is by preference, I look at the wider picture :wink: :
CVH wrote:
Fri Jun 23, 2023 7:21 am
By number of segments or by tolerance (length of the sagitta), the selection or the indicated or all the remaining.
Next step is to include circles, ellipses, polylines and splines.
Regards,
CVH

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

Re: Selecting an object within a script

Post by CVH » Mon Jun 26, 2023 9:41 pm

Shutterstock wrote:
Mon Jun 26, 2023 9:20 pm
N number was totally enoughly good for what they are doing
Consider 10 points ... 9 segments ... DiscretizeArc ... ALL >>>
- A 45 degree arc in nine 5 degree segments.
- A 4.5 degree arc in nine 1/2 degree segments.
- An arc with radius 1000 in 9 very coarse segments.
:wink:

Regards,
CVH

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Mon Jun 26, 2023 10:03 pm

CVH wrote:
Mon Jun 26, 2023 9:41 pm
Shutterstock wrote:
Mon Jun 26, 2023 9:20 pm
N number was totally enoughly good for what they are doing
Consider 10 points ... 9 segments ... DiscretizeArc ... ALL >>>
- A 45 degree arc in nine 5 degree segments.
- A 4.5 degree arc in nine 1/2 degree segments.
- An arc with radius 1000 in 9 very coarse segments.
:wink:

Regards,
CVH
aaah yes

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

Re: Selecting an object within a script

Post by CVH » Tue Jun 27, 2023 7:07 am

Shutterstock wrote:
Mon Jun 26, 2023 10:03 pm
aaah yes
The arc with radius 1000 units chopped in 9 may be a good representation when it is short.
But when it is let's say 180 degrees then the line segments are about 347.3 units long and the deviation with the original arc or discretization tolerance is about 15.2 units.

It is all about preferences. :wink:

Regards,
CVH

Shutterstock
Active Member
Posts: 29
Joined: Wed Jun 14, 2023 4:02 pm

Re: Selecting an object within a script

Post by Shutterstock » Tue Jun 27, 2023 7:59 am

I've asked the users and they told me in practice they don't have much arcs and can handle some extra clicks when arcs are really different.

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”