// // Created by Scheaven on 2020/5/31. // #include "geometry_util.h" using namespace std; SPoint::_Point() {} SPoint::_Point(float x, float y) { this->x = x; this->y = y; this->z = 0; } SPoint::_Point(double a, double b, double c) { x = a; y = b; z = c; } float calDistance(SPoint A, SPoint B) { float x_d, y_d; x_d = A.x - B.x; y_d = A.y - B.y; float len = sqrt(x_d * x_d + 4*y_d * y_d); return len; } //bool Pt_in_Polygon(SPoint point, RegInfo* polygon) //{ // int nCross = 0; // for (int i = 0; i < polygon->count; ++i) // { // SPoint p1 = polygon[i]; // SPoint p2 = polygon[(i+1)%polygon->count]; // // if ( p1.y == p2.y ) // continue; // if ( p.y < min(p1.y, p2.y) ) // continue; // if ( p.y >= max(p1.y, p2.y) ) // continue; // // float x = (float)(p.y - p1.y) * (float)(p2.x - p1.x) / (float)(p2.y - p1.y) + p1.x; // // if ( x > p.x ) // { // nCross++; // } // // } // // if ((nCross % 2) == 1) // { // return true; // } // else // { // return false; // } //} float computeArea(const SPoint * pt,int n ) { float area0 = 0.f; for (int i = 0 ; i < n ; i++ ) { int j = (i+1)%n; area0 += pt[i].x * pt[j].y; area0 -= pt[i].y * pt[j].x; } return 0.5f * fabs(area0); } struct PointAngle{ SPoint p; float angle; }; float Polygon::area() const { return computeArea(pt,n); } static inline int cross(const SPoint* a,const SPoint* b) { return a->x * b->y - a->y * b->x; } static inline SPoint* vsub(const SPoint* a,const SPoint* b, SPoint* res) { res->x = a->x - b->x; res->y = a->y - b->y; return res; } static int line_sect(const SPoint* x0,const SPoint* x1,const SPoint* y0,const SPoint* y1, SPoint* res) { SPoint dx, dy, d; vsub(x1, x0, &dx); vsub(y1, y0, &dy); vsub(x0, y0, &d); float dyx = (float)cross(&dy, &dx); if (!dyx) return 0; dyx = cross(&d, &dx) / dyx; if (dyx <= 0 || dyx >= 1) return 0; res->x = int(y0->x + dyx * dy.x); res->y = int(y0->y + dyx * dy.y); return 1; } static int left_of(const SPoint* a,const SPoint* b,const SPoint* c) { SPoint tmp1, tmp2; int x; vsub(b, a, &tmp1); vsub(c, b, &tmp2); x = cross(&tmp1, &tmp2); return x < 0 ? -1 : x > 0; } static void poly_edge_clip(const Polygon* sub,const SPoint* x0,const SPoint* x1, int left, Polygon* res) { int i, side0, side1; SPoint tmp; const SPoint* v0 = sub->pt+ sub->n - 1; const SPoint* v1; res->clear(); side0 = left_of(x0, x1, v0); if (side0 != -left) res->add(*v0); for (i = 0; i < sub->n; i++) { v1 = sub->pt + i; side1 = left_of(x0, x1, v1); if (side0 + side1 == 0 && side0) /* last point and current straddle the edge */ if (line_sect(x0, x1, v0, v1, &tmp)) res->add(tmp); if (i == sub->n - 1) break; if (side1 != -left) res->add(*v1); v0 = v1; side0 = side1; } } static int poly_winding(const Polygon* p) { return left_of(p->pt, p->pt + 1, p->pt + 2); } void intersectPolygonSHPC(const Polygon * sub, const Polygon* clip, Polygon* res) { int i; Polygon P1,P2; Polygon *p1 = &P1; Polygon *p2 = &P2; Polygon *tmp; int dir = poly_winding(clip); poly_edge_clip(sub, clip->pt + clip->n - 1, clip->pt, dir, p2); for (i = 0; i < clip->n - 1; i++) { tmp = p2; p2 = p1; p1 = tmp; if(p1->n == 0) { p2->n = 0; break; } poly_edge_clip(p1, clip->pt + i, clip->pt + i + 1, dir, p2); } res->clear(); for (i = 0 ; i < p2->n ; i++) res->add(p2->pt[i]); } void intersectPolygonSHPC(const Polygon & sub,const Polygon& clip,Polygon& res) { intersectPolygonSHPC(&sub, &clip, &res); } Line::Line(SPoint a, SPoint b, bool _is_seg) { s = a; e = b; is_seg = _is_seg; } Line::Line() {} bool PointCmp(const SPoint &a,const SPoint &b,const SPoint ¢er) { if (a.x >= 0 && b.x < 0) return true; if (a.x == 0 && b.x == 0) return a.y > b.y; int det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y); if (det < 0) return true; if (det > 0) return false; int d1 = (a.x - center.x) * (a.x - center.x) + (a.y - center.y) * (a.y - center.y); int d2 = (b.x - center.x) * (b.x - center.y) + (b.y - center.y) * (b.y - center.y); return d1 > d2; } SPoint ClockwiseSortPoints(std::vector &vPoints) { SPoint center; double x = 0,y = 0; for (int i = 0;i < vPoints.size();i++) { x += vPoints[i].x; y += vPoints[i].y; } center.x = (int)x/vPoints.size(); center.y = (int)y/vPoints.size(); for(int i = 0;i < vPoints.size() - 1;i++) { for (int j = 0;j < vPoints.size() - i - 1;j++) { if (PointCmp(vPoints[j],vPoints[j+1],center)) { SPoint tmp = vPoints[j]; vPoints[j] = vPoints[j + 1]; vPoints[j + 1] = tmp; } } } return center; } SPoint add(const SPoint& lhs, const SPoint& rhs) { SPoint res; res.x = lhs.x + rhs.x; res.y = lhs.y + rhs.y; res.z = lhs.z + rhs.z; return res; } SPoint sub(const SPoint& lhs, const SPoint& rhs) { SPoint res; res.x = lhs.x - rhs.x; res.y = lhs.y - rhs.y; res.z = lhs.z - rhs.z; return res; } SPoint mul(const SPoint& p, double ratio) { SPoint res; res.x = p.x * ratio; res.y = p.y * ratio; res.z = p.z * ratio; return res; } SPoint div(const SPoint& p, double ratio) { SPoint res; res.x = p.x / ratio; res.y = p.y / ratio; res.z = p.z / ratio; return res; } bool equal(const SPoint& lhs, const SPoint& rhs) { return(lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); } double length(const SPoint& vec) { return (sqrt(pow(vec.x, 2) + pow(vec.y, 2) + pow(vec.z, 2))); } SPoint normalize(const SPoint& vec) { SPoint res; res = div(vec, length(vec)); return res; } double dotMultiply(const SPoint& op, const SPoint& p1, const SPoint& p2) { return ((p1.x - op.x) * (p2.x - op.x) + (p1.y - op.y) * (p2.y - op.y) + (p1.z - op.z) * (p2.z - op.z)); } double dotMultiply(const SPoint& vec1, const SPoint& vec2) { return(vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z); } SPoint multiply(const SPoint& op, const SPoint& p1, const SPoint& p2) { SPoint result; result.x = (p1.y - op.y) * (p2.z - op.z) - (p2.y - op.y) * (p1.z - op.z); result.y = (p1.z - op.z) * (p2.x - op.x) - (p2.z - op.z) * (p1.x - op.x); result.z = (p1.x - op.x) * (p2.y - op.y) - (p2.x - op.x) * (p1.y - op.y); return result; } SPoint multiply(const SPoint& vec1, const SPoint& vec2) { SPoint result; result.x = vec1.y * vec2.z - vec2.y * vec1.z; result.y = vec1.z * vec2.x - vec2.z * vec1.x; result.z = vec1.x * vec2.y - vec2.x * vec1.y; return result; } bool isponl(const SPoint& p, const Line& l) { SPoint line_vec = sub(l.e, l.s); SPoint point_vec1 = sub(p, l.s); SPoint point_vec2 = sub(p, l.e); SPoint mul_vec = multiply(line_vec, point_vec1); double dot = dotMultiply(point_vec1, point_vec2); if (l.is_seg) { if (equal(p,l.s) || equal(p,l.e)) return true; return (0.0 == length(mul_vec) && dot < 0.0); } else { return (0.0 == length(mul_vec)); } } double Cos(const SPoint& vec1, const SPoint& vec2) { SPoint unit_vec1 = normalize(vec1); SPoint unit_vec2 = normalize(vec2); return dotMultiply(unit_vec1, unit_vec2); } double Cos(const SPoint& op, const SPoint& p1, const SPoint& p2) { SPoint vec1 = sub(p1, op); SPoint vec2 = sub(p2, op); return Cos(vec1, vec2); } bool isSegIntersect(const Line& l1, const Line& l2, SPoint& inter_p) { SPoint line1 = sub(l1.e, l1.s); SPoint line2 = sub(l2.e, l2.s); SPoint norm1 = normalize(line1); SPoint norm2 = normalize(line2); if (l1.is_seg) { if (isponl(l1.s, l2)) { inter_p = l1.s; return true; } if (isponl(l1.e, l2)) { inter_p = l1.e; return true; } if (isponl(l2.s, l1)) { inter_p = l2.s; return true; } if (isponl(l2.e, l1)) { inter_p = l2.e; return true; } double dot1 = dotMultiply(multiply(sub(l2.s, l1.s), line1), multiply(sub(l2.e, l1.s), line1)); double dot2 = dotMultiply(multiply(sub(l1.s, l2.s), line2), multiply(sub(l1.e, l2.s), line2)); if (dot1 < 0.0 && dot2 < 0.0) { double t1 = length(multiply(sub(l1.s, l2.s), norm2)) / length(multiply(norm2, norm1)); double t2 = length(multiply(sub(l2.s, l1.s), norm1)) / length(multiply(norm1, norm2)); inter_p = add(l1.s, mul(norm1, t1)); return true; } else { return false; } } else { if (Cos(line1, line2) == 1.0) return false; double t1 = length(multiply(sub(l1.s, l2.s), norm2)) / length(multiply(norm2, norm1)); double t2 = length(multiply(sub(l2.s, l1.s), norm1)) / length(multiply(norm1, norm2)); inter_p = add(l1.s, mul(norm1, t1)); return true; } } // bool p_inPolygon(Point p, vector point_vec) // { // int nCross = 0; // for (int i = 0; i < point_vec.size(); ++i) // { // Point p1(point_vec[i].x, point_vec[i].y); // Point p2(point_vec[(i+1)%point_vec.size()].x, point_vec[(i+1)%point_vec.size()].y); // if ( p1.y == p2.y ) // continue; // if ( p.y < min(p1.y, p2.y) ) // continue; // if ( p.y >= max(p1.y, p2.y) ) // continue; // float x = (float)(p.y - p1.y) * (float)(p2.x - p1.x) / (float)(p2.y - p1.y) + p1.x; // if ( x > p.x ) // { // nCross++; // } // } // if ((nCross % 2) == 1) // { // return true; // } // else // { // return false; // } // }