102 lines
2.6 KiB
C++
102 lines
2.6 KiB
C++
#ifndef HELPERPOLY3_H
|
|
#define HELPERPOLY3_H
|
|
|
|
#include "../../../geo/Point2.h"
|
|
#include "../../../geo/Point3.h"
|
|
#include "../../../geo/BBox2.h"
|
|
#include "../../../geo/BBox3.h"
|
|
#include "../../../floorplan/v2/Floorplan.h"
|
|
#include "../../../grid/Grid.h"
|
|
|
|
/** helper class for polygon methods */
|
|
struct HelperPoly3 {
|
|
|
|
BBox2 bbox_cm;
|
|
std::vector<Point2> points_cm;
|
|
|
|
/** empty ctor */
|
|
HelperPoly3() {
|
|
;
|
|
}
|
|
|
|
/** ctor from floorplan-polygon */
|
|
HelperPoly3(const Floorplan::FloorOutlinePolygon& poly) {
|
|
for (Point2 p : poly.poly.points) { add(p * 100); }
|
|
}
|
|
|
|
/** ctor from floorplan-quad */
|
|
HelperPoly3(const Floorplan::Quad3& quad) {
|
|
add(quad.p1*100); add(quad.p2*100); add(quad.p3*100); add(quad.p4*100);
|
|
}
|
|
|
|
/** ctor from floorplan-polygon */
|
|
HelperPoly3(const Floorplan::Polygon2& poly) {
|
|
for (Point2 p : poly.points) { add(p * 100); }
|
|
}
|
|
|
|
void add(const Point2 p) {
|
|
points_cm.push_back(p);
|
|
bbox_cm.add(p);
|
|
}
|
|
|
|
void add(const Point3& p) {
|
|
points_cm.push_back(p.xy());
|
|
bbox_cm.add(p.xy());
|
|
}
|
|
|
|
/** does the polygon contain the given point (in cm)? */
|
|
bool contains(const Point2 p_cm) const {
|
|
|
|
// not within bbox? -> not within polygon
|
|
if (!bbox_cm.contains(p_cm)) {return false;}
|
|
|
|
// ensure the point is at least a bit outside of the polygon
|
|
const float x1_cm = bbox_cm.getMin().x - 17.71920;
|
|
const float y1_cm = bbox_cm.getMin().y - 23.10923891;
|
|
|
|
// construct line between point outside of the polygon and the point in question
|
|
const Line2 l(x1_cm, y1_cm, p_cm.x, p_cm.y);
|
|
|
|
// determine the number of intersections
|
|
int hits = 0;
|
|
const int cnt = points_cm.size();
|
|
for (int i = 0; i < cnt; ++i) {
|
|
const Point2 p1 = points_cm[(i+0)%cnt];
|
|
const Point2 p2 = points_cm[(i+1)%cnt];
|
|
const Line2 l12(p1, p2);
|
|
if (l12.getSegmentIntersection(l)) {++hits;}
|
|
}
|
|
|
|
// inside or outside?
|
|
return ((hits % 2) == 1);
|
|
|
|
}
|
|
|
|
/** call a user-function for each GRID-ALIGNED point within the polygon */
|
|
void forEachGridPoint(const int gridSize_cm, std::function<void(int x_cm, int y_cm)> callback) const {
|
|
|
|
int x1 = std::floor(bbox_cm.getMin().x / gridSize_cm) * gridSize_cm;
|
|
int x2 = std::ceil(bbox_cm.getMax().x / gridSize_cm) * gridSize_cm;
|
|
|
|
int y1 = std::floor(bbox_cm.getMin().y / gridSize_cm) * gridSize_cm;
|
|
int y2 = std::ceil(bbox_cm.getMax().y / gridSize_cm) * gridSize_cm;
|
|
|
|
// process each point within the (aligned) bbox
|
|
for (int y = y1; y <= y2; y += gridSize_cm) {
|
|
for (int x = x1; x <= x2; x += gridSize_cm) {
|
|
|
|
// does this point belong to the polygon?
|
|
if (!contains(Point2(x,y))) {continue;}
|
|
|
|
// call the callback
|
|
callback(x,y);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // HELPERPOLY3_H
|