Using offset in 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.

Post Reply
RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Using offset in a script

Post by RR88 » Sun Apr 29, 2018 7:25 am

Hello.

I want to create a new entity from the offset of an existing entity in my drawing. How can I do this in a script? More precisely, how can I specify the distance and the side where the offsetted shape should be? It should work without a user interactivity respectively a mouse event.

Regards.
Arch Linux, QCad 3.22.0 Prof.

RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Re: Using offset in a script

Post by RR88 » Sun Apr 29, 2018 3:01 pm

I tried this code:

Code: Select all

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

var itms = doc.queryAllEntities();
var itm = doc.queryEntity(itms[0]);

var s = itm.getPolylineShape();

var offs = s.getOffsetShapes(.5, 1, RS.LeftHand);
Am I right, that getOffsetShapes returns nothing because I'm using the trial version? https://github.com/qcad/qcad/blob/fe6ef ... .cpp#L1897 seems to be empty.
Arch Linux, QCad 3.22.0 Prof.

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Using offset in a script

Post by andrew » Mon Apr 30, 2018 9:01 am

getOffsetShapes is only implemented for simple shapes like lines, arcs, circles and ellipses.

Offsetting polylines requires more information (join type) and can take multiple polylines as input.

If QCAD Professional (or indeed a QCAD Professional trial version) is running, you can offset polylines from a script as follows:

Code: Select all

// distance: Distance of the offset
// number: Number of offsets to create
// pos Position indicating side of offset (see also setForceInside, setForceSide)
// joinType Join type for sharp corners (RS.JoinRound, RS.JoinMiter)
// preview True for preview mode (fast but not complete)
var worker = new RPolygonOffset(distance, number, pos, joinType, preview);
// optionally: force side and ignore pos:
worker.setForceSide(RS.LeftHand);

// add input polylines:
worker.addPolyline(polyline1);
worker.addPolyline(polyline2);
worker.addPolyline(polyline3);
...

var resultingPolylines = worker.getOffsetShapes();
Note: This is currently not part of the public QCAD API.

RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Re: Using offset in a script

Post by RR88 » Mon Apr 30, 2018 6:08 pm

Thanks for your answer.
andrew wrote: Note: This is currently not part of the public QCAD API.
... but it should be.

Here is my working script https://github.com/zippy84/lc-qcad/blob ... offsets.js, for those who are interested in.
Arch Linux, QCad 3.22.0 Prof.

RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Re: Using offset in a script

Post by RR88 » Sun May 06, 2018 5:12 pm

I found a special case where RPolygonOffset does not work proper. My drawing is attached and my script is:

Code: Select all

var doc = getDocument();
var di = getDocumentInterface();
var entities = doc.queryAllEntities();
var ent = doc.queryEntity(entities[0]);
var blkId = ent.getReferencedBlockId();
var itms = doc.queryBlockEntities(blkId);
di.setCurrentBlock(blkId);
var itm = doc.queryEntity(100);

var newShapes = [];

for (var k = 0; k < itm.countSegments(); k++) {
    var seg = itm.getSegmentAt(k);
    if (isLineShape(seg)) {
        if (seg.getLength() < 1e-5) {
            continue;
        }
    }

    newShapes.push(seg.clone());
}

itm.setShape(new RPolyline(newShapes));

var op = new RModifyObjectsOperation();
itm.reverse();
op.addObject(itm, false);
di.applyOperation(op);

var worker = new RPolygonOffset(.15/2, 1, RVector.invalid, RS.JoinMiter, false);
worker.setForceSide(RS.RightHand);
worker.addPolyline(itm.castToShape());

var offs = worker.getOffsetShapes();
Itm is defined as:

Code: Select all

RLine(RShape(address: "0x104f9fc0"), startPoint: RVector(7.46514, -3.58589, 0, true), endPoint: RVector(7.46514, -16.9197, 0, true))
RLine(RShape(address: "0x4fee5460"), startPoint: RVector(7.46514, -16.9197, 0, true), endPoint: RVector(15.0485, -16.9197, 0, true))
RLine(RShape(address: "0x8651390"), startPoint: RVector(15.0485, -16.9197, 0, true), endPoint: RVector(15.0485, -3.58647, 0, true))
RArc(RShape(address: "0x75c84000"), center: RVector(11.256, -14.0402, 0, true), radius: 11.1204, startAngle: 70.0601, endAngle: 109.931, startPoint: RVector(15.0485, -3.58647, 0, true), endPoint: RVector(7.46514, -3.58589, 0, true), sweep: 0.695883, reversed: false)
RLine(RShape(address: "0x162a2f30"), startPoint: RVector(7.46514, -3.58589, 0, true), endPoint: RVector(7.46514, -3.58589, 0, true))
It is obviously not clean, because of the zero-length line at the end.

Why is offs empty and is there another way to remove the line?
Attachments
Err.dxf
(105.03 KiB) Downloaded 535 times
Arch Linux, QCad 3.22.0 Prof.

RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Re: Using offset in a script

Post by RR88 » Mon May 07, 2018 3:45 pm

Also this does not work:

Code: Select all

var doc = getDocument();
var di = getDocumentInterface();
var entities = doc.queryAllEntities();
var ent = doc.queryEntity(entities[0]);
var blkId = ent.getReferencedBlockId();
var itms = doc.queryBlockEntities(blkId);
di.setCurrentBlock(blkId);
var itm = doc.queryEntity(100);

var pl = new RPolyline();

for (var k = 0; k < itm.countSegments(); k++) {
    var seg = itm.getSegmentAt(k);
    if (isLineShape(seg)) {
        if (seg.getLength() < 1e-5) {
            continue;
        }
    }

    pl.appendShapeAuto(seg.clone());
}

pl.convertToClosed();
pl.reverse();

var worker = new RPolygonOffset(.15/2, 1, RVector.invalid, RS.JoinMiter, false);
worker.setForceSide(RS.RightHand);
worker.addPolyline(pl);

var offs = worker.getOffsetShapes();
Arch Linux, QCad 3.22.0 Prof.

RR88
Full Member
Posts: 51
Joined: Sun Apr 29, 2018 7:04 am
Location: Leinefelde

Re: Using offset in a script

Post by RR88 » Mon May 07, 2018 4:23 pm

This script works:

Code: Select all

var doc = getDocument();
var di = getDocumentInterface();
var entities = doc.queryAllEntities();
var ent = doc.queryEntity(entities[0]);
var blkId = ent.getReferencedBlockId();
var itms = doc.queryBlockEntities(blkId);
di.setCurrentBlock(blkId);
var itm = doc.queryEntity(100);

var pl = new RPolyline();

var a = [];

for (var k = 0; k < itm.countSegments(); k++) {
    var seg = itm.getSegmentAt(k);
    if (isLineShape(seg)) {
        if (seg.getLength() < 1e-5) {
            continue;
        }
    }

    a.push(seg.clone());
}

a.push(a.shift());

for (var i = 0; i < a.length; i++) {
    pl.appendShapeAuto(a[i]);
}

pl.convertToClosed();
pl.reverse();

var worker = new RPolygonOffset(.15/2, 1, RVector.invalid, RS.JoinMiter, false);
worker.setForceSide(RS.RightHand);
worker.addPolyline(pl);

var offs = worker.getOffsetShapes();

var op = new RAddObjectsOperation();
op.addObject(shapeToEntity(doc, offs[0].data()), false);
di.applyOperation(op);
Note that the arc-shape is not longer the last element in a. It looks like a bug.
Arch Linux, QCad 3.22.0 Prof.

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”