How to get coordinates according to step value

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: How to get coordinates according to step value

Post by CVH » Mon Dec 18, 2023 3:59 pm

WildWolfCJ wrote:
Mon Dec 18, 2023 10:39 am
Has the script for this function been completed?
Define what function ... Last mentioned were issues with ellipses.

SEM dots of larger art will produce a vast number of positions AKA RVectors.
Of multiple pieces of line-art there might be overlapping areas.
Without filtering you get SEM dots that are 'engraved' twice.
What is of no real issue with a mill or a drill, filled with ink on paper, filled on screen, but it is a major issue in your case.

Filtering on duplicate RVectors requires to collect them all and verify the RVectors one on one.
What can be a time consuming process.
On top, there is an end to how many entries that can be collected in an array.

Overlapping loops will not be hatched (yes XOR yes = no).
The solution is thus to merge loops of overlapping art and handle that as a group.
Where to cut loops depend on self intersections and mutual loop-loop intersections.
Every loop or every intermediate loop when merging should end up without intersections with itself or something else.

As long as offsets of curved art returns spooky intersections they can't be reliably merged to a closed contour.

Even disregarding the hatching route, falling back on an X-Y scan process requires well defined contours.

Meanwhile I also looked at the bitmap route, QCAD does the raster scanning out of the box.
The bitmap limit X*Y = 2,147,483,647 would handle a square with a side of 18.53638m in a 0.4mm raster.
I don't think that your SEM area is in the range of 324 squared meters :roll: or 81m² with a 0.2mm raster. :wink:
It is you that ruled out this route.
Closed and even merged outer contours of line-art regarding a circular offset have an other interest for me.

And yes, the latest tests with all sorts of ellipses where promising.
Handling little ellipse arcs are more troublesome than offsets of small arcs, especially where butt-ends overlap.
Remember that I am not paid for this.

Regards,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Tue Dec 19, 2023 2:12 am

HI CVH
Thank you for your patient reply
Define what function ... Last mentioned were issues with ellipses.
This script is to obtain the rasterized coordinates of a polyline with line width. You can ignore other entities for the time being. The requirements for this script are as follows
1 Read a DXF file and scan all polylines in it
2 Get the outline for a polyline with line width (the outline should also be a polyline)
3 Generate coordinate files based on contours
Of multiple pieces of line-art there might be overlapping areas.
We will ensure that there are no duplicate areas in the design DXF
Remember that I am not paid for this.
We can pay for script development

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Tue Dec 19, 2023 4:46 am

hi cvh
Exploded the TTF text to outer contours and replaced the line-art with contours.
I'm reading Nifty's plan over and over again, and I have a question
1 How to generate the outline of line art?
Attachments
VeryCapture_20231219114623.jpg
VeryCapture_20231219114623.jpg (98.6 KiB) Viewed 73382 times

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

Re: How to get coordinates according to step value

Post by CVH » Tue Dec 19, 2023 5:33 pm

WildWolfCJ,

The pen related outlines of ellipses where a side route.
Getting proper and clean offsets as polylines was problematic.

The approximation with a polyline are not tangentially connected arcs. (REllipse.approximateWithArcs(..))
OQ ... RPolygonOffset(..) of such a polyline is fairly impossible to clean up, clipped or not.
OQ of an ellipse (arc) returns fitPoint splines. (REllipse.getOffsetShapes(..))
These splines are not symmetric, while an ellipse is, and open ended fitpoints splines end 'normal'.
The 2-3 last sections at an ending are not quasi parallel with the ellipse arc.
Inner offsets of an ellipse may self-intersect when the ellipse is too narrow ...
... and/or include inversion points where the offset is larger than the radius of the local curvature
... and/or is as a whole not valid when the ellipse is far too narrow.
Additional butt-endings are not supported right out the box and these may intersect themselves or with the offset art.

I think that I covered all the above issues, see a snippet of my trial document.
Remember here that all the results are generated from a selection in one single click.
WildWolfCJ_Weights.Ellipse.dxf
(295.68 KiB) Downloaded 121 times
The resulting line-art in magenta is merely the representation of the pen related contours.
A visualization says so much more than a collection of core RPolyline's each with a long list of RVector's, bulge factors and so on ... :lol:
WildWolfCJ wrote:
Tue Dec 19, 2023 2:12 am
We will ensure that there are no duplicate areas in the design DXF
You said earlier that it will be used as a Command Line script.
With no GUI present, no preview of the art in the drawing document there are two choices:
- Or it rejects everything it can not cope with ... Unintended entity types, overlaps for example, self-intersections, internal errors ....
The list is endless and you need a clever routine to exclude things, errors and so on.
- Or it can cope with all line-art (and more) that it encounters in the dxf file.
WildWolfCJ wrote:
Tue Dec 19, 2023 4:46 am
1 How to generate the outline of line art?
For that RPolygonOffset(..) is mostly used, similar as the QCAD Pro GUI OQ method.
RPolygonOffset(..) is the newer art replacing OffsetProWorker.
Discussed earlier and it should not be that hard to implement it for very trivial cases ... Have you even tried to?

- - - - - -

Now that without the use of RPolygonOffset(..) ellipse entities return clean, singular, parallel (as good as it gets), tangentially connected (as good as it gets) and perfectly closed offsets without triggering unexpected errors later on ...
Now I can move on with other polyline offsets.


Do not expect this to be as clean per example from the start, even in GUI mode I can trigger false offsets with OQ using a half pen sized offset.
e_surprised :(

In the attached file select all the results (All on layer 'Results', all magenta)
Create a new layer for a hatch entity. (Also current on creation)
Add a new hatch from selection (HA), pattern 'SEM_Dots', scale 0.4 ... OK
:!: Outlines need to be utterly perfect for it to work ... And they are :!:
Select the hatch, explode (XP) into point entities.
And there you have all points inside the selected outlines.
Simply a matter of exporting these point positions to a CSV.

Hatching or scanning and exporting are the two easiest part ... :lol:

Regards,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Wed Dec 20, 2023 2:55 am

HICVH
Thank you very much for your guidance, it has benefited me a lot.
The pen related outlines of ellipses where a side route.
Getting proper and clean offsets as polylines was problematic.
I will not consider the ellipse case for the time being, I only need to deal with polylines
Remember here that all the results are generated from a selection in one single click.
I don’t understand how the unclosed polyline in the attachment can be manually generated by magenta closed outline, please check the attachment,
For that RPolygonOffset(..) is mostly used, similar as the QCAD Pro GUI OQ method.
I haven't used the RPolygonOffset method yet, I will use this method next to get the polyline outline.
the QCAD Pro GUI OQ method. What does OQ mean? Is it an abbreviation for a method?

Thank you again for your help. Next I will summarize this information and write a script. I will update if I encounter any problems.
Attachments
VeryCapture_20231220094319.jpg
VeryCapture_20231220094319.jpg (373.6 KiB) Viewed 73312 times

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

Re: How to get coordinates according to step value

Post by CVH » Wed Dec 20, 2023 6:19 pm

WildWolfCJ wrote:
Wed Dec 20, 2023 2:55 am
I don’t understand how the unclosed polyline in the attachment can be manually generated by magenta closed outline, please check the attachment,
OK, wow, that explains a lot. :o
We both are thus at the two opposite extremes of the development spectrum. :wink:

OQ is the QCAD 2 key keyboard shortcut sequence for the tool under menu Draw .. Polyline .. Offset.
- In QCAD GUI mode open a file with an open ended polyline or start a new file and draw a new polyline.
- Create a new layer for the offset shape, LineWeight 0.00mm and a different color may be handy. (= Current on creation)
- Type the key O, release and then key Q or whatever keys that are on a non-Latin keyboard.
- In the Options Toolbar enter an offset value (Half the pen size) and opt for: Single offset, Offset Whole the Polyline, Round Joints.
Clipping or not is less important with trivial cases, the outcome may vary and you can activate/deactivate that in preview mode.
- Indicate near your line-art and an offset preview will be shown.
- If satisfactory then create it with clicking left once.
- Indicate near the other side of the same line-art and click left again.
- Terminate the offset tool with a right click. (Or with escape, or with the key-sequence QQ)
You now have an offset at both sides of the line-art.

For the round butt-endings we need another GUI tool: menu Draw .. Arc .. 2 Points and Angle (Keyboard shortcut = A2)
- In the Options Toolbar enter an angle value of 180 degrees.
Orientation depends on what point you will indicate first and you can alter that in preview mode after the first arc endpoint is given.
- Indicated two matching endpoints of the offset shapes, use a proper orientation so that the arc bulges outwards.
- Repeat this for the opposite endings.
- Terminate the arc tool with a right click.
You now have 4 independent drawing entities: 2 offset shapes and 2 arcs.

For merging these we need to select them all 4, if 'free-floating' you can also double-click left near one of the shapes.
Now activate the GUI tool under menu Draw .. Polyline .. Polyline from Selection(OC).
The selection is turned into a single polyline, see selection in the Property Editor. (Re-select if if it was not)
When selected this should report to be (logically) closed in the Property Editor.
Otherwise you need to verify what went wrong for it not to form a single and perfectly closed contour.
For that verify the position of the red and dark-blue end markers if selected, zoom in on them to have a closer look.

- - - - - -

For a script exploiting RPolygonOffset(..) there is no human to indicated sides ... To verify results ... To do whatever.
The inner or outer side of arbitrary line-art is an unknown fact and even methods to determinate that may return ambiguous answers.
We can fall back on forcing the side parameter (RS.LeftHand, RS.RightHand) and pos = RVector.invalid.

I opted for twice RS.LeftHand reversing a clone of the base shape in between, resulting in two (arrays of) RPolyline shapes.
Remind that these are low level mathematical representations, there is nothing for you to view in a document.

A 180 degree arc is nothing more than setting the last bulge factor of an open ended RPolyline shape to tan(180°/4)=1.0 and because the two shapes are pre-oriented I can simply append the second to the first.
If the single RPolyline is geometrically closed it is converted to a logical closed RPolyline and stored for later handling.

At this point I cast a copy to the drawing document in the GUI so that I can verify the outcome.
In fact, they are the magenta entities on layer 'Results'.

This all looks fairly straightforward ... But it isn't.
Using the GUI we humans can start over new if it didn't work out as expected.

What with none or more than one RPolyline from RPolygonOffset(..)?
Are they clean? Do they Include minute self-intersections, inversions of arcs and/or ... ?
What with minute differences at connection points between shapes. How good is 'almost' connected? How good can it be?
What if two endings are more than a pen apart for round butt-end?
How tolerant for small but unavoidable Floating Point errors, accumulated math flaws, loss of accuracy?
....
...
.
Every step of the process needs to be verified for what it produces and if that is valid or not. (Define what is valid :wink: )
Each type of base entity is handled in a similar but specialized fashion.
Lines, Arcs, open ended Polylines, geometrically closed Polylines, Ellipses and their arcs, ....
Some methods rely on another.
Remark that when the endpoints of a single open entity come close enough you end up with an inner and outer contour instead of single outline.
See almost fully closed ellipse arc examples.

Busy ...

Regards,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Mon Dec 25, 2023 3:08 am

hi cvh Thank you for your patient reply and wish you a Merry Christmas
According to your answer, I obtained the outline of the polyline in the GUI. Attached is a screenshot of my implementation steps. I will use JS to implement this function next. I will update it if I encounter any problems.
Attachments
VeryCapture_20231225100800.jpg
VeryCapture_20231225100800.jpg (616.2 KiB) Viewed 72651 times

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

Re: How to get coordinates according to step value

Post by CVH » Mon Dec 25, 2023 9:37 am

Thanks and that is mutual.

Doing this with the GUI is one ... You are able to tweak things until satisfactory.

Scripting this requires pro features to start with and these are not to somewhat less documented.
(These resources may change, may be replaced or removed at any time without notice)

For polyline offsets it is a good idea to fall back on 'not clipped'.
With clipped you can force faulty or partial results, especially when the base polyline includes arc segments.

And as explained, there is no human indicating sides, rejecting solutions or requesting additional partial offsets at other positions.
Trivial cases are fine and an outer offset is usually straightforward.

Remark that the inner offset of your top example almost touches itself ... Self-intersects.
If it would cross itself twice then there are 2 triangle shaped inner offsets instead of one singular.
If the base shape would intersect itself then both offsets will self-intersect and intersect the other offset ...

The manual trimming at key points is harder to mimic but then auto 'clipping' fails too.
I already trashed code of several attempts.
Each time it is a little robuster until other unexpected issues occur and it's a major step back.

Kind regards and with all the best wishes, best intentions,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Wed Dec 27, 2023 8:01 am

HI CVH thanks for your reply
I have made progress, I have successfully used the RPolygonOffset function, and obtained the internal and external contours of the closed polyline, please see the attachment (I will deal with the closed polyline situation first).
I have another question, how to get the handle attribute of the entity through js? It is easy to get this value in C#, but I have been looking for it for a long time in JS.
Attachments
VeryCapture_20231227145945.jpg
VeryCapture_20231227145945.jpg (183.85 KiB) Viewed 72145 times

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Wed Dec 27, 2023 8:11 am

There is another question. Lineweight can be based on layers or blocks.
Lineweight can be easily obtained by layer,
if (lw == RLineweight.WeightByLayer) {
var layerId = polyline.getLayerId();
var layerEntity = doc.queryLayer(layerId)
lw = layerEntity.getLineweight()
}
How to get lineweight by block?

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

Re: How to get coordinates according to step value

Post by CVH » Wed Dec 27, 2023 8:13 am

WildWolfCJ wrote:
Wed Dec 27, 2023 8:01 am
how to get the handle attribute of the entity through js?
With the entity queried from the document:

Code: Select all

var entity = doc.queryEntity(id);    // Where: doc = current RDocument and id the entity id in question
var handle = entity.getHandle();
https://qcad.org/doc/qcad/3.0/developer ... 2a9f17cd6b

id, handle and drawing order are different things.
The id is usually an integer value from a filtered list, a selection list, ...

Regards,
CVH

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

Re: How to get coordinates according to step value

Post by CVH » Wed Dec 27, 2023 9:55 am

WildWolfCJ wrote:
Wed Dec 27, 2023 8:01 am
I have made progress,
Pure theoretically: What if the Lineweight in your example would be 25% larger?
Or the object would be 25% smaller with the same pen.

What if the base shape self-intersect?
Ending so that it just touches one of its own segments is enough.
WildWolfCJ wrote:
Wed Dec 27, 2023 8:11 am
How to get lineweight by block?

Code: Select all

        // Optionally we could retrieve the block definition and its Lineweight:
        var blockId = polyline.getBlockId();
        var block = doc.queryBlock(blockId);
        var blockLw = block.getLineweight();
But you are not out the woods yet, this is for just one level deep.
Block references can include other nested block references and you need to resolve the Lineweight following the chain.
At some point it is unclear to me what weight to resolve to for nested blocks with various properties.
I have the same determination issues in the GUI and for layer '0' that may be by compatibility preference.

There is a resource: getLineweight (bool resolve, const QStack< REntity * > &blockRefStack) const
And another: getLineweightInUnits (const QStack< REntity * > &blockRefStack) const
Found no example on usage and would not know how to include a blockRefStack parameter.

Now, entities in blocks are much harder to handle for the rest of the SEM operation too.
Thinking of scale in X/Y/Z, orientation, ... And that for each stacked/nested block ...
Took the easy way out ... Excluding them. :wink:

Below is a snippet of my code.
Incomplete at the start there I also let the pen size be superseded by a cylindrical mill diameter per entity or per layer ...
... Or by the surface diameter of a conical cutter of given size, at given depth per layer.
Based on data stored in custom properties.

Code: Select all

    var weightUnresolved = polyline.getLineweight();

    // Fail on weight by block:
    if (weightUnresolved === RLineweight.WeightByBlock) {
        EAction.handleUserWarning("Encountered Lineweight By Block, entity skipped.");
        return undefined;
    }

    // Replace weight by layer with the layer property:
    if (weightUnresolved === RLineweight.WeightByLayer) {
        var layerId = polyline.getLayerId();
        var layerEntity = doc.queryLayer(layerId)
        weightUnresolved = layerEntity.getLineweight()
    }

    // Replace weight 'Default' with Application Preference:
    if (weightUnresolved === RLineweight.WeightByLwDefault) {
        weightUnresolved = RSettings.getIntValue("GraphicsView/DefaultLineweight", RLineweight.Weight025);
    }

    // Fail on invalid weight:
    if (weightUnresolved === RLineweight.WeightInvalid || !isNumber(weightUnresolved)) {
        EAction.handleUserWarning("Encountered invalid Lineweight, entity skipped.");
        return undefined;
    }

    // Convert pen size in 1/100mm to document units:
    var weight = RUnit.convert(weightUnresolved, RS.Millimeter, doc.getUnit());
 
    // Return half the pen size in document units:
    return weight / 200;

Regards,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Wed Dec 27, 2023 10:29 am

HI CVH Thanks for your enthusiastic help, both lineweight and handle have been successfully obtained.
But there is a strange phenomenon. I use RPolygonOffset to obtain the outline. Some DXFs work fine, but the two outlines obtained by the attached DXF overlap. The JS file is privately sent to you. Can you give me some guidance?
Attachments
qcad_createdrawing111.dxf
(141.86 KiB) Downloaded 99 times
VeryCapture_20231227172830.jpg
VeryCapture_20231227172830.jpg (330.34 KiB) Viewed 72092 times

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

Re: How to get coordinates according to step value

Post by CVH » Wed Dec 27, 2023 10:47 am

WildWolfCJ wrote:
Wed Dec 27, 2023 10:29 am
Some DXFs work fine, but the two outlines obtained by the attached DXF overlap.
The JS file is privately sent to you. Can you give me some guidance?
I never have said that RPolygonOffset works flawless every time nor does Polyline Offset (OQ).
Try smaller half pen sizes, for example equal or below 0.1 ... Probably some sort of fixed tolerance kicks in.
This might be overcome with scaling up the pen and the logical copy of the base entity by factor 10 ... 1000 and scale the results back.
Try polylines with arc segments, especially tangentially connected arc segments.
Scaling the base and the offset is no solution here.

I'll take a look at it later today, there are more pressing tasks that need to be accomplished today ... Now the sun is up.
Fortunately, I don't know weekends/holidays and I don't invest time in vacations/festivities. :lol:

Regards,
CVH

WildWolfCJ
Full Member
Posts: 84
Joined: Fri Oct 20, 2023 7:21 am

Re: How to get coordinates according to step value

Post by WildWolfCJ » Thu Dec 28, 2023 7:09 am

HI CVH Thank you for taking time out of your busy schedule to reply,
"I never have said that RPolygonOffset works flawless every time nor does Polyline Offset (OQ).
"My current situation is that I can obtain the internal and external contours using the same parameters in QCAD GUI OQ, but I can only obtain the internal contours using RPolygonOffset.
"
var worker = new RPolygonOffset(offset, 1, RVector.invalid, RS.JoinRound, false);
worker.setForceSide(RS.RightHand);
worker.addPolyline(polyline.getPolylineShape());
var offs = worker.getOffsetShapes();
var op = new RAddObjectsOperation();
var shapeEntity1, shapeEntity2;
for (var j = 0; j < offs.length; j++) {
shapeEntity1 = shapeToEntity(doc, offs[j].data());
op.addObject(shapeEntity1, false);
print("new handle =" + shapeEntity1.getHandle());
}

var worker2 = new RPolygonOffset(offset, 1, RVector.invalid, RS.JoinRound, false);
worker2.setForceSide(RS.LeftHand);
var offs2 = worker2.getOffsetShapes();
var op2 = new RAddObjectsOperation();
for (var j = 0; j < offs2.length; j++) {
shapeEntity2 = shapeToEntity(doc, offs2[j].data());
op2.addObject(shapeEntity2, false);
print("new handle =" + shapeEntity2.getHandle());
}
"
Attached is my test DXF file.
Attachments
test_polyline - 2.dxf
(95.68 KiB) Downloaded 112 times

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”