This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/geo/Polygon2.h
frank 8ea7b7f3b6 adjusted 3D modeling for walls
refactoring
new helper classes / methods
2018-07-22 13:47:07 +02:00

126 lines
2.8 KiB
C++

#ifndef POLYGON2_H
#define POLYGON2_H
#include "Point2.h"
#include <vector>
#include "Line2.h"
#include "BBox2.h"
static bool polygonContainsPoint(const std::vector<Point2>& poly, const Point2 p);
class Polygon2 {
std::vector<Point2> pts;
public:
void add(const Point2 p) {
pts.push_back(p);
}
std::vector<Point2>::iterator begin() {return pts.begin();}
std::vector<Point2>::iterator end() {return pts.end();}
std::vector<Point2>::const_iterator begin() const {return pts.begin();}
std::vector<Point2>::const_iterator end() const {return pts.end();}
std::vector<Point2>& getVector() {return pts;}
Point2& operator [] (const size_t idx) {
return pts[idx];
}
/** get polygon as list of lines */
std::vector<Line2> getLines() const {
std::vector<Line2> res;
for (size_t i = 0; i < pts.size(); ++i) {
const Point2 p1 = pts[(i+0)];
const Point2 p2 = pts[(i+1)%pts.size()];
res.push_back(Line2(p1, p2));
}
return res;
}
struct CutRes {
Point2 p;
size_t i1,i2; // line, given by two points, within this poly
size_t j1,j2; // line, given by two points, within other, given poly
CutRes(Point2 p, size_t i1, size_t i2, size_t j1, size_t j2) : p(p), i1(i1), i2(i2), j1(j1), j2(j2) {;}
};
BBox2 getBBox() const {
BBox2 bb;
for (const Point2 p : pts) {bb.add(p);}
return bb;
}
bool contains(const Point2 p) const {
return polygonContainsPoint(pts, p);
}
std::vector<CutRes> getIntersections(const Polygon2& o, bool limit = true) const {
std::vector<CutRes> res;
for (size_t i = 0; i < pts.size(); ++i) {
const size_t i1 = (i+0);
const size_t i2 = (i+1) % pts.size();
const Line2 l1(pts[i1], pts[i2]);
for (size_t j = 0; j < o.pts.size(); ++j) {
const size_t j1 = (j+0);
const size_t j2 = (j+1) % o.pts.size();
const Line2 l2(o.pts[j1], o.pts[j2]);
Point2 p;
//if (l1.getSegmentIntersection(l2, p)) {
if (intersects(l1, l2, limit, p)) {
res.push_back(CutRes(p, i1,i2, j1,j2));
}
}
}
return res;
}
};
/** does the given polygon (list of points) contain the given point? */
static bool polygonContainsPoint(const std::vector<Point2>& poly, const Point2 p) {
// https://en.wikipedia.org/wiki/Winding_number
// http://geomalgorithms.com/a03-_inclusion.html
// BBox2 bb
// bb.grow(Point2(0.001, 0.001));
// if (!bb.contains(p)) {return false;}
double sum = 0;
for (size_t i = 0; i < poly.size(); ++i) {
const Point2 p1 = poly[i];
const Point2 p2 = poly[(i+1)%poly.size()];
const Point2 d1 = (p1-p).normalized();
const Point2 d2 = (p2-p).normalized();
sum += std::acos(dot(d1, d2));
}
// normalize (x = number of windings)
const double x = sum / M_PI / 2;
// only look at the fractional part
//const double y = x - std::floor(x);
return std::abs(x) >= 0.975;// && (std::abs(y) >= 0.9 || std::abs(y) < 0.1);
}
#endif // POLYGON2_H