Script changing cut out width - help request

Use this forum for all posts and questions about the free QCAD Community Edition version 3

Moderator: andrew

Post Reply
Philip
Newbie Member
Posts: 8
Joined: Mon Jun 17, 2024 10:31 pm

Script changing cut out width - help request

Post by Philip » Mon Jun 17, 2024 10:56 pm

Hi,
I want to write a script that changes the width of cut outs. The use case is that I have a contour (outline) for a part that slots into another part. These parts are made of wood with a specific width. When the wood sheet thickness changes, I want to use my script to automatically find these cut outs and change the width.
To find these design elements I start of with searching for lines that are of the length of the “old” cut outs. After that I check if the lines to the left and right side are perpendicular. Once the entity’s creating these design elements are found they are stored in a 2 dim. Array. The length of the first dimension should match the count of the cut outs in the design found and the length of the second dimension is always 3 (assumption is that cutouts in the part always have 3 lines).
The code I write seems to work in most cases but on some files it does not. Can someone here help me find the root cause and correct the code?
Attached is the code of the script as well as a dxf file where it works and on where it does not work. Thank you very much for you help and time.

The CutOutChangeWidth.js file:

Code: Select all

include("scripts/EAction.js");

function CutOutChangeWidth(guiAction) {
    EAction.call(this, guiAction);
	this.pos = undefined;
    this.cutOutWidthOld = undefined;
    this.cutOutNewWidth = undefined;
    this.tollerance = undefined;
	this.pointMerge = 1;
	this.angleDeviation = 0.1;
	this.applystatus = false;
    this.setUiOptions("CutOutChangeWidth.ui");
}

CutOutChangeWidth.prototype = new EAction();
CutOutChangeWidth.includeBasePath = includeBasePath;

CutOutChangeWidth.prototype.beginEvent = function() {
    EAction.prototype.beginEvent.call(this);
    var di = this.getDocumentInterface();
};

CutOutChangeWidth.prototype.slotCutOutWidthOldChanged = function(v) {
    this.cutOutWidthOld = v;
};

CutOutChangeWidth.prototype.slotTolleranceChanged = function(u) {
    this.tollerance = u;
};

CutOutChangeWidth.prototype.slotPointMergeChanged = function(uuu) {
    this.pointMerge = uuu;
};

CutOutChangeWidth.prototype.slotAngleDeviationChanged = function(uuuu) {
    this.angleDeviation = uuuu;
};

CutOutChangeWidth.prototype.slotNewWidthChanged = function(uuuuu) {
    this.cutOutNewWidth = uuuuu;
};

CutOutChangeWidth.prototype.slotApplyAll = function() {
	this.applystatus = true;
    var di = this.getDocumentInterface();
    var document = this.getDocument();
    var selected = document.querySelectedEntities();
	var mylinelength;
    var e, entityId, entity, color, type_M;

    if (true) {
        var visible = document.queryAllVisibleEntities();
        var entityIdsToSelect = [];
		var entityIdsToChange = [];
		var entitysConnectedAtStartAndPurpendicular;
		var entitysConnectedAtEndAndPurpendicular;
		
        for (e = 0; e < visible.length; ++e) {
            entityId = visible[e];
            entity = document.queryEntity(entityId);
            if (isLineEntity(entity)) {
				mylinelength = entity.getLength();
			}
			/*We want to find lines that are equal the user defined old cut out width +/- the tollerance*/
			if (mylinelength < (this.cutOutWidthOld+this.tollerance) && mylinelength>(this.cutOutWidthOld-this.tollerance)) {
				entitysConnectedAtStartAndPurpendicular = false;
				entitysConnectedAtEndAndPurpendicular = false;
				// Store entity IDs in a 2-dim array named entityIdsToChange [number of cutouts] [3]
				entityIdsToChange.push([entityId,0,0]);
				/*Next we need to check if these lines have other lines that are attached to the ends of the first line*/
				for (ee = 0; ee < visible.length; ++ee) {
					otherentityId = visible[ee];
					otherentity = document.queryEntity(otherentityId);
					if (ee != e && isLineEntity(otherentity)) {
						if (CheckDistanceBelowTollerance(entity.getStartPoint(),otherentity.getStartPoint(),this.pointMerge) || (CheckDistanceBelowTollerance(entity.getStartPoint(),otherentity.getEndPoint(),this.pointMerge)))
						{
							if (CheckPerpendicular(entity.getAngle(), otherentity.getAngle(), this.angleDeviation)) {
								entitysConnectedAtStartAndPurpendicular = true;
								// Store entity IDs in a 2-dim array named entityIdsToChange [number of cutouts] [3] 
								entityIdsToChange[entityIdsToChange.length-1][1] = otherentityId;
							}					
						}
						if (CheckDistanceBelowTollerance(entity.getEndPoint(),otherentity.getStartPoint(),this.pointMerge) || (CheckDistanceBelowTollerance(entity.getEndPoint(),otherentity.getEndPoint(),this.pointMerge)))
						{
							if (CheckPerpendicular(entity.getAngle(), otherentity.getAngle(), this.angleDeviation)) {
								entitysConnectedAtEndAndPurpendicular = true;
								// Store entity IDs in a 2-dim array named entityIdsToChange [number of cutouts] [3]
								entityIdsToChange[entityIdsToChange.length-1][2] = otherentityId;
							}
						}
					}				
				}
				if (entitysConnectedAtStartAndPurpendicular==true && entitysConnectedAtEndAndPurpendicular==true) {
					entityIdsToSelect.push(entityId);
				} else {
					entityIdsToChange.pop();
				}
            }
        }
        if (entityIdsToSelect.length!==0) {
            di.selectEntities(entityIdsToSelect);
        }
		/*EAction.handleUserMessage(qsTr("entityIdsToChange: "+ entityIdsToChange));	*/	
		if (entityIdsToChange.length!==0) {	
			var op = new RModifyObjectsOperation();
			const colorYellow = new RColor("Yellow");
			const colorRed = new RColor("Red");
			const colorMagenta = new RColor("magenta");
			/*Create a new Layer for the new CutOuts*/
			var linetypeId = document.getLinetypeId("CONTINUOUS");
			var layer = new RLayer(document, "New CutOuts", false, false, new RColor("red"), linetypeId, RLineweight.Weight000);
			op.addObject(layer);
			di.applyOperation(op);
			var op = new RModifyObjectsOperation();
			for (eee = 0; eee < entityIdsToChange.length; ++eee) {
				var entity2 = document.queryEntity(entityIdsToChange[eee][0]);
				entity2.setColor(colorRed);
				entity2.setLayerName("New CutOuts");
				lengthen(entity2,true,(this.cutOutNewWidth-entity2.getLength())/2);
				lengthen(entity2,false,(this.cutOutNewWidth-entity2.getLength()));
				// lengthen(entity2,false,5);
				op.addObject(entity2, false, true);
				var entity3 = document.queryEntity(entityIdsToChange[eee][1]);
				entity3.setColor(colorYellow);
				entity3.setLayerName("New CutOuts");
				// move entity3 relative movement distanceX and distanceY defined by delta (entityIdsToChange[eee][0].getStartPoint()-entity2.getStartPoint())		
				MoveXentity3 = entity2.getStartPoint().x-document.queryEntity(entityIdsToChange[eee][0]).getStartPoint().x;
				MoveYentity3 = entity2.getStartPoint().y-document.queryEntity(entityIdsToChange[eee][0]).getStartPoint().y;
				MoveLine(entity3,MoveXentity3,MoveYentity3);
				op.addObject(entity3, false, true);
				var entity4 = document.queryEntity(entityIdsToChange[eee][2]);
				entity4.setColor(colorMagenta);
				entity4.setLayerName("New CutOuts");
				MoveXentity4 = entity2.getEndPoint().x-document.queryEntity(entityIdsToChange[eee][0]).getEndPoint().x;
				MoveYentity4 = entity2.getEndPoint().y-document.queryEntity(entityIdsToChange[eee][0]).getEndPoint().y;
				MoveLine(entity4,MoveXentity4,MoveYentity4);
				op.addObject(entity4, false, true);/*		
				for (eeee = 0; eeee < 3; ++eeee) {
					var entity2 = document.queryEntity(entityIdsToChange[eee][eeee]);
					// modify clone of entity:
					entity2.setColor(colorYellow);
					op.addObject(entity2, false);
				}*/
			}
		}
    }
    di.applyOperation(op);
    EAction.activateMainWindow();
    this.terminate();
};

function lengthen(line, lengthenAtStart, amount) {
    const startX = line.getStartPoint().x;
    const startY = line.getStartPoint().y;
    const endX = line.getEndPoint().x;
    const endY = line.getEndPoint().y;
    // Calculate the direction vector of the line
    const dx = endX - startX;
    const dy = endY - startY;
    // Calculate the length of the original line
    const lineLength = Math.sqrt(dx * dx + dy * dy);
    // Normalize the direction vector
    const unitDx = dx / lineLength;
    const unitDy = dy / lineLength;
    if (lengthenAtStart) {
        // Calculate new start point
        const newStartX = startX - unitDx * amount;
        const newStartY = startY - unitDy * amount;
        line.setStartPoint(new RVector(newStartX, newStartY));
    } else {
        // Calculate new end point
        const newEndX = endX + unitDx * amount;
        const newEndY = endY + unitDy * amount;
		line.setEndPoint(new RVector(newEndX, newEndY));
	}
}

function CheckPerpendicular(Angle1,Angle2,AngleTolleranceRad) {
	const perpendicularAngle = 1.5708
	number = Math.abs((Math.abs(Angle1-Angle2))-(perpendicularAngle*2))-perpendicularAngle
	if (Math.abs(number) < AngleTolleranceRad) {
		return true;
	}
	else {
		return false;
	}
}

function MoveLine(line, DeltaX, DeltaY) {
    const startX = line.getStartPoint().x;
    const startY = line.getStartPoint().y;
    const endX = line.getEndPoint().x;
    const endY = line.getEndPoint().y;
	line.setStartPoint(new RVector(startX+DeltaX, startY+DeltaY));
	line.setEndPoint(new RVector(endX+DeltaX, endY+DeltaY));
}

function CheckDistanceBelowTollerance(Point1,Point2,DistanceTollerance) {
	if (Math.abs(Point1.x-Point2.x) < DistanceTollerance) {
		if (Math.abs(Point1.y-Point2.y) < DistanceTollerance) {
			return true;
		}
		else {
			return false;
		}
	}
	else {
		return false;
	}
}

CutOutChangeWidth.init = function(basePath) {
    var action = new RGuiAction(qsTr("&CutOutChangeWidth"), RMainWindowQt.getMainWindow());
    action.setRequiresDocument(true);
    action.setScriptFile(basePath + "/CutOutChangeWidth.js");
    action.setGroupSortOrder(100000);
    action.setSortOrder(0);
    action.setWidgetNames(["ExamplesMenu"]);
};
The CutOutChangeWidth.ui file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>CutOutChangeWidth</class>
 <widget class="QWidget" name="CutOutChangeWidth">
  <layout class="QHBoxLayout">
   <item>
    <widget class="QLabel" name="CutOutWidthOldLabel">
     <property name="text">
      <string>&amp;CutOutWidthOld:</string>
     </property>
     <property name="buddy">
      <cstring>CutOutWidthOld</cstring>
     </property>
    </widget>
   </item>
   <item>
    <widget class="RMathLineEdit" name="CutOutWidthOld">
     <property name="text">
      <string notr="true">4</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QLabel" name="TolleranceLabel">
     <property name="text">
      <string>Width Tollerance:</string>
     </property>
     <property name="budd2">
      <cstring>Width Tollerance</cstring>
     </property>
    </widget>
   </item>
   <item>
    <widget class="RMathLineEdit" name="Tollerance">
     <property name="text">
      <string notr="true">0.1</string>
     </property>
    </widget>
   </item>
      <item>
    <widget class="QLabel" name="PointMergeLabel">
     <property name="text">
      <string>Point Merge Distance:</string>
     </property>
     <property name="budd2">
      <cstring>Point Merge Distance</cstring>
     </property>
    </widget>
   </item>
   <item>
    <widget class="RMathLineEdit" name="PointMerge">
     <property name="text">
      <string notr="true">0.1</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QLabel" name="AngleDeviationFromPerpendicularLabel">
     <property name="text">
      <string>Angle Deviation (Rad):</string>
     </property>
     <property name="budd2">
      <cstring>Angle Deviation (Rad)</cstring>
     </property>
    </widget>
   </item>
   <item>
    <widget class="RMathLineEdit" name="AngleDeviation">
     <property name="text">
      <string notr="true">1</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QLabel" name="CutOutWidthNewLabel">
     <property name="text">
      <string>New Width:</string>
     </property>
     <property name="budd2">
      <cstring>New Width</cstring>
     </property>
    </widget>
   </item>
   <item>
    <widget class="RMathLineEdit" name="NewWidth">
     <property name="text">
      <string notr="true">4</string>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QToolButton" name="ApplyAll">
     <property name="autoFillBackground">
      <bool>false</bool>
     </property>
     <property name="text">
      <string>ApplyAll</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>RMathLineEdit</class>
   <extends>QLineEdit</extends>
   <header>RMathLineEdit.h</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>
this does work pic.JPG
This is an exsample (picture) where it does work
this does work pic.JPG (17 KiB) Viewed 87926 times
CutOut_UI-pic.JPG
This is what my UI looks like
CutOut_UI-pic.JPG (18.98 KiB) Viewed 87926 times
Does work.dxf
This is a dxf file that does work.
(25.47 KiB) Downloaded 881 times
Does not work2.dxf
This is a dxf file where the script does not work.
(25.71 KiB) Downloaded 834 times

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

Re: Script changing cut out width - help request

Post by CVH » Tue Jun 18, 2024 6:24 am

Hi, and welcome to the QCAD forum.

First.
Are you aware that your entities are not drawn straightened out?
And that the angles between them is not typically 90 degrees?

Adding a dx/dy is then not straightforward but in a way this is handled.
At this point it is unsure to me if that holds in any case.
May I add that QCAD has resources to lengthen/shorten shapes or to move them.

Your default angle tolerance is 0.1 what is in radians or almost 6 degrees.
In the UI example we see 0.4 or about 23 degrees.
QCAD GUI angles are commonly in degrees, it is then a good idea to convert your input from degrees to radians.

- It is not common to use const under QCAD, simply use var for declaring variables.
- Your indentations are a mix of tab and/or spaces, under QCAD 4 spaces for a tab are common.
- Instead of placing your comments between /* and */ you can start the line with //.
- In your slot change functions you don't need to diversify between v, u, uu, ...
These have function scope and v or value will do for all.
- Your begin event does nothing, there is no reason to get the current document interface.
The only way of terminating your tool is to apply all the conversions or with the default escape event of EAction.
That includes clicking the right mouse button but I don't see you handling MouseTip nor CommandPrompt.
- It is dangerous to define global functions with existent names (e.g. lengthen) with the risk of overwriting the original.
I would prototype them and/or also ensure that they can not be mixed up by name.
CutOutChangeWidth.lengthen would already be better but it is textually longer.
CutOutChangeWidth.prototype.lengthen can be called as this.lengthen.
- I don't see you declaring all variables: ee, eee, otherentityId, otherentity, ...

As far as I can test it it works just the same on both DXF files.
All depending on the options.

It can fail on getAngle() of an RArcEntity ...
In the for (e = 0; e < visible.length; ++e) loop you don't really exclude an RArcEntity.

Code: Select all

            if (isLineEntity(entity)) {
                mylinelength = entity.getLength();
            }
            else {
                continue;
            }
May fix that.

Also encountered an exception on an undefined operation.
di.applyOperation(op); should be inside
if (entityIdsToChange.length!==0) { ... }


Am I right that if you widen slots then other parts of the design need to be shortened?

May I add that slots with sharp corners won't fit when routed with a rotating cutter.
And then even Laser, Plasma and WaterJet have a minute to larger (round) size.
The minimal inner corner radius is the cutter radius.
In a way you need to support rounded corners.

You don't test for odd things like for example entities with no length.
These may be connected within tolerance and be perpendicular within tolerance.

Regards,
CVH
Last edited by CVH on Tue Jun 18, 2024 8:16 am, edited 1 time in total.

Philip
Newbie Member
Posts: 8
Joined: Mon Jun 17, 2024 10:31 pm

Re: Script changing cut out width - help request

Post by Philip » Tue Jun 18, 2024 8:14 am

Hi CVH,

thank you so much for your answer and detailed help. All your coments will help improve my code and make it operational and more robust.
I was assuming that QCAD has resources to lengthen/shorten as well as move shapes. Actually I did try and use them in a first attempt, but failed and the creation of my own functions was a work around. If this is not a big deal would you give me an exsample on how I could use the resources QCAD offers for these functions?

I agree to your comments on the fact that the code will not handle all possible use cases and has still big room for improvement.

Your interpretation of the line:

Code: Select all

if (ee != e && isLineEntity(otherentity))
was correct - that I was trying to exclude evaluating the same entity. I will use your propossal instead.

Yes - As lines are shortend / lengthend other lines will have to be also modified. That part of the task I have not tackled yet.

You are correct that a CNC mill (laser, plasma or water jet) all come with a tool diameter (radius) causing not perfect corners but rounded corners and that the code would not handle this (yet). However this is currently not in my scope as this would be handled by other process steps in my toolchain when generating CAM data.

To explain: I design, mill (with my cnc) and build remote control model airplanes as a hobby and wanted to speed up things by scripting something as well as learn and practise programming. So the code is not intended for industrial use nor is precission bejond 0.01mm required.

To sum up: I will update my code with your input and report when I make progress. :wink:
Thank you so much for your help and I wish you a wonderful day. Philip

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

Re: Script changing cut out width - help request

Post by CVH » Tue Jun 18, 2024 8:22 am

Philip,
I was writing my reply and accidentally hit 'Submit' instead of 'Preview'. :oops:
Please have a new look at my answer again.

ee != e would hold because they are indexes of the same list.
We tend to use i,j,k,...
And e as short for entity.
Comparing id's is fail-safe because they are unique. :wink:

Regards,
CVH

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

Re: Script changing cut out width - help request

Post by CVH » Tue Jun 18, 2024 9:38 am

Philip wrote:
Tue Jun 18, 2024 8:14 am
I was assuming that QCAD has resources to lengthen/shorten as well as move shapes. Actually I did try and use them in a first attempt, but failed and the creation of my own functions was a work around. If this is not a big deal would you give me an exsample on how I could use the resources QCAD offers for these functions?
On REntity level that depends, not all methods are implemented for all entity types.
A lot more can be done on a lower level.

RLineEntity.trimEndPoint(trimPoint, clickPoint, extend)
RLineEntity.trimStartPoint(trimPoint, clickPoint, extend)

https://qcad.org/doc/qcad/3.0/developer ... a94b862122
https://qcad.org/doc/qcad/3.0/developer ... f7383bbcc9
Can already be exploited but rather intended for user input with an indicated position.
  • RLineEntity is your line segment ... It must be a line entity
    trimPoint the new point, an RVector, absolute in X & Y
    clickPoint is probably not required = RVector.invalid
    extend = true or false, true for lengthen
REntity.move(offset)
https://qcad.org/doc/qcad/3.0/developer ... 1b52e8a745
Is of the parent class REntity and implemented for all or almost all entity types.
  • REntity is your line segment ... And not limited to line entities
    offset is an offset RVector ... Relative dX and dY.
The offset vector can be obtained by subtracting points:
var offset = targetPoint.operator_subtract(point); for example but the inverse may be required depending what to move.

At some point you might want to take the long route.
Deriving a mathematical representation of your entity as an RLine shape.
Then there are more options: https://qcad.org/doc/qcad/3.0/developer ... _line.html
Like setLength()
Casting the RLine back as entity.

This may be of interest too:
RMath.fuzzyCompare (v1, v2, tolerance)
https://qcad.org/doc/qcad/3.0/developer ... 0e5d105485
If omitted the tolerance is 1e-9

You might have seen that we tend to use Camel-Case.
We don't write 'otherentity' but we write 'otherEntity'
But not 'OtherEntity', under QCAD it is common to start variables with a lower case. :wink:

Regards,
CVH

Philip
Newbie Member
Posts: 8
Joined: Mon Jun 17, 2024 10:31 pm

Re: Script changing cut out width - help request

Post by Philip » Fri Jun 21, 2024 8:03 am

Hi,

I have improved the code with the input received. In a next step I need to make a decision: If I continue writing a script for indivualal lines or for polylines. I believe that creating the script for polylines will be somewhat a shortcut. The question I have is: would this (in all cases) only be possible with the pro version, or can there also be a solution that works for the community editon? I have checked this site: https://www.qcad.org/en/qcad-documentat ... features that shows that the polylines are apart from the basic functionality only available with the Pro edition. Is this true for the GUI only, or is it also valid for scripts?
Some checks I made showed that a

Code: Select all

polyline.appendVertex(new RVector(0, 0), 0,0,0);
command would work, but a

Code: Select all

polyline.moveVertexAt(2,new RVector(40, 20));
would fail in execution. Is this a consequence of me using the community edition - or do I have a error in the code? I checked the documentation but could not find any information on if function is part of community edition or not: https://www.qcad.org/doc/qcad/latest/de ... a809afe156. Does someone know? Thank you and kind regards Philip

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

Re: Script changing cut out width - help request

Post by CVH » Fri Jun 21, 2024 9:49 am

Philip wrote:
Fri Jun 21, 2024 8:03 am
Is this a consequence of me using the community edition - or do I have a error in the code?
So, you are scripting under QCAD CE.
A detail you should have mentioned because you are posting on the QCAD Pro forum. :wink:

No, it probably not a CE consequence.
moveVertexAt() or setVertexAt() is part of the RPolyline Class
https://qcad.org/doc/qcad/3.0/developer ... yline.html
Remark that the first method is relative by an offset and the second is in absolute coordinates.
It should be obvious that the polyline has to have 3 vertices for your example, the index is zero based.

Such methods are not implemented for the RPolylineEntity Class
https://qcad.org/doc/qcad/3.0/developer ... ntity.html

The solution is to cast the REntity to an RShape, a lower mathematical representation.

Code: Select all

var entity;    // A reference to an REntity 
var polyShape = entity.castToShape()
Philip wrote:
Fri Jun 21, 2024 8:03 am
I believe that creating the script for polylines will be somewhat a shortcut.
Yes and no, Polylines and Line segments are different things but you can merge/explode the one into the other.
They will handle differently. Polyline segments are connected by default.
At some point you will eventually handle the segments individually (getSegmentAt())
And that are again RLine and/or RArc shapes.

Regards,
CVH

Philip
Newbie Member
Posts: 8
Joined: Mon Jun 17, 2024 10:31 pm

Re: Script changing cut out width - help request

Post by Philip » Fri Jun 21, 2024 10:36 am

Hi,
thank you for your answer and help. :)
A detail you should have mentioned because you are posting on the QCAD Pro forum. :wink:
I am sorry - when choosing a category for my topic (in the forum) the words "Script Programming" caught my eye and I overlooked the section being dedicated to the Professional Version :oops: . Can I myself or a admin cure the Issue by moving the thread to the community section?
Thank you especially for your hint that I will have to use

Code: Select all

var entity;    // A reference to an REntity 
var polyShape = entity.castToShape()
. I am aware that I will have to handle segments individually at some point :) .

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

Re: Script changing cut out width - help request

Post by CVH » Fri Jun 21, 2024 10:55 am

Philip wrote:
Fri Jun 21, 2024 10:36 am
Can I myself or a admin cure the Issue by moving the thread to the community section?
There is no Scripting section under https://www.qcad.org/rsforum/viewforum.php?f=76
But it was important information that was left out.

Remind the you have to convert the RShape back to an REntity type before updating the document.

Regards,
CVH

Philip
Newbie Member
Posts: 8
Joined: Mon Jun 17, 2024 10:31 pm

Re: Script changing cut out width - help request

Post by Philip » Fri Aug 02, 2024 8:49 pm

Hi,
I have had some success creating a script to change the cut out width / depth of slots or tabs. The script is not perfect but it works for my current needs. If anyone is interesed I have attached the files to this post. To execute the script one needs to copy the files to the script folder. :wink:
PolylineToolsCE.zip
2August2024
(16.26 KiB) Downloaded 864 times
Kind regards
Philip

Post Reply

Return to “QCAD Community Edition”