arma::vec2 intersectionPoint(const Line2 & l1, const Line2 & l2) { const double num1 = l1.b() * l2.c() - l2.b() * l1.c(); const double num2 = l2.a() * l1.c() - l1.a() * l2.c(); const double denom = l1.a() * l2.b() - l2.a() * l1.b(); arma::vec2 pt; pt << num1 / denom << endr << num2 / denom; return pt; }
Solution split(const Line2& line, bool up) const { Solution result; result.points = points; for (const auto& facet: facets) { if (doIntersect(facet.polygon, line)) { Facet facet1; facet1.transformation = facet.transformation; Facet facet2; Transformation2 reflection( sqr(line.b()) - sqr(line.a()), -2*line.a()*line.b(), -2*line.a()*line.c(), -2*line.a()*line.b(), sqr(line.a()) - sqr(line.b()), -2*line.b()*line.c(), sqr(line.a()) + sqr(line.b()) ); facet2.transformation = reflection*facet.transformation; auto inverse = facet.transformation.inverse(); bool fail = false; for (auto edge = facet.polygon.edges_begin(); edge != facet.polygon.edges_end(); ++edge) { const auto len2 = edge->squared_length(); const auto len2new = edge->transform(facet2.transformation).squared_length(); if (len2 != len2new) { throw runtime_error("bad transform"); } if (line.has_on_positive_side(edge->source()) == up) { facet1.polygon.push_back(edge->source()); } else { facet2.polygon.push_back(reflection(edge->source())); } auto intersect = intersection(*edge, line); if (intersect) { Point2* p = boost::get<Point2>(&*intersect); if (p) { auto revPoint = inverse(*p); if (!result.points.count(revPoint)) { result.points[revPoint] = result.points.size(); } facet1.polygon.push_back(*p); facet2.polygon.push_back(*p); } else { fail = true; } } } auto normalize = [&](Facet& f) { auto area = f.polygon.area(); if (area == 0) { return; } vector<Point2> points(f.polygon.size()); for (size_t i = 0; i < f.polygon.size(); ++i) { points[i] = f.polygon[i]; } points.erase(unique(points.begin(), points.end()), points.end()); if (points.empty()) { return; } if (area < 0) { reverse(points.begin(), points.end()); } Polygon2 p; for (const auto& pnt: points) { p.push_back(pnt); } f.polygon = p; result.facets.push_back(f); }; if (!fail) { normalize(facet1); normalize(facet2); } else { result.facets.push_back(facet); } } else { result.facets.push_back(facet); } } for (const auto& f: result.facets) { result.polygon.join(f.polygon); } return result; }