ipad commit 2025-12-17-01-15
This commit is contained in:
commit
bab5060120
1962 files changed
+216780
No files matched your search
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
With This Script it is possible to make boolean Operations on Shapes.
|
||||
The style of the resulting shape will be the style of the highest ranking Element that was used.
|
||||
The ranking of the elements is based on their background. The "denser" the background, the higher the ranking (the order of backgroundstyles is shown below). If they have the same background the opacity will decide. If thats also the same its decided by the order they were created.
|
||||
The ranking is also important for the difference operation, so a transparent object for example will cut a hole into a solid object.
|
||||

|
||||

|
||||
|
||||
|
||||
See documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.9.20")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
const ShadowGroupMarker = "ShadowCloneOf-";
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(
|
||||
el=>["ellipse", "rectangle", "diamond"].includes(el.type) ||
|
||||
el.groupIds.some(id => id.startsWith(ShadowGroupMarker)) ||
|
||||
(["line", "arrow"].includes(el.type) && el.roundness === null)
|
||||
);
|
||||
if(elements.length === 0) {
|
||||
new Notice ("Select ellipses, rectangles or diamonds");
|
||||
return;
|
||||
}
|
||||
|
||||
const PolyBool = ea.getPolyBool();
|
||||
const polyboolAction = await utils.suggester(["union (a + b)", "intersect (a && b)", "difference (a - b)", "reversed difference (b - a)", "xor"], [
|
||||
PolyBool.union, PolyBool.intersect, PolyBool.difference, PolyBool.differenceRev, PolyBool.xor
|
||||
], "What would you like todo with the object");
|
||||
|
||||
const shadowClones = elements.filter(element => element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
shadowClones.forEach(shadowClone => {
|
||||
let parentId = shadowClone.groupIds
|
||||
.filter(id => id.startsWith(ShadowGroupMarker))[0]
|
||||
.slice(ShadowGroupMarker.length);
|
||||
const shadowCloneIndex = elements.findIndex(element => element.id == parentId);
|
||||
if (shadowCloneIndex == -1) return;
|
||||
elements[shadowCloneIndex].backgroundColor = shadowClone.backgroundColor;
|
||||
elements[shadowCloneIndex].fillStyle = shadowClone.fillStyle;
|
||||
})
|
||||
const borderElements = elements.filter(element => !element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
groups = ea.getMaximumGroups(borderElements);
|
||||
groups = groups.map((group) => group.sort((a, b) => RankElement(b) - RankElement(a)));
|
||||
groups.sort((a, b) => RankElement(b[0]) - RankElement(a[0]));
|
||||
|
||||
ea.style.strokeColor = groups[0][0].strokeColor;
|
||||
ea.style.backgroundColor = groups[0][0].backgroundColor;
|
||||
ea.style.fillStyle = groups[0][0].fillStyle;
|
||||
ea.style.strokeWidth = groups[0][0].strokeWidth;
|
||||
ea.style.strokeStyle = groups[0][0].strokeStyle;
|
||||
ea.style.roughness = groups[0][0].roughness;
|
||||
ea.style.opacity = groups[0][0].opacity;
|
||||
|
||||
const basePolygons = groups.shift().map(element => traceElement(element));
|
||||
const toolPolygons = groups.flatMap(group => group.map(element => traceElement(element)));
|
||||
|
||||
const result = polyboolAction({
|
||||
regions: basePolygons,
|
||||
inverted: false
|
||||
}, {
|
||||
regions: toolPolygons,
|
||||
inverted: false
|
||||
});
|
||||
const polygonHierachy = subordinateInnerPolygons(result.regions);
|
||||
drawPolygonHierachy(polygonHierachy);
|
||||
ea.deleteViewElements(elements);
|
||||
ea.addElementsToView(false,false,true);
|
||||
return;
|
||||
|
||||
|
||||
|
||||
function traceElement(element) {
|
||||
const diamondPath = (diamond) => [
|
||||
SxVEC(1/2, [0, diamond.height]),
|
||||
SxVEC(1/2, [diamond.width, 0]),
|
||||
addVec([SxVEC(1/2, [0, diamond.height]), ([diamond.width, 0])]),
|
||||
addVec([SxVEC(1/2, [diamond.width, 0]), ([0, diamond.height])]),
|
||||
SxVEC(1/2, [0, diamond.height])
|
||||
];
|
||||
const rectanglePath = (rectangle) => [
|
||||
[0,0],
|
||||
[0, rectangle.height],
|
||||
[rectangle.width, rectangle.height],
|
||||
[rectangle.width, 0],
|
||||
[0, 0]
|
||||
]
|
||||
const ellipsePath = (ellipse) => {
|
||||
const angle = ellipse.angle;
|
||||
const width = ellipse.width;
|
||||
const height = ellipse.height;
|
||||
const ellipseAtPoint = (t) => {
|
||||
const spanningVector = [width/2*Math.cos(t), height/2*Math.sin(t)];
|
||||
const baseVector = [width/2, height/2];
|
||||
return addVec([spanningVector, baseVector]);
|
||||
}
|
||||
let points = [];
|
||||
step = (2*Math.PI)/64
|
||||
for (let t = 0; t < 2*Math.PI; t = t + step) {
|
||||
points.push(ellipseAtPoint(t));
|
||||
}
|
||||
return points;
|
||||
}
|
||||
let polygon;
|
||||
let correctForPolygon = [0, 0];
|
||||
switch (element.type) {
|
||||
case "diamond":
|
||||
polygon = diamondPath(element);
|
||||
break;
|
||||
case "rectangle":
|
||||
polygon = rectanglePath(element);
|
||||
break;
|
||||
case "ellipse":
|
||||
polygon = ellipsePath(element);
|
||||
break;
|
||||
case "line":
|
||||
case "arrow":
|
||||
if (element.angle != 0) {
|
||||
let smallestX = 0;
|
||||
let smallestY = 0;
|
||||
element.points.forEach(point => {
|
||||
if (point[0] < smallestX) smallestX = point[0];
|
||||
if (point[1] < smallestY) smallestY = point[1];
|
||||
});
|
||||
polygon = element.points.map(point => {
|
||||
return [
|
||||
point[0] -= smallestX,
|
||||
point[1] -= smallestY
|
||||
];
|
||||
});
|
||||
correctForPolygon = [smallestX, smallestY];
|
||||
break;
|
||||
}
|
||||
if (element.roundness) {
|
||||
new Notice("This script does not work with curved lines or arrows yet!");
|
||||
return [];
|
||||
}
|
||||
polygon = element.points;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (element.angle == 0) return polygon.map(v => addVec([v, [element.x, element.y]]));
|
||||
|
||||
polygon = polygon.map(v => addVec([v, SxVEC(-1/2, [element.width, element.height])]));
|
||||
polygon = rotateVectorsByAngle(polygon, element.angle);
|
||||
return polygon.map(v => addVec([v, [element.x, element.y], SxVEC(1/2, [element.width, element.height]), correctForPolygon]));
|
||||
}
|
||||
|
||||
function RankElement(element) {
|
||||
let score = 0;
|
||||
const backgroundRank = [
|
||||
"dashed",
|
||||
"none",
|
||||
"hachure",
|
||||
"zigzag",
|
||||
"zigzag-line",
|
||||
"cross-hatch",
|
||||
"solid"
|
||||
]
|
||||
score += (backgroundRank.findIndex((fillStyle) => fillStyle == element.fillStyle) + 1) * 10;
|
||||
if (element.backgroundColor == "transparent") score -= 100;
|
||||
if (element.points && getVectorLength(element.points[element.points.length - 1]) > 8) score -= 100;
|
||||
if (score < 0) score = 0;
|
||||
score += element.opacity / 100;
|
||||
return score;
|
||||
}
|
||||
|
||||
function drawPolygonHierachy(polygonHierachy) {
|
||||
const backgroundColor = ea.style.backgroundColor;
|
||||
const strokeColor = ea.style.strokeColor;
|
||||
const setInnerStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = "transparent";
|
||||
}
|
||||
const setBorderStyle = () => {
|
||||
ea.style.backgroundColor = "transparent";
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
const setFilledStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
|
||||
polygonHierachy.forEach(polygon => {
|
||||
setFilledStyle();
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
if (polygon.innerPolygons.length === 0) {
|
||||
ea.addLine(path);
|
||||
return;
|
||||
}
|
||||
const outerBorder = path;
|
||||
const innerPolygons = addInnerPolygons(polygon.innerPolygons);
|
||||
path = path.concat(innerPolygons.backgroundPath);
|
||||
path.push(polygon.path[0]);
|
||||
setInnerStyle();
|
||||
const backgroundId = ea.addLine(path);
|
||||
setBorderStyle();
|
||||
const outerBorderId = ea.addLine(outerBorder)
|
||||
const innerBorderIds = innerPolygons.borderPaths.map(path => ea.addLine(path));
|
||||
const allIds = [innerBorderIds, outerBorderId, backgroundId].flat();
|
||||
ea.addToGroup(allIds);
|
||||
const background = ea.getElement(backgroundId);
|
||||
background.groupIds.push(ShadowGroupMarker + outerBorderId);
|
||||
});
|
||||
}
|
||||
|
||||
function addInnerPolygons(polygonHierachy) {
|
||||
let firstPath = [];
|
||||
let secondPath = [];
|
||||
let borderPaths = [];
|
||||
polygonHierachy.forEach(polygon => {
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
borderPaths.push(path);
|
||||
firstPath = firstPath.concat(path);
|
||||
secondPath.push(polygon.path[0]);
|
||||
drawPolygonHierachy(polygon.innerPolygons);
|
||||
});
|
||||
return {
|
||||
backgroundPath: firstPath.concat(secondPath.reverse()),
|
||||
borderPaths: borderPaths
|
||||
};
|
||||
}
|
||||
|
||||
function subordinateInnerPolygons(polygons) {
|
||||
const polygonObjectPrototype = (polygon) => {
|
||||
return {
|
||||
path: polygon,
|
||||
innerPolygons: []
|
||||
};
|
||||
}
|
||||
|
||||
const insertPolygonIntoHierachy = (polygon, hierarchy) => {
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygon[pointIndex], polygonObject.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
hierarchy[i].innerPolygons = insertPolygonIntoHierachy(polygon, hierarchy[i].innerPolygons);
|
||||
return hierarchy;
|
||||
}
|
||||
}
|
||||
polygon = polygonObjectPrototype(polygon);
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygonObject.path[pointIndex], polygon.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
polygon.innerPolygons.push(hierarchy.splice(i, 1)[0]);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
hierarchy.push(polygon);
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
let polygonHierachy = [];
|
||||
polygons.forEach(polygon => {
|
||||
polygonHierachy = insertPolygonIntoHierachy(polygon, polygonHierachy);
|
||||
})
|
||||
|
||||
return polygonHierachy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given point lays in the polygon
|
||||
* @param point array [x, y]
|
||||
* @param polygon array [[x, y], ...]
|
||||
* @returns true if inside, false if not, null if the point is on one of the polygons vertecies
|
||||
*/
|
||||
function pointInPolygon(point, polygon) {
|
||||
const x = point[0];
|
||||
const y = point[1];
|
||||
let inside = false;
|
||||
|
||||
// odd even test if point is in polygon
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i][0];
|
||||
const yi = polygon[i][1];
|
||||
const xj = polygon[j][0];
|
||||
const yj = polygon[j][1];
|
||||
|
||||
const intersect =
|
||||
yi > y !== yj > y &&
|
||||
x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
|
||||
|
||||
if (intersect) {
|
||||
inside = !inside;
|
||||
}
|
||||
|
||||
if ((x === xi && y === yi) || (x === xj && y === yj)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
function getVectorLength(vector) {
|
||||
return Math.sqrt(vector[0]**2+vector[1]**2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two Vectors together
|
||||
*/
|
||||
function addVec(vectors) {
|
||||
return vectors.reduce((acc, vec) => [acc[0] + vec[0], acc[1] + vec[1]], [0, 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of the vector
|
||||
*/
|
||||
function negVec(vector) {
|
||||
return [-vector[0], -vector[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies Vector with a scalar
|
||||
*/
|
||||
function SxVEC(scalar, vector) {
|
||||
return [vector[0] * scalar, vector[1] * scalar];
|
||||
}
|
||||
|
||||
function rotateVector (vec, ang) {
|
||||
var cos = Math.cos(ang);
|
||||
var sin = Math.sin(ang);
|
||||
return [vec[0] * cos - vec[1] * sin, vec[0] * sin + vec[1] * cos];
|
||||
}
|
||||
|
||||
function rotateVectorsByAngle(vectors, angle) {
|
||||
const cosAngle = Math.cos(angle);
|
||||
const sinAngle = Math.sin(angle);
|
||||
|
||||
const rotationMatrix = [
|
||||
[cosAngle, -sinAngle],
|
||||
[sinAngle, cosAngle]
|
||||
];
|
||||
|
||||
return applyTranformationMatrix(vectors, rotationMatrix);
|
||||
}
|
||||
|
||||
function applyTranformationMatrix(vectors, transformationMatrix) {
|
||||
const result = [];
|
||||
for (const vector of vectors) {
|
||||
const x = vector[0];
|
||||
const y = vector[1];
|
||||
|
||||
const newX = transformationMatrix[0][0] * x + transformationMatrix[0][1] * y;
|
||||
const newY = transformationMatrix[1][0] * x + transformationMatrix[1][1] * y;
|
||||
|
||||
result.push([newX, newY]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<path
|
||||
d="m 24.000085,1.5001668 c -0.386664,0 -0.771381,0.00992 -1.153418,0.029456 -0.382035,0.019538 -0.761505,0.048738 -1.138431,0.087333 -0.376928,0.038595 -0.751077,0.086489 -1.122412,0.1436604 -0.371337,0.057172 -0.740095,0.1231708 -1.105359,0.1984375 -0.365266,0.075267 -0.72701,0.1598168 -1.085722,0.2526978 -0.358713,0.092881 -0.714405,0.1943596 -1.066085,0.304374 C 16.976978,2.6261398 16.62896,2.7444758 16.284794,2.8711426 15.940628,2.9978093 15.600354,3.132931 15.264185,3.275769 14.928014,3.4186072 14.596073,3.5694093 14.26838,3.7279378 13.940685,3.8864665 13.617667,4.0523606 13.29893,4.2260986 12.980192,4.3998368 12.66565,4.5812681 12.356352,4.7697347 12.047052,4.9582013 11.74261,5.1540648 11.443229,5.356779 11.143849,5.5594932 10.849575,5.7692003 10.560596,5.9856812 10.271615,6.2021619 9.9881012,6.4251244 9.7100016,6.654891 9.4319021,6.8846574 9.1592182,7.1213204 8.8924805,7.3638916 8.6257427,7.6064628 8.3649942,7.8552043 8.1100993,8.1100993 7.8552043,8.3649942 7.6064628,8.6257427 7.3638916,8.8924805 7.1213204,9.1592182 6.8846574,9.4319021 6.654891,9.7100016 6.4251244,9.9881012 6.2021619,10.271615 5.9856812,10.560596 5.7692003,10.849575 5.5594932,11.143849 5.356779,11.443229 5.1540648,11.74261 4.9582013,12.047052 4.7697347,12.356352 4.5812681,12.66565 4.3998368,12.980192 4.2260986,13.29893 4.0523606,13.617667 3.8864665,13.940685 3.7279378,14.26838 3.5694093,14.596073 3.4186072,14.928014 3.275769,15.264185 3.132931,15.600354 2.9978093,15.940628 2.8711426,16.284794 2.7444758,16.62896 2.6261398,16.976978 2.5161255,17.328658 c -0.1100144,0.35168 -0.2114932,0.707372 -0.3043742,1.066085 -0.092881,0.358712 -0.177431,0.720456 -0.2526978,1.085722 -0.075267,0.365264 -0.1412659,0.734022 -0.1984375,1.105359 -0.057171,0.371335 -0.1050652,0.745484 -0.1436604,1.122412 -0.038595,0.376926 -0.067795,0.756396 -0.087333,1.138431 -0.019538,0.382037 -0.029456,0.766754 -0.029456,1.153418 0,0.386665 0.00992,0.770865 0.029456,1.152902 0.019538,0.382035 0.048738,0.762022 0.087333,1.138948 0.038595,0.376927 0.086489,0.751076 0.1436604,1.122412 0.057172,0.371337 0.1231708,0.739578 0.1984375,1.104842 0.075267,0.365266 0.1598168,0.727526 0.2526978,1.086239 0.092881,0.358713 0.1943598,0.713888 0.3043742,1.065568 0.1100143,0.35168 0.2283503,0.699698 0.3550171,1.043864 0.1266667,0.344166 0.2617884,0.684439 0.4046264,1.02061 0.1428382,0.336169 0.2936403,0.668627 0.4521688,0.996321 0.1585287,0.327695 0.3244228,0.650712 0.4981608,0.96945 0.1737382,0.318738 0.3551695,0.632763 0.5436361,0.942061 0.1884666,0.3093 0.3843301,0.613742 0.5870443,0.913123 0.2027142,0.299381 0.4124213,0.593654 0.6289022,0.882633 0.2164807,0.288981 0.4394432,0.573012 0.6692098,0.851111 0.2297664,0.2781 0.4664294,0.550267 0.7090006,0.817005 0.2425712,0.266737 0.4913127,0.528002 0.7462077,0.782898 0.2548949,0.254894 0.5156434,0.503637 0.7823812,0.746207 0.2667377,0.242572 0.5394216,0.478717 0.8175211,0.708484 0.2780996,0.229767 0.5616134,0.453246 0.8505944,0.669727 0.288979,0.216481 0.583253,0.426188 0.882633,0.628902 0.299381,0.202714 0.603823,0.398577 0.913123,0.587044 0.309298,0.188467 0.62384,0.369381 0.942578,0.54312 0.318737,0.173737 0.641755,0.340148 0.96945,0.498677 0.327693,0.158529 0.659634,0.309331 0.995805,0.452169 0.336169,0.142838 0.676443,0.277443 1.020609,0.40411 0.344166,0.126665 0.692184,0.24552 1.043864,0.355533 0.304779,0.09534 0.613889,0.181052 0.923975,0.26355 0.08249,0.310063 0.168215,0.618701 0.263549,0.923458 0.110015,0.351679 0.228351,0.699699 0.355018,1.043864 0.126665,0.344165 0.261788,0.684439 0.404626,1.02061 0.142838,0.336169 0.29364,0.668111 0.452169,0.995804 0.158528,0.327694 0.324423,0.65123 0.498161,0.969967 0.173736,0.318737 0.355169,0.632763 0.543636,0.942061 0.188465,0.309299 0.38433,0.613743 0.587044,0.913123 0.202714,0.29938 0.412422,0.593654 0.628902,0.882633 0.216481,0.288981 0.439444,0.573013 0.66921,0.851111 0.229766,0.2781 0.465913,0.550267 0.708484,0.817005 0.242571,0.266736 0.491831,0.528003 0.746724,0.782898 0.254895,0.254893 0.515645,0.503637 0.782381,0.746207 0.266738,0.242571 0.539422,0.478718 0.817522,0.708484 0.278098,0.229766 0.561614,0.453246 0.850594,0.669727 0.288979,0.216479 0.583253,0.426188 0.882633,0.628902 0.29938,0.202714 0.603824,0.398578 0.913123,0.587044 0.309298,0.188467 0.623324,0.369383 0.942061,0.543119 0.318737,0.173738 0.642273,0.34015 0.969967,0.498678 0.327693,0.158528 0.659634,0.309331 0.995805,0.452169 0.336169,0.142838 0.676444,0.277443 1.020609,0.40411 0.344165,0.126665 0.692185,0.245519 1.043864,0.355533 0.351679,0.110015 0.707372,0.211494 1.066085,0.304375 0.358711,0.09288 0.720457,0.176914 1.085722,0.252181 0.365263,0.07527 0.734022,0.141782 1.105359,0.198954 0.371335,0.05717 0.745485,0.105065 1.122412,0.14366 0.376925,0.0386 0.756397,0.0678 1.138431,0.08733 0.382036,0.01954 0.766755,0.02946 1.153418,0.02946 0.386665,0 0.770866,-0.0099 1.152902,-0.02946 0.382034,-0.01954 0.762023,-0.04874 1.138948,-0.08733 0.376927,-0.0386 0.751077,-0.08649 1.122412,-0.14366 0.371336,-0.05717 0.73Line truncated
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
With This Script it is possible to make boolean Operations on Shapes.
|
||||
The style of the resulting shape will be the style of the highest ranking Element that was used.
|
||||
The ranking of the elements is based on their background. The "denser" the background, the higher the ranking (the order of backgroundstyles is shown below). If they have the same background the opacity will decide. If thats also the same its decided by the order they were created.
|
||||
The ranking is also important for the difference operation, so a transparent object for example will cut a hole into a solid object.
|
||||

|
||||

|
||||
|
||||
|
||||
See documentation for more details:
|
||||
https://zsviczian.github.io/obsidian-excalidraw-plugin/ExcalidrawScriptsEngine.html
|
||||
|
||||
```javascript
|
||||
*/
|
||||
if(!ea.verifyMinimumPluginVersion || !ea.verifyMinimumPluginVersion("1.9.20")) {
|
||||
new Notice("This script requires a newer version of Excalidraw. Please install the latest version.");
|
||||
return;
|
||||
}
|
||||
const ShadowGroupMarker = "ShadowCloneOf-";
|
||||
|
||||
const elements = ea.getViewSelectedElements().filter(
|
||||
el=>["ellipse", "rectangle", "diamond"].includes(el.type) ||
|
||||
el.groupIds.some(id => id.startsWith(ShadowGroupMarker)) ||
|
||||
(["line", "arrow"].includes(el.type) && el.roundness === null)
|
||||
);
|
||||
if(elements.length === 0) {
|
||||
new Notice ("Select ellipses, rectangles or diamonds");
|
||||
return;
|
||||
}
|
||||
|
||||
const PolyBool = ea.getPolyBool();
|
||||
const polyboolAction = await utils.suggester(["union (a + b)", "intersect (a && b)", "difference (a - b)", "reversed difference (b - a)", "xor"], [
|
||||
PolyBool.union, PolyBool.intersect, PolyBool.difference, PolyBool.differenceRev, PolyBool.xor
|
||||
], "What would you like todo with the object");
|
||||
|
||||
const shadowClones = elements.filter(element => element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
shadowClones.forEach(shadowClone => {
|
||||
let parentId = shadowClone.groupIds
|
||||
.filter(id => id.startsWith(ShadowGroupMarker))[0]
|
||||
.slice(ShadowGroupMarker.length);
|
||||
const shadowCloneIndex = elements.findIndex(element => element.id == parentId);
|
||||
if (shadowCloneIndex == -1) return;
|
||||
elements[shadowCloneIndex].backgroundColor = shadowClone.backgroundColor;
|
||||
elements[shadowCloneIndex].fillStyle = shadowClone.fillStyle;
|
||||
})
|
||||
const borderElements = elements.filter(element => !element.groupIds.some(id => id.startsWith(ShadowGroupMarker)));
|
||||
groups = ea.getMaximumGroups(borderElements);
|
||||
groups = groups.map((group) => group.sort((a, b) => RankElement(b) - RankElement(a)));
|
||||
groups.sort((a, b) => RankElement(b[0]) - RankElement(a[0]));
|
||||
|
||||
ea.style.strokeColor = groups[0][0].strokeColor;
|
||||
ea.style.backgroundColor = groups[0][0].backgroundColor;
|
||||
ea.style.fillStyle = groups[0][0].fillStyle;
|
||||
ea.style.strokeWidth = groups[0][0].strokeWidth;
|
||||
ea.style.strokeStyle = groups[0][0].strokeStyle;
|
||||
ea.style.roughness = groups[0][0].roughness;
|
||||
ea.style.opacity = groups[0][0].opacity;
|
||||
|
||||
const basePolygons = groups.shift().map(element => traceElement(element));
|
||||
const toolPolygons = groups.flatMap(group => group.map(element => traceElement(element)));
|
||||
|
||||
const result = polyboolAction({
|
||||
regions: basePolygons,
|
||||
inverted: false
|
||||
}, {
|
||||
regions: toolPolygons,
|
||||
inverted: false
|
||||
});
|
||||
const polygonHierachy = subordinateInnerPolygons(result.regions);
|
||||
drawPolygonHierachy(polygonHierachy);
|
||||
ea.deleteViewElements(elements);
|
||||
ea.addElementsToView(false,false,true);
|
||||
return;
|
||||
|
||||
|
||||
|
||||
function traceElement(element) {
|
||||
const diamondPath = (diamond) => [
|
||||
SxVEC(1/2, [0, diamond.height]),
|
||||
SxVEC(1/2, [diamond.width, 0]),
|
||||
addVec([SxVEC(1/2, [0, diamond.height]), ([diamond.width, 0])]),
|
||||
addVec([SxVEC(1/2, [diamond.width, 0]), ([0, diamond.height])]),
|
||||
SxVEC(1/2, [0, diamond.height])
|
||||
];
|
||||
const rectanglePath = (rectangle) => [
|
||||
[0,0],
|
||||
[0, rectangle.height],
|
||||
[rectangle.width, rectangle.height],
|
||||
[rectangle.width, 0],
|
||||
[0, 0]
|
||||
]
|
||||
const ellipsePath = (ellipse) => {
|
||||
const angle = ellipse.angle;
|
||||
const width = ellipse.width;
|
||||
const height = ellipse.height;
|
||||
const ellipseAtPoint = (t) => {
|
||||
const spanningVector = [width/2*Math.cos(t), height/2*Math.sin(t)];
|
||||
const baseVector = [width/2, height/2];
|
||||
return addVec([spanningVector, baseVector]);
|
||||
}
|
||||
let points = [];
|
||||
step = (2*Math.PI)/64
|
||||
for (let t = 0; t < 2*Math.PI; t = t + step) {
|
||||
points.push(ellipseAtPoint(t));
|
||||
}
|
||||
return points;
|
||||
}
|
||||
let polygon;
|
||||
let correctForPolygon = [0, 0];
|
||||
switch (element.type) {
|
||||
case "diamond":
|
||||
polygon = diamondPath(element);
|
||||
break;
|
||||
case "rectangle":
|
||||
polygon = rectanglePath(element);
|
||||
break;
|
||||
case "ellipse":
|
||||
polygon = ellipsePath(element);
|
||||
break;
|
||||
case "line":
|
||||
case "arrow":
|
||||
if (element.angle != 0) {
|
||||
let smallestX = 0;
|
||||
let smallestY = 0;
|
||||
element.points.forEach(point => {
|
||||
if (point[0] < smallestX) smallestX = point[0];
|
||||
if (point[1] < smallestY) smallestY = point[1];
|
||||
});
|
||||
polygon = element.points.map(point => {
|
||||
return [
|
||||
point[0] -= smallestX,
|
||||
point[1] -= smallestY
|
||||
];
|
||||
});
|
||||
correctForPolygon = [smallestX, smallestY];
|
||||
break;
|
||||
}
|
||||
if (element.roundness) {
|
||||
new Notice("This script does not work with curved lines or arrows yet!");
|
||||
return [];
|
||||
}
|
||||
polygon = element.points;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (element.angle == 0) return polygon.map(v => addVec([v, [element.x, element.y]]));
|
||||
|
||||
polygon = polygon.map(v => addVec([v, SxVEC(-1/2, [element.width, element.height])]));
|
||||
polygon = rotateVectorsByAngle(polygon, element.angle);
|
||||
return polygon.map(v => addVec([v, [element.x, element.y], SxVEC(1/2, [element.width, element.height]), correctForPolygon]));
|
||||
}
|
||||
|
||||
function RankElement(element) {
|
||||
let score = 0;
|
||||
const backgroundRank = [
|
||||
"dashed",
|
||||
"none",
|
||||
"hachure",
|
||||
"zigzag",
|
||||
"zigzag-line",
|
||||
"cross-hatch",
|
||||
"solid"
|
||||
]
|
||||
score += (backgroundRank.findIndex((fillStyle) => fillStyle == element.fillStyle) + 1) * 10;
|
||||
if (element.backgroundColor == "transparent") score -= 100;
|
||||
if (element.points && getVectorLength(element.points[element.points.length - 1]) > 8) score -= 100;
|
||||
if (score < 0) score = 0;
|
||||
score += element.opacity / 100;
|
||||
return score;
|
||||
}
|
||||
|
||||
function drawPolygonHierachy(polygonHierachy) {
|
||||
const backgroundColor = ea.style.backgroundColor;
|
||||
const strokeColor = ea.style.strokeColor;
|
||||
const setInnerStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = "transparent";
|
||||
}
|
||||
const setBorderStyle = () => {
|
||||
ea.style.backgroundColor = "transparent";
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
const setFilledStyle = () => {
|
||||
ea.style.backgroundColor = backgroundColor;
|
||||
ea.style.strokeColor = strokeColor;
|
||||
}
|
||||
|
||||
polygonHierachy.forEach(polygon => {
|
||||
setFilledStyle();
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
if (polygon.innerPolygons.length === 0) {
|
||||
ea.addLine(path);
|
||||
return;
|
||||
}
|
||||
const outerBorder = path;
|
||||
const innerPolygons = addInnerPolygons(polygon.innerPolygons);
|
||||
path = path.concat(innerPolygons.backgroundPath);
|
||||
path.push(polygon.path[0]);
|
||||
setInnerStyle();
|
||||
const backgroundId = ea.addLine(path);
|
||||
setBorderStyle();
|
||||
const outerBorderId = ea.addLine(outerBorder)
|
||||
const innerBorderIds = innerPolygons.borderPaths.map(path => ea.addLine(path));
|
||||
const allIds = [innerBorderIds, outerBorderId, backgroundId].flat();
|
||||
ea.addToGroup(allIds);
|
||||
const background = ea.getElement(backgroundId);
|
||||
background.groupIds.push(ShadowGroupMarker + outerBorderId);
|
||||
});
|
||||
}
|
||||
|
||||
function addInnerPolygons(polygonHierachy) {
|
||||
let firstPath = [];
|
||||
let secondPath = [];
|
||||
let borderPaths = [];
|
||||
polygonHierachy.forEach(polygon => {
|
||||
let path = polygon.path;
|
||||
path.push(polygon.path[0]);
|
||||
borderPaths.push(path);
|
||||
firstPath = firstPath.concat(path);
|
||||
secondPath.push(polygon.path[0]);
|
||||
drawPolygonHierachy(polygon.innerPolygons);
|
||||
});
|
||||
return {
|
||||
backgroundPath: firstPath.concat(secondPath.reverse()),
|
||||
borderPaths: borderPaths
|
||||
};
|
||||
}
|
||||
|
||||
function subordinateInnerPolygons(polygons) {
|
||||
const polygonObjectPrototype = (polygon) => {
|
||||
return {
|
||||
path: polygon,
|
||||
innerPolygons: []
|
||||
};
|
||||
}
|
||||
|
||||
const insertPolygonIntoHierachy = (polygon, hierarchy) => {
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygon[pointIndex], polygonObject.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
hierarchy[i].innerPolygons = insertPolygonIntoHierachy(polygon, hierarchy[i].innerPolygons);
|
||||
return hierarchy;
|
||||
}
|
||||
}
|
||||
polygon = polygonObjectPrototype(polygon);
|
||||
for (let i = 0; i < hierarchy.length; i++) {
|
||||
const polygonObject = hierarchy[i];
|
||||
let inside = null;
|
||||
let pointIndex = 0;
|
||||
do {
|
||||
inside = pointInPolygon(polygonObject.path[pointIndex], polygon.path);
|
||||
pointIndex++
|
||||
} while (inside === null);
|
||||
if (inside) {
|
||||
polygon.innerPolygons.push(hierarchy.splice(i, 1)[0]);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
hierarchy.push(polygon);
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
let polygonHierachy = [];
|
||||
polygons.forEach(polygon => {
|
||||
polygonHierachy = insertPolygonIntoHierachy(polygon, polygonHierachy);
|
||||
})
|
||||
|
||||
return polygonHierachy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given point lays in the polygon
|
||||
* @param point array [x, y]
|
||||
* @param polygon array [[x, y], ...]
|
||||
* @returns true if inside, false if not, null if the point is on one of the polygons vertecies
|
||||
*/
|
||||
function pointInPolygon(point, polygon) {
|
||||
const x = point[0];
|
||||
const y = point[1];
|
||||
let inside = false;
|
||||
|
||||
// odd even test if point is in polygon
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i][0];
|
||||
const yi = polygon[i][1];
|
||||
const xj = polygon[j][0];
|
||||
const yj = polygon[j][1];
|
||||
|
||||
const intersect =
|
||||
yi > y !== yj > y &&
|
||||
x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
|
||||
|
||||
if (intersect) {
|
||||
inside = !inside;
|
||||
}
|
||||
|
||||
if ((x === xi && y === yi) || (x === xj && y === yj)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return inside;
|
||||
}
|
||||
|
||||
|
||||
function getVectorLength(vector) {
|
||||
return Math.sqrt(vector[0]**2+vector[1]**2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two Vectors together
|
||||
*/
|
||||
function addVec(vectors) {
|
||||
return vectors.reduce((acc, vec) => [acc[0] + vec[0], acc[1] + vec[1]], [0, 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of the vector
|
||||
*/
|
||||
function negVec(vector) {
|
||||
return [-vector[0], -vector[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies Vector with a scalar
|
||||
*/
|
||||
function SxVEC(scalar, vector) {
|
||||
return [vector[0] * scalar, vector[1] * scalar];
|
||||
}
|
||||
|
||||
function rotateVector (vec, ang) {
|
||||
var cos = Math.cos(ang);
|
||||
var sin = Math.sin(ang);
|
||||
return [vec[0] * cos - vec[1] * sin, vec[0] * sin + vec[1] * cos];
|
||||
}
|
||||
|
||||
function rotateVectorsByAngle(vectors, angle) {
|
||||
const cosAngle = Math.cos(angle);
|
||||
const sinAngle = Math.sin(angle);
|
||||
|
||||
const rotationMatrix = [
|
||||
[cosAngle, -sinAngle],
|
||||
[sinAngle, cosAngle]
|
||||
];
|
||||
|
||||
return applyTranformationMatrix(vectors, rotationMatrix);
|
||||
}
|
||||
|
||||
function applyTranformationMatrix(vectors, transformationMatrix) {
|
||||
const result = [];
|
||||
for (const vector of vectors) {
|
||||
const x = vector[0];
|
||||
const y = vector[1];
|
||||
|
||||
const newX = transformationMatrix[0][0] * x + transformationMatrix[0][1] * y;
|
||||
const newY = transformationMatrix[1][0] * x + transformationMatrix[1][1] * y;
|
||||
|
||||
result.push([newX, newY]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<path
|
||||
d="m 24.000085,1.5001668 c -0.386664,0 -0.771381,0.00992 -1.153418,0.029456 -0.382035,0.019538 -0.761505,0.048738 -1.138431,0.087333 -0.376928,0.038595 -0.751077,0.086489 -1.122412,0.1436604 -0.371337,0.057172 -0.740095,0.1231708 -1.105359,0.1984375 -0.365266,0.075267 -0.72701,0.1598168 -1.085722,0.2526978 -0.358713,0.092881 -0.714405,0.1943596 -1.066085,0.304374 C 16.976978,2.6261398 16.62896,2.7444758 16.284794,2.8711426 15.940628,2.9978093 15.600354,3.132931 15.264185,3.275769 14.928014,3.4186072 14.596073,3.5694093 14.26838,3.7279378 13.940685,3.8864665 13.617667,4.0523606 13.29893,4.2260986 12.980192,4.3998368 12.66565,4.5812681 12.356352,4.7697347 12.047052,4.9582013 11.74261,5.1540648 11.443229,5.356779 11.143849,5.5594932 10.849575,5.7692003 10.560596,5.9856812 10.271615,6.2021619 9.9881012,6.4251244 9.7100016,6.654891 9.4319021,6.8846574 9.1592182,7.1213204 8.8924805,7.3638916 8.6257427,7.6064628 8.3649942,7.8552043 8.1100993,8.1100993 7.8552043,8.3649942 7.6064628,8.6257427 7.3638916,8.8924805 7.1213204,9.1592182 6.8846574,9.4319021 6.654891,9.7100016 6.4251244,9.9881012 6.2021619,10.271615 5.9856812,10.560596 5.7692003,10.849575 5.5594932,11.143849 5.356779,11.443229 5.1540648,11.74261 4.9582013,12.047052 4.7697347,12.356352 4.5812681,12.66565 4.3998368,12.980192 4.2260986,13.29893 4.0523606,13.617667 3.8864665,13.940685 3.7279378,14.26838 3.5694093,14.596073 3.4186072,14.928014 3.275769,15.264185 3.132931,15.600354 2.9978093,15.940628 2.8711426,16.284794 2.7444758,16.62896 2.6261398,16.976978 2.5161255,17.328658 c -0.1100144,0.35168 -0.2114932,0.707372 -0.3043742,1.066085 -0.092881,0.358712 -0.177431,0.720456 -0.2526978,1.085722 -0.075267,0.365264 -0.1412659,0.734022 -0.1984375,1.105359 -0.057171,0.371335 -0.1050652,0.745484 -0.1436604,1.122412 -0.038595,0.376926 -0.067795,0.756396 -0.087333,1.138431 -0.019538,0.382037 -0.029456,0.766754 -0.029456,1.153418 0,0.386665 0.00992,0.770865 0.029456,1.152902 0.019538,0.382035 0.048738,0.762022 0.087333,1.138948 0.038595,0.376927 0.086489,0.751076 0.1436604,1.122412 0.057172,0.371337 0.1231708,0.739578 0.1984375,1.104842 0.075267,0.365266 0.1598168,0.727526 0.2526978,1.086239 0.092881,0.358713 0.1943598,0.713888 0.3043742,1.065568 0.1100143,0.35168 0.2283503,0.699698 0.3550171,1.043864 0.1266667,0.344166 0.2617884,0.684439 0.4046264,1.02061 0.1428382,0.336169 0.2936403,0.668627 0.4521688,0.996321 0.1585287,0.327695 0.3244228,0.650712 0.4981608,0.96945 0.1737382,0.318738 0.3551695,0.632763 0.5436361,0.942061 0.1884666,0.3093 0.3843301,0.613742 0.5870443,0.913123 0.2027142,0.299381 0.4124213,0.593654 0.6289022,0.882633 0.2164807,0.288981 0.4394432,0.573012 0.6692098,0.851111 0.2297664,0.2781 0.4664294,0.550267 0.7090006,0.817005 0.2425712,0.266737 0.4913127,0.528002 0.7462077,0.782898 0.2548949,0.254894 0.5156434,0.503637 0.7823812,0.746207 0.2667377,0.242572 0.5394216,0.478717 0.8175211,0.708484 0.2780996,0.229767 0.5616134,0.453246 0.8505944,0.669727 0.288979,0.216481 0.583253,0.426188 0.882633,0.628902 0.299381,0.202714 0.603823,0.398577 0.913123,0.587044 0.309298,0.188467 0.62384,0.369381 0.942578,0.54312 0.318737,0.173737 0.641755,0.340148 0.96945,0.498677 0.327693,0.158529 0.659634,0.309331 0.995805,0.452169 0.336169,0.142838 0.676443,0.277443 1.020609,0.40411 0.344166,0.126665 0.692184,0.24552 1.043864,0.355533 0.304779,0.09534 0.613889,0.181052 0.923975,0.26355 0.08249,0.310063 0.168215,0.618701 0.263549,0.923458 0.110015,0.351679 0.228351,0.699699 0.355018,1.043864 0.126665,0.344165 0.261788,0.684439 0.404626,1.02061 0.142838,0.336169 0.29364,0.668111 0.452169,0.995804 0.158528,0.327694 0.324423,0.65123 0.498161,0.969967 0.173736,0.318737 0.355169,0.632763 0.543636,0.942061 0.188465,0.309299 0.38433,0.613743 0.587044,0.913123 0.202714,0.29938 0.412422,0.593654 0.628902,0.882633 0.216481,0.288981 0.439444,0.573013 0.66921,0.851111 0.229766,0.2781 0.465913,0.550267 0.708484,0.817005 0.242571,0.266736 0.491831,0.528003 0.746724,0.782898 0.254895,0.254893 0.515645,0.503637 0.782381,0.746207 0.266738,0.242571 0.539422,0.478718 0.817522,0.708484 0.278098,0.229766 0.561614,0.453246 0.850594,0.669727 0.288979,0.216479 0.583253,0.426188 0.882633,0.628902 0.29938,0.202714 0.603824,0.398578 0.913123,0.587044 0.309298,0.188467 0.623324,0.369383 0.942061,0.543119 0.318737,0.173738 0.642273,0.34015 0.969967,0.498678 0.327693,0.158528 0.659634,0.309331 0.995805,0.452169 0.336169,0.142838 0.676444,0.277443 1.020609,0.40411 0.344165,0.126665 0.692185,0.245519 1.043864,0.355533 0.351679,0.110015 0.707372,0.211494 1.066085,0.304375 0.358711,0.09288 0.720457,0.176914 1.085722,0.252181 0.365263,0.07527 0.734022,0.141782 1.105359,0.198954 0.371335,0.05717 0.745485,0.105065 1.122412,0.14366 0.376925,0.0386 0.756397,0.0678 1.138431,0.08733 0.382036,0.01954 0.766755,0.02946 1.153418,0.02946 0.386665,0 0.770866,-0.0099 1.152902,-0.02946 0.382034,-0.01954 0.762023,-0.04874 1.138948,-0.08733 0.376927,-0.0386 0.751077,-0.08649 1.122412,-0.14366 0.371336,-0.05717 0.73Line truncated
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
Reference in new issue
Block a user