112 lines
2.9 KiB
C++
112 lines
2.9 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#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
|