adjusted 3D modeling for walls
refactoring new helper classes / methods
This commit is contained in:
88
geo/Line2.h
88
geo/Line2.h
@@ -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
|
||||
|
||||
10
geo/Point2.h
10
geo/Point2.h
@@ -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
125
geo/Polygon2.h
Normal 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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user