geometric shape example
Hello everyone! I have a problem and would like to know the names of algorithms that could solve it.
Suppose I have a geometric shape, such as a .shp file, and a predefined number of points that I want to allocate within this shape, while maintaining a minimum distance from the edge. What would be the most effective way to allocate these points so that they maintain the greatest possible distance from each other, meet the predefined number of points, and respect the minimum distance from the edge? Is there an algorithm that can help me solve this problem, especially considering that the geometric shape could be very irregular?
I tried creating grids along the geometric shape and allocating points in the middle of each grid, but the distribution is not good.
def _generate_systematic_sample_points(self, shp, plot_area):
if self.sample_number < 1:
max_number_of_points = math.ceil((self.sample_number * self.total_area) / plot_area)
else:
max_number_of_points = self.sample_number
grid_number = math.ceil(math.sqrt(max_number_of_points))
extent = shp.extent()
x_min, y_min, x_max, y_max = extent.xMinimum(), extent.yMinimum(), extent.xMaximum(), extent.yMaximum()
if not (np.isfinite(x_min) and np.isfinite(y_min) and np.isfinite(x_max) and np.isfinite(y_max)):
QgsMessageLog.logMessage("Layer extent contains infinite or NaN values.", 'Your Plugin Name', Qgis.Critical)
return None
if x_min >= x_max or y_min >= y_max:
QgsMessageLog.logMessage("Invalid range of x or y values.", 'Your Plugin Name', Qgis.Critical)
return None
side_length = math.sqrt(plot_area)
x_spacing = (x_max - x_min) / grid_number
y_spacing = (y_max - y_min) / grid_number
valid_points = []
offset = 0
while len(valid_points) < max_number_of_points and offset < side_length:
for i in range(grid_number):
for j in range(grid_number):
x = x_min + j * x_spacing + offset
y = y_min + i * y_spacing + offset
if x > x_max or y > y_max:
continue
square_centroid = QgsPointXY(x + side_length / 2, y + side_length / 2)
point = QgsGeometry.fromPointXY(square_centroid)
if self._check_point_within_polygons(point, shp) and self._check_points_distance(point, plot_area,
valid_points):
valid_points.append(point)
if len(valid_points) >= max_number_of_points:
break
if len(valid_points) >= max_number_of_points:
break
offset += side_length / 2
if len(valid_points) < max_number_of_points:
remaining_points = max_number_of_points - len(valid_points)
attempts = 0
max_attempts = 3000
while remaining_points > 0 and attempts < max_attempts:
x = np.random.uniform(x_min, x_max)
y = np.random.uniform(y_min, y_max)
point = QgsGeometry.fromPointXY(QgsPointXY(x, y))
if self._check_point_within_polygons(point, shp) and self._check_points_distance(point, plot_area,
valid_points):
valid_points.append(point)
remaining_points -= 1
attempts += 1
if len(valid_points) < max_number_of_points:
QMessageBox.warning(self.dlg, "Warning!",
"Unable to generate plots with the established criteria. Only the possible plots were generated.")
if valid_points:
point_layer = self.create_point_layer(valid_points, shp.crs())
return point_layer
else:
QgsMessageLog.logMessage("Could not generate plots with the established criteria.", 'Your Plugin Name',
Qgis.Critical)
return None