00001
00002 #ifndef vgl_clip_txx_
00003 #define vgl_clip_txx_
00004
00005
00006
00007
00008 #include "vgl_clip.h"
00009 #include <vcl_cstdlib.h>
00010 #include <vcl_cstdio.h>
00011 #include <vcl_algorithm.h>
00012
00013 template <class T>
00014 bool vgl_clip_lineseg_to_line(T &x1, T &y1,
00015 T &x2, T &y2,
00016 T a,T b,T c)
00017 {
00018 T f1 = a*x1+b*y1+c;
00019 T f2 = a*x2+b*y2+c;
00020 if (f1<0) {
00021 if (f2<0)
00022 return false;
00023
00024 x1 = (f2*x1 - f1*x2)/(f2-f1);
00025 y1 = (f2*y1 - f1*y2)/(f2-f1);
00026 return true;
00027 }
00028 else {
00029 if (f2<0)
00030 {
00031 x2 = (f2*x1 - f1*x2)/(f2-f1);
00032 y2 = (f2*y1 - f1*y2)/(f2-f1);
00033 }
00034
00035 return true;
00036 }
00037 }
00038
00039 template <class T>
00040 bool vgl_clip_line_to_box(T a, T b, T c,
00041 T x1, T y1,
00042 T x2, T y2,
00043 T &bx, T &by,
00044 T &ex, T &ey)
00045 {
00046 if (x1>x2) vcl_swap(x1,x2);
00047 if (y1>y2) vcl_swap(y1,y2);
00048
00049
00050 if (a == 0 && b == 0) return false;
00051
00052 bool b_set = false,
00053 e_set = false;
00054
00055 if (a != 0)
00056 {
00057
00058 by = y1; bx = -(b*y1+c)/a;
00059
00060 ey = y2; ex = -(b*y2+c)/a;
00061
00062 b_set = bx >= x1 && bx <= x2;
00063 e_set = ex >= x1 && ex <= x2;
00064 }
00065
00066 if (b_set && e_set) return true;
00067 if (b_set) { vcl_swap(bx,ex); vcl_swap(by,ey); vcl_swap(b_set,e_set); }
00068
00069
00070 if (b != 0)
00071 {
00072
00073 bx = x1; by = -(a*x1+c)/b;
00074 b_set = by >= y1 && by <= y2;
00075 if (b_set && e_set) return true;
00076 if (b_set) { vcl_swap(bx,ex); vcl_swap(by,ey); e_set=true; }
00077
00078
00079 bx = x2; by = -(a*x2+c)/b;
00080 b_set = by >= y1 && ey <= y2;
00081 }
00082
00083 return b_set && e_set;
00084 }
00085
00086
00087 #ifdef BUILD_NONCOMMERCIAL
00088
00089 extern "C" {
00090 #include "internals/gpc.h"
00091 }
00092
00093 #define MALLOC(p, T, c, s) { if ((c) > 0) { \
00094 p= (T*)vcl_malloc(c * sizeof(T)); if (!(p)) { \
00095 vcl_fprintf(stderr, "vgl: gpc malloc failure: %s\n", s); \
00096 vcl_exit(0);}} else p=NULL; }
00097
00098 #define FREE(p) { if (p) { vcl_free(p); (p)= NULL; } }
00099
00100 namespace {
00101
00102
00103 template <class T>
00104 gpc_polygon
00105 vgl_to_gpc( const vgl_polygon<T>& vgl_poly )
00106 {
00107 gpc_polygon gpc_poly;
00108 gpc_poly.num_contours = vgl_poly.num_sheets();
00109 MALLOC( gpc_poly.hole, int, gpc_poly.num_contours, "allocating hole array" );
00110 MALLOC( gpc_poly.contour, gpc_vertex_list, gpc_poly.num_contours, "allocating contour array" );
00111 for ( int s = 0; s < gpc_poly.num_contours; ++s ) {
00112 gpc_poly.hole[s] = 0;
00113 gpc_poly.contour[s].num_vertices = vgl_poly[s].size();
00114 MALLOC( gpc_poly.contour[s].vertex, gpc_vertex, vgl_poly[s].size(), "allocating vertex list" );
00115 for ( unsigned int p = 0; p < vgl_poly[s].size(); ++p ) {
00116 gpc_poly.contour[s].vertex[p].x = vgl_poly[s][p].x();
00117 gpc_poly.contour[s].vertex[p].y = vgl_poly[s][p].y();
00118 }
00119 }
00120
00121 return gpc_poly;
00122 }
00123
00124
00125 template <class T>
00126 void
00127 add_gpc_to_vgl( vgl_polygon<T>& vgl_poly, const gpc_polygon& gpc_poly )
00128 {
00129 for ( int c=0; c < gpc_poly.num_contours; ++c ) {
00130 vgl_poly.new_sheet();
00131 for ( int p=0; p < gpc_poly.contour[c].num_vertices; ++p ) {
00132 vgl_poly.push_back( T(gpc_poly.contour[c].vertex[p].x),
00133 T(gpc_poly.contour[c].vertex[p].y) );
00134 }
00135 }
00136 }
00137 }
00138
00139 #endif // BUILD_NONCOMMERCIAL
00140
00141 template <class T>
00142 vgl_polygon<T>
00143 vgl_clip(vgl_polygon<T> const& poly1, vgl_polygon<T> const& poly2, vgl_clip_type op, int *p_retval)
00144 {
00145
00146 if ( poly1.num_sheets() == 0 ) {
00147 *p_retval = 1;
00148 switch ( op )
00149 {
00150 case vgl_clip_type_intersect: return poly1;
00151 case vgl_clip_type_difference: return poly1;
00152 case vgl_clip_type_union: return poly2;
00153 case vgl_clip_type_xor: return poly2;
00154 default: *p_retval = -1; return vgl_polygon<T>();
00155 }
00156 }
00157 if ( poly2.num_sheets() == 0 ) {
00158 *p_retval = 1;
00159 switch ( op )
00160 {
00161 case vgl_clip_type_intersect: return poly2;
00162 case vgl_clip_type_difference: return poly1;
00163 case vgl_clip_type_union: return poly1;
00164 case vgl_clip_type_xor: return poly1;
00165 default: *p_retval = -1; return vgl_polygon<T>();
00166 }
00167 }
00168
00169 vgl_polygon<T> result;
00170
00171 #ifdef BUILD_NONCOMMERCIAL
00172 gpc_polygon p1 = vgl_to_gpc( poly1 );
00173 gpc_polygon p2 = vgl_to_gpc( poly2 );
00174 gpc_polygon p3;
00175
00176 gpc_op g_op = GPC_INT;
00177 switch ( op )
00178 {
00179 case vgl_clip_type_intersect: g_op = GPC_INT; break;
00180 case vgl_clip_type_difference: g_op = GPC_DIFF; break;
00181 case vgl_clip_type_union: g_op = GPC_UNION; break;
00182 case vgl_clip_type_xor: g_op = GPC_XOR; break;
00183 default: break;
00184 }
00185
00186 int retval = gpc_polygon_clip( g_op, &p1, &p2, &p3 );
00187 *p_retval = retval;
00188
00189 if (retval == 0) {
00190 gpc_free_polygon( &p1 );
00191 gpc_free_polygon( &p2 );
00192 return result;
00193 }
00194 add_gpc_to_vgl( result, p3 );
00195
00196 gpc_free_polygon( &p1 );
00197 gpc_free_polygon( &p2 );
00198 gpc_free_polygon( &p3 );
00199
00200 #else // BUILD_NONCOMMERCIAL
00201 *p_retval = -1;
00202 vcl_fprintf(stdout,"WARNING: GPC is only free for non-commercial use -- assuming disjoint polygons.\n");
00203 vcl_fprintf(stderr,"WARNING: GPC is only free for non-commercial use -- assuming disjoint polygons.\n");
00204 switch ( op )
00205 {
00206 default:
00207 case vgl_clip_type_intersect: result = vgl_polygon<T>(); break;
00208 case vgl_clip_type_difference: result = poly1; break;
00209 case vgl_clip_type_union:
00210 case vgl_clip_type_xor:
00211 result = poly1;
00212 for (unsigned int i=0; i<poly2.num_sheets(); ++i)
00213 result.push_back(poly2[i]);
00214 break;
00215 }
00216
00217 #endif // BUILD_NONCOMMERCIAL
00218
00219 return result;
00220 }
00221
00222 template <class T>
00223 vgl_polygon<T>
00224 vgl_clip(vgl_polygon<T> const& poly1, vgl_polygon<T> const& poly2, vgl_clip_type op )
00225 {
00226 int retval;
00227 return vgl_clip(poly1, poly2, op, &retval);
00228 }
00229
00230 #undef VGL_CLIP_INSTANTIATE
00231 #define VGL_CLIP_INSTANTIATE(T) \
00232 template vgl_polygon<T > vgl_clip(vgl_polygon<T >const&,vgl_polygon<T >const&,vgl_clip_type); \
00233 template bool vgl_clip_lineseg_to_line(T&,T&,T&,T&,T,T,T); \
00234 template bool vgl_clip_line_to_box(T,T,T,T,T,T,T,T&,T&,T&,T&); \
00235 template vgl_line_segment_2d<T > vgl_clip_line_to_box(vgl_line_2d<T >const&,vgl_box_2d<T >const&)
00236
00237 #endif // vgl_clip_txx_