From 596173e25aaee8846255eef98798ac929efed337 Mon Sep 17 00:00:00 2001 From: sebvtl Date: Mon, 25 Nov 2024 17:20:02 +0000 Subject: [PATCH] =?UTF-8?q?T=C3=A9l=C3=A9verser=20les=20fichiers=20vers=20?= =?UTF-8?q?"Triangulator"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Triangulator/Triangulator.jsx | 1325 +++++++++++++++++++++++++++++++++ 1 file changed, 1325 insertions(+) create mode 100644 Triangulator/Triangulator.jsx diff --git a/Triangulator/Triangulator.jsx b/Triangulator/Triangulator.jsx new file mode 100644 index 0000000..31653d0 --- /dev/null +++ b/Triangulator/Triangulator.jsx @@ -0,0 +1,1325 @@ +//(c) www.illustratorscripts.com + + +(function () { + //hue variation of color of triangles + var HUE_VAR = 20; + //saturation variation of triangles + var SAT_VAR = 10; + //lightness variation of triangles + var LIGHT_VAR = 10; + + //additional points to add to shape as vertices + var NUM_POINTS = 60 + + //setting this to [R,G,B], 0..255, ie: COL=[12,20,255] + //will override selection color being picked + + var COL; + + if (ScriptUI.environment.keyboardState.altKey) + NUM_POINTS = parseInt(prompt("enter point density. recommended range is 100..10000", 100)) + + + var doc; + + + + function main() { + + if (app.documents.length == 0 || app.selection.length != 1 || !(app.selection[0].constructor.name == "PathItem" || app.selection[0].constructor.name == "CompoundPathItem")) { + alert(''' +Triangulator.jsx. +Select single path or compund path. Text should be +converted to outlines first. Press [ALT] when starting script for additional options. +Check for more at illustratorscripts.com + '''); + return; + } + + clearConsole(); + + doc = app.activeDocument; + var selectedItem = doc.selection[0] + + var holes = []; + var outerPath = null; + + //converts compounds to holes/outer paths + if (selectedItem.constructor.name == "CompoundPathItem") { + for (p = 0; p < selectedItem.pathItems.length; p++) { + //ignore small holes + if (Math.abs(selectedItem.pathItems[p].area) < 30) + continue; + holes.push(flattenPath(selectedItem.pathItems[p])); + } + if (holes.length == 1 && outerPath == null) { + outerPath = holes[0]; + holes = []; + } else { + var minx = holes[0][0][0]; + var outer = 0; + for (p = 0; p < holes.length; p++) { + for (q = 0; q < holes[p].length; q++) { + if (holes[p][q][0] < minx) { + minx = holes[p][q][0]; + outer = p; + } + } + } + outerPath = holes[outer]; + holes.splice(outer, 1); + } + } else //or just one path + outerPath = flattenPath(selectedItem); + + if (!outerPath) { + alert("Bad path"); + return; + } + + var dd; + var fillRGB; + try { + if (selectedItem.pathItems) + dd = selectedItem.pathItems[0].fillColor + else + if (!selectedItem.filled) throw "not filled" + else + dd = selectedItem.fillColor + + fillRGB = getRGBFromColor(dd); + + } catch (e) { + trace(e) + fillRGB = [255, 255, 255] + } + + + COL = COL || fillRGB + + + var pathA = cutHolesInPath(outerPath, holes) + + var points = []; + + var rnd = NUM_POINTS; + for (var i = 0; i < rnd; i++) { + var B = selectedItem.geometricBounds; + var x = B[0] + Math.random() * (B[2] - B[0]); + var y = B[1] + Math.random() * (B[3] - B[1]); + if (pointInsidePoly([x, y], pathA)) { + points.push([x, y]) + } + + } + points = points.concat(pathA) + + // Triangulate the points using Delaunay triangulation + var triangles = Delaunay.triangulate(points); + // Create a new layer for the triangulated shape + //change data format + var triangles2 = []; + + for (var i = 0; i < triangles.length; i += 3) { + var triangle = [triangles[i], triangles[i + 1], triangles[i + 2]]; + triangles2.push(triangle); + } + + + drawTriangles2(triangles2, points, pathA) + + } + + + /////////////////////////////////// geom + + //132532 + + + + function drawTriangles2(triangles, points,outerPath) { + + + var layer = doc.layers.add(); + layer.name = "Triangulated Shape"; + + + // Construct a map from point indices to arrays of adjacent triangles + // indexas - taskas, taskas turi masyva trikampiu kurie eina per ji + var adj = {}; + for (var i = 0; i < triangles.length; i++) { + //kampu taskai + var a = triangles[i][0]; + var b = triangles[i][1]; + var c = triangles[i][2]; + //jei kampas neturi dezutes, sukuriam jam + if (!adj[a]) adj[a] = []; + if (!adj[b]) adj[b] = []; + if (!adj[c]) adj[c] = []; + //i ta kampa padedam trikampio nr + adj[a].push(i); + adj[b].push(i); + adj[c].push(i); + } + + var processedPoints = {} + var processedTriangles = {} + var l = points.length; + + //::::::::::: FAUX SHADOW + + for (var i = 0; i < l; i++) { + var toContinue = false; + //pick random point + var p = ~~(Math.random() * l); + if (processedPoints[p]) + continue; + + processedPoints[p] = true; + + //kazkur bugas, nzn, jau velu krc + if (!adj[p]) continue; + //check all triangles around that point, make sure all unprocessed + for (var j = 0; j < adj[p].length; j++) { + + var triangle = triangles[adj[p][j]]; + //even one triangle processed, we break out + if (processedTriangles[triangle]) { + toContinue = true + break; + } + + //::::::::: uncomment bellow for consistant shadows, } must be uncommented too + // } + + // if (toContinue) continue; + + // //check all triangles aroudn that point again + + // for (var j = 0; j < adj[p].length; j++) { + // //check all triangles aroudn that point + // var triangle = triangles[adj[p][j]]; + + //::::::::: end uncomment + + processedTriangles[triangle] = true; + var a = triangle[0]; + var b = triangle[1]; + var c = triangle[2]; + var v = points[p]; + + var trianglePoints = [points[a], points[b], points[c]] + var cc = calculateTriangleCentroid(trianglePoints); + + if (!pointInsidePoly(cc, outerPath)) + continue; + + + var angle = Math.atan2(cc[1] - v[1], cc[0] - v[0]) + angle = Math.abs(angle) + + trianglePoints.push(trianglePoints[0]); + drawOneTriangle(trianglePoints, angle, layer) + } + } + //::::::: REMAINING TRIANGLES + //return; + for (var i = 0; i < triangles.length; i++) { + var triangle = triangles[i]; + if (processedTriangles[triangle]) + continue; + var a = triangle[0]; + var b = triangle[1]; + var c = triangle[2]; + var trianglePoints = [points[a], points[b], points[c]] + var cc = calculateTriangleCentroid(trianglePoints); + if (!pointInsidePoly(cc, outerPath)) + continue; + + trianglePoints.push(trianglePoints[0]); + drawOneTriangle(trianglePoints, Math.random() * 2, layer) + + + + } + + + + } + + function drawOneTriangle(trianglePoints, angle, layer, dbg) { + var drawnPath = doc.pathItems.add(); + drawnPath.setEntirePath(trianglePoints); + variateOneLIGHTNESS(drawnPath, [HUE_VAR, SAT_VAR, -angle * LIGHT_VAR], COL) + drawnPath.stroked = true; + drawnPath.strokeWidth = .01 + drawnPath.moveToEnd(layer); + } + + + function setGradient(cell, pathItem, center) { + // Create a new gradient fill + var gc = getCellCenter(cell) + + var cx = center[0] - gc[0]; + var cy = center[1] - gc[1]; + + var gradient = doc.gradients.add(); + gradient.type = GradientType.RADIAL; + + // set the center point and radius of the gradient + gradient.gradientStops[0].rampPoint = 0; + gradient.gradientStops[1].rampPoint = 100; + gradient.gradientStops[0].midPoint = 80; + gradient.gradientStops[1].midPoint = 80; + var col0 = new RGBColor(); + col0.green = 0, col0.blue = 0, col0.red = 0; + var col1 = new RGBColor(); + //col1.green=255,col1.blue=255,col1.red=255; + col1.green = 155, col1.blue = 155, col1.red = 155; + + gradient.gradientStops[0].color = col1; + gradient.gradientStops[1].color = col0; + + // // translate the gradient origin to [cx, cy] + // var tx = cx - gradient.gradientStops[0].rampPoint / 100 * (cx - gradient.gradientStops[1].rampPoint); + // var ty = cy - gradient.gradientStops[0].rampPoint / 100 * (cy - gradient.gradientStops[1].rampPoint); + // gradient.gradientTransform = new Matrix(1, 0, 0, 1, cx, cy); + + // trace(tx) + + // Apply the gradient fill to the path + + + var gc = new GradientColor(); + gc.gradient = gradient; + //gc.matrix=concatenateTranslationMatrix(gc.matrix,cx,cy) + //gc.origin=center + + + var moveMatrix = getTranslationMatrix(cx, cy); + var rotateMatrix = concatenateRotationMatrix(moveMatrix, 0); + var totalMatrix = concatenateScaleMatrix(rotateMatrix, 110, 110); + + + + + pathItem.fillColor = gc; + pathItem.fillOverprint = false + pathItem.transform(totalMatrix, false, false, true, false, 0, Transformation.CENTER); + + } + function drawPath(a, n) { + + var drawnPath = doc.pathItems.add(); + try { + drawnPath.setEntirePath(a); + } catch (e) { + } + + drawnPath.stroked = true; + drawnPath.strokeColor = doc.swatches[n].color + + } + function setGradient2(pathItem, center) { + // Create a new gradient fill + var gradient = doc.gradients.add(); + gradient.type = GradientType.RADIAL; // Set the gradient type to radial + gradient.gradientOrigin = [center[1], center[0]] + + + // Set the center of the gradient to [cx, cy] + var centerColor = gradient.gradientStops.add(); + centerColor.color = doc.defaultFillColor; // Use the default fill color + centerColor.location = 0; + + // Set the outer edge of the gradient to the maximum distance of the path from the center + var outerColor = gradient.gradientStops.add(); + outerColor.color = doc.defaultFillColor; // Use the default fill color + outerColor.location = 1; + + // Apply the gradient fill to the path + + + var color_of_gradient = new GradientColor(); + color_of_gradient.gradient = gradient; + + pathItem.fillColor = color_of_gradient; + } + function drawPath(a, n) { + + var drawnPath = doc.pathItems.add(); + try { + drawnPath.setEntirePath(a); + } catch (e) { + } + + drawnPath.stroked = true; + drawnPath.strokeColor = doc.swatches[n].color + + } + + + function curve4(x1, y1, //Anchor1 + x2, y2, //Control1 + x3, y3, //Control2 + x4, y4, //Anchor2 + nSteps // Flattening value + ) { + var pointList = new Array(); + var dx1 = x2 - x1; + var dy1 = y2 - y1; + var dx2 = x3 - x2; + var dy2 = y3 - y2; + var dx3 = x4 - x3; + var dy3 = y4 - y3; + + var subdiv_step = 1.0 / (nSteps + 1); + var subdiv_step2 = subdiv_step * subdiv_step; + var subdiv_step3 = subdiv_step * subdiv_step * subdiv_step; + + var pre1 = 3.0 * subdiv_step; + var pre2 = 3.0 * subdiv_step2; + var pre4 = 6.0 * subdiv_step2; + var pre5 = 6.0 * subdiv_step3; + + var tmp1x = x1 - x2 * 2.0 + x3; + var tmp1y = y1 - y2 * 2.0 + y3; + + var tmp2x = (x2 - x3) * 3.0 - x1 + x4; + var tmp2y = (y2 - y3) * 3.0 - y1 + y4; + + var fx = x1; + var fy = y1; + + var dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3; + var dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3; + + var ddfx = tmp1x * pre4 + tmp2x * pre5; + var ddfy = tmp1y * pre4 + tmp2y * pre5; + + var dddfx = tmp2x * pre5; + var dddfy = tmp2y * pre5; + + var step = nSteps; + + pointList.push([x1, y1]); // Start Here + while (step--) { + fx += dfx; + fy += dfy; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pointList.push([fx, fy]); + } + // pointList.push ([x4, y4]); // Last step must go exactly to x4, y4 + return pointList; + } + + function flattenPath(obj) { + var newpath = new Array(); + var curveList; + var pt, nextpt; + var isFlattened = false; + + if (!obj.hasOwnProperty("pathPoints")) + return null; + + for (pt = 0; pt < obj.pathPoints.length; pt++) { + nextpt = pt + 1; + if (nextpt == obj.pathPoints.length) + nextpt = 0; + if (obj.pathPoints[pt].anchor[0] == obj.pathPoints[pt].rightDirection[0] && obj.pathPoints[pt].anchor[1] == obj.pathPoints[pt].rightDirection[1] && + obj.pathPoints[nextpt].anchor[0] == obj.pathPoints[nextpt].leftDirection[0] && obj.pathPoints[nextpt].anchor[1] == obj.pathPoints[nextpt].leftDirection[1]) { + newpath.push(obj.pathPoints[pt].anchor); + } else { + isFlattened = true; + curveList = curve4(obj.pathPoints[pt].anchor[0], obj.pathPoints[pt].anchor[1], + obj.pathPoints[pt].rightDirection[0], obj.pathPoints[pt].rightDirection[1], + obj.pathPoints[nextpt].leftDirection[0], obj.pathPoints[nextpt].leftDirection[1], + obj.pathPoints[nextpt].anchor[0], obj.pathPoints[nextpt].anchor[1], + 2); + newpath = newpath.concat(curveList); + } + } + // Make path round + // newpath.push (newpath[0]); + return newpath; + } + + + function removeWalls(current, neighbor) { + var c0 = getCellCenter(current); + var c1 = getCellCenter(neighbor); + + + drawPath([c0, c1], 6) + } + + function drawVoronoi(cells, centers, points, doc) { + // Create a new layer to draw the Voronoi cells on + var layer = doc.layers.add(); + layer.name = "Voronoi Diagram"; + + // Loop through each cell and draw its edges and fill + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + + // Create a new path object for the cell's edges + var edges = doc.pathItems.add(); + edges.filled = false; + edges.stroked = true; + edges.strokeWidth = 0.5; + + cell.push(cell[0]) + edges.setEntirePath(cell); + + + + // setGradient(cell, edges, points[centers[i]]) + } + } + + + // Helper function to compute the circumcenter of a triangle + function circumcenter(a, b, c) { + // Define the coordinates of the points + var ax = a[0], ay = a[1]; + var bx = b[0], by = b[1]; + var cx = c[0], cy = c[1]; + + // Define the distances between the points + var a2 = ax * ax + ay * ay; + var b2 = bx * bx + by * by; + var c2 = cx * cx + cy * cy; + + // Define the denominator of the formula + var d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)); + + // Define the coordinates of the circumcenter + var ux = ((a2 * (by - cy) + b2 * (cy - ay) + c2 * (ay - by)) / d); + var uy = ((a2 * (cx - bx) + b2 * (ax - cx) + c2 * (bx - ax)) / d); + + // Return the coordinates of the circumcenter as an array + return [[ux, uy], d]; + } + + function sortCellPaths(cells) { + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + + // Sort the points in the cell by their angle with respect to the cell center + var center = getCellCenter(cell); + cell.sort(function (a, b) { + var angleA = Math.atan2(a[1] - center[1], a[0] - center[0]); + var angleB = Math.atan2(b[1] - center[1], b[0] - center[0]); + return angleA - angleB; + }); + } + return cells + } + + + + + // Helper function to compute the center of a Voronoi cell + //not corect! just basic center of path + function getCellCenter(cell) { + var sumX = 0, sumY = 0; + for (var i = 0; i < cell.length; i++) { + sumX += cell[i][0]; + sumY += cell[i][1]; + } + return [sumX / cell.length, sumY / cell.length]; + } + + //from Jongware + function cutHolesInPath(path, holes) { + if (getWinding(path) < 0) + path.reverse(); + + // Remove holes by joining them with the outer edge + if (holes.length) { + for (hh = 0; hh < holes.length; hh++) { + var h = holes[hh]; + if (getWinding(h) > 0) + h.reverse(); + + var maxpt = 0; + for (i = 1; i < h.length; i++) { + if (h[i][0] > h[maxpt][0] || (h[i][0] == h[maxpt][0] && h[i][1] < h[maxpt][1])) + maxpt = i; + } + while (maxpt > 0) { + h.push(h.shift()); + maxpt--; + } + } + holes.sort(function (a, b) { if (a[0][0] > b[0][0]) return -1; if (a[0][0] < b[0][0]) return 1; return (a[0][1] < b[0][1]) ? 1 : -1; }); + for (hh = 0; hh < holes.length; hh++) { + var h = holes[hh]; + var maxpt = 0; + + for (i = 1; i < h.length; i++) + if (h[i][0] > h[maxpt][0] || (h[i][0] == h[maxpt][0] && h[i][1] < h[maxpt][1])) + maxpt = i; + + var d2 = null; + var closestpt; + for (i = 0; i < path.length; i++) { + if (path[i][0] > h[maxpt][0]) { + if (d2 == null) { + d2 = ClosestPointOnLine(h[maxpt], [path[i], path[(i + 1) % path.length]])[1]; + closestpt = i; + } else { + var dd2 = ClosestPointOnLine(h[maxpt], [path[i], path[(i + 1) % path.length]])[1]; + if (dd2 < d2) { + d2 = dd2; + closestpt = i; + } + } + } + } + + path.splice(closestpt, 0, [path[closestpt][0], path[closestpt][1] + 0.1]); + closestpt++; + h.splice(maxpt, 0, [h[maxpt][0], h[maxpt][1]]); + + h[maxpt][1] -= 0.1; + for (var i = maxpt; i >= 0; i--) { + path.splice(closestpt, 0, h[i]); + } + for (var i = h.length - 1; i > maxpt; i--) { + path.splice(closestpt, 0, h[i]); + } + } + } + + return path + } + function getWinding(path) { + // Return area of a simple (ie. non-self-intersecting) polygon. + // Will be negative for counterclockwise winding. + var i, next; + var accum = 0; + for (i = 0; i < path.length - 1; i++) { + next = i + 1; + accum += path[next][0] * path[i][1] - path[i][0] * path[next][1]; + } + next = 0; + accum += path[next][0] * path[i][1] - path[i][0] * path[next][1]; + return accum / 2; + } + function calculateTriangleCentroid(tri) { + //util_inspect_properties(tri) + var centerX = (tri[0][0] + tri[1][0] + tri[2][0]) / 3; + var centerY = (tri[0][1] + tri[1][1] + tri[2][1]) / 3; + return [centerX, centerY]; + } + + function pointInsidePoly(pt, poly) { + for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) + ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1] < poly[i][1])) + && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) + && (c = !c); + + return c; + } + + function drawTriangles(triangles, points, outerPath) { + var layer = doc.layers.add(); + layer.name = "Triangulated Shape"; + + for (var i = 0; i < triangles.length; i += 3) { + var triangle = [[points[triangles[i]][0], points[triangles[i]][1]], + [points[triangles[i + 1]][0], points[triangles[i + 1]][1]], + [points[triangles[i + 2]][0], points[triangles[i + 2]][1]], + [points[triangles[i]][0], points[triangles[i]][1]] + ] + + if (pointInsidePoly(calculateTriangleCentroid(triangle), outerPath)) { + var drawnPath = doc.pathItems.add(); + + drawnPath.setEntirePath(triangle); + //drawnPath.filled = true; + //drawnPath.fillColor = new RGBColor(255, 0, 0); + variateOneLIGHTNESS(drawnPath, [0, 0, -Math.random() * 100], [255, 255, 255]) + drawnPath.stroked = true; + drawnPath.moveToEnd(layer); + } + } + } + + + function linePathIntersect(line, path) { + var x1 = line[0][0]; + var y1 = line[0][1]; + var x2 = line[1][0]; + var y2 = line[1][1]; + for (var i = 0; i < path.length - 1; i++) { + var x3 = path[i][0]; + var y3 = path[i][1]; + var x4 = path[i + 1][0]; + var y4 = path[i + 1][1]; + var den = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)); + if (den == 0) continue; + var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / den; + var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / den; + if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) { + return true; + } + } + return false; + } + + + function getPointsOfPath(selectedItem) { + + var pathA = []; + for (var i = 0; i < selectedItem.pathPoints.length; i++) { + var x = selectedItem.pathPoints[i].anchor[0]; + var y = selectedItem.pathPoints[i].anchor[1]; + pathA.push([x, y]); + } + return pathA; + + } + + + + + ////////maze + + + + + function getAdjacentCells(cells) { + var adj = {}; + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + for (var j = 0; j < cell.length; j++) { + var point = cell[j]; + if (!adj[point]) adj[point] = []; + //keeps index of cells + adj[point].push(i); + } + } + return adj; + } + + function generateMaze(neighbours, startCellIndex) { + var currentCell = neighbours[startCellIndex]; + visited[startCellIndex] = true; + + for (var i = 0; i < currentCell.length; i++) { + var neighbourIndex = currentCell[i]; + + // if the neighbour hasn't been visited, add it to the list of unvisited neighbours + if (!visited[neighbourIndex]) { + + if (Math.random() > .4) { + generateMaze(neighbours, neighbourIndex) + removeWalls(cells[startCellIndex], cells[neighbourIndex]); + + } + + } + } + + } + function getNeighbouringCells(cells) { + var neighbours = {}; + + // get cells adjacent to each vertex + var adjacentCells = getAdjacentCells(cells); + + // iterate over each cell + for (var i = 0; i < cells.length; i++) { + var cell = cells[i]; + var cellNeighbours = []; + + // check each vertex of the current cell + for (var j = 0; j < cell.length; j++) { + var vertex = cell[j]; + + // iterate over adjacent cells for the current vertex + for (var k = 0; k < adjacentCells[vertex].length; k++) { + var adjacentCellIndex = adjacentCells[vertex][k]; + + // add the adjacent cell index to the current cell's neighbours + if (adjacentCellIndex !== i && cellNeighbours.indexOf(adjacentCellIndex) === -1) { + cellNeighbours.push(adjacentCellIndex); + } + } + } + + neighbours[i] = cellNeighbours; + } + + return neighbours; + } + function generateMaze2(neighbours, startCellIndex) { + var visited = {}; + var stack = [startCellIndex]; + var maze = {}; + + // mark the starting cell as visited + visited[startCellIndex] = true; + + // set previous cell to starting cell + var prevIndex = startCellIndex; + + // loop until the stack is empty + while (stack.length > 0) { + var currentIndex = stack[stack.length - 1]; + var currentCell = neighbours[currentIndex]; + var unvisitedNeighbours = []; + + // check each neighbouring cell + for (var i = 0; i < currentCell.length; i++) { + var neighbourIndex = currentCell[i]; + + // if the neighbour hasn't been visited, add it to the list of unvisited neighbours + if (!visited[neighbourIndex]) { + unvisitedNeighbours.push(neighbourIndex); + } + } + + // if there are unvisited neighbours, pick one at random and remove the wall between the current cell and the chosen neighbour + if (unvisitedNeighbours.length > 0) { + var chosenIndex = Math.floor(Math.random() * unvisitedNeighbours.length); + var chosenCell = unvisitedNeighbours[chosenIndex]; + + // remove the wall between the current cell and the chosen neighbour + if (!maze[currentIndex]) { + maze[currentIndex] = []; + } + removeWalls(cells[currentIndex], cells[chosenCell]); + + if (!maze[chosenCell]) { + maze[chosenCell] = []; + } + maze[currentIndex].push(chosenCell); + maze[chosenCell].push(currentIndex); + + // mark the chosen neighbour as visited and add it to the stack + visited[chosenCell] = true; + stack.push(chosenCell); + + // update previous cell + prevIndex = currentIndex; + } else { + // backtracking: if there are no unvisited neighbours, remove the current cell from the stack and continue with the previous cell + stack.pop(); + currentIndex = prevIndex; + } + } + + return maze; + } + function drawTriangle(i) { + var triangle = + [[points[triangles2[i][0]][0], points[triangles2[i][0]][1]], + [points[triangles2[i][1]][0], points[triangles2[i][1]][1]], + [points[triangles2[i][2]][0], points[triangles2[i][2]][1]], + [points[triangles2[i][0]][0], points[triangles2[i][0]][1]] + ] + + var drawnPath = doc.pathItems.add(); + drawnPath.setEntirePath(triangle); + drawnPath.stroked = true; + + + } + + + + + /////////////////////////////////// misc + + + + + + + + + Array.prototype.indexOf = function (searchElement, fromIndex) { + var startIndex = fromIndex || 0; + var length = this.length; + + for (var i = startIndex; i < length; i++) { + if (this[i] == searchElement) { + return i; + } + } + + return -1; + }; + function clearConsole() { + return; + if (app.name === "ExtendScript Toolkit") { + app.clc(); + } else { + var estApp = BridgeTalk.getSpecifier("estoolkit"); + if (estApp) { + var bt = new BridgeTalk; + bt.target = estApp; + bt.body = "app.clc()"; + bt.send(); + } + } + } + function util_inspect_properties(f) { + $.writeln(f.reflect.name); + var props = f.reflect.properties; + var array = []; + for (var i = 0; i < props.length; i++) + try { + array.push(props[i].name + ": " + f[props[i].name]) + } catch (_) { } + array.sort(); + $.writeln(array.join("\r")); + } + + function traceON(v) { + return; + trace(JSON.stringify(v)) + } + + function trace() { + return; + var s = ""; + for (var i = 0; i < arguments.length; i++) { + s += arguments[i] + " " + } + $.writeln(s); + } + // Compute the distance from segment Line to Pt + // Returns [ Point, Distance ] + function ClosestPointOnLine(pt, line) { + var X1 = line[0][0], Y1 = line[0][1]; + var X2 = line[1][0], Y2 = line[1][1]; + var px = pt[0], py = pt[1]; + + var dx = X2 - X1; + var dy = Y2 - Y1; + + var nx, ny; + + if (dx == 0 && dy == 0) { + // It's a point not a line segment. + // dx = px - X1 + // dy = py - Y1 + // distance = Sqr(dx * dx + dy * dy) + nx = X1; + ny = Y1; + } else { + // Calculate the t that minimizes the distance. + var t = ((px - X1) * dx + (py - Y1) * dy) / (dx * dx + dy * dy); + + // See if this represents one of the segment's + // end points or a point in the middle. + if (t <= 0) { + nx = X1; + ny = Y1; + } else if (t >= 1) { + nx = X2; + ny = Y2; + } else { + nx = X1 + t * dx; + ny = Y1 + t * dy; + } + } + + dx = px - nx; + dy = py - ny; + + return [[nx, ny], Math.sqrt(dx * dx + dy * dy)]; + } + + + + function getCurrentColors() { + var doc = app.activeDocument; + var currentColors = {}; + var dd + var fillRGB + try { + dd = doc.defaultFillColor + fillRGB = getRGBFromColor(dd); + } catch (e) { + fillRGB = [255, 255, 255] + } + var fillRGBColor = getRGBColorFromArray(fillRGB); + currentColors.fill = fillRGBColor; + //!!!!!!!!!!! add try/cacth + var strokeRGB = getRGBFromColor(doc.defaultStrokeColor); + var strokeRGBColor = getRGBColorFromArray(strokeRGB); + currentColors.stroke = strokeRGBColor; + return currentColors; + } + function getRGBFromColor(color) { + + if (color.typename == "RGBColor") { + return [color.red, color.green, color.blue]; + } else if (color.typename == "GrayColor") { + return [color.gray, color.gray, color.gray]; + } else if (color.typename == "CMYKColor") { + var cyan = color.cyan / 100; + var magenta = color.magenta / 100; + var yellow = color.yellow / 100; + var black = color.black / 100; + + var red = 1 - Math.min(1, cyan * (1 - black) + black); + var green = 1 - Math.min(1, magenta * (1 - black) + black); + var blue = 1 - Math.min(1, yellow * (1 - black) + black); + + return [Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255)]; + } else { + return [0, 0, 0]; + } + } + function getRGBColorFromArray(rgbArray) { + var red = rgbArray[0]; + var green = rgbArray[1]; + var blue = rgbArray[2]; + + red = range(red, 0, 255); + green = range(green, 0, 255); + blue = range(blue, 0, 255); + + var rgbColor = new RGBColor(); + rgbColor.red = red; + rgbColor.green = green; + rgbColor.blue = blue; + return rgbColor; + } + function range(v, d, u) { + if (v > u) v = u; + if (v < d) v = d; + return v; + } + function rgbToHsl(color) { + var r = color.red / 255; + var g = color.green / 255; + var b = color.blue / 255; + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if (max == min) { + h = s = 0; + } else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return { + hue: Math.round(h * 360), + saturation: Math.round(s * 100), + lightness: Math.round(l * 100) + }; + } + function hslToRgb(h, s, l) { + var chroma = (1 - Math.abs((2 * l / 100) - 1)) * (s / 100); + var hueSegment = h / 60; + var x = chroma * (1 - Math.abs((hueSegment % 2) - 1)); + var r1, g1, b1; + if (hueSegment >= 0 && hueSegment < 1) { + r1 = chroma; + g1 = x; + b1 = 0; + } else if (hueSegment >= 1 && hueSegment < 2) { + r1 = x; + g1 = chroma; + b1 = 0; + } else if (hueSegment >= 2 && hueSegment < 3) { + r1 = 0; + g1 = chroma; + b1 = x; + } else if (hueSegment >= 3 && hueSegment < 4) { + r1 = 0; + g1 = x; + b1 = chroma; + } else if (hueSegment >= 4 && hueSegment < 5) { + r1 = x; + g1 = 0; + b1 = chroma; + } else { + r1 = chroma; + g1 = 0; + b1 = x; + } + var m = (l / 100) - (chroma / 2); + var r = Math.round((r1 + m) * 255); + var g = Math.round((g1 + m) * 255); + var b = Math.round((b1 + m) * 255); + return [r, g, b]; + } + + + function variateOneLIGHTNESS(p, h, cc) { + c = p.fillColor; + c = getRGBFromColor(c); + ///!!! + c = getRGBColorFromArray(cc ? cc : c); + c = rgbToHsl(c); + p.filled = true; + p.fillColor = getRGBColorFromArray(hslToRgb(c.hue + h[0] * Math.random() - h[0] / 2, c.saturation + h[1] * Math.random() - h[1] / 2, c.lightness + h[2])); + } + + var Delaunay; + +(function() { + "use strict"; + + var EPSILON = 1.0 / 1048576.0; + + function supertriangle(vertices) { + var xmin = Number.POSITIVE_INFINITY, + ymin = Number.POSITIVE_INFINITY, + xmax = Number.NEGATIVE_INFINITY, + ymax = Number.NEGATIVE_INFINITY, + i, dx, dy, dmax, xmid, ymid; + + for(i = vertices.length; i--; ) { + if(vertices[i][0] < xmin) xmin = vertices[i][0]; + if(vertices[i][0] > xmax) xmax = vertices[i][0]; + if(vertices[i][1] < ymin) ymin = vertices[i][1]; + if(vertices[i][1] > ymax) ymax = vertices[i][1]; + } + + dx = xmax - xmin; + dy = ymax - ymin; + dmax = Math.max(dx, dy); + xmid = xmin + dx * 0.5; + ymid = ymin + dy * 0.5; + + return [ + [xmid - 20 * dmax, ymid - dmax], + [xmid , ymid + 20 * dmax], + [xmid + 20 * dmax, ymid - dmax] + ]; + } + + function circumcircle(vertices, i, j, k) { + var x1 = vertices[i][0], + y1 = vertices[i][1], + x2 = vertices[j][0], + y2 = vertices[j][1], + x3 = vertices[k][0], + y3 = vertices[k][1], + fabsy1y2 = Math.abs(y1 - y2), + fabsy2y3 = Math.abs(y2 - y3), + xc, yc, m1, m2, mx1, mx2, my1, my2, dx, dy; + + /* Check for coincident points */ + if(fabsy1y2 < EPSILON && fabsy2y3 < EPSILON) + throw new Error("Eek! Coincident points!"); + + if(fabsy1y2 < EPSILON) { + m2 = -((x3 - x2) / (y3 - y2)); + mx2 = (x2 + x3) / 2.0; + my2 = (y2 + y3) / 2.0; + xc = (x2 + x1) / 2.0; + yc = m2 * (xc - mx2) + my2; + } + + else if(fabsy2y3 < EPSILON) { + m1 = -((x2 - x1) / (y2 - y1)); + mx1 = (x1 + x2) / 2.0; + my1 = (y1 + y2) / 2.0; + xc = (x3 + x2) / 2.0; + yc = m1 * (xc - mx1) + my1; + } + + else { + m1 = -((x2 - x1) / (y2 - y1)); + m2 = -((x3 - x2) / (y3 - y2)); + mx1 = (x1 + x2) / 2.0; + mx2 = (x2 + x3) / 2.0; + my1 = (y1 + y2) / 2.0; + my2 = (y2 + y3) / 2.0; + xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2); + yc = (fabsy1y2 > fabsy2y3) ? + m1 * (xc - mx1) + my1 : + m2 * (xc - mx2) + my2; + } + + dx = x2 - xc; + dy = y2 - yc; + return {i: i, j: j, k: k, x: xc, y: yc, r: dx * dx + dy * dy}; + } + + function dedup(edges) { + var i, j, a, b, m, n; + + for(j = edges.length; j; ) { + b = edges[--j]; + a = edges[--j]; + + for(i = j; i; ) { + n = edges[--i]; + m = edges[--i]; + + if((a === m && b === n) || (a === n && b === m)) { + edges.splice(j, 2); + edges.splice(i, 2); + break; + } + } + } + } + + Delaunay = { + triangulate: function(vertices, key) { + var n = vertices.length, + i, j, indices, st, open, closed, edges, dx, dy, a, b, c; + + /* Bail if there aren't enough vertices to form any triangles. */ + if(n < 3) + return []; + + /* Slice out the actual vertices from the passed objects. (Duplicate the + * array even if we don't, though, since we need to make a supertriangle + * later on!) */ + vertices = vertices.slice(0); + + if(key) + for(i = n; i--; ) + vertices[i] = vertices[i][key]; + + /* Make an array of indices into the vertex array, sorted by the + * vertices' x-position. Force stable sorting by comparing indices if + * the x-positions are equal. */ + indices = new Array(n); + + for(i = n; i--; ) + indices[i] = i; + + indices.sort(function(i, j) { + var diff = vertices[j][0] - vertices[i][0]; + return diff !== 0 ? diff : i - j; + }); + + /* Next, find the vertices of the supertriangle (which contains all other + * triangles), and append them onto the end of a (copy of) the vertex + * array. */ + st = supertriangle(vertices); + vertices.push(st[0], st[1], st[2]); + + /* Initialize the open list (containing the supertriangle and nothing + * else) and the closed list (which is empty since we havn't processed + * any triangles yet). */ + open = [circumcircle(vertices, n + 0, n + 1, n + 2)]; + closed = []; + edges = []; + + /* Incrementally add each vertex to the mesh. */ + for(i = indices.length; i--; edges.length = 0) { + c = indices[i]; + + /* For each open triangle, check to see if the current point is + * inside it's circumcircle. If it is, remove the triangle and add + * it's edges to an edge list. */ + for(j = open.length; j--; ) { + /* If this point is to the right of this triangle's circumcircle, + * then this triangle should never get checked again. Remove it + * from the open list, add it to the closed list, and skip. */ + dx = vertices[c][0] - open[j].x; + if(dx > 0.0 && dx * dx > open[j].r) { + closed.push(open[j]); + open.splice(j, 1); + continue; + } + + /* If we're outside the circumcircle, skip this triangle. */ + dy = vertices[c][1] - open[j].y; + if(dx * dx + dy * dy - open[j].r > EPSILON) + continue; + + /* Remove the triangle and add it's edges to the edge list. */ + edges.push( + open[j].i, open[j].j, + open[j].j, open[j].k, + open[j].k, open[j].i + ); + open.splice(j, 1); + } + + /* Remove any doubled edges. */ + dedup(edges); + + /* Add a new triangle for each edge. */ + for(j = edges.length; j; ) { + b = edges[--j]; + a = edges[--j]; + open.push(circumcircle(vertices, a, b, c)); + } + } + + /* Copy any remaining open triangles to the closed list, and then + * remove any triangles that share a vertex with the supertriangle, + * building a list of triplets that represent triangles. */ + for(i = open.length; i--; ) + closed.push(open[i]); + open.length = 0; + + for(i = closed.length; i--; ) + if(closed[i].i < n && closed[i].j < n && closed[i].k < n) + open.push(closed[i].i, closed[i].j, closed[i].k); + + /* Yay, we're done! */ + return open; + }, + contains: function(tri, p) { + /* Bounding box test first, for quick rejections */ + if (p[0] < tri[0][0] && p[0] < tri[1][0] && p[0] < tri[2][0] || + p[0] > tri[0][0] && p[0] > tri[1][0] && p[0] > tri[2][0] || + p[1] < tri[0][1] && p[1] < tri[1][1] && p[1] < tri[2][1] || + p[1] > tri[0][1] && p[1] > tri[1][1] && p[1] > tri[2][1]) + return null; + + var a = tri[1][0] - tri[0][0], + b = tri[2][0] - tri[0][0], + c = tri[1][1] - tri[0][1], + d = tri[2][1] - tri[0][1], + i = a * d - b * c; + + /* Degenerate tri. */ + if (i === 0.0) + return null; + + var u = (d * (p[0] - tri[0][0]) - b * (p[1] - tri[0][1])) / i, + v = (a * (p[1] - tri[0][1]) - c * (p[0] - tri[0][0])) / i; + + /* If we're outside the tri, fail */ + if (u < 0.0 || v < 0.0 || (u + v) > 1.0) + return null; + + return [u, v]; +}, + }; + + if(typeof module !== "undefined") + module.exports = Delaunay; +})(); + main() + +})(); +