00001
00002 #include "gevd_contour.h"
00003
00004
00005 #include <vcl_iostream.h>
00006 #include <vcl_cstdlib.h>
00007 #include <vcl_vector.h>
00008 #include <vcl_algorithm.h>
00009 #include <vxl_config.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vdgl/vdgl_digital_curve.h>
00012 #include <vdgl/vdgl_edgel_chain.h>
00013 #include <vdgl/vdgl_interpolator.h>
00014 #include <vdgl/vdgl_interpolator_linear.h>
00015 #include <vtol/vtol_vertex_2d.h>
00016 #include <vtol/vtol_edge_2d.h>
00017 #include <gevd/gevd_pixel.h>
00018 #ifdef DEBUG
00019 # include <vul/vul_timer.h>
00020 #endif
00021
00022 const int INVALID = -1;
00023
00024
00025
00026 const vxl_byte TWOPI = 8, HALFPI = 2 ;
00027
00028 const int DIS[] = { 1, 1, 0,-1,-1,-1, 0, 1,
00029 1, 1, 0,-1,-1,-1, 0, 1,
00030 1, 1, 0,-1,-1,-1, 0, 1};
00031 const int DJS[] = { 0, 1, 1, 1, 0,-1,-1,-1,
00032 0, 1, 1, 1, 0,-1,-1,-1,
00033 0, 1, 1, 1, 0,-1,-1,-1};
00034
00035
00036 const int RIS[] = { 1, 0,-1, 0,
00037 1,-1,-1, 1,
00038 2, 0,-2, 0,
00039 2, 1,-1,-2,-2,-1, 1, 2,
00040 2,-2,-2, 2,
00041 3, 0,-3, 0,
00042 3, 1,-1,-3,-3,-1, 1, 3,
00043 3, 2,-2,-3,-3,-2, 2, 3,
00044 4, 0,-4, 0};
00045 const int RJS[] = { 0, 1, 0,-1,
00046 1, 1,-1,-1,
00047 0, 2, 0,-2,
00048 1, 2, 2, 1,-1,-2,-2,-1,
00049 2, 2,-2,-2,
00050 0, 3, 0,-3,
00051 1, 3, 3, 1,-1,-3,-3,-1,
00052 2, 3, 3, 2,-2,-3,-3,-2,
00053 0, 4, 0,-4};
00054 const int RNS[] = { 4, 8, 12, 20, 24, 28, 36, 44, 48};
00055 const float RGS[] = { 1.f, 1.414213f, 2.f, 2.236067f, 2.828427f,
00056 3.f, 3.162277f, 3.605551f, 4.f};
00057
00058
00059 const int MINLENGTH = 3;
00060 const int FRAME = 4;
00061
00062 bool gevd_contour::talkative = true;
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 gevd_contour::gevd_contour(float min_strength, int min_length,
00074 float min_jump, float max_gap)
00075 : minStrength(min_strength), minLength(min_length),
00076 minJump(min_jump), maxSpiral(0),
00077 edgeMap(), vertexMap()
00078 {
00079 if (minStrength < 0) {
00080 vcl_cerr << "gevd_contour::gevd_contour -- negative min_strength: "
00081 << minStrength << ". Reset to 0.\n";
00082 minStrength = 0;
00083 }
00084 if (minLength < MINLENGTH) {
00085 vcl_cerr << "gevd_contour::gevd_contour -- too small min_length: "
00086 << minLength << ". Reset to " << MINLENGTH << ".\n";
00087 minLength = MINLENGTH;
00088 }
00089 if (minJump < 0) {
00090 vcl_cerr << "gevd_contour::gevd_contour -- negative min_jump: "
00091 << minJump << ". Reset to 0.\n";
00092 minJump = 0;
00093 }
00094 if (minJump > minStrength) {
00095 vcl_cerr << "gevd_contour::gevd_contour -- too large min_jump: "
00096 << min_jump << ". Reset to " << minStrength << ".\n";
00097 minJump = minStrength;
00098 }
00099 if (max_gap < 1) {
00100 vcl_cerr << "gevd_contour::gevd_contour -- too small max_gap: "
00101 << max_gap << ". Reset to 1.\n";
00102 max_gap = 1;
00103 }
00104 if (max_gap > FRAME) {
00105 vcl_cerr << "gevd_contour::gevd_contour -- too large max_gap: "
00106 << max_gap << ". Reset to " << FRAME << vcl_endl;
00107 max_gap = FRAME;
00108 }
00109 for (int i = 0; i < 9; i++)
00110 if (max_gap <= RGS[i])
00111 maxSpiral= i+1;
00112 }
00113
00114
00115
00116 gevd_contour::~gevd_contour()
00117 {
00118 delete edgeMap;
00119 delete vertexMap;
00120 }
00121
00122
00123
00124
00125
00126
00127 bool
00128 gevd_contour::FindNetwork(gevd_bufferxy& edgels,
00129 const int njunction,
00130 const int* junctionx, const int* junctiony,
00131 vcl_vector<vtol_edge_2d_sptr>*& edges,
00132 vcl_vector<vtol_vertex_2d_sptr >*& vertices)
00133 {
00134
00135
00136 if (!edges)
00137 edges = new vcl_vector<vtol_edge_2d_sptr>;
00138 else
00139 edges->clear();
00140 if (!vertices)
00141 vertices = new vcl_vector<vtol_vertex_2d_sptr >;
00142 else
00143 vertices->clear();
00144
00145
00146 if (talkative)
00147 vcl_cout << "*** Link edge elements into connected edges/vertices.\n";
00148
00149
00150 vertexMap = new vbl_array_2d<vtol_vertex_2d_sptr>(edgels.GetSizeX(), edgels.GetSizeY());
00151 vertexMap->fill(NULL);
00152 edgeMap = new vbl_array_2d<vtol_edge_2d_sptr>(edgels.GetSizeX(), edgels.GetSizeY());
00153 edgeMap->fill(NULL);
00154
00155
00156 int n;
00157
00158 vcl_vector<vtol_edge_2d_sptr> *edges2 = new vcl_vector<vtol_edge_2d_sptr>;
00159 n = this->FindChains(edgels,
00160 njunction,
00161 junctionx, junctiony,
00162 *edges2);
00163 if (!n)
00164 return false;
00165
00166
00167
00168 if (edges2->size() < 1000)
00169 vcl_sort (edges2->begin(), edges2->end());
00170
00171
00172
00173 for (unsigned int i= 0; i< edges2->size(); i++)
00174 (*edges2)[i]->set_id(i);
00175
00176
00177 vcl_vector<vtol_vertex_2d_sptr > vertices2;
00178 this->FindJunctions(edgels,
00179 *edges2, vertices2);
00180
00181
00182 for (unsigned int i= 0; i< edges2->size(); i++)
00183 edges->push_back( (*edges2)[i]);
00184
00185 for (unsigned int i=0; i< vertices2.size(); i++)
00186 vertices->push_back( vertices2[i]);
00187
00188 return true;
00189 }
00190
00191
00192
00193 static bool
00194 on_contour(const gevd_bufferxy& edgels, const int i, const int j)
00195 {
00196 double pix = (1 + vnl_math::sqrt2) * floatPixel(edgels, i, j);
00197 for (vxl_byte dir = 0; dir < TWOPI; dir += HALFPI)
00198 if (floatPixel(edgels, i+DIS[dir], j+DJS[dir]) > pix)
00199 return false;
00200 return true;
00201 }
00202
00203
00204
00205 static void
00206 RecordPixel(int i, int j, gevd_bufferxy& edgels,
00207 vcl_vector<int>& iloc, vcl_vector<int>& jloc)
00208 {
00209 floatPixel(edgels, i, j) = -floatPixel(edgels, i, j);
00210 iloc.push_back(i), jloc.push_back(j);
00211 }
00212
00213
00214
00215
00216
00217
00218 static int
00219 NextPixel(int& i, int& j, const gevd_bufferxy& edgels)
00220 {
00221 float maxpix = 0, npix;
00222 int maxdir = 0, dir;
00223 for (dir = 0; dir < TWOPI; dir += HALFPI)
00224 if ((npix = floatPixel(edgels, i+DIS[dir], j+DJS[dir])) > maxpix) {
00225 maxpix = npix;
00226 maxdir = dir+TWOPI;
00227 }
00228 if (!maxdir) {
00229 for (dir = 1; dir < TWOPI; dir += HALFPI)
00230 if ((npix = floatPixel(edgels, i+DIS[dir], j+DJS[dir])) > maxpix) {
00231 maxpix = npix;
00232 maxdir = dir+TWOPI;
00233 }
00234 }
00235 if (maxdir)
00236 i += DIS[maxdir], j += DJS[maxdir];
00237 return maxdir;
00238 }
00239
00240
00241
00242
00243
00244
00245 static int
00246 next_pixel(int& i, int& j, const vbl_array_2d<vtol_vertex_2d_sptr>& vertexMap)
00247 {
00248 int maxdir = 0, dir;
00249 for (dir = 0; dir < TWOPI; dir += HALFPI)
00250 if (vertexMap.get(i+DIS[dir], j+DJS[dir])) {
00251 maxdir = dir+TWOPI;
00252 break;
00253 }
00254 if (!maxdir) {
00255 for (dir = 1; dir < TWOPI; dir += HALFPI)
00256 if (vertexMap.get(i+DIS[dir], j+DJS[dir])) {
00257 maxdir = dir+TWOPI;
00258 break;
00259 }
00260 }
00261 if (maxdir)
00262 i += DIS[maxdir], j += DJS[maxdir];
00263 return maxdir;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 int
00277 gevd_contour::FindChains(gevd_bufferxy& edgels, const int njunction,
00278 const int* junctionx, const int* junctiony,
00279 vcl_vector<vtol_edge_2d_sptr>& edges)
00280 {
00281 #ifdef DEBUG
00282 vul_timer t;
00283 #endif
00284
00285
00286
00287
00288 vtol_vertex_2d_sptr mark = new vtol_vertex_2d;
00289 for (int k = 0; k < njunction; k++) {
00290 vertexMap->put(junctionx[k], junctiony[k], mark);
00291 }
00292
00293
00294
00295 const int rmax = FRAME;
00296 const int xmax = edgels.GetSizeX()-rmax-1;
00297 const int ymax = edgels.GetSizeY()-rmax-1;
00298 vcl_vector<int> xloc(xmax+ymax), yloc(xmax+ymax);
00299
00300 for (int j = rmax; j <= ymax; j++)
00301 for (int i = rmax; i <= xmax; i++)
00302 {
00303
00304 if (floatPixel(edgels, i, j) > minStrength &&
00305 on_contour(edgels, i, j)) {
00306 int x = i, y = j;
00307
00308
00309 if (!NextPixel(x, y, edgels)) {
00310 floatPixel(edgels, i, j) = 0;
00311 continue;
00312 }
00313
00314
00315 xloc.clear(), yloc.clear();
00316 RecordPixel(i, j, edgels, xloc, yloc);
00317 int ii = x, jj = y;
00318 RecordPixel(ii, jj, edgels, xloc, yloc);
00319 if (NextPixel(x, y, edgels))
00320 RecordPixel(x, y, edgels, xloc, yloc);
00321 else {
00322 x = i, y = j;
00323 if (NextPixel(x, y, edgels)) {
00324 xloc.clear(), yloc.clear();
00325 RecordPixel(ii, jj, edgels, xloc, yloc);
00326 RecordPixel(i, j, edgels, xloc, yloc);
00327 RecordPixel(x, y, edgels, xloc, yloc);
00328 ii = i, jj = j;
00329 } else {
00330 floatPixel(edgels, i, j) = 0;
00331 floatPixel(edgels, ii, jj) = 0;
00332 continue;
00333 }
00334 }
00335
00336
00337 if ((x - ii)*(ii - xloc[0]) +
00338 (y - jj)*(jj - yloc[0]) < 0) {
00339 xloc[1] = xloc[0], yloc[1] = yloc[0];
00340 xloc[0] = ii, yloc[0] = jj;
00341 }
00342
00343
00344 while (NextPixel(x, y, edgels))
00345 RecordPixel(x, y, edgels, xloc, yloc);
00346
00347 if (vcl_abs(xloc[0]-x) > 1 ||
00348 vcl_abs(yloc[0]-y) > 1) {
00349 if (next_pixel(x, y, *vertexMap))
00350 xloc.push_back(x), yloc.push_back(y);
00351 x = xloc[0], y = yloc[0];
00352
00353 vcl_vector<int> xloctemp( xloc.size()), yloctemp( yloc.size());
00354 for (unsigned int iii=0; iii< xloc.size(); iii++)
00355 xloctemp[iii]= xloc[xloc.size()-1-iii];
00356 for (unsigned int jjj=0; jjj< yloc.size(); jjj++)
00357 yloctemp[jjj]= yloc[yloc.size()-1-jjj];
00358
00359 while (NextPixel(x, y, edgels))
00360 RecordPixel(x, y, edgels, xloc, yloc);
00361 if (next_pixel(x, y, *vertexMap))
00362 xloc.push_back(x), yloc.push_back(y);
00363 }
00364 int len = xloc.size();
00365
00366
00367 if (len < minLength) {
00368 for (int k = 0; k < len; k++)
00369 floatPixel(edgels, xloc[k], yloc[k]) = 0;
00370 continue;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 vtol_edge_2d_sptr edge = new vtol_edge_2d();
00383 vdgl_edgel_chain * ec = new vdgl_edgel_chain;
00384 vdgl_interpolator * it = new vdgl_interpolator_linear(ec);
00385 vdgl_digital_curve * dc = new vdgl_digital_curve(it);
00386
00387 for (int k=0; k< len; k++)
00388 {
00389 x= xloc[k];
00390 y= yloc[k];
00391 ec->add_edgel( vdgl_edgel( x, y));
00392 edgeMap->put(x, y, edge);
00393 }
00394 edge->set_curve(*dc);
00395 LookupTableInsert(edges, edge);
00396 }
00397 }
00398
00399
00400 for (int k = 0; k < njunction; k++)
00401 vertexMap->put(junctionx[k], junctiony[k],NULL);
00402 for (int j = rmax; j <= ymax; j++)
00403 for (int i = rmax; i <= xmax; i++)
00404 if (floatPixel(edgels, i, j) < 0)
00405 floatPixel(edgels, i, j) = - floatPixel(edgels, i, j);
00406
00407 if (talkative)
00408 vcl_cout << "Find " << edges.size()
00409 << " chains/cycles, with pixels > " << minLength
00410 << " and strength > " << minStrength
00411 #ifdef DEBUG
00412 << ", in " << t.real() << " msecs."
00413 #endif
00414 << vcl_endl;
00415 return edges.size();
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 bool
00427 DetectJunction(vtol_vertex_2d& end, int& index,
00428 vtol_edge_2d_sptr& weaker, vtol_edge_2d_sptr& stronger,
00429 const int maxSpiral,
00430 const gevd_bufferxy& edgels, vbl_array_2d<vtol_edge_2d_sptr>& edgeMap)
00431 {
00432
00433 if (end.numsup() > 1)
00434 return false;
00435 vcl_vector<vtol_edge_sptr> edges; end.edges(edges);
00436 weaker = edges[0]->cast_to_edge_2d();
00437 vdgl_digital_curve_sptr dc = weaker->curve()->cast_to_vdgl_digital_curve();
00438
00439 const int len = dc->get_interpolator()->get_edgel_chain()->size();
00440
00441
00442
00443 const int rfuzz = vcl_min(len, 3*MINLENGTH);
00444 vtol_edge_2d_sptr* labels = new vtol_edge_2d_sptr[rfuzz];
00445 if (&end == weaker->v1()->cast_to_vertex_2d())
00446 for (int r = 0; r < rfuzz; r++) {
00447 vdgl_edgel edgel= dc->get_interpolator()->get_edgel_chain()->edgel( r);
00448 labels[r] = edgeMap.get( int(edgel.get_x()), int(edgel.get_y()));
00449 edgeMap.put(int(edgel.get_x()), int(edgel.get_y()), NULL);
00450 }
00451 else
00452 for (int r = 0; r < rfuzz; r++) {
00453 vdgl_edgel edgel= dc->get_interpolator()->get_edgel_chain()->edgel(len-1-r);
00454 labels[r] = edgeMap.get( int( edgel.get_x()), int( edgel.get_y()));
00455 edgeMap.put(int(edgel.get_x()), int(edgel.get_y()), NULL);
00456 }
00457
00458
00459 stronger = NULL;
00460 int jx = int(end.x()), jy = int(end.y());
00461 for (int l = 0, n = 0; l < maxSpiral; l++) {
00462 float maxpix = 0; int maxn = 0;
00463 for (; n < RNS[l]; n++) {
00464 int x = jx+RIS[n], y = jy+RJS[n];
00465 if (edgeMap.get(x, y) &&
00466 floatPixel(edgels, x, y) > maxpix) {
00467 maxpix = floatPixel(edgels, x, y);
00468 maxn = n;
00469 }
00470 }
00471 if (maxpix) {
00472 stronger = edgeMap.get(jx+RIS[maxn], jy+RJS[maxn]);
00473 jx += RIS[maxn], jy += RJS[maxn];
00474 break;
00475 }
00476 }
00477
00478 if (&end == weaker->v1()->cast_to_vertex_2d())
00479 for (int r=0; r< rfuzz; r++) {
00480 vdgl_edgel edge= dc->get_interpolator()->get_edgel_chain()->edgel(r);
00481 edgeMap.put(int( edge.get_x()), int( edge.get_y()), labels[r]);
00482 }
00483 else
00484 for (int r=0; r< rfuzz; r++) {
00485 vdgl_edgel edgel= dc->get_interpolator()->get_edgel_chain()->edgel(len-1-r);
00486 edgeMap.put(int( edgel.get_x()), int( edgel.get_y()),labels[r]);
00487 }
00488 delete[] labels;
00489
00490 if (!stronger)
00491 return false;
00492
00493
00494 index = int(INVALID);
00495
00496 vdgl_digital_curve_sptr dc2 =(stronger->curve()->cast_to_vdgl_digital_curve());
00497
00498
00499 for (unsigned int n = 0; n < dc2->get_interpolator()->get_edgel_chain()->size(); ++n)
00500 {
00501 vdgl_edgel edgel= dc2->get_interpolator()->get_edgel_chain()->edgel(n);
00502
00503 if ( int( edgel.get_x())== jx && int( edgel.get_y())== jy)
00504 {
00505 index = n;
00506 break;
00507 }
00508 }
00509 return true;
00510 }
00511
00512
00513
00514
00515
00516 static bool
00517 ConfirmJunctionOnCycle(int index, float threshold,
00518 vtol_edge_2d& cycle, const gevd_bufferxy& edgels)
00519 {
00520 vdgl_digital_curve_sptr dc =(cycle.curve()->cast_to_vdgl_digital_curve());
00521 const int len = dc->get_interpolator()->get_edgel_chain()->size();
00522 const int wrap = 10*len;
00523 const int radius = 3;
00524
00525 for (int n = index-radius; n <= index+radius; n++)
00526 {
00527 int nm = (n-1+wrap)%len;
00528 int np = (n+1+wrap)%len;
00529
00530 vdgl_edgel edgel_m= dc->get_interpolator()->get_edgel_chain()->edgel( nm);
00531 vdgl_edgel edgel_p= dc->get_interpolator()->get_edgel_chain()->edgel( np);
00532
00533 if (vcl_fabs(floatPixel(edgels, int( edgel_p.x()), int( edgel_p.y())) -
00534 floatPixel(edgels, int( edgel_m.x()), int( edgel_m.y())))
00535 > threshold)
00536 return true;
00537 }
00538 return false;
00539 }
00540
00541
00542
00543
00544
00545 void
00546 BreakCycle(vtol_vertex_2d& junction, const int index,
00547 vtol_edge_2d& stronger, vtol_edge_2d_sptr& split,
00548 vbl_array_2d<vtol_edge_2d_sptr>& edgeMap, vbl_array_2d<vtol_vertex_2d_sptr>& vertexMap)
00549 {
00550 vdgl_digital_curve_sptr dc = (stronger.curve()->cast_to_vdgl_digital_curve());
00551 const int len = dc->get_interpolator()->get_edgel_chain()->size();
00552
00553
00554 int jx = int(junction.x()), jy = int(junction.y());
00555 vertexMap.put(jx, jy, NULL);
00556
00557 vdgl_edgel tempedgel= dc->get_interpolator()->get_edgel_chain()->edgel( index);
00558 jx = int( tempedgel.x()), jy = int( tempedgel.y());
00559 junction.set_x(jx), junction.set_y(jy);
00560 vertexMap.put(jx, jy, &junction);
00561 edgeMap.put(jx, jy, NULL);
00562
00563
00564 split = new vtol_edge_2d();
00565
00566 vdgl_edgel_chain *es= new vdgl_edgel_chain;
00567 vdgl_interpolator *it= new vdgl_interpolator_linear( vdgl_edgel_chain_sptr( es));
00568 vdgl_digital_curve *ds = new vdgl_digital_curve( vdgl_interpolator_sptr( it));
00569
00570 split->set_curve(*ds->cast_to_curve());
00571
00572 int i=0;
00573 for (int k = index; k < len; i++,k++) {
00574 vdgl_edgel e= dc->get_interpolator()->get_edgel_chain()->edgel( k);
00575 es->add_edgel( e);
00576 edgeMap.put(int(e.x()), int(e.y()), split);
00577 }
00578 for (int k = 0; i < len; i++,k++) {
00579 vdgl_edgel c= dc->get_interpolator()->get_edgel_chain()->edgel( k);
00580 es->add_edgel( c);
00581 edgeMap.put(int(c.x()), int(c.y()), split);
00582 }
00583
00584 split->set_v1(&junction);
00585 split->set_v2(&junction);
00586 }
00587
00588
00589
00590
00591
00592 static bool
00593 ConfirmJunctionOnChain(int index, float threshold,
00594 vtol_edge_2d& chain, const gevd_bufferxy& edgels)
00595 {
00596 vdgl_digital_curve_sptr dc = chain.curve()->cast_to_vdgl_digital_curve();
00597 const int len = dc->get_interpolator()->get_edgel_chain()->size()-1;
00598
00599 if (len < 2*MINLENGTH-1)
00600 return false;
00601
00602 const int fuzz = MINLENGTH-1;
00603 const int radius = 3;
00604
00605 for (int n = vcl_max(index-radius, fuzz); n <= vcl_min(index+radius,len-1-fuzz); n++)
00606 {
00607 vdgl_edgel cp1= dc->get_interpolator()->get_edgel_chain()->edgel(n+1);
00608 vdgl_edgel cm1= dc->get_interpolator()->get_edgel_chain()->edgel(n-1);
00609
00610 if (vcl_fabs(floatPixel(edgels, int(cp1.x()), int(cp1.y())) -
00611 floatPixel(edgels, int(cp1.x()), int(cm1.y())))
00612 > threshold)
00613 {
00614 return true;
00615 }
00616 }
00617 return false;
00618 }
00619
00620
00621
00622
00623 void
00624 BreakChain(vtol_vertex_2d& junction, const int index,
00625 vtol_edge_2d& stronger,
00626 vtol_edge_2d_sptr& longer, vtol_edge_2d_sptr& shorter,
00627 vbl_array_2d<vtol_edge_2d_sptr>& edgeMap, vbl_array_2d<vtol_vertex_2d_sptr>& vertexMap)
00628 {
00629 vdgl_digital_curve_sptr dc = stronger.curve()->cast_to_vdgl_digital_curve();
00630 vdgl_edgel_chain_sptr cxy= dc->get_interpolator()->get_edgel_chain();
00631
00632 const int l0 = dc->get_interpolator()->get_edgel_chain()->size();
00633 const int l1 = index+1, l2 = l0-index;
00634
00635
00636 int jx = int(junction.x()), jy = int(junction.y());
00637 vertexMap.put(jx, jy, NULL);
00638 vdgl_edgel c= dc->get_interpolator()->get_edgel_chain()->edgel( index);
00639 jx = int(c.x()), jy = int(c.y());
00640 junction.set_x(jx), junction.set_y(jy);
00641 vertexMap.put(jx, jy, &junction);
00642 edgeMap.put( jx, jy, NULL);
00643
00644
00645 vtol_edge_2d_sptr edge1 = new vtol_edge_2d();
00646
00647 vdgl_edgel_chain *ec= new vdgl_edgel_chain;
00648 vdgl_interpolator *it= new vdgl_interpolator_linear( ec);
00649 vdgl_digital_curve *dc1 = new vdgl_digital_curve( it);
00650
00651 edge1->set_curve(*dc1);
00652
00653 vdgl_edgel_chain *cxy1= ec;
00654
00655 for (int k = 0; k < l1; k++)
00656 {
00657 cxy1->add_edgel ( (*cxy)[k] );
00658 (*cxy1)[k] = (*cxy)[k];
00659 edgeMap.put( int((*cxy1)[k].x()), int((*cxy1)[k].y()), edge1);
00660 }
00661
00662
00663 vtol_vertex_sptr v1 = stronger.v1();
00664
00665 if (v1->numsup() == 1)
00666 edgeMap.put( int((*cxy1)[0].x()), int((*cxy1)[0].y()), NULL);
00667 edge1->set_v1(v1.ptr());
00668 edge1->set_v2(&junction);
00669
00670
00671 vtol_edge_2d_sptr edge2 = new vtol_edge_2d();
00672
00673 vdgl_edgel_chain *ec2= new vdgl_edgel_chain;
00674 vdgl_interpolator *it2= new vdgl_interpolator_linear( ec2);
00675 vdgl_digital_curve *dc2= new vdgl_digital_curve( it2);
00676
00677 edge2->set_curve(*dc2);
00678
00679 vdgl_edgel_chain *cxy2= ec2;
00680
00681
00682 for (int k = 0; k < l2; k++)
00683 {
00684 cxy2->add_edgel( cxy->edgel( k+index));
00685 edgeMap.put( int((*cxy2)[k].x()), int((*cxy2)[k].y()), edge2);
00686 }
00687
00688
00689 vtol_vertex_sptr v2 = stronger.v2();
00690
00691 if (v2->numsup() == 1)
00692 edgeMap.put( int((*cxy2)[l2-1].x()), int((*cxy2)[l2-1].y()), NULL);
00693
00694 edge2->set_v1(&junction);
00695 edge2->set_v2(v2.ptr());
00696
00697 if (l1 >= l2)
00698 longer = edge1, shorter = edge2;
00699 else
00700 longer = edge2, shorter = edge1;
00701 }
00702
00703
00704
00705
00706 void
00707 LoopChain(vtol_vertex_2d& junction, const int index,
00708 vtol_edge_2d& chain,
00709 vtol_edge_2d_sptr& straight, vtol_edge_2d_sptr& curled,
00710 vbl_array_2d<vtol_edge_2d_sptr>& edgeMap, vbl_array_2d<vtol_vertex_2d_sptr>& vertexMap)
00711 {
00712 vdgl_digital_curve_sptr dc = chain.curve()->cast_to_vdgl_digital_curve();
00713
00714 vdgl_edgel_chain_sptr cxy= dc->get_interpolator()->get_edgel_chain();
00715 const int l0 = cxy->size();
00716
00717
00718 int jx = int(junction.x()), jy = int(junction.y());
00719 vertexMap.put(jx, jy, NULL);
00720 jx = int((*cxy)[index].x()), jy = int((*cxy)[index].y());
00721 junction.set_x(jx), junction.set_y(jy);
00722 vertexMap.put(jx, jy, &junction);
00723 edgeMap.put( jx, jy, NULL);
00724
00725
00726 straight = new vtol_edge_2d(), curled = new vtol_edge_2d();
00727 const int l1 = index+1, l2 = l0-index;
00728
00729 if (&junction == chain.v1()->cast_to_vertex_2d())
00730 {
00731 vdgl_edgel_chain *ec= new vdgl_edgel_chain;
00732 vdgl_interpolator *it= new vdgl_interpolator_linear( ec);
00733 vdgl_digital_curve *c= new vdgl_digital_curve( it);
00734
00735 curled->set_curve(*c);
00736
00737 vdgl_edgel_chain *xy= ec;
00738 for (int k = 0; k < l1; k++)
00739 {
00740 xy->add_edgel ( (*cxy)[k] );
00741 (*xy)[k] = (*cxy)[k];
00742 edgeMap.put( int((*xy)[k].x()), int((*xy)[k].y()), curled);
00743 }
00744
00745 curled->set_v1(&junction);
00746 curled->set_v2(&junction);
00747
00748
00749 ec= new vdgl_edgel_chain;
00750 it= new vdgl_interpolator_linear( ec);
00751 c = new vdgl_digital_curve( it);
00752
00753 straight->set_curve(*c);
00754
00755 xy= ec;
00756
00757 for (int k = 0; k < l2; k++)
00758 {
00759 xy->add_edgel ( (*cxy)[k+index] );
00760 (*xy)[k] = (*cxy)[k+index];
00761 edgeMap.put( int((*xy)[k].x()), int((*xy)[k].y()), straight);
00762 }
00763
00764 if (chain.v2()->numsup()==1)
00765 {
00766 edgeMap.put( int((*xy)[l2-1].x()), int((*xy)[l2-1].y()), NULL);
00767 }
00768
00769 straight->set_v1(&junction);
00770 straight->set_v2(chain.v2().ptr());
00771 }
00772 else
00773 {
00774 vdgl_edgel_chain *ec= new vdgl_edgel_chain;
00775 vdgl_interpolator *it= new vdgl_interpolator_linear( ec);
00776 vdgl_digital_curve *c= new vdgl_digital_curve( it);
00777
00778 straight->set_curve(*c);
00779
00780
00781 vdgl_edgel_chain *xy= ec;
00782
00783 for (int k = 0; k < l1; k++)
00784 {
00785 xy->add_edgel ( (*cxy)[k] );
00786 (*xy)[k] = (*cxy)[k];
00787 edgeMap.put( int((*xy)[k].x()), int((*xy)[k].y()), straight);
00788 }
00789
00790 if (chain.v1()->numsup()==1)
00791 {
00792 edgeMap.put( int((*xy)[0].x()), int((*xy)[0].y()), NULL);
00793 }
00794
00795 straight->set_v1(chain.v1().ptr());
00796 straight->set_v2(&junction);
00797
00798
00799 ec= new vdgl_edgel_chain;
00800 it= new vdgl_interpolator_linear( ec);
00801 c = new vdgl_digital_curve( it);
00802
00803 curled->set_curve(*c);
00804
00805 xy = ec;
00806 for (int k = 0; k < l2; k++)
00807 {
00808 xy->add_edgel ( (*cxy)[k+index] );
00809 (*xy)[k] = (*cxy)[k+index];
00810 edgeMap.put( int((*xy)[k].x()), int((*xy)[k].y()), curled);
00811 }
00812
00813 curled->set_v1(&junction);
00814 curled->set_v2(&junction);
00815 }
00816 }
00817
00818
00819 int
00820 NumConnectedRays(vtol_vertex_2d& v)
00821 {
00822 int nray = 0;
00823 vcl_vector<vtol_edge_sptr> segs; v.edges(segs);
00824 for (unsigned int i=0; i< segs.size(); i++)
00825 {
00826 if (segs[i]->v1()->cast_to_vertex_2d() == &v) nray++;
00827 if (segs[i]->v2()->cast_to_vertex_2d() == &v) nray++;
00828 }
00829 return nray;
00830 }
00831
00832
00833
00834 vtol_vertex_2d_sptr
00835 DetectTouch(const vtol_vertex_2d& end, const int maxSpiral,
00836 vbl_array_2d<vtol_vertex_2d_sptr>& vertexMap)
00837 {
00838 const int jx = int(end.x()), jy = int(end.y());
00839 for (int l = 0, n = 0; l < maxSpiral; l++) {
00840 vtol_vertex_2d_sptr other = NULL;
00841 int maxray = 0;
00842 for (; n < RNS[l]; n++) {
00843 vtol_vertex_2d_sptr nbr = vertexMap.get(jx+RIS[n], jy+RJS[n]);
00844 int nray = (nbr ? NumConnectedRays(*nbr) : 0);
00845 if (nray > maxray) {
00846 maxray = nray;
00847 other = nbr;
00848 }
00849 }
00850 if (maxray)
00851 return other;
00852 }
00853 return NULL;
00854 }
00855
00856
00857
00858 vtol_edge_2d_sptr
00859 DanglingEdge(vtol_vertex_2d& v)
00860 {
00861 vcl_vector<vtol_edge_sptr> segs; v.edges(segs);
00862
00863 if (segs.size()==1)
00864 return segs[0]->cast_to_edge_2d();
00865 else
00866 return 0;
00867 }
00868
00869
00870
00871
00872 void
00873 MergeEndPtsOfChain(vtol_vertex_2d& endpt, vtol_vertex_2d& other, vtol_edge_2d& common,
00874 vbl_array_2d<vtol_edge_2d_sptr>& edgeMap, vbl_array_2d<vtol_vertex_2d_sptr>&vertexMap)
00875 {
00876 int px = int(other.x()), py = int(other.y());
00877 vertexMap.put(px, py, NULL);
00878 edgeMap.put( px, py, &common);
00879 if (common.v1() == &other)
00880 common.set_v1(&endpt);
00881 else
00882 common.set_v2(&endpt);
00883 }
00884
00885
00886
00887
00888 void
00889 MergeEndPtTouchingEndPt(vtol_vertex_2d& end1, vtol_vertex_2d