15 # include <vcl_msvc_warnings.h> 29 x1 = (f2*x1 - f1*x2)/(f2-f1);
30 y1 = (f2*y1 - f1*y2)/(f2-f1);
36 x2 = (f2*x1 - f1*x2)/(f2-f1);
37 y2 = (f2*y1 - f1*y2)/(f2-f1);
51 if (x1>x2) std::swap(x1,x2);
52 if (y1>y2) std::swap(y1,y2);
55 if (a == 0 && b == 0)
return false;
63 by = y1; bx = -(b*y1+c)/a;
65 ey = y2; ex = -(b*y2+c)/a;
67 b_set = bx >= x1 && bx <= x2;
68 e_set = ex >= x1 && ex <= x2;
71 if (b_set && e_set)
return true;
72 if (b_set) { std::swap(bx,ex); std::swap(by,ey); std::swap(b_set,e_set); }
78 bx = x1; by = -(a*x1+c)/b;
79 b_set = by >= y1 && by <= y2;
80 if (b_set && e_set)
return true;
81 if (b_set) { std::swap(bx,ex); std::swap(by,ey); e_set=
true; }
84 bx = x2; by = -(a*x2+c)/b;
85 b_set = by >= y1 && ey <= y2;
88 return b_set && e_set;
93 #ifdef BUILD_NONCOMMERCIAL 99 #define MALLOC(p, T, c, s) { if ((c) > 0) { \ 100 p= (T*)std::malloc(c * sizeof(T)); if (!(p)) { \ 101 std::fprintf(stderr, "vgl: gpc malloc failure: %s\n", s); \ 102 std::exit(0);}} else p=NULL; } 104 #define FREE(p) { if (p) { std::free(p); (p)= NULL; } } 115 MALLOC( gpc_poly.
hole,
int, gpc_poly.
num_contours,
"allocating hole array" );
118 gpc_poly.
hole[s] = 0;
121 for (
unsigned int p = 0; p < vgl_poly[s].size(); ++p ) {
147 #include <clipper.hxx> 155 ClipperLib::Paths clipper_poly;
156 for (
size_t s = 0; s < vgl_poly.
num_sheets(); ++s ) {
157 ClipperLib::Path path;
158 for (
size_t p = 0; p < vgl_poly[s].size(); ++p ) {
159 ClipperLib::IntPoint pt((ClipperLib::cInt)((
double)vgl_poly[s][p].x()*scale),
160 (ClipperLib::cInt)((
double)vgl_poly[s][p].y()*scale));
163 clipper_poly.push_back(path);
172 add_clipper_to_vgl(
vgl_polygon<T>& vgl_poly,
const ClipperLib::Paths& clipper_poly,
double scale )
174 for (
const auto & c : clipper_poly) {
176 for (
size_t p=0; p < c.size(); ++p ) {
177 vgl_poly.
push_back( T((
double)c[p].X/scale),
178 T((
double)c[p].Y/scale) );
186 bounds(
vgl_polygon<T> vgl_poly, T& min_x, T& max_x, T& min_y, T& max_y)
188 for (
size_t s=0; s < vgl_poly.
num_sheets(); ++s) {
189 for (
size_t p=0; p < vgl_poly[s].size(); ++p) {
191 min_x = max_x = vgl_poly[0][0].x();
192 min_y = max_y = vgl_poly[0][0].y();
195 min_x = std::min(vgl_poly[s][p].x(), min_x);
196 min_y = std::min(vgl_poly[s][p].y(), min_y);
197 max_x = std::max(vgl_poly[s][p].x(), max_x);
198 max_y = std::max(vgl_poly[s][p].y(), max_y);
235 #ifdef BUILD_NONCOMMERCIAL 258 add_gpc_to_vgl( result, p3 );
265 ClipperLib::Clipper clpr;
270 int halfSignificantDigits = std::numeric_limits<ClipperLib::cInt>::digits10/2;
272 T min_x, max_x, min_y, max_y;
273 bounds( poly1, min_x, max_x, min_y, max_y);
274 max_x = std::max(max_x, std::abs(min_x));
275 max_y = std::max(max_y, std::abs(min_y));
276 T max1 = std::max(max_x, max_y);
278 bounds( poly2, min_x, max_x, min_y, max_y);
279 max_x = std::max(max_x, std::abs(min_x));
280 max_y = std::max(max_y, std::abs(min_y));
281 T max2 = std::max(max_x, max_y);
283 T max = std::max(max1, max2);
284 double scale = std::pow(10.0, halfSignificantDigits) / max;
287 ClipperLib::Paths p1 = vgl_to_clipper( poly1, scale );
288 ClipperLib::Paths p2 = vgl_to_clipper( poly2, scale );
289 ClipperLib::Paths p3;
291 ClipperLib::ClipType g_op = ClipperLib::ctIntersection;
302 clpr.AddPaths(p1, ClipperLib::ptSubject,
true);
303 clpr.AddPaths(p2, ClipperLib::ptClip,
true);
304 int retval = clpr.Execute(g_op, p3, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
307 add_clipper_to_vgl( result, p3, scale );
311 std::fprintf(stdout,
"WARNING: GPC is only free for non-commercial use -- assuming disjoint polygons.\n");
312 std::fprintf(stderr,
"WARNING: GPC is only free for non-commercial use -- assuming disjoint polygons.\n");
321 for (
unsigned int i=0; i<poly2.
num_sheets(); ++i)
336 return vgl_clip(poly1, poly2, op, &retval);
339 #undef VGL_CLIP_INSTANTIATE 340 #define VGL_CLIP_INSTANTIATE(T) \ 341 template vgl_polygon<T > vgl_clip(vgl_polygon<T >const&,vgl_polygon<T >const&,vgl_clip_type); \ 342 template vgl_polygon<T > vgl_clip(vgl_polygon<T >const&,vgl_polygon<T >const&,vgl_clip_type,int *); \ 343 template bool vgl_clip_lineseg_to_line(T&,T&,T&,T&,T,T,T); \ 344 template bool vgl_clip_line_to_box(T,T,T,T,T,T,T,T&,T&,T&,T&); \ 345 template vgl_line_segment_2d<T > vgl_clip_line_to_box(vgl_line_2d<T >const&,vgl_box_2d<T >const&) 347 #endif // vgl_clip_hxx_
bool vgl_clip_lineseg_to_line(T &x1, T &y1, T &x2, T &y2, T a, T b, T c)
clips away the portion where ax+by+c<0. return false if nothing left.
gpc_vertex_list * contour
void new_sheet()
Add a new (empty) sheet to the polygon.
vgl_polygon< T > vgl_clip(const vgl_polygon< T > &poly1, const vgl_polygon< T > &poly2, vgl_clip_type op=vgl_clip_type_intersect)
Clip a polygon against another polygon.
void push_back(T x, T y)
Add a new point to the last sheet.
vgl_clip_type
Type of polygon "clip" operations.
vgl_line_segment_2d< T > vgl_clip_line_to_box(vgl_line_2d< T > const &l, vgl_box_2d< T > const &b)
clip given line to given box, and return resulting line segment.
void gpc_free_polygon(gpc_polygon *polygon)
int gpc_polygon_clip(gpc_op set_operation, gpc_polygon *subject_polygon, gpc_polygon *clip_polygon, gpc_polygon *result_polygon)
unsigned int num_sheets() const