adjusted 3D modeling for walls

refactoring
new helper classes / methods
This commit is contained in:
2018-07-22 13:47:07 +02:00
parent da06bacb6b
commit 8ea7b7f3b6
13 changed files with 693 additions and 104 deletions

View File

@@ -33,29 +33,41 @@ public:
// }
/** get intersection between these two lines (unlimited length!) */
bool getLineIntersection(const Line2& other, Point2& result) const {
float getAngle() const {
return std::atan2(p2.y-p1.y, p2.x-p1.x);
}
double bx = p2.x - p1.x;
double by = p2.y - p1.y;
void reverse() {
std::swap(p1, p2);
}
double dx = other.p2.x - other.p1.x;
double dy = other.p2.y - other.p1.y;
float getLength() const {
return p1.getDistance(p2);
}
double b_dot_d_perp = bx*dy - by*dx;
/** get intersection between these two lines (unlimited length!) */
bool getLineIntersection(const Line2& other, Point2& result) const {
if(b_dot_d_perp == 0) {return false;}
double bx = p2.x - p1.x;
double by = p2.y - p1.y;
double cx = other.p1.x - p1.x;
double cy = other.p1.y - p1.y;
double t = (cx*dy - cy*dx) / b_dot_d_perp;
double dx = other.p2.x - other.p1.x;
double dy = other.p2.y - other.p1.y;
result.x = p1.x + t * bx;
result.y = p1.y + t * by;
double b_dot_d_perp = bx*dy - by*dx;
return true;
if(b_dot_d_perp == 0) {return false;}
}
double cx = other.p1.x - p1.x;
double cy = other.p1.y - p1.y;
double t = (cx*dy - cy*dx) / b_dot_d_perp;
result.x = p1.x + t * bx;
result.y = p1.y + t * by;
return true;
}
bool getSegmentIntersection(const Line2& other) const {
@@ -207,4 +219,50 @@ public:
};
static inline bool intersects(const Line2& l1, const Line2& l2, bool limit, Point2& pos) {
// (sx1,sy1) + (dx1, dy1)*u = (sx2, sy2) + (dx2, dy2)*v
// solve((c+d*v-a)/b = (g+h*v-e)/f, v)
// solve((a+b*u-c)/d = (e+f*u-g)/h, u)
// bf != 0
// dh != 0
// df != bh // kollinear (b/d != f/h)
const float sx1 = l1.p1.x; // a
const float sy1 = l1.p1.y; // e
const float dx1 = l1.p2.x - l1.p1.x; // b
const float dy1 = l1.p2.y - l1.p1.y; // f
const float sx2 = l2.p1.x; // c
const float sy2 = l2.p1.y; // g
const float dx2 = l2.p2.x - l2.p1.x; // d
const float dy2 = l2.p2.y - l2.p1.y; // h
// collinear?
const float a1 = dx2*dy1;
const float a2 = dx1*dy2;
if (std::abs(a1-a2) < 0.0001) {return false;}
const float v = (dy1*(sx1-sx2) + dx1*(sy2-sy1)) / (dx2*dy1 - dx1*dy2);
const float u = (dy2*(sx1-sx2) + dx2*(sy2-sy1)) / (dx2*dy1 - dx1*dy2);
//const float x = sx2 + v*dx2;
//const float y = sy2 + v*dy2;
const float x = sx1 + u*dx1;
const float y = sy1 + u*dy1;
if (!limit || (u >= 0 && v >= 0 && u <= 1 && v <= 1)) {
pos = Point2(x,y);
return true;
}
return false;
}
#endif // LINE2D_H

View File

@@ -78,4 +78,14 @@ inline void swap(Point2& p1, Point2& p2) {
std::swap(p1.y, p2.y);
}
namespace std {
template <> struct hash<Point2> {
std::size_t operator()(const Point2& p) const {
uint32_t x = *((uint32_t*)&(p.x));
uint32_t y = *((uint32_t*)&(p.y));
return std::hash<uint32_t>()(x^y);
}
};
}
#endif // POINT2_H

125
geo/Polygon2.h Normal file
View File

@@ -0,0 +1,125 @@
#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

View File

@@ -55,6 +55,24 @@ public:
return *this;
}
/** switch between CW<->CCW */
void reverse() {
std::swap(p2, p3);
}
void rotate_deg(const Point3 rot) {
p1 = p1.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
p2 = p2.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
p3 = p3.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
}
// void ensureCCW() {
// Point3 norm = cross(p3-p1, p2-p1);
// if (norm.z < 0) {
// reverse();
// }
// }
Point3 getNormal() const {
return cross( p2-p1, p3-p1 ).normalized();
}