00001
00002 #include "bmdl_mesh.h"
00003
00004
00005
00006 #include <vgl/vgl_intersection.h>
00007 #include <vgl/vgl_lineseg_test.h>
00008 #include <vgl/algo/vgl_fit_lines_2d.h>
00009 #include <vgl/vgl_area.h>
00010 #include <vgl/vgl_polygon.h>
00011 #include <vgl/vgl_line_2d.h>
00012 #include <vgl/vgl_distance.h>
00013 #include <vil/vil_bilin_interp.h>
00014 #include <vcl_cassert.h>
00015 #include <vcl_map.h>
00016
00017
00018 bool bmdl_mesh::next_trace_point(unsigned int& i, unsigned int& j, int& dir,
00019 const unsigned int* &p, unsigned int value,
00020 unsigned int ni1, unsigned int nj1,
00021 vcl_ptrdiff_t istep, vcl_ptrdiff_t jstep)
00022 {
00023 bool moved = false;
00024
00025 switch (dir) {
00026 case 1:
00027 if (i<ni1 && p[istep]==value) { ++i; p+=istep; moved = true; }
00028 break;
00029 case 2:
00030 if (j<nj1 && p[jstep]==value) { ++j; p+=jstep; moved = true; }
00031 break;
00032 case 3:
00033 if (i>0 && p[-istep]==value) { --i; p-=istep; moved = true; }
00034 break;
00035 case 0:
00036 if (j>0 && p[-jstep]==value) { --j; p-=jstep; moved = true; }
00037 break;
00038 default:
00039 return false;
00040 }
00041
00042 if (moved) {
00043
00044 switch (dir) {
00045 case 0:
00046 if (i<ni1 && p[istep]==value) { ++i; p+=istep; dir=1; }
00047 break;
00048 case 1:
00049 if (j<nj1 && p[jstep]==value) { ++j; p+=jstep; dir=2; }
00050 break;
00051 case 2:
00052 if (i>0 && p[-istep]==value) { --i; p-=istep; dir=3; }
00053 break;
00054 case 3:
00055 if (j>0 && p[-jstep]==value) { --j; p-=jstep; dir=0; }
00056 break;
00057 default:
00058 return false;
00059 }
00060 }
00061 else {
00062
00063 dir = (dir+3)%4;
00064 }
00065 return true;
00066 }
00067
00068
00069
00070 bool bmdl_mesh::trace_boundary(vcl_vector<vgl_point_2d<double> >& pts,
00071 unsigned int value,
00072 const vil_image_view<unsigned int>& labels,
00073 vil_image_view<bool>& visited,
00074 unsigned int i, unsigned int j)
00075 {
00076 unsigned int ni = labels.ni();
00077 unsigned int nj = labels.nj();
00078 vcl_ptrdiff_t istep = labels.istep(), jstep=labels.jstep();
00079 const unsigned* p = &labels(i,j);
00080 if (*p != value)
00081 return false;
00082
00083
00084 int dir = 2;
00085
00086 unsigned int i0=i, j0=j;
00087 unsigned int ni1=ni-1, nj1=nj-1;
00088
00089 do {
00090 if (dir == 2) {
00091 if (visited(i,j))
00092 return false;
00093 visited(i,j) = true;
00094 }
00095 unsigned int pi = i+((dir==0||dir==3)?1:0);
00096 unsigned int pj = j+((dir/2==0)?1:0);
00097 pts.push_back(vgl_point_2d<double>(pi-0.5, pj-0.5));
00098 next_trace_point(i,j,dir,p,value,ni1,nj1,istep,jstep);
00099 }
00100 while (i!=i0 || j!=j0 || dir!=2);
00101
00102 return true;
00103 }
00104
00105
00106
00107
00108 vcl_vector<vgl_polygon<double> >
00109 bmdl_mesh::trace_boundaries(const vil_image_view<unsigned int>& labels,
00110 bool drop_clipped)
00111 {
00112 int ni = labels.ni();
00113 int nj = labels.nj();
00114
00115 unsigned int num_labels = 0;
00116 for (int j=0; j<nj; ++j)
00117 for (int i=0; i<ni; ++i)
00118 if (labels(i,j) > num_labels)
00119 num_labels = labels(i,j);
00120
00121 vcl_vector<vgl_polygon<double> > boundaries(num_labels,vgl_polygon<double>(0));
00122 for (unsigned i=0; i<num_labels; ++i)
00123 boundaries[i].clear();
00124 vil_image_view<bool> visited(ni,nj);
00125 visited.fill(false);
00126
00127 for (int j=0; j<nj; ++j) {
00128 for (int i=0; i<ni; ++i) {
00129 unsigned int l = labels(i,j);
00130 if (l<2) continue;
00131 if (!visited(i,j) && (i==0 || labels(i-1,j)!=l)) {
00132 assert(l-2<boundaries.size());
00133 vgl_polygon<double>& poly = boundaries[l-2];
00134 vcl_vector<vgl_point_2d<double> > sheet;
00135
00136
00137
00138 if (trace_boundary(sheet,l,labels,visited,i,j) &&
00139 (!drop_clipped || !is_clipped(sheet,ni,nj)))
00140 poly.push_back(sheet);
00141 }
00142 }
00143 }
00144
00145 return boundaries;
00146 }
00147
00148
00149 bool bmdl_mesh::is_clipped(const vcl_vector<vgl_point_2d<double> >& poly,
00150 unsigned ni, unsigned nj)
00151 {
00152
00153 --ni;
00154 --nj;
00155 for (unsigned int i=0; i<poly.size(); ++i)
00156 {
00157 if (poly[i].x() < 0.0 || poly[i].y() < 0.0 ||
00158 poly[i].x() > ni || poly[i].y() > nj)
00159 return true;
00160 }
00161
00162 return false;
00163 }
00164
00165
00166 namespace
00167 {
00168
00169 unsigned int& get_edge_bin(vil_image_view<unsigned int>& edge_bins,
00170 const vgl_point_2d<double>& p1,
00171 const vgl_point_2d<double>& p2)
00172 {
00173 unsigned int *binp = 0;
00174 if (vcl_abs(p2.x() - p1.x()) < 0.5)
00175 {
00176 binp = &edge_bins(static_cast<unsigned int>(p1.x()+1.0),
00177 static_cast<unsigned int>((p1.y()+p2.y())/2.0+0.5), 0);
00178 }
00179 else
00180 {
00181 binp = &edge_bins(static_cast<unsigned int>((p1.x()+p2.x())/2.0+0.5),
00182 static_cast<unsigned int>(p1.y()+1.0), 1);
00183 }
00184 return *binp;
00185 }
00186 }
00187
00188
00189
00190 unsigned int bmdl_mesh::link_boundary_edges(const vil_image_view<unsigned int>& labels,
00191 const vcl_vector<vgl_polygon<double> >& polygons,
00192 vcl_vector<bmdl_edge>& edges,
00193 vcl_vector<bmdl_region>& regions)
00194 {
00195 unsigned int ni = labels.ni();
00196 unsigned int nj = labels.nj();
00197 vil_image_view<unsigned int> edge_labels(ni+1, nj+1, 2);
00198 edge_labels.fill(0);
00199
00200 unsigned int joint_count = 0;
00201 unsigned int last_joint = static_cast<unsigned int>(-1);
00202
00203 regions.resize(polygons.size());
00204 for (unsigned int i=0; i<polygons.size(); ++i)
00205 {
00206 const vgl_polygon<double>& poly = polygons[i];
00207 if (poly.num_sheets() < 1)
00208 continue;
00209
00210 unsigned int num_cw=0, num_ccw=0;
00211 vcl_vector<bool> is_hole(poly.num_sheets(),false);
00212 for (unsigned int j=0; j<poly.num_sheets(); ++j)
00213 {
00214 double area = vgl_area_signed(vgl_polygon<double>(poly[j]));
00215 is_hole[j] = (area > 0.0);
00216 if (is_hole[j])
00217 ++num_ccw;
00218 else
00219 ++num_cw;
00220 }
00221
00222 if (num_cw == 0)
00223 continue;
00224 else if (num_cw > 1)
00225 {
00226 vcl_cerr << "Ignoring polygon with multiple connected components "<< i << vcl_endl;
00227 for (unsigned int k=0; k<is_hole.size(); ++k)
00228 if (!is_hole[k])
00229 {
00230 vcl_cout << " "<<poly[k][0].x()<<", "<<poly[k][0].y()<<vcl_endl;
00231 }
00232 continue;
00233 }
00234 bmdl_region& region = regions[i];
00235 if (num_ccw > 0)
00236 region.hole_edge_idxs.resize(num_ccw);
00237 unsigned int hole_count = 0;
00238 for (unsigned int j=0; j<poly.num_sheets(); ++j)
00239 {
00240 const vcl_vector<vgl_point_2d<double> >& pts = poly[j];
00241 vcl_vector<unsigned int>& edge_idxs = (!is_hole[j]) ?
00242 region.edge_idxs :
00243 region.hole_edge_idxs[hole_count++];
00244 for (unsigned int k1=pts.size()-1,k2=0; k2<pts.size(); k1=k2++)
00245 {
00246 vgl_vector_2d<double> v(pts[k2]-pts[k1]);
00247 vgl_point_2d<double> p = pts[k1] + 0.5*v;
00248 p += vgl_vector_2d<double>(-0.5*v.y(), 0.5*v.x());
00249 int x = static_cast<int>(p.x()+0.5);
00250 int y = static_cast<int>(p.y()+0.5);
00251 unsigned l = 0;
00252 if (x >= 0 && (unsigned)x < ni && y >=0 && (unsigned)y < nj)
00253 {
00254 l = labels(x,y);
00255 if (l > 0)
00256 l -= 1;
00257 }
00258
00259
00260 unsigned int& bin = get_edge_bin(edge_labels,pts[k1],pts[k2]);
00261
00262 if (bin > 0)
00263 {
00264 if (edge_idxs.empty() || edge_idxs.back() != bin-1)
00265 {
00266
00267 if (!edge_idxs.empty() && edges[edge_idxs.back()].building1 == i+1)
00268 {
00269 edges[edge_idxs.back()].joint2 = edges[bin-1].joint2;
00270 --joint_count;
00271 }
00272 edge_idxs.push_back(bin-1);
00273 assert(edges[edge_idxs.back()].building1 == l);
00274 assert(edges[edge_idxs.back()].building2 == i+1);
00275 last_joint = edges[edge_idxs.back()].joint1;
00276 }
00277 }
00278 else
00279 {
00280 if (edge_idxs.empty() || edges[edge_idxs.back()].building2 != l)
00281 {
00282
00283 edge_idxs.push_back(edges.size());
00284 edges.push_back(bmdl_edge(i+1,l));
00285 edges.back().pts.push_back(pts[k1]);
00286 edges.back().joint1 = last_joint;
00287 edges.back().joint2 = joint_count++;
00288 last_joint = edges.back().joint2;
00289 }
00290 edges[edge_idxs.back()].pts.push_back(pts[k2]);
00291 bin = edge_idxs.back()+1;
00292 }
00293 }
00294
00295 if (edge_idxs.size() > 1)
00296 {
00297
00298 if (edge_idxs.front() == edge_idxs.back() &&
00299 edges[edge_idxs.front()].building2 == i+1)
00300 {
00301 edge_idxs.pop_back();
00302 }
00303
00304 else if (edges[edge_idxs.front()].building2 == edges[edge_idxs.back()].building2 &&
00305 edges[edge_idxs.front()].building2 != i+1)
00306 {
00307 vcl_vector<vgl_point_2d<double> >& pts1 = edges[edge_idxs.front()].pts;
00308 vcl_vector<vgl_point_2d<double> >& pts2 = edges[edge_idxs.back()].pts;
00309
00310 for (unsigned int k=1; k<pts2.size(); ++k)
00311 {
00312 unsigned int& bin = get_edge_bin(edge_labels,pts2[k-1],pts2[k]);
00313 bin = edge_idxs.front()+1;
00314 }
00315 assert((pts1.front() - pts2.back()).length() < 1e-6);
00316 pts2.insert(pts2.end(),pts1.begin()+1,pts1.end());
00317 pts1.swap(pts2);
00318 assert(edge_idxs.back()+1 == edges.size());
00319 last_joint = edges[edge_idxs.back()].joint1;
00320 edge_idxs.pop_back();
00321 edges.pop_back();
00322 --joint_count;
00323 }
00324
00325 else if (edges[edge_idxs.back()].building1 == i+1 &&
00326 edges[edge_idxs.front()].building2 == i+1 &&
00327 edges[edge_idxs.back()].joint2 != edges[edge_idxs.front()].joint2 )
00328 {
00329 edges[edge_idxs.back()].joint2 = edges[edge_idxs.front()].joint2;
00330 --joint_count;
00331 --last_joint;
00332 }
00333 }
00334
00335 if (edges[edge_idxs.front()].building1 == i+1)
00336 {
00337 edges[edge_idxs.front()].joint1 = last_joint;
00338 }
00339 }
00340 }
00341 return joint_count;
00342 }
00343
00344
00345
00346
00347 void bmdl_mesh::simplify_polygon( vcl_vector<vgl_point_2d<double> >& pts, double tol )
00348 {
00349 vgl_fit_lines_2d<double> line_fitter(3,tol);
00350
00351 line_fitter.add_point(pts.back());
00352 line_fitter.add_curve(pts);
00353 line_fitter.fit();
00354 const vcl_vector<vgl_line_segment_2d<double> >& segs = line_fitter.get_line_segs();
00355 const vcl_vector<int>& indices = line_fitter.get_indices();
00356 vcl_vector<vgl_point_2d<double> > new_pts;
00357 vgl_point_2d<double> isect;
00358 for ( unsigned int i=0; i< indices.size(); )
00359 {
00360 if (indices[i] < 0)
00361 {
00362 new_pts.push_back(pts[i++]);
00363 continue;
00364 }
00365 const vgl_line_segment_2d<double>& seg = segs[indices[i]];
00366
00367 if (new_pts.size() > 1 && vgl_distance(new_pts.back(),seg.point1())< 1.0 &&
00368 angle(vgl_vector_2d<double>(new_pts.back()-new_pts[new_pts.size()-2]),
00369 vgl_vector_2d<double>(seg.point1()-seg.point2())) > 0.5) {
00370 vgl_intersection(vgl_line_2d<double>(new_pts[new_pts.size()-2], new_pts.back()),
00371 vgl_line_2d<double>(seg.point1(),seg.point2()),
00372 isect);
00373 new_pts.back() = isect;
00374 }
00375 else
00376 new_pts.push_back(seg.point1());
00377 new_pts.push_back(seg.point2());
00378
00379 for (int curr_seg_idx = indices[i];
00380 i<indices.size() && indices[i] == curr_seg_idx; ++i)
00381 ;
00382 }
00383 if (new_pts.size() > 3 && vgl_distance(new_pts.back(),new_pts.front())<1.0 &&
00384 angle(vgl_vector_2d<double>(new_pts.back()-new_pts[new_pts.size()-2]),
00385 vgl_vector_2d<double>(new_pts[0]-new_pts[1])) > 0.5) {
00386 vgl_intersection(vgl_line_2d<double>(new_pts[new_pts.size()-2], new_pts.back()),
00387 vgl_line_2d<double>(new_pts[0],new_pts[1]),
00388 isect);
00389 new_pts[0] = isect;
00390 new_pts.pop_back();
00391 }
00392 pts.swap(new_pts);
00393 }
00394
00395
00396
00397 void bmdl_mesh::simplify_boundaries( vcl_vector<vgl_polygon<double> >& boundaries )
00398 {
00399
00400 for (unsigned int i=0; i<boundaries.size(); ++i)
00401 {
00402 vgl_polygon<double>& poly = boundaries[i];
00403 for (unsigned int j=0; j<poly.num_sheets(); ++j)
00404 {
00405 vcl_vector<vgl_point_2d<double> >& pts = poly[j];
00406
00407 vcl_vector<vgl_point_2d<double> > new_pts;
00408 for (unsigned p1=pts.size()-1, p2=0; p2<pts.size(); p1=p2, ++p2) {
00409 new_pts.push_back(vgl_point_2d<double>((pts[p1].x()+pts[p2].x())/2, (pts[p1].y()+pts[p2].y())/2));
00410 }
00411 pts.swap(new_pts);
00412
00413 simplify_polygon(pts,0.01);
00414 simplify_polygon(pts,0.5);
00415 }
00416 }
00417 }
00418
00419
00420
00421
00422 void bmdl_mesh::simplify_edge( vcl_vector<vgl_point_2d<double> >& pts, double tol )
00423 {
00424 vgl_fit_lines_2d<double> line_fitter(3,tol);
00425 line_fitter.add_curve(pts);
00426 line_fitter.fit();
00427 const vcl_vector<vgl_line_segment_2d<double> >& segs = line_fitter.get_line_segs();
00428 const vcl_vector<int>& indices = line_fitter.get_indices();
00429 vcl_vector<vgl_point_2d<double> > new_pts;
00430
00431 new_pts.push_back(pts.front());
00432 vgl_point_2d<double> isect;
00433 for ( unsigned int i=0; i< indices.size(); )
00434 {
00435 if (indices[i] < 0)
00436 {
00437 if (i==0 || i==indices.size()-1)
00438 ++i;
00439 else if (new_pts.empty() || new_pts.back() != pts[i])
00440 new_pts.push_back(pts[i++]);
00441
00442 continue;
00443 }
00444 const vgl_line_segment_2d<double>& seg = segs[indices[i]];
00445
00446 if (new_pts.size() > 1 && vgl_distance(new_pts.back(),seg.point1())< 1.0 &&
00447 angle(vgl_vector_2d<double>(new_pts.back()-new_pts[new_pts.size()-2]),
00448 vgl_vector_2d<double>(seg.point1()-seg.point2())) > 0.5) {
00449 vgl_intersection(vgl_line_2d<double>(new_pts[new_pts.size()-2], new_pts.back()),
00450 vgl_line_2d<double>(seg.point1(),seg.point2()),
00451 isect);
00452 new_pts.back() = isect;
00453 }
00454
00455 else if (i>0 || (seg.point1()-pts.front()).length()>0.5)
00456 new_pts.push_back(seg.point1());
00457
00458
00459 if (new_pts.size()>1 && new_pts.back() == new_pts[new_pts.size()-2])
00460 new_pts.pop_back();
00461
00462
00463 for (int curr_seg_idx = indices[i];
00464 i<indices.size() && indices[i] == curr_seg_idx; ++i)
00465 ;
00466
00467
00468 if (i<indices.size() || (seg.point2()-pts.back()).length()>0.5)
00469 new_pts.push_back(seg.point2());
00470
00471 if (new_pts.size()>1 && new_pts.back() == new_pts[new_pts.size()-2])
00472 new_pts.pop_back();
00473 }
00474
00475 new_pts.push_back(pts.back());
00476 pts.swap(new_pts);
00477 }
00478
00479
00480
00481 void bmdl_mesh::simplify_edges( vcl_vector<bmdl_edge>& edges )
00482 {
00483 for (unsigned int i=0; i<edges.size(); ++i)
00484 {
00485 vcl_vector<vgl_point_2d<double> >& pts = edges[i].pts;
00486
00487
00488 vcl_vector<vgl_point_2d<double> > new_pts;
00489 new_pts.push_back(pts.front());
00490 for (unsigned j=1; j<pts.size(); ++j) {
00491 new_pts.push_back(vgl_point_2d<double>((pts[j-1].x()+pts[j].x())/2,
00492 (pts[j-1].y()+pts[j].y())/2));
00493 }
00494 new_pts.push_back(pts.back());
00495 pts.swap(new_pts);
00496
00497 simplify_edge(pts, 0.01);
00498 simplify_edge(pts, 0.5);
00499 }
00500 }
00501
00502
00503
00504
00505
00506 void bmdl_mesh::mesh_lidar(const vcl_vector<vgl_polygon<double> >& boundaries,
00507 const vil_image_view<unsigned int>& labels,
00508 const vil_image_view<double>& heights,
00509 const vil_image_view<double>& ground,
00510 imesh_mesh& mesh)
00511 {
00512 unsigned ni = labels.ni();
00513 unsigned nj = labels.nj();
00514
00515
00516 vcl_vector<double> bld_heights(boundaries.size());
00517 for (unsigned int j=0; j<nj; ++j){
00518 for (unsigned int i=0; i<ni; ++i){
00519 if (labels(i,j) > 1){
00520 bld_heights[labels(i,j)-2] = heights(i,j);
00521 }
00522 }
00523 }
00524
00525 imesh_vertex_array<3> *verts = new imesh_vertex_array<3>;
00526 imesh_face_array *faces = new imesh_face_array;
00527
00528
00529 for (unsigned int b=0; b<boundaries.size(); ++b) {
00530 if (boundaries[b].num_sheets() == 0)
00531 continue;
00532 const vcl_vector<vgl_point_2d<double> >& pts = boundaries[b][0];
00533 if (pts.size()<3)
00534 continue;
00535
00536 unsigned int first_pt = verts->size();
00537 vcl_vector< unsigned int > roof;
00538 for (unsigned i=0; i<pts.size(); ++i) {
00539 const vgl_point_2d<double>& pt = pts[i];
00540 double g = vil_bilin_interp_safe_extend(ground, pt.x(), pt.y());
00541 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(), g));
00542 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(),bld_heights[b]));
00543 unsigned int bi = first_pt + 2*i;
00544 faces->push_back(imesh_quad(bi+1,bi,bi+2,bi+3));
00545 roof.push_back(bi+1);
00546 }
00547
00548 vcl_vector< unsigned int >& last_face = (*faces)[faces->size()-1];
00549 last_face[2] = first_pt;
00550 last_face[3] = first_pt+1;
00551
00552 faces->push_back(roof);
00553 }
00554
00555 vcl_auto_ptr<imesh_vertex_array_base> vb(verts);
00556 vcl_auto_ptr<imesh_face_array_base> fb(faces);
00557 mesh.set_vertices(vb);
00558 mesh.set_faces(fb);
00559 }
00560
00561
00562 namespace{
00563 unsigned int add_joint_vertex(imesh_vertex_array<3>& verts,
00564 vcl_vector<unsigned int>& vert_stack,
00565 const imesh_vertex<3>& v)
00566 {
00567 bool found = false;
00568 vcl_vector<unsigned int>::iterator i=vert_stack.begin();
00569 for (; i!=vert_stack.end() && verts[*i][2] <= v[2]; ++i)
00570 {
00571 if (verts[*i][2] == v[2])
00572 {
00573 found = true;
00574 break;
00575 }
00576 }
00577 if (found)
00578 return *i;
00579
00580 unsigned int bi = verts.size();
00581 verts.push_back(v);
00582 vert_stack.insert(i,bi);
00583 return bi;
00584 }
00585
00586
00587 inline vcl_vector<unsigned int>::const_iterator
00588 find_by_height(const vcl_vector<unsigned int>& idxs,
00589 const imesh_vertex_array<3>& verts,
00590 double height)
00591 {
00592 for (vcl_vector<unsigned int>::const_iterator i=idxs.begin(); i!=idxs.end(); ++i)
00593 if (verts[*i][2] == height)
00594 return i;
00595 return idxs.end();
00596 }
00597 }
00598
00599
00600
00601
00602 void bmdl_mesh::mesh_lidar(const vcl_vector<bmdl_edge>& edges,
00603 const vcl_vector<bmdl_region>& regions,
00604 unsigned int num_joints,
00605 const vil_image_view<unsigned int>& labels,
00606 const vil_image_view<double>& heights,
00607 const vil_image_view<double>& ground,
00608 imesh_mesh& mesh)
00609 {
00610 unsigned ni = labels.ni();
00611 unsigned nj = labels.nj();
00612
00613
00614 vcl_vector<double> bld_heights(regions.size());
00615 for (unsigned int j=0; j<nj; ++j)
00616 {
00617 for (unsigned int i=0; i<ni; ++i)
00618 {
00619 if (labels(i,j) > 1){
00620 bld_heights[labels(i,j)-2] = heights(i,j);
00621 }
00622 }
00623 }
00624
00625 vcl_vector<vcl_vector<unsigned int> > face_list(regions.size());
00626 for (unsigned int i = 0; i<regions.size(); ++i)
00627 {
00628 const vcl_vector<unsigned int>& edge_idxs = regions[i].edge_idxs;
00629 for (unsigned int j = 0; j<edge_idxs.size(); ++j)
00630 {
00631 if (edges[edge_idxs[j]].building1 == i+1)
00632 {
00633 face_list[i].push_back(edges[edge_idxs[j]].joint1);
00634
00635 face_list[i].push_back(num_joints + 2*edge_idxs[j]);
00636 face_list[i].push_back(num_joints + 2*edge_idxs[j] + 1);
00637 }
00638 else
00639 {
00640 face_list[i].push_back(edges[edge_idxs[j]].joint2);
00641
00642 face_list[i].push_back(num_joints + 2*edge_idxs[j] + 1);
00643 face_list[i].push_back(num_joints + 2*edge_idxs[j]);
00644 }
00645 }
00646 }
00647 imesh_half_edge_set he2d(face_list);
00648
00649
00650 vcl_vector<vcl_vector<unsigned int> > edge_to_mesh(edges.size());
00651 vcl_vector<vcl_vector<unsigned int> > joint_vert_stack(num_joints);
00652
00653 imesh_vertex_array<3> *verts = new imesh_vertex_array<3>;
00654 imesh_face_array *faces = new imesh_face_array;
00655
00656
00657 for (unsigned int e=0; e<edges.size(); ++e)
00658 {
00659 const bmdl_edge& edge = edges[e];
00660 const vgl_point_2d<double>& pt1 = edge.pts.front();
00661 const vgl_point_2d<double>& pt2 = edge.pts.back();
00662 vcl_vector<unsigned int>& jvs1 = joint_vert_stack[edge.joint1];
00663 vcl_vector<unsigned int>& jvs2 = joint_vert_stack[edge.joint2];
00664
00665 bool b1_gnd = edge.building1 == 0 || regions[edge.building1-1].edge_idxs.empty();
00666 bool b2_gnd = edge.building2 == 0 || regions[edge.building2-1].edge_idxs.empty();
00667
00668 if (b1_gnd || b2_gnd)
00669 {
00670 double g1 = vil_bilin_interp_safe_extend(ground, pt1.x(), pt1.y());
00671 add_joint_vertex(*verts, jvs1, imesh_vertex<3>(pt1.x(),-pt1.y(), g1));
00672 double g2 = vil_bilin_interp_safe_extend(ground, pt2.x(), pt2.y());
00673 add_joint_vertex(*verts, jvs2, imesh_vertex<3>(pt2.x(),-pt2.y(), g2));
00674 }
00675 if (!b1_gnd)
00676 {
00677 double h = bld_heights[edge.building1-1];
00678 add_joint_vertex(*verts, jvs1, imesh_vertex<3>(pt1.x(),-pt1.y(),h));
00679 add_joint_vertex(*verts, jvs2, imesh_vertex<3>(pt2.x(),-pt2.y(),h));
00680 }
00681 if (!b2_gnd)
00682 {
00683 double h = bld_heights[edge.building2-1];
00684 add_joint_vertex(*verts, jvs1, imesh_vertex<3>(pt1.x(),-pt1.y(),h));
00685 add_joint_vertex(*verts, jvs2, imesh_vertex<3>(pt2.x(),-pt2.y(),h));
00686 }
00687 }
00688
00689 typedef vcl_pair<unsigned int, unsigned int> uint_pair;
00690 vcl_map<uint_pair, vcl_vector<unsigned int> > revised_stack;
00691
00692 for (unsigned int i=0; i<joint_vert_stack.size(); ++i){
00693
00694 imesh_half_edge_set::v_const_iterator e1 = he2d.vertex_begin(i), ei = e1;
00695 imesh_half_edge_set::v_const_iterator invalid_e(imesh_invalid_idx,he2d);
00696 if (ei == invalid_e)
00697 continue;
00698 int f1 = static_cast<int>(ei->face_index());
00699 if (e1 == ++ei)
00700 continue;
00701 int f2 = static_cast<int>(ei->face_index());
00702 if (e1 == ++ei)
00703 continue;
00704 int f3 = static_cast<int>(ei->face_index());
00705 if (e1 == ++ei)
00706 continue;
00707 int f4 = static_cast<int>(ei->face_index());
00708 assert(e1 == ++ei);
00709
00710
00711 if ((f1 > f2 && f1 > f4 && f3 > f2 && f3 > f4) ||
00712 (f2 > f1 && f2 > f3 && f4 > f1 && f4 > f3) )
00713 {
00714 if (f1 > f2)
00715 {
00716 int tmp = f1;
00717 f1 = f2;
00718 f2 = f3;
00719 f3 = f4;
00720 f4 = tmp;
00721 }
00722
00723
00724 const vcl_vector<unsigned int>& jvs = joint_vert_stack[i];
00725
00726 double h1 = (f1<0)?(*verts)[jvs.front()][2]:bld_heights[f1];
00727 double h2 = bld_heights[f2];
00728 double h3 = (f3<0)?(*verts)[jvs.front()][2]:bld_heights[f3];
00729 vcl_vector<unsigned int> new_stack1;
00730 for (unsigned int k=0; k<jvs.size(); ++k)
00731 {
00732 double z = (*verts)[jvs[k]][2];
00733 if (z == h1 || z == h2 || z == h3)
00734 new_stack1.push_back(jvs[k]);
00735 }
00736 revised_stack[uint_pair(f2,i)] = new_stack1;
00737
00738 h1 = (f3<0)?(*verts)[jvs.front()][2]:bld_heights[f3];
00739 h2 = bld_heights[f4];
00740 h3 = (f1<0)?(*verts)[jvs.front()][2]:bld_heights[f1];
00741 vcl_vector<unsigned int> new_stack2;
00742 for (unsigned int k=0; k<jvs.size(); ++k)
00743 {
00744 double z = (*verts)[jvs[k]][2];
00745 if (z == h1 || z == h2 || z == h3)
00746 new_stack2.push_back(jvs[k]);
00747 }
00748 revised_stack[uint_pair(f4,i)] = new_stack2;
00749 }
00750 }
00751
00752
00753
00754 for (unsigned int b=0; b<regions.size(); ++b) {
00755 if (regions[b].edge_idxs.empty())
00756 continue;
00757 unsigned int roof_face = 0;
00758 for (int h=-1; h<(int)regions[b].hole_edge_idxs.size(); ++h)
00759 {
00760 const vcl_vector<unsigned int>& edge_idxs = (h<0) ? regions[b].edge_idxs :
00761 regions[b].hole_edge_idxs[h];
00762 vcl_vector< unsigned int > roof;
00763 for (unsigned int e=0; e<edge_idxs.size(); ++e)
00764 {
00765 const bmdl_edge& edge = edges[edge_idxs[e]];
00766 vcl_vector<unsigned int> e2m = edge_to_mesh[edge_idxs[e]];
00767 vcl_vector<vgl_point_2d<double> > pts = edge.pts;
00768 unsigned int other = 0;
00769 unsigned int j1 = edge.joint1;
00770 unsigned int j2 = edge.joint2;
00771 if (edge.building1 == b+1)
00772 {
00773 other = edge.building2;
00774 }
00775 else if (edge.building2 == b+1)
00776 {
00777 other = edge.building1;
00778 vcl_reverse(pts.begin(), pts.end());
00779 vcl_reverse(e2m.begin(), e2m.end());
00780 vcl_swap(j1,j2);
00781 }
00782 else
00783 vcl_cout << "mismatch "<<b+1<<", "<<edge.building1<<", "<<edge.building2<<vcl_endl;
00784
00785
00786
00787 vcl_map<uint_pair, vcl_vector<unsigned int> >::const_iterator rvs1 = revised_stack.find(uint_pair(b,j1));
00788 vcl_map<uint_pair, vcl_vector<unsigned int> >::const_iterator rvs2 = revised_stack.find(uint_pair(b,j2));
00789 const vcl_vector<unsigned int>& jvs1 = (rvs1==revised_stack.end())
00790 ? joint_vert_stack[j1]
00791 : rvs1->second;
00792 const vcl_vector<unsigned int>& jvs2 = (rvs2==revised_stack.end())
00793 ? joint_vert_stack[j2]
00794 : rvs2->second;
00795
00796
00797 bool on_ground = other == 0 || regions[other-1].edge_idxs.empty();
00798
00799 typedef vcl_vector<unsigned int>::const_iterator vfitr;
00800 typedef vcl_vector<unsigned int>::const_reverse_iterator vritr;
00801
00802 vfitr i1beg = jvs1.begin();
00803 vfitr i1end = find_by_height(jvs1, *verts, bld_heights[b]);
00804 vfitr i2beg = jvs2.begin();
00805 vfitr i2end = find_by_height(jvs2, *verts, bld_heights[b]);
00806 assert(i1end != jvs1.end());
00807 assert(i2end != jvs2.end());
00808 if (!on_ground)
00809 {
00810 i1beg = find_by_height(jvs1, *verts, bld_heights[other-1]);
00811 i2beg = find_by_height(jvs2, *verts, bld_heights[other-1]);
00812 assert(i1beg != jvs1.end());
00813 assert(i2beg != jvs2.end());
00814 if (bld_heights[other-1] > bld_heights[b])
00815 {
00816 vcl_swap(i1beg, i1end);
00817 vcl_swap(i2beg, i2end);
00818 }
00819 }
00820
00821 if (!on_ground && edge.building1 == b+1)
00822 {
00823
00824 vcl_vector<unsigned int>& e2m_set = edge_to_mesh[edge_idxs[e]];
00825 roof.push_back(*i1beg);
00826 for (unsigned int i=1; i<pts.size()-1; ++i) {
00827 const vgl_point_2d<double>& pt = pts[i];
00828 unsigned int bi = verts->size();
00829 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(),bld_heights[b]));
00830 roof.push_back(bi);
00831 e2m_set.push_back(bi);
00832 }
00833 continue;
00834 }
00835
00836 vcl_vector<unsigned int> face;
00837
00838 roof.push_back(*i1end);
00839 ++i1end;
00840 face.insert(face.end(), vritr(i1end), vritr(i1beg));
00841
00842 if (on_ground)
00843 {
00844
00845 for (unsigned int i=1; i<pts.size()-1; ++i) {
00846 const vgl_point_2d<double>& pt = pts[i];
00847 double g = vil_bilin_interp_safe_extend(ground, pt.x(), pt.y());
00848 unsigned int bi = verts->size();
00849 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(), g));
00850 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(),bld_heights[b]));
00851 roof.push_back(bi+1);
00852
00853 face.push_back(bi);
00854 face.push_back(bi+1);
00855 faces->push_back(face);
00856
00857 face.clear();
00858 face.push_back(bi+1);
00859 face.push_back(bi);
00860 }
00861 }
00862 else
00863 {
00864 if (e2m.empty() && pts.size() > 2)
00865 continue;
00866 for (unsigned int i=1; i<pts.size()-1; ++i) {
00867 const vgl_point_2d<double>& pt = pts[i];
00868 unsigned int bi = verts->size();
00869 verts->push_back(imesh_vertex<3>(pt.x(),-pt.y(),bld_heights[b]));
00870 roof.push_back(bi);
00871
00872 face.push_back(e2m[i-1]);
00873 face.push_back(bi);
00874 faces->push_back(face);
00875
00876 face.clear();
00877 face.push_back(bi);
00878 face.push_back(e2m[i-1]);
00879 }
00880 }
00881
00882 ++i2end;
00883 face.insert(face.end(), i2beg, i2end);
00884 faces->push_back(face);
00885 face.clear();
00886 }
00887 if (roof.size() > 2)
00888 {
00889 if (h<0){
00890 roof_face = faces->size();
00891 faces->push_back(roof);
00892 }
00893 else
00894 roof_subtract_hole(*verts,(*faces)[roof_face],roof);
00895 }
00896 }
00897 }
00898
00899 vcl_auto_ptr<imesh_vertex_array_base> vb(verts);
00900 vcl_auto_ptr<imesh_face_array_base> fb(faces);
00901 mesh.set_vertices(vb);
00902 mesh.set_faces(fb);
00903 }
00904
00905
00906
00907 void bmdl_mesh::roof_subtract_hole(const imesh_vertex_array<3>& verts,
00908 vcl_vector<unsigned int>& face,
00909 const vcl_vector<unsigned int>& hole)
00910 {
00911 unsigned int i1, i2;
00912 bool valid = false;
00913 for (i1=0; i1<face.size(); ++i1)
00914 {
00915 vgl_point_2d<double> v1(verts[face[i1]][0],verts[face[i1]][1]);
00916 for (i2=0; i2<hole.size(); ++i2)
00917 {
00918 vgl_point_2d<double> v2(verts[hole[i2]][0],verts[hole[i2]][1]);
00919
00920 valid = true;
00921 for (unsigned int j1 = face.size()-1, j2=0; j2<face.size() && valid; j1=j2, ++j2)
00922 {
00923 if (j1 == i1 || j2 == i1)
00924 continue;
00925 vgl_point_2d<double> v3(verts[face[j1]][0],verts[face[j1]][1]);
00926 vgl_point_2d<double> v4(verts[face[j2]][0],verts[face[j2]][0]);
00927 valid = !vgl_lineseg_test_lineseg(v1.x(),v1.y(),v2.x(),v2.y(),
00928 v3.x(),v3.y(),v4.x(),v4.y());
00929 }
00930 for (unsigned int j1 = hole.size()-1, j2=0; j2<hole.size() && valid; j1=j2, ++j2)
00931 {
00932 if (j1 == i2 || j2 == i2)
00933 continue;
00934 vgl_point_2d<double> v3(verts[hole[j1]][0],verts[hole[j1]][1]);
00935 vgl_point_2d<double> v4(verts[hole[j2]][0],verts[hole[j2]][1]);
00936 valid = !vgl_lineseg_test_lineseg(v1.x(),v1.y(),v2.x(),v2.y(),
00937 v3.x(),v3.y(),v4.x(),v4.y());
00938 }
00939 if (valid)
00940 break;
00941 }
00942 if (valid)
00943 break;
00944 }
00945
00946 if (!valid)
00947 {
00948 vcl_cout << "couldn't find connection for hole"<<vcl_endl;
00949 return;
00950 }
00951
00952 vcl_vector<unsigned int> new_idxs;
00953 new_idxs.push_back(face[i1]);
00954 new_idxs.insert(new_idxs.end(), hole.begin()+i2, hole.end());
00955 new_idxs.insert(new_idxs.end(), hole.begin(), hole.begin()+i2);
00956 new_idxs.push_back(hole[i2]);
00957 face.insert(face.begin()+i1, new_idxs.begin(), new_idxs.end());
00958 }
00959