In actual I want to create a 2d styler and I will have place n number of lights in to that. Walls of the home can be polygon and we have to place n lights in that polygon such that each of them are are evenly distributed. Current I did some work work it is not actually working because it is actually consider the enlosing rectangle of the polygon and distributing lights in that.
Here is the example.
function distributePoints(polygon, numberOfPoints) {
const bounds = getPolygonBounds(polygon);
const area = polygonArea(polygon);
const spacing = Math.sqrt(area / numberOfPoints);
const cols = Math.floor((bounds.maxX - bounds.minX) / spacing);
const rows = Math.floor((bounds.maxY - bounds.minY) / spacing);
const distributedPoints = [];
for (let i = 0; i <= rows; i++) {
for (let j = 0; j <= cols; j++) {
const point = {
x: bounds.minX + j * spacing,
y: bounds.minY + i * spacing,
};
if (isPointInPolygon(point, polygon)) {
distributedPoints.push(point);
}
}
}
return distributedPoints;
}
function getPolygonBounds(polygon) {
let minX = Infinity;
let maxX = -Infinity;
let minY = Infinity;
let maxY = -Infinity;
polygon.points.forEach((point) => {
if (point.x < minX)
minX = point.x;
if (point.x > maxX)
maxX = point.x;
if (point.y < minY)
minY = point.y;
if (point.y > maxY)
maxY = point.y;
});
return { minX, maxX, minY, maxY };
}
function polygonArea(polygon) {
let area = 0;
const { points } = polygon;
const n = points.length;
for (let i = 0; i < n; i++) {
const j = (i + 1) % n;
area += points[i].x * points[j].y;
area -= points[j].x * points[i].y;
}
return Math.abs(area / 2.0);
}
function isPointInPolygon(point, polygon) {
let inside = false;
const { x, y } = point;
const { points } = polygon;
const n = points.length;
for (let i = 0, j = n - 1; i < n; j = i++) {
const xi = points[i].x, yi = points[i].y;
const xj = points[j].x, yj = points[j].y;
const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
if (intersect)
inside = !inside;
}
return inside;
}
// Generate a random polygon within the bounds of the SVG
function generateRandomPolygon(numberOfVertices, maxX, maxY) {
const points = [];
for (let i = 0; i < numberOfVertices; i++) {
points.push({
x: Math.random() * maxX,
y: Math.random() * maxY,
});
}
return { points };
}
function generateRandomSimplePolygon(numberOfVertices, maxX, maxY) {
const points = [];
// Generate random points
for (let i = 0; i < numberOfVertices; i++) {
points.push({
x: Math.random() * maxX,
y: Math.random() * maxY,
});
}
// Compute the centroid of the points
const centroid = points.reduce((acc, point) => {
acc.x += point.x / points.length;
acc.y += point.y / points.length;
return acc;
}, { x: 0, y: 0 });
// Sort points by angle from centroid to ensure a simple polygon
points.sort((a, b) => {
const angleA = Math.atan2(a.y - centroid.y, a.x - centroid.x);
const angleB = Math.atan2(b.y - centroid.y, b.x - centroid.x);
return angleA - angleB;
});
return { points };
}
const randomPolygon = generateRandomSimplePolygon(30, 700, 700);
const points = distributePoints(randomPolygon, 4);
renderVisualization(randomPolygon, points);
// Render the polygon and points on an SVG element
function renderVisualization(polygon, points) {
const svgNS = "http://www.w3.org/2000/svg";
const svgElement = document.createElementNS(svgNS, "svg");
svgElement.setAttribute("width", "700");
svgElement.setAttribute("height", "700");
svgElement.style.border = "1px solid black";
// Render the polygon
const polygonElement = document.createElementNS(svgNS, "polygon");
polygonElement.setAttribute("points", polygon.points.map((p) => `${p.x},${p.y}`).join(" "));
polygonElement.setAttribute("stroke", "black");
polygonElement.setAttribute("fill", "transparent");
svgElement.appendChild(polygonElement);
// Render the points
points.forEach((point) => {
const pointElement = document.createElementNS(svgNS, "circle");
pointElement.setAttribute("cx", point.x.toString());
pointElement.setAttribute("cy", point.y.toString());
pointElement.setAttribute("r", "3");
pointElement.setAttribute("fill", "red");
svgElement.appendChild(pointElement);
});
document.body.appendChild(svgElement);
}