Automatically add dimension labels to drawing with a script

Is there a way to create dimension labels with a script? For example, in the command line, the following input will create a dimension label:

dimaligned
0,0
100,0
100

Is there an easy way to do this within a script, short of including and pulling apart the Dimension scripts?

One method is to duplicate the functionality of the dim scripts.
Analog to this story:

The major part of the dim scripts is data collection.
That data you have at hand.
The last value might be an issue, the side is relative to the actual pointer position.
With DimAligned.js as example:
The data is collected in ‘this.data’ as a new RDimAlignedData.
The last case of DimAligned.prototype.pickCoordinate creates the operation and finally cast it.

The other method would be to preset all the data and parse it to the dim script.
Analog to this story:

Regards,
CVH

I decided to take the second route you suggested, with mixed success. I have fully working functions for horizontal and aligned dims, however I’m still having trouble creating functions for vertical and angular dims. I will post what success I have had so far.

My horizontal dim function, which works correctly; it receives the co-ordinates as lists and convert them to RVectors internally (I had to tweak the getOperation function because it tries to read the toolbar value for Scale, which causes an error if it isn’t present):

function drawHorizontalDim(extensionPoint1, extensionPoint2, definitionPoint)
{
        include("scripts/Draw/Dimension/DimRotated/DimRotated.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimRotated();

        // Amend getOperation for absence of scale value in toolbar
        a.getOperation = function(preview) {
        if (!this.data.isValid()) {
            return undefined;
        }

        var doc = this.getDocument();
        var scale = 1;
        var scaled_data = this.data;

        scaled_data.setLinearFactor(1/scale);

        var entity = new RDimRotatedEntity(doc, scaled_data);
        if (!isEntity(entity)) {
            return undefined;
        }

        return new RAddObjectOperation(entity, this.getToolTitle());
        };

        a.setDocumentInterface(di);

        a.data.setExtensionPoint1(new RVector(extensionPoint1));
        a.data.setExtensionPoint2(new RVector(extensionPoint2));
        a.data.setDefinitionPoint(new RVector(definitionPoint));
        // Locks the rotation of the measurement at 0
        a.data.setRotation(0.0);

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}

My aligned dim function, which works correctly in much the same way:

function drawAlignedDim(extensionPoint1, extensionPoint2, definitionPoint)
{
        include("scripts/Draw/Dimension/DimAligned/DimAligned.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimAligned();

        // Amend getOperation for absence of scale value in toolbar
        a.getOperation = function(preview) {
        if (!this.data.isValid()) {
            return undefined;
        }

        var doc = this.getDocument();
        var scale = 1;
        var scaled_data = this.data;

        scaled_data.setLinearFactor(1/scale);

        var entity = new RDimAlignedEntity(doc, scaled_data);
        if (!isEntity(entity)) {
            return undefined;
        }

        return new RAddObjectOperation(entity, this.getToolTitle());
        };

        a.setDocumentInterface(di);

        a.data.setExtensionPoint1(new RVector(extensionPoint1));
        a.data.setExtensionPoint2(new RVector(extensionPoint2));
        a.data.setDefinitionPoint(new RVector(definitionPoint));

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}

My vertical dim function; this almost works but the definitionPoint isn’t used correctly. Unlike the horizontal dim function, which aligns the label to the absolute y value of definitionPoint, regardless of the x value, the vertical one seems to be stuck either exactly between extensionPoint 1 and 2, or aligned with extensionPoint1, and nothing else (I have tried multiple x and y values and these are the only results I can achieve):

function drawVerticalDim(extensionPoint1, extensionPoint2, definitionPoint)
{
        include("scripts/Draw/Dimension/DimRotated/DimRotated.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimRotated();

        // Amend getOperation for absence of scale value in toolbar
        a.getOperation = function(preview) {
        if (!this.data.isValid()) {
            return undefined;
        }

        var doc = this.getDocument();
        var scale = 1;
        var scaled_data = this.data;

        scaled_data.setLinearFactor(1/scale);

        var entity = new RDimRotatedEntity(doc, scaled_data);
        if (!isEntity(entity)) {
            return undefined;
        }

        return new RAddObjectOperation(entity, this.getToolTitle());
        };

        a.setDocumentInterface(di);

        a.data.setExtensionPoint1(new RVector(extensionPoint1));
        a.data.setExtensionPoint2(new RVector(extensionPoint2));
        a.data.setDefinitionPoint(new RVector(definitionPoint));
        a.data.setRotation(Math.PI / 2);

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}

And finally, my angular dim function; this doesn’t work at all yet.

function drawAngularDim(firstEntity, secondEntity, dimArcPosition)
{
        include("scripts/Draw/Dimension/DimAngular/DimAngular.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimAngular();

        a.setDocumentInterface(di);

        a.firstEntity = firstEntity;
        a.secondEntity = secondEntity;
        a.dimArcPosition = dimArcPosition;

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}

You will have to dig somewhat further:

At first glance, way too little parsed.
Where are those 1ste and 2nd entity defined?

In the switch from DimAngular.prototype.pickEntity one can see that Qcad looks
for the ClosestSimpleShape near the position.
So Qcad is still picking entities…

The data that is really needed is collected in:
this.data3P for a new RDimAngular3PEntity
or in this.data2L for a new RDimAngular2LEntity.

It is correct that DimHorizontal & DimVertical are both DimRotated.
The diff is set in DimHorizontal.js and DimVertical.js:
this.data.setRotation = 0 or pi/2.

Regards,
CVH

BTW,
I would be very interested in your scripts.
In a way you are making a simple API for dimensions.

I have a crude script in the pipeline that reproducible documents entities to csv.
I am doing a lot of math on entities props so it is handy to have the numbers in full.

My goal is to code the round trip too.
From reproducible data back to entities.
And why not for dimensions too.

Regards,
CVH

I set this.data.setRotation in my functions and thought that would be enough but evidently not. I have just rewritten them to use the DimHorizontal.js and DimVertical.js, rather than both of them using DimRotated.js and they both work now, so I must have missed something before.

function drawHorizontalDim(extensionPoint1, extensionPoint2, definitionPoint)
{
        include("scripts/Draw/Dimension/DimHorizontal/DimHorizontal.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimHorizontal();

        // Amend getOperation for absence of scale value in toolbar
        a.getOperation = function(preview) {
        if (!this.data.isValid()) {
            return undefined;
        }

        var doc = this.getDocument();
        var scale = 1;
        var scaled_data = this.data;

        scaled_data.setLinearFactor(1/scale);

        var entity = new RDimRotatedEntity(doc, scaled_data);
        if (!isEntity(entity)) {
            return undefined;
        }

        return new RAddObjectOperation(entity, this.getToolTitle());
        };

        a.setDocumentInterface(di);

        a.data.setExtensionPoint1(new RVector(extensionPoint1));
        a.data.setExtensionPoint2(new RVector(extensionPoint2));
        a.data.setDefinitionPoint(new RVector(definitionPoint));
        //a.data.setRotation(0.0);

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}



function drawVerticalDim(extensionPoint1, extensionPoint2, definitionPoint)
{
        include("scripts/Draw/Dimension/DimVertical/DimVertical.js");
        var di = getDocumentInterface();
        var doc = this.getDocument();
        // create and initialize tool:
        var a = new DimVertical();

        // Amend getOperation for absence of scale value in toolbar
        a.getOperation = function(preview) {
        if (!this.data.isValid()) {
            return undefined;
        }

        var doc = this.getDocument();
        var scale = 1;
        var scaled_data = this.data;

        scaled_data.setLinearFactor(1/scale);

        var entity = new RDimRotatedEntity(doc, scaled_data);
        if (!isEntity(entity)) {
            return undefined;
        }

        return new RAddObjectOperation(entity, this.getToolTitle());
        };

        a.setDocumentInterface(di);

        a.data.setExtensionPoint1(new RVector(extensionPoint1));
        a.data.setExtensionPoint2(new RVector(extensionPoint2));
        a.data.setDefinitionPoint(new RVector(definitionPoint));

        // run operation on current document:
        var op = a.getOperation(false);
        di.applyOperation(op);
}
//! [drawVerticalDim]



I have been creating RLines, RLineData and RLineEntitys and passing them to the function as arguments, hoping that I could do the choosing for it, but so far it hasn’t worked.

Thanks for your help by the way, I hope these functions are of some use to you. If you want to see how I am using them, here’s my github repo.

Glad we are getting somewhere…

That is the essence of my reply.

The approach as with interfacing with a user that points in a drawing:

  • a.firstEntity = firstEntity;
    a.secondEntity = secondEntity;
    a.dimArcPosition = dimArcPosition;

Requires that those entities exist in the drawing.
It is not enough that you define the RLine, REntity or RShape.
You still have to cast them and re-query them if needed.

Besides it can handle inner an outer angle,
DimAngular.js has two outcomes:
a new RDimAngular3PEntity
or a new RDimAngular2LEntity.
I think that you have to concentrate on that.
One route through DimAngular.prototype.getOperation at a time.
And then execute the op.

Regards,
CVH