Distribution of n number of equi-distant point in polygon

26 views Asked by At

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.

  1. 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);
    });
  }

  1. 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.

0

There are 0 answers