mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-20 19:06:53 +01:00
188 lines
5.6 KiB
C++
188 lines
5.6 KiB
C++
|
|
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
|
|
|
Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) {
|
|
Vector<Vector<Vector2>> finished_polygons;
|
|
|
|
#ifdef CLIPPER_ENABLED
|
|
using namespace Clipper2Lib;
|
|
|
|
Paths64 polyon_paths_solution;
|
|
|
|
ClipType clipper_cliptype = ClipType::Union;
|
|
FillRule clipper_fillrule = FillRule::EvenOdd;
|
|
|
|
if (is_a_open) {
|
|
// Polyline with Polygon
|
|
Clipper64 clipper_64;
|
|
|
|
Paths64 polyline_paths;
|
|
Paths64 polygon_paths_b;
|
|
|
|
Path64 polyline_path_a;
|
|
Path64 polygon_path_b;
|
|
|
|
for (const Vector2 &polyline_point : p_polypath_a) {
|
|
const Point64 &point = Point64(polyline_point.x * (real_t)SCALE_FACTOR, polyline_point.y * (real_t)SCALE_FACTOR);
|
|
polyline_path_a.push_back(point);
|
|
}
|
|
polyline_paths.push_back(polyline_path_a);
|
|
|
|
for (const Vector2 &polypath_outline_point : p_polypath_b) {
|
|
const Point64 &point = Point64(polypath_outline_point.x * (real_t)SCALE_FACTOR, polypath_outline_point.y * (real_t)SCALE_FACTOR);
|
|
polygon_path_b.push_back(point);
|
|
}
|
|
polygon_paths_b.push_back(polygon_path_b);
|
|
|
|
switch (p_op) {
|
|
case OPERATION_UNION:
|
|
// not supported for polyline (in Godot)
|
|
return finished_polygons;
|
|
|
|
case OPERATION_DIFFERENCE:
|
|
clipper_cliptype = ClipType::Difference;
|
|
clipper_fillrule = FillRule::EvenOdd;
|
|
clipper_64.AddOpenSubject(polyline_paths);
|
|
clipper_64.AddClip(polygon_paths_b);
|
|
break;
|
|
|
|
case OPERATION_INTERSECTION:
|
|
clipper_cliptype = ClipType::Intersection;
|
|
clipper_fillrule = FillRule::EvenOdd;
|
|
clipper_64.AddOpenSubject(polyline_paths);
|
|
clipper_64.AddClip(polygon_paths_b);
|
|
break;
|
|
|
|
case OPERATION_XOR:
|
|
// not supported for polyline
|
|
return finished_polygons;
|
|
}
|
|
|
|
Paths64 polygon_solution, polyline_solution;
|
|
clipper_64.Execute(clipper_cliptype, clipper_fillrule, polygon_solution, polyline_solution);
|
|
polyon_paths_solution = polyline_solution;
|
|
|
|
} else {
|
|
// Polygon with Polygon
|
|
Paths64 polygon_paths;
|
|
Paths64 polygon_clip_paths;
|
|
|
|
Path64 polygon_path_a;
|
|
Path64 polygon_path_b;
|
|
|
|
for (const Vector2 &polypath_outline_point : p_polypath_a) {
|
|
const Point64 &point = Point64(polypath_outline_point.x * (real_t)SCALE_FACTOR, polypath_outline_point.y * (real_t)SCALE_FACTOR);
|
|
polygon_path_a.push_back(point);
|
|
}
|
|
polygon_paths.push_back(polygon_path_a);
|
|
|
|
for (const Vector2 &polypath_outline_point : p_polypath_b) {
|
|
const Point64 &point = Point64(polypath_outline_point.x * (real_t)SCALE_FACTOR, polypath_outline_point.y * (real_t)SCALE_FACTOR);
|
|
polygon_path_b.push_back(point);
|
|
}
|
|
polygon_clip_paths.push_back(polygon_path_b);
|
|
|
|
switch (p_op) {
|
|
case OPERATION_UNION:
|
|
clipper_cliptype = ClipType::Union;
|
|
clipper_fillrule = FillRule::NonZero;
|
|
|
|
polyon_paths_solution = Union(polygon_paths, polygon_clip_paths, clipper_fillrule);
|
|
break;
|
|
case OPERATION_DIFFERENCE:
|
|
clipper_cliptype = ClipType::Difference;
|
|
clipper_fillrule = FillRule::EvenOdd;
|
|
|
|
polyon_paths_solution = Difference(polygon_paths, polygon_clip_paths, clipper_fillrule);
|
|
break;
|
|
case OPERATION_INTERSECTION:
|
|
clipper_cliptype = ClipType::Intersection;
|
|
clipper_fillrule = FillRule::NonZero;
|
|
|
|
polyon_paths_solution = Intersect(polygon_paths, polygon_clip_paths, clipper_fillrule);
|
|
break;
|
|
case OPERATION_XOR:
|
|
clipper_cliptype = ClipType::Xor;
|
|
clipper_fillrule = FillRule::NonZero;
|
|
|
|
polyon_paths_solution = Xor(polygon_paths, polygon_clip_paths, clipper_fillrule);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (const Path64 &polyon_path : polyon_paths_solution) {
|
|
Vector<Vector2> finished_polygon;
|
|
for (const Point64 &polyon_path_point : polyon_path) {
|
|
finished_polygon.push_back(Vector2(static_cast<real_t>(polyon_path_point.x), static_cast<real_t>(polyon_path_point.y)) / (real_t)SCALE_FACTOR);
|
|
}
|
|
finished_polygons.push_back(finished_polygon);
|
|
}
|
|
#endif // CLIPPER_ENABLED
|
|
|
|
return finished_polygons;
|
|
}
|
|
|
|
Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
|
|
Vector<Vector<Vector2>> finished_polygons;
|
|
|
|
#ifdef CLIPPER_ENABLED
|
|
using namespace Clipper2Lib;
|
|
|
|
JoinType clipper_jointype = JoinType::Miter;
|
|
|
|
switch (p_join_type) {
|
|
case JOIN_SQUARE:
|
|
clipper_jointype = JoinType::Square;
|
|
break;
|
|
case JOIN_ROUND:
|
|
clipper_jointype = JoinType::Round;
|
|
break;
|
|
case JOIN_MITER:
|
|
clipper_jointype = JoinType::Miter;
|
|
break;
|
|
}
|
|
|
|
EndType clipper_endtype = EndType::Polygon;
|
|
|
|
switch (p_end_type) {
|
|
case END_POLYGON:
|
|
clipper_endtype = EndType::Polygon;
|
|
break;
|
|
case END_JOINED:
|
|
clipper_endtype = EndType::Joined;
|
|
break;
|
|
case END_BUTT:
|
|
clipper_endtype = EndType::Butt;
|
|
break;
|
|
case END_SQUARE:
|
|
clipper_endtype = EndType::Square;
|
|
break;
|
|
case END_ROUND:
|
|
clipper_endtype = EndType::Round;
|
|
break;
|
|
}
|
|
|
|
Paths64 polygon_paths;
|
|
|
|
Path64 polygon_path;
|
|
for (const Vector2 &polypath_outline_point : p_polypath) {
|
|
const Point64 &point = Point64(polypath_outline_point.x * (real_t)SCALE_FACTOR, polypath_outline_point.y * (real_t)SCALE_FACTOR);
|
|
polygon_path.push_back(point);
|
|
}
|
|
polygon_paths.push_back(polygon_path);
|
|
|
|
Paths64 paths_solution = InflatePaths(polygon_paths, p_delta, clipper_jointype, clipper_endtype);
|
|
|
|
for (const Path64 &scaled_path : paths_solution) {
|
|
Vector<Vector2> polypath;
|
|
for (const Point64 &scaled_point : scaled_path) {
|
|
polypath.push_back(Vector2(static_cast<real_t>(scaled_point.x), static_cast<real_t>(scaled_point.y)) / (real_t)SCALE_FACTOR);
|
|
}
|
|
finished_polygons.push_back(polypath);
|
|
}
|
|
#endif // CLIPPER_ENABLED
|
|
|
|
return finished_polygons;
|
|
}
|
|
|