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"]);
};
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>&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>