diff --git a/index.html b/index.html
index 4ad59ad..99b498c 100644
--- a/index.html
+++ b/index.html
@@ -5,12 +5,6 @@
Geometric Pattern Generator
-
diff --git a/src/Tile.ts b/src/Tile.ts
index b0c4b90..46d61a2 100644
--- a/src/Tile.ts
+++ b/src/Tile.ts
@@ -53,7 +53,7 @@ class Tile {
// Draw the lines and add them to the linesGroup
for (const radius of radii) {
- const lines = this.createLine(radius, direction);
+ const lines = this.createPath(radius, direction);
linesGroup.appendChild(lines);
}
@@ -63,17 +63,22 @@ class Tile {
const largestRadius = radii[radii.length - 1];
// Convert the linesGroup.lines into an array
- Array.from(linesGroup.querySelectorAll("line")).forEach((line) => {
+ Array.from(linesGroup.querySelectorAll("path")).forEach((line) => {
// Extract the line start and end for the current line
const lineStart = {
- x: parseFloat(line.getAttribute("x1") as string),
- y: parseFloat(line.getAttribute("y1") as string),
+ x: parseFloat(line.getAttribute("d")?.split(" ")[1] as string),
+ y: parseFloat(line.getAttribute("d")?.split(" ")[2] as string),
+ // x: parseFloat(line.getAttribute("x1") as string),
+ // y: parseFloat(line.getAttribute("y1") as string),
};
const lineEnd = {
- x: parseFloat(line.getAttribute("x2") as string),
- y: parseFloat(line.getAttribute("y2") as string),
+ x: parseFloat(line.getAttribute("d")?.split(" ")[4] as string),
+ y: parseFloat(line.getAttribute("d")?.split(" ")[5] as string),
+ // x: parseFloat(line.getAttribute("x2") as string),
+ // y: parseFloat(line.getAttribute("y2") as string),
};
+ console.log("Line start:", lineStart, "Line end:", lineEnd);
// Determine if there is an intersection for the current line
const intersection = this.lineArcIntersection(
lineStart,
@@ -84,8 +89,29 @@ class Tile {
if (intersection) {
console.log("Intersection found", intersection);
- line.setAttribute("x1", String(intersection.x));
- line.setAttribute("y1", String(intersection.y));
+ console.log(
+ "Modify lines 'd' attribute '",
+ line.getAttribute("d"),
+ "'"
+ );
+ console.log(
+ "Updating arrtibute with this: `",
+ `M ${intersection.x} ${intersection.y} ${line
+ .getAttribute("d")
+ ?.split(" ")
+ .slice(4, 6)
+ .join(" ")}`,
+ "'"
+ );
+ line.setAttribute(
+ "d",
+ `M ${intersection.x} ${intersection.y} ${line
+ .getAttribute("d")
+ ?.split(" ")
+ .slice(4, 6)
+ .join(" ")}`
+ );
+ // line.setAttribute("y1", String(intersection.y));
} else {
console.log("No intersection found");
}
@@ -138,6 +164,38 @@ class Tile {
return lines;
}
+ // Maybe the line is causing problem? (I don't seem to be able to join a line to a path so make the lines paths?)
+ createPath(radius: number, direction: "horizontal" | "vertical"): SVGElement {
+ console.log(
+ "Creating a single path with direction",
+ direction,
+ "and length",
+ radius
+ );
+ const paths = document.createElementNS("http://www.w3.org/2000/svg", "g");
+ const pathOffset = 0;
+
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
+
+ // Horizontal Lines start at x1=0 y1=radius and finish at x2=100, y2=radius
+ // Vertical Lines start at x1=radius y1=0 and finish at x2=radius, y2=100
+ let d;
+ if (direction === "horizontal") {
+ d = `M 0 ${radius} L 100 ${radius}`;
+ } else {
+ d = `M ${radius} 0 L ${radius} 100`;
+ }
+
+ path.setAttribute("d", d);
+ path.setAttribute("stroke", "black");
+ path.setAttribute("stroke-width", "1");
+ path.setAttribute("fill", "none");
+
+ paths.appendChild(path);
+
+ return paths;
+ }
+
// return an SVG arc for the given start coordinates and radius between the start and end angle
createArc(
cx: number,
diff --git a/src/index.ts b/src/index.ts
index f8c4e95..7ea3ccd 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,9 +1,10 @@
import Tile from "./Tile";
+import { joinClosePaths } from "./utils";
// Create a grid of patterned tiles
const grid = document.getElementById("grid");
-const numRows = 10;
-const numCols = 12;
+const numRows = 2;
+const numCols = 2;
const outerSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg");
outerSVG.setAttribute("viewBox", `0 0 ${numCols * 100} ${numRows * 100}`);
@@ -27,15 +28,30 @@ for (let row = 0; row < numRows; row++) {
// Define the SVG element using the tile content
const tileGroup = tile.element;
// Apply a grid offset and rotation to the tile
- tileGroup.setAttribute(
- "transform",
- `translate(${col * 100} ${row * 100}) rotate(${rotation} 50 50)`
- );
+ // tileGroup.setAttribute(
+ // "transform",
+ // `translate(${col * 100} ${row * 100}) rotate(${rotation} 50 50)`
+ // );
// Append the SVG element 'tileGroup' to the SVG
- outerSVG?.appendChild(tileGroup);
+ // outerSVG?.appendChild(tileGroup);
+ // Iterate through the children of tileGroup and append them directly to outerSVG
+ while (tileGroup.firstChild) {
+ const child = tileGroup.firstChild;
+ // Check if the child is an SVGElement
+ if (child instanceof SVGElement) {
+ // Apply a grid offset and rotation to the child element
+ child.setAttribute(
+ "transform",
+ `translate(${col * 100} ${row * 100}) rotate(${rotation} 50 50)`
+ );
+ }
+ outerSVG?.appendChild(child);
+ }
}
}
+joinClosePaths(outerSVG, 5); // Add this line after creating the grid
+
// SVG Export (Save (Download) an SVG when the download button is clicked)
const downloadButton = document.getElementById("download-svg");
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..3dd0555
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,64 @@
+export const joinClosePaths = (outerSVG: SVGSVGElement, threshold: number) => {
+ const paths = Array.from(outerSVG.querySelectorAll("path"));
+
+ for (let i = 0; i < paths.length; i++) {
+ // console.log("Picking a path");
+ for (let j = i + 1; j < paths.length; j++) {
+ // console.log("Comparing to all other paths");
+ const path1 = paths[i];
+ const path2 = paths[j];
+
+ const path1D = path1.getAttribute("d") as string;
+ const path2D = path2.getAttribute("d") as string;
+
+ const path1Start = path1D.split(" ").slice(1, 3);
+ const path1End = path1D.split(" ").slice(-2);
+
+ const path2Start = path2D.split(" ").slice(1, 3);
+ const path2End = path2D.split(" ").slice(-2);
+
+ const start1 = {
+ x: parseFloat(path1Start[0]),
+ y: parseFloat(path1Start[1]),
+ };
+ const end1 = { x: parseFloat(path1End[0]), y: parseFloat(path1End[1]) };
+ const start2 = {
+ x: parseFloat(path2Start[0]),
+ y: parseFloat(path2Start[1]),
+ };
+ const end2 = { x: parseFloat(path2End[0]), y: parseFloat(path2End[1]) };
+
+ const combinations = [
+ { a: start1, b: start2 },
+ { a: start1, b: end2 },
+ { a: end1, b: start2 },
+ { a: end1, b: end2 },
+ ];
+
+ for (const combination of combinations) {
+ // console.log("Comparing combinations...");
+ const dist = Math.hypot(
+ combination.a.x - combination.b.x,
+ combination.a.y - combination.b.y
+ );
+ if (threshold >= dist) {
+ console.log("too far to join");
+ }
+ if (dist < threshold) {
+ console.log("Found close path ends...");
+ path1.setAttribute(
+ "d",
+ `${path1D} L ${combination.b.x} ${combination.b.y} ${path2D
+ .split(" ")
+ .slice(3)
+ .join(" ")}`
+ );
+ outerSVG.removeChild(path2);
+ paths.splice(j, 1);
+ j--;
+ break;
+ }
+ }
+ }
+ }
+};