Script to change object size by layer name

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
slamdunk
Newbie Member
Posts: 3
Joined: Mon Apr 21, 2025 3:04 am

Script to change object size by layer name

Post by slamdunk » Mon Apr 21, 2025 3:14 am

Can somebody please help me with a command line script to change object size by layer ?

Layer - STEP_RISER_GROOVE change size 2 from 16.00 to 18.00 ?

Sample dxf is attached

QCAD pro 3.32
Step01_1.dxf
Sample dxf
(5.52 KiB) Downloaded 558 times
Thank you.

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

Re: Script to change object size by layer name

Post by CVH » Mon Apr 21, 2025 6:54 am

Hi, and welcome to the QCAD forum.

Using QCAD Pro in GUI mode that is made easy.
Select the magenta Polyline and change its size 2 property to 18 in the Property Editor.

The focal point is the center of the 'rectangle', meaning that it grows 1 unit up and 1 unit down in this case.
If that is not the intention, you must specify and account for in which direction the 'rectangle' should grow.


An OS command line script to do this action on data in a DXF is less easy.
The Polyline does indeed represent a rectangular shape but seen from DXF perceptive it is nothing more than line-art with a closed nature.
There is nothing like a named object type for Simple quadrilaterals, nor for complex or any other shape than Circles or Ellipses.
At best it can be called a 'Polygon'.

A Polyline is representing a rectangular shape when:
- There are 4 line segments. => All bulge factors are zero.
- Every 2 consecutive segments form a 90 degree angle.
- It is logically closed and has 4 distinct vertices.
OR
- It is not logically closed, has 4 distinct vertices and a fifth that coincides with the first what makes it geometrically closed.

size 1 is always the largest reported size of the two.
It is the base angle that adapts.

Note that the QCAD GUI even allows for a 'rectangle' with rounded corners what has at least 8 vertices and 4 bulging segments.
And that may rather resemble a circle with for example: size 1 = size 2 = 20 and Radius = 10.
Then the Base Angle is always reported as zero or 90° even when rotated otherwise. :roll: (A zero-length line has no well defined orientation)

Further, these are undocumented Pro features.
The RPolylineData Class Reference doesn't list:
  • RPolylineData.getBaseAngle()
    RPolylineData.getWidth()
    RPolylineData.getHeight()
    RPolylineData.setWidth(value)
    RPolylineData.setHeight(value)
Unsure but these functions will probably work when polylineProxy is availible.
Not knowing when it is considered a 'rectangle' and how to test for it. :|
Perhaps the getters simply return 'undefined' when not a 'rectangle'.


The basics for writing an OS Command Line script can be found is this tutorial.
Line 66-69 is the simplistic action of this example and must be replaced by dedicated code.
That should look if a given Layer exists, query the entities of that Layer, filter on Polylines, filter on rectangles 16 high and adapt their height.
Importing (Off-screen) and exporting the file back is handled.


Regards,
CVH
Last edited by CVH on Mon Apr 21, 2025 9:22 am, edited 2 times in total.

slamdunk
Newbie Member
Posts: 3
Joined: Mon Apr 21, 2025 3:04 am

Re: Script to change object size by layer name

Post by slamdunk » Mon Apr 21, 2025 9:09 am

QCAD Pro in GUI is easy but I've tens of dxf files. I'm a novice, couldn't make this work with your suggestions. Have you tested?

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

Re: Script to change object size by layer name

Post by CVH » Mon Apr 21, 2025 12:01 pm

slamdunk wrote:
Mon Apr 21, 2025 9:09 am
couldn't make this work with your suggestions. Have you tested?
In the mean time I have tested it with success.
Adapting 'tens of dxf files' manually with the GUI would take as long. :lol:

Copied ExTool.js and stored it as a new script file under ... QCAD/scripts/Tools/ExTool/PolyGrowTool.js
Where the 3 dots stand for your QCAD installation folder, QCAD or QCAD/CAM or any custom path that you used.

Replaced line 66-69 with the code below:

Code: Select all

    // Ensure that the RPolyline proxy is present:
    if (!RPolyline.hasProxy()) {
        di.destroy();
        print("This Command Line tool requires Pro resources");
        return;
    }

    // Check if the user layer exist in the document, ifso get ID:
    if (!doc.hasLayer(userLayer)) {
        di.destroy();
        print("Layer not found");
        return;
    }
    else {
        var layerId = doc.getLayerId(userLayer);
    }

    // Query all polyline entities from the document, report result:
    var ids = doc.queryAllEntities(false, false, RS.EntityPolyline);
    print("Polyline entities found: " + ids.length.toString());

    // Filter on entity layer:
    var polyIds = [];
    var e;
    for (var i=0; i<ids.length; i++) {
        e = doc.queryEntityDirect(ids[i]);
        if (e.getLayerId() == layerId) {
            polyIds.push(ids[i]);
        }
    }

    // Terminate on no polyline entities or report number:
    if (polyIds.length < 1) {
        di.destroy();
        print("No polylines found");
        return;
    }
    else {
        print("Polyline entities on user layer: " + polyIds.length.toString());
    }

    // Adapt polyline entities when considered as rectangle with a size 16:
    var eData, eAngle, eWidth, eHeight;
    var adapted = [];
    var toDelete = [];
    for (var i=0; i<polyIds.length; i++) {
        e = doc.queryEntity(polyIds[i]);
        eData = e.getData();
        eAngle = eData.getBaseAngle();
        eWidth = eData.getWidth();
        eHeight = eData.getHeight();
        print("BaseAngle: " + eAngle.toString());
        print("Width: " + eWidth.toString());
        print("Height: " + eHeight.toString());

        // Skip other than 'rectangles':
        if (isNaN(eAngle)) {
            continue;
        }

        if (RMath.fuzzyCompare(eHeight, 16.0)) {
            eData.setHeight(18.0);
            adapted.push(eData);
            toDelete.push(e);
        }
        else if (RMath.fuzzyCompare(eWidth, 16.0)) {
            eData.setWidth(18.0);
            adapted.push(eData);
            toDelete.push(e);
        }
    }

    // Terminate on nothing to adapt:
    if (adapted.length < 1) {
        di.destroy();
        print("No polylines adapted");
        return;
    }
    else {
        print("Entities adapted: " + adapted.length.toString());
    }

    // Update entities in the document:
    var op = new RModifyObjectsOperation();
    var newPoly;
    for (var i=0; i<adapted.length; i++) {
        newPoly = new RPolylineEntity(doc, adapted[i]);
        op.addObject(newPoly, false);
        op.deleteObject(toDelete[i]);
    }

    di.applyOperation(op);
The user layer, source value and target value are hard-coded.
Quick and dirty but it does the trick.

As test I added an arbitrary polyline to your document.
It seems that NaN is returned when the polyline is not really a 'rectangle' :wink: :

Code: Select all

Polyline entities found: 6
Polyline entities on user layer: 2
BaseAngle: NaN
Width: 0
Height: 0
BaseAngle: 0
Width: 985.0000000000001
Height: 16
Entities adapted: 1
This can now be called with for example:

Code: Select all

qcadcmd.com -no-gui -autostart scripts/Tools/ExTool/PolyGrowTool.js -f -o Step01_1rev.dxf Step01_1.dxf
For handling multiple files use a batch file that calls QCAD with this script for each.
You can look that up on the forum or online for your OS. :wink:

Regards,
CVH

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

Re: Script to change object size by layer name

Post by CVH » Tue Apr 22, 2025 7:17 am

I opted to query all entities of the RS.EntityPolyline type in the document and filter them by layer.

Another route would be to query all the entities on the intended layer and filter them by type.

Code: Select all

    // Query all entities on the user layer, report result:
    var ids = doc.queryLayerEntities(layerId, false);
    print("Entities found on user layer: " + ids.length.toString());

    // Filter on entity type:
    var polyIds = [];
    var e;
    for (var i=0; i<ids.length; i++) {
        var e = doc.queryEntityDirect(ids[i]);
        if (isPolylineEntity(e)) {
            polyIds.push(ids[i]);
        }
    }

    // Terminate on no polyline entities or report number:
    if (polyIds.length < 1) {
        di.destroy();
        print("No polylines found on user layer");
        return;
    }
    else {
        print("Polyline entities on user layer: " + polyIds.length.toString());
    }

At the top of ExTool the Simple API is included to draw a line with the example script.
This functionality is no longer required and that line of code may be removed or ruled out:

Code: Select all

//include("scripts/simple.js"); // No longer required  
Regards,
CVH

slamdunk
Newbie Member
Posts: 3
Joined: Mon Apr 21, 2025 3:04 am

Re: Script to change object size by layer name

Post by slamdunk » Sun Apr 27, 2025 1:04 am

Thanks a ton. I don't have Tools folder. Searched everywhere inside QCAD. Could you please share arguments.js file?

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

Re: Script to change object size by layer name

Post by CVH » Sun Apr 27, 2025 2:18 am

Hi,

In a standard installation most tool scripts are only present in compiled form.
Chances are that you don't have the folders below physically present:
... QCAD/scripts/Tools/
... QCAD/scripts/Tools/ExTool/


The same would be true for the folders of standard tools under:
... QCAD/scripts/Block/
... QCAD/scripts/Draw/
... QCAD/scripts/Edit/

and so on.

You can simply add the required folders manually.
In this way we can override standard included tool scripts in compiled form.
A custom adapted ArcTangential.js would replace the standard script in compiled form when stored under:
.../scripts/Draw/Arc/ArcTangential/ and this folder structure also doesn't readily exist.
See related forum topic

BUT:
Because it is a Command Line script that doesn't have to be fitted in a folder structure mimicking a GUI menu structure you can save it anywhere.
PolyGrowTool.js can also be placed directly under ... QCAD/scripts/ or outside the QCAD installation folder.
As long as you also adapt that in the -autostart switch.


The file arguments.js is required by several Command Line tools and also present in compiled form.
Then it is important that the include is an absolute path starting with scripts.
include("scripts/Tools/arguments.js"); and not a relative path like include("../arguments.js");
What is already the case in the copied example.

The file can also be found on Github.

Regards,
CVH

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”