/* * © 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 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 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