I am creating a home styler using Three.JS. After creating a room that I want to allow user to generate x numbers of lights inside the room. The number of lights can be set by user. I want to automatically place the lights at the points that are equi-distant from each other as well as from the boundary line of the room (polygon).
Following are the approaches I used but have some limitations in it. The turf.js was used for these.
- Creating Voronoi Inside polygon: In this approach we can set the number of voronoi to be generated inside the polygon and placing the light on the center of each vornoi. But I voronoi sizes are not identical and are generated through random points inside polygon. Here is the code
clipVoronoiInsidePolygon() {
// Define your points
// Define a polygon to clip the Voronoi diagram to
this.clearAutoGeneratedLights();
const flatArray = this.convertVerticesToFlatArray();
if (flatArray.length == 0) return;
flatArray.push(flatArray[0]);
const polygon = turf.polygon([flatArray]);
const bbox = turf.bbox(polygon);
const points = turf.randomPoint(this.generateLight, { bbox: bbox });
// Generate the Voronoi diagram
const voronoiPolygons = turf.voronoi(points, { bbox: bbox });
// Clip each Voronoi cell with the polygon
const clippedVoronoiCells = voronoiPolygons.features
.map((cell) => turf.intersect(cell, polygon))
.filter(Boolean);
// Use clippedVoronoiCells as needed, for example, logging them
clippedVoronoiCells.map((vornoi) => {
// console.log(vornoi);
this.centerOfVornoi(vornoi?.geometry.coordinates);
});
}
- Cliping Square Grid inside Polygon: In this approach we the size of each box is identical and we can place the lights at the center of each box of the grid for making it equi-distant. But the number of boxes inside the polygon can not be adjusted. Hence user can not define the number of lights he needs.
clipSquareInsidePolygon() {
this.clearAutoGeneratedLights();
const flatArray = this.convertVerticesToFlatArray();
if (flatArray.length == 0) return;
flatArray.push(flatArray[0]);
const polygon = turf.polygon([flatArray]);
const targetCells = this.generateLight; // Assuming this is your desired number of cells
const area = turf.area(polygon);
// Calculate the side length of each cell to approximately achieve the target number of cells
// Assuming a square cell for simplicity: area of cell = side length^2
const desiredCellArea = area / targetCells; // in square meters
let sideLengthKilometers = Math.sqrt(desiredCellArea) / 1000; // Convert meters to kilometers
const bbox = turf.bbox(polygon);
const options = {
units: 'kilometers' as turf.Units,
size: sideLengthKilometers,
mask: polygon,
};
const squareGrid = turf.squareGrid(bbox, options.size, options);
squareGrid.features.map((box) =>
this.centerOfVornoi(box.geometry.coordinates)
);
}
This is what I have tried so far. About the tech I am using is Angular with Three JS.