00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef GUGR_CONTOUR_H
00021 #define GUGR_CONTOUR_H
00022
00023 #ifndef NDEBUG
00024 #include <iostream>
00025 #endif
00026
00027 namespace gugr {
00028
00029 using gul::Ptr;
00030 using guar::rational;
00031 using gul::point2;
00032 using gul::rtr;
00033 using gul::RefMap;
00034
00035 struct polyline
00036 {
00037 Ptr<point2<rational> > verts;
00038 int nVerts;
00039
00040 Ptr<line> lines;
00041
00042 template< class T >
00043 bool init( int nP, const Ptr< point2<T> >& P, T minx, T miny, T scalei )
00044 {
00045 T x,y;
00046 int i,j;
00047 rational vx,vy;
00048 unsigned long *cbuf =
00049 (unsigned long *)alloca(gul::rtr<T>::mantissa_length());
00050
00051 verts.reserve_pool(nP);
00052 lines.reserve_pool(nP);
00053
00054 x = (P[0].x - minx)*scalei;
00055 y = (P[0].y - miny)*scalei;
00056 verts[0].x = rational(coord2int(x,cbuf),cbuf);
00057 verts[0].y = rational(coord2int(y,cbuf),cbuf);
00058 j = 0;
00059 i = 1;
00060
00061 for( ;; )
00062 {
00063 while( i < nP )
00064 {
00065 x = (P[i].x - minx)*scalei;
00066 y = (P[i].y - miny)*scalei;
00067 vx = rational(coord2int(x,cbuf),cbuf);
00068 vy = rational(coord2int(y,cbuf),cbuf);
00069
00070 if( (compare(vx,verts[j].x)!=0) ||
00071 (compare(vy,verts[j].y)!=0) )
00072 break;
00073
00074 i++;
00075 }
00076
00077 if( i == nP ) break;
00078
00079 j++;
00080
00081 verts[j].x = vx;
00082 verts[j].y = vy;
00083 lines[j-1] = line( verts[j-1], verts[j] );
00084 }
00085
00086 nVerts = j+1;
00087 if( (compare(verts[nVerts-1].x,verts[0].x)==0) &&
00088 (compare(verts[nVerts-1].y,verts[0].y)==0) )
00089 nVerts--;
00090
00091 if( nVerts < 2 ) return false;
00092
00093 lines[nVerts-1] = line( verts[nVerts-1], verts[0] );
00094 return true;
00095 }
00096
00097 template<>
00098 bool init( int nP, const Ptr< point2<rational> >& P )
00099 {
00100 int i,j;
00101
00102 verts.reserve_pool(nP);
00103 lines.reserve_pool(nP);
00104
00105 verts[0] = P[0];
00106 j = 0;
00107 i = 1;
00108
00109 for(;;)
00110 {
00111 while( (i < nP) &&
00112 (compare(P[i].x,verts[j].x)==0) &&
00113 (compare(P[i].y,verts[j].y)==0) )
00114 i++;
00115
00116 if( i == nP ) break;
00117
00118 j++;
00119 verts[j] = P[i];
00120 lines[j-1] = line( verts[j-1], verts[j] );
00121
00122 }
00123
00124 nVerts = j+1;
00125 if( (compare(verts[nVerts-1].x,verts[0].x)==0) &&
00126 (compare(verts[nVerts-1].y,verts[0].y)==0) )
00127 nVerts--;
00128
00129 if( nVerts < 2 ) return false;
00130
00131 lines[nVerts-1] = line( verts[nVerts-1], verts[0] );
00132 return true;
00133 }
00134 };
00135
00136 struct contour_node
00137 {
00138 int nVerts;
00139 Ptr<vertex> verts;
00140
00141 Ptr<line> lines;
00142
00143 int nOwners;
00144 Ptr<void*> owners;
00145
00146 bool side;
00147 bool hole;
00148
00149 contour_node *parent;
00150 RefMap<void> childs;
00151
00152 segment *hseg;
00153 segment *seg;
00154
00155 bool hseg_firstref;
00156
00157 contour_node *next;
00158 contour_node *prev;
00159
00160 contour_node(bool aside)
00161 {
00162 parent = 0;
00163 side = aside;
00164 nOwners = 0; }
00165
00166 bool hasOwner( void *o )
00167 {
00168 int i;
00169
00170 for( i=0; i < nOwners; i++ )
00171 {
00172 if( owners[i] == o )
00173 return true;
00174 }
00175 return false;
00176 }
00177
00178 void get_polyline( gul::polyline<gul::point2<guar::rational> >& pl )
00179 {
00180 int i;
00181
00182 pl.P.reserve_pool(nVerts);
00183 pl.n = nVerts;
00184
00185 for( i = 0; i < nVerts; i++ )
00186 pl.P[i] = verts[i].v();
00187 }
00188
00189 void get_polyline_joined( gul::polyline<gul::point2<guar::rational> >& pl )
00190 {
00191 int i,j,i1,iend;
00192
00193 pl.P.reserve_pool(nVerts);
00194 pl.n = nVerts;
00195
00196
00197
00198 i1 = nVerts-1;
00199 for( i = 0; i < nVerts; i++ )
00200 {
00201 if( (compare(lines[i].dx(),lines[i1].dx())!=0) ||
00202 (compare(lines[i].dy(),lines[i1].dy())!=0) )
00203 break;
00204 i1 = i;
00205 }
00206 if( i == nVerts )
00207 {
00208 pl.n = 0;
00209 return;
00210 }
00211
00212 pl.P[0] = verts[i].v();
00213
00214
00215 i1 = iend = i;
00216 i++;
00217 if( i >= nVerts ) i = 0;
00218 j = 1;
00219
00220 for(;;)
00221 {
00222
00223 while( i != iend )
00224 {
00225 if( (compare(lines[i].dx(),lines[i1].dx())!=0) ||
00226 (compare(lines[i].dy(),lines[i1].dy())!=0) )
00227 break;
00228
00229 i++;
00230 if( i >= nVerts ) i = 0;
00231 }
00232
00233
00234 if( i == iend )
00235 break;
00236
00237 pl.P[j] = verts[i].v();
00238
00239
00240 i1 = i;
00241 i++;
00242 if( i >= nVerts ) i = 0;
00243 j++;
00244 }
00245
00246 pl.n = j;
00247 }
00248
00249 void Insert( contour_node *achild )
00250 {
00251 int side;
00252 RefMap<void>::Node pos,child;
00253
00254 side = childs.SearchNode( (void *)achild, compare_pointer_to_pointer,
00255 &pos );
00256 if( side != 0 )
00257 {
00258 child = childs.NewNode((void *)achild);
00259 achild->parent = this;
00260 childs.InsertNode( child, pos, side );
00261 }
00262 }
00263
00264
00265 void dump( int indent )
00266 {
00267 RefMap<void>::Node mn;
00268 int i;
00269
00270 for( i = 0; i < indent; i++ ) std::cout << " ";
00271 std::cout << "contour " << (void *)this << "\n";
00272 for( i = 0; i < indent; i++ ) std::cout << " ";
00273 std::cout << "parent = " << (void *)parent << "\n";
00274 for( i = 0; i < indent; i++ ) std::cout << " ";
00275 std::cout << "childs = (\n";
00276
00277 mn = childs.First();
00278 while( !mn.IsEmpty() )
00279 {
00280 for( i = 0; i < indent; i++ ) std::cout << " ";
00281 std::cout << " " << mn.key() << "\n";
00282 mn = childs.Successor( mn );
00283 }
00284 for( i = 0; i < indent; i++ ) std::cout << " ";
00285 std::cout << ")\n\n";
00286
00287
00288 mn = childs.First();
00289 while( !mn.IsEmpty() )
00290 {
00291 ((contour_node *)mn.key())->dump(indent+4);
00292 mn = childs.Successor( mn );
00293 }
00294 }
00295
00296 };
00297
00298 void AppendContour( polyline *c, int keyleft, int keyright,
00299 List< ListNode<segment> >& segs );
00300
00301 template< class EP >
00302 struct seg_point_info
00303 {
00304 EP *f;
00305 EP *n;
00306 EP *t;
00307
00308 void *operator new( size_t s )
00309 {
00310 size_t dummy;
00311 void *p = PoolAlloc( s, &dummy );
00312 if( p == NULL ) throw PoolAllocError();
00313 return(p);
00314 }
00315 void operator delete( void *p, size_t s )
00316 {
00317 if( p != 0 ) PoolFree( p, s );
00318 }
00319 };
00320
00321 template< class EP >
00322 void AppendContourFNT( polyline *c, Ptr<EP>& F, Ptr<EP>& N, Ptr<EP>& T,
00323 int keyleft, int keyright, List< ListNode<segment> >& segs );
00324
00325
00326 void LeftSideContour( graph_edge *e, graph_edge_list& E, contour_node *cn );
00327 void RightSideContour( graph_edge *e, graph_edge_list& E, contour_node *cn );
00328
00329
00330
00331
00332
00333
00334
00335 void FindContours(
00336 graph_edge_list& E, graph_vertex_list& V,
00337 const rational& far_maxx, const rational& far_maxy,
00338 List< ListNode<segment> >& outsegs,
00339 List<contour_node>& contours );
00340
00341
00342
00343
00344 void RemoveUnnecessaryEdges(
00345 graph_edge_list& E, graph_vertex_list& V,
00346 const rational& far_maxx, const rational& far_maxy,
00347 int key_inside, int key_outside,
00348 List< ListNode<segment> >& outsegs );
00349
00350
00351
00352
00353
00354 GULAPI void OddEvenRule(
00355 List< ListNode<polyline> >& inC,
00356 const rational& far_maxx, const rational& far_maxy,
00357 int key_inside, int key_outside,
00358 graph_edge_list& E, graph_vertex_list& V,
00359 List< ListNode<segment> >& outsegs );
00360
00361 }
00362
00363 #endif
00364
00365