00001 #ifndef OPENTISSUE_COLLISION_VCLIP_VCLIP_H
00002 #define OPENTISSUE_COLLISION_VCLIP_VCLIP_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/collision/vclip/vclip_mesh.h>
00013 #include <OpenTissue/core/math/math_coordsys.h>
00014
00015 #include <vector>
00016 #include <cmath>
00017
00018 namespace OpenTissue
00019 {
00020 namespace vclip
00021 {
00022
00066 class VClip
00067 {
00068 public:
00069
00070 typedef vclip_mesh_type::vertex_halfedge_circulator vertex_halfedge_circulator;
00071 typedef vclip_mesh_type::face_halfedge_circulator face_halfedge_circulator;
00072 typedef vclip_mesh_type::face_iterator face_iterator;
00073 typedef vclip_mesh_type::vertex_type vertex_type;
00074 typedef vclip_mesh_type::halfedge_type halfedge_type;
00075 typedef vclip_mesh_type::face_type face_type;
00076 typedef vertex_type * vertex_pointer;
00077 typedef halfedge_type * halfedge_pointer;
00078 typedef face_type * face_pointer;
00079 typedef Feature * feature_pointer;
00080 typedef halfedge_type::plane_type plane_type;
00081
00082 typedef vclip_mesh_type::math_types math_types;
00083 typedef math_types::vector3_type vector3_type;
00084 typedef math_types::real_type real_type;
00085
00086 typedef unsigned char state_type;
00087 typedef enum {PENETRATION,CONTINUE,DISJOINT} result_type;
00088 typedef OpenTissue::math::CoordSys<real_type> coordsys_type;
00089
00090 public:
00091
00095 const static state_type vertex_vertex_state = 0;
00096 const static state_type vertex_edge_state = 1;
00097 const static state_type edge_vertex_state = 4;
00098 const static state_type vertex_face_state = 2;
00099 const static state_type face_vertex_state = 8;
00100 const static state_type edge_edge_state = 5;
00101 const static state_type edge_face_state = 6;
00102 const static state_type face_edge_state = 9;
00103
00110 const static int INSIDE = 0x000;
00111 const static int OUTSIDE = 0x001;
00112 const static int MIN = 0x002;
00113 const static int MAX = 0x004;
00114
00115 public:
00116
00117 feature_pointer m_vertexA;
00118 feature_pointer m_vertexB;
00119 feature_pointer m_vertex;
00120 feature_pointer m_edgeA;
00121 feature_pointer m_edgeB;
00122 feature_pointer m_edge;
00123 feature_pointer m_face;
00124
00125 real_type m_distance;
00126
00137 std::vector<int> m_code;
00138
00145 std::vector<real_type> m_parameter;
00146
00147 private:
00148
00149 result_type vertex_vertex(
00150 coordsys_type const & AtoB
00151 , coordsys_type const & BtoA
00152 , vector3_type & cpA
00153 , vector3_type & cpB
00154 )
00155 {
00156 vertex_pointer vA = static_cast<vertex_pointer>(m_vertexA);
00157 vertex_pointer vB = static_cast<vertex_pointer>(m_vertexB);
00158
00159
00160 vector3_type p = vB->m_coord;
00161 BtoA.xform_point(p);
00162 vertex_halfedge_circulator hA(*vA),end;
00163 for(;hA!=end;++hA)
00164 {
00165 if(hA->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(p)<0)
00166 {
00167 m_vertexA = &(*hA);
00168 return CONTINUE;
00169 }
00170 }
00171
00172
00173 p = vA->m_coord;
00174 AtoB.xform_point(p);
00175 vertex_halfedge_circulator hB(*vB);
00176 for(;hB!=end;++hB)
00177 {
00178 if(hB->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(p)<0)
00179 {
00180 m_vertexB = &(*hB);
00181 return CONTINUE;
00182 }
00183 }
00184
00185 cpA = vA->m_coord;
00186 cpB = vB->m_coord;
00187 vector3_type diff = cpA-cpB;
00188 m_distance = std::sqrt( diff*diff );
00189
00190 return (m_distance>0)?DISJOINT:PENETRATION;
00191 };
00192
00193
00194 result_type vertex_face(
00195 coordsys_type const & VtoF
00196 , vector3_type & cpV
00197 , vector3_type & cpF
00198 , vclip_mesh_type * mesh
00199 )
00200 {
00201 vertex_pointer v = static_cast<vertex_pointer>(m_vertex);
00202 face_pointer f = static_cast<face_pointer>(m_face);
00203
00204 vector3_type p;
00205 real_type d = static_cast<real_type>(0.0);
00206 real_type dmin = static_cast<real_type>(0.0);
00207 bool updated = false;
00208
00209
00210
00211 p = v->m_coord;
00212 VtoF.xform_point(p);
00213
00214 {
00215 face_halfedge_circulator h(*f),hend;
00216 for(;h!=hend;++h)
00217 {
00218 if((d = h->m_voronoi_plane_EF.signed_distance(p))<dmin)
00219 {
00220 m_face = &(*(h));
00221 dmin = d;
00222 updated = true;
00223 }
00224 }
00225 }
00226
00227
00228
00229 if(updated)
00230 {
00231 return CONTINUE;
00232 }
00233
00234
00235 if((d = f->m_plane.signed_distance(p)) == 0)
00236 {
00237 cpV = v->m_coord;
00238 cpF = p;
00239 return PENETRATION;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 vector3_type q;
00250
00251 {
00252 vertex_halfedge_circulator h(*v),hend;
00253 for(;h!=hend;++h)
00254 {
00255 q = h->get_destination_iterator()->m_coord;
00256 VtoF.xform_point(q);
00257 real_type d2 = f->m_plane.signed_distance(q);
00258 if( ((d<0)&&(d2>d)) || ((d>0)&&(d2<d)) )
00259 {
00260 m_vertex = &(*h);
00261 return CONTINUE;
00262 }
00263 }
00264 }
00265
00266
00267 if(d>0)
00268 {
00269 m_distance = d;
00270 cpV = v->m_coord;
00271 cpF = p - f->m_plane.n()*d;
00272 return DISJOINT;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 {
00284 vclip_mesh_type::face_iterator ft = mesh->face_begin();
00285 vclip_mesh_type::face_iterator fend = mesh->face_end();
00286 for(;ft!=fend;++ft)
00287 {
00288 real_type d2 = ft->m_plane.signed_distance(p);
00289 if(d2>d)
00290 {
00291 d = d2;
00292 m_face = &(*ft) ;
00293 }
00294 }
00295 }
00296
00297 if(d>0)
00298 {
00299 return CONTINUE;
00300 }
00301
00302
00303
00304 m_distance = d;
00305 cpV = v->m_coord;
00306 cpF = p - f->m_plane.n()*d;
00307 return PENETRATION;
00308 };
00309
00310
00311 result_type vertex_edge(
00312 coordsys_type const & VtoE
00313 , coordsys_type const & EtoV
00314 , vector3_type & cpV
00315 , vector3_type & cpE
00316 )
00317 {
00318 vertex_pointer v = static_cast<vertex_pointer>(m_vertex);
00319 halfedge_pointer e = static_cast<halfedge_pointer>(m_edge);
00320 vector3_type p;
00321
00322
00323 p = v->m_coord;
00324 VtoE.xform_point(p);
00325 if(e->m_voronoi_plane_VE.signed_distance(p)>0)
00326 {
00327 m_edge = &(*(e->get_destination_iterator()));
00328 return CONTINUE;
00329 }
00330 if(e->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(p)>0)
00331 {
00332 m_edge = &(*(e->get_origin_iterator()));
00333 return CONTINUE;
00334 }
00335 if(e->m_voronoi_plane_EF.signed_distance(p)>0)
00336 {
00337 m_edge = &(*(e->get_face_iterator()));
00338 return CONTINUE;
00339 }
00340 if(e->get_twin_iterator()->m_voronoi_plane_EF.signed_distance(p)>0)
00341 {
00342 m_edge = &(*(e->get_twin_iterator()->get_face_iterator()));
00343 return CONTINUE;
00344 }
00345
00346
00347 vector3_type origin = e->get_origin_iterator()->m_coord;
00348 vector3_type destination = e->get_destination_iterator()->m_coord;
00349 EtoV.xform_point(origin);
00350 EtoV.xform_point(destination);
00351
00352 real_type min_t = static_cast<real_type>(0.0);
00353 real_type max_t = static_cast<real_type>(1.0);
00354 feature_pointer min_neighbor = 0;
00355 feature_pointer max_neighbor = 0;
00356 real_type t;
00357
00358 vertex_halfedge_circulator h(*v),hend;
00359 for(;h!=hend;++h)
00360 {
00361 real_type dO = h->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(origin);
00362 real_type dD = h->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(destination);
00363 if(dO >= 0)
00364 {
00365 if(dD>=0)
00366 continue;
00367 if((t = dO/(dO-dD))<max_t)
00368 {
00369 max_t = t;
00370 max_neighbor = &(*h);
00371 if(max_t<min_t)
00372 break;
00373 }
00374 }
00375 else
00376 {
00377 if(dD<0)
00378 {
00379 min_neighbor = max_neighbor = &(*h);
00380 break;
00381 }
00382 if((t = dO/(dO-dD))>min_t)
00383 {
00384 min_t = t;
00385 min_neighbor = &(*h);
00386 if(min_t>max_t)
00387 break;
00388 }
00389 }
00390 }
00391
00392
00393 if( h!=hend && (min_neighbor == max_neighbor))
00394 {
00395 m_vertex = min_neighbor;
00396 return CONTINUE;
00397 }
00398
00399
00400
00401
00402 vector3_type offset;
00403 vector3_type segment = destination - origin;
00404
00405 if((min_neighbor)||(max_neighbor))
00406 {
00407 if(min_neighbor)
00408 {
00409 offset = origin + segment*min_t;
00410 offset -= v->m_coord;
00411 if(is_zero(offset))
00412 {
00413 cpV = v->m_coord;
00414 cpE = p;
00415 return PENETRATION;
00416 }
00417 if(offset*segment>0)
00418 {
00419 m_vertex = min_neighbor;
00420 return CONTINUE;
00421 }
00422 }
00423 if(max_neighbor)
00424 {
00425 offset = origin + segment*max_t;
00426 offset -= v->m_coord;
00427 if(is_zero(offset))
00428 {
00429 cpV = v->m_coord;
00430 cpE = p;
00431 return PENETRATION;
00432 }
00433 if(offset*segment<0)
00434 {
00435 m_vertex = max_neighbor;
00436 return CONTINUE;
00437 }
00438 }
00439 }
00440
00441
00442 cpV = v->m_coord;
00443 offset = p - e->get_origin_iterator()->m_coord;
00444
00445 cpE = e->get_origin_iterator()->m_coord + e->m_u * (offset * (e->m_u));
00446 vector3_type diff = cpE - p;
00447 m_distance = std::sqrt(diff*diff);
00448 return DISJOINT;
00449 };
00450
00451
00452 result_type edge_edge_subtest(
00453 vector3_type const & origin
00454 , vector3_type const & destination
00455 , vector3_type const & segment
00456 , vector3_type & cp
00457 )
00458 {
00459 halfedge_pointer e = static_cast<halfedge_pointer>(m_edge);
00460
00461 real_type min_t = static_cast<real_type>(0.0);
00462 real_type max_t = static_cast<real_type>(1.0);
00463 feature_pointer min_neighbor = 0;
00464 feature_pointer max_neighbor = 0;
00465
00466
00467 real_type dO = - e->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(origin);
00468 real_type dD = - e->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(destination);
00469 if(dO < 0)
00470 {
00471 if(dD<0)
00472 {
00473 m_edge = &(*e->get_origin_iterator());
00474 return CONTINUE;
00475 }
00476 min_t = dO/(dO-dD);
00477 min_neighbor = &(*e->get_origin_iterator());
00478 }
00479 else if (dD < 0)
00480 {
00481 max_t = dO/(dO-dD);
00482 max_neighbor = &(*e->get_origin_iterator());
00483 }
00484
00485 dO = - e->m_voronoi_plane_VE.signed_distance(origin);
00486 dD = - e->m_voronoi_plane_VE.signed_distance(destination);
00487 if(dO < 0)
00488 {
00489 if(dD<0)
00490 {
00491 m_edge = &(*e->get_destination_iterator());
00492 return CONTINUE;
00493 }
00494 min_t = dO/(dO-dD);
00495 min_neighbor = &(*(e->get_destination_iterator()));
00496 }
00497 else if (dD < 0)
00498 {
00499 max_t = dO/(dO-dD);
00500 max_neighbor = &(*e->get_destination_iterator());
00501 }
00502
00503 feature_pointer vMinNbr = min_neighbor;
00504 feature_pointer vMaxNbr = max_neighbor;
00505 real_type vmin = min_t;
00506 real_type vmax = max_t;
00507
00508
00509 int i;
00510 real_type t;
00511 plane_type * plane = 0;
00512 feature_pointer nbr = 0;
00513 vector3_type point;
00514 for(i=0;i<2;++i)
00515 {
00516 if(i==1)
00517 {
00518 plane = &(e->get_twin_iterator()->m_voronoi_plane_EF);
00519 nbr = &(*(e->get_twin_iterator()->get_face_iterator()));
00520 }
00521 else
00522 {
00523 plane = &(e->m_voronoi_plane_EF);
00524 nbr = &(*(e->get_face_iterator()));
00525 }
00526 dO = - plane->signed_distance(origin);
00527 dD = - plane->signed_distance(destination);
00528 if(dO<0)
00529 {
00530 if(dD<0)
00531 {
00532
00533
00534
00535
00536 if(vMinNbr)
00537 {
00538 point = origin + segment*vmin;
00539 point -= static_cast<vertex_pointer>(vMinNbr)->m_coord;
00540 if(is_zero(point))
00541 {
00542 cp = static_cast<vertex_pointer>(min_neighbor)->m_coord;
00543 return PENETRATION;
00544 }
00545 if(point*segment>0)
00546 {
00547 m_edge = &(*vMinNbr);
00548 return CONTINUE;
00549 }
00550 }
00551 if(vMaxNbr)
00552 {
00553 point = origin + segment*vmax;
00554 point -= static_cast<vertex_pointer>(vMaxNbr)->m_coord;
00555 if(is_zero(point))
00556 {
00557 cp = static_cast<vertex_pointer>(max_neighbor)->m_coord;
00558 return PENETRATION;
00559 }
00560 if(point*segment<0)
00561 {
00562 m_edge = &(*vMaxNbr);
00563 return CONTINUE;
00564 }
00565 }
00566 m_edge = nbr;
00567 return CONTINUE;
00568 }
00569 else if((t =dO/(dO-dD))>min_t)
00570 {
00571 min_t = t;
00572 min_neighbor = nbr;
00573 if(min_t>max_t)
00574 break;
00575 }
00576 }
00577 else if(dD < 0)
00578 {
00579 if((t = dO/(dO-dD))<max_t)
00580 {
00581 max_t = t;
00582 max_neighbor = nbr;
00583 if(max_t<min_t)
00584 break;
00585 }
00586 }
00587 }
00588
00589
00590
00591 real_type dmin;
00592 if(i<2)
00593 {
00594 if(min_neighbor->m_type==Feature::VERTEX)
00595 {
00596 point = origin + segment*min_t;
00597 point -= static_cast<vertex_pointer>(min_neighbor)->m_coord;
00598 if(is_zero(point))
00599 {
00600 cp = static_cast<vertex_pointer>(min_neighbor)->m_coord;
00601 return PENETRATION;
00602 }
00603
00604
00605
00606
00607
00608 m_edge = (point*segment>=0) ? min_neighbor : max_neighbor;
00609 return CONTINUE;
00610 }
00611 if(max_neighbor->m_type==Feature::VERTEX)
00612 {
00613 point = origin + segment*max_t;
00614 point -= static_cast<vertex_pointer>(max_neighbor)->m_coord;
00615 if(is_zero(point))
00616 {
00617 cp = static_cast<vertex_pointer>(max_neighbor)->m_coord;
00618 return PENETRATION;
00619 }
00620 m_edge = (point * segment<=0) ? max_neighbor : min_neighbor;
00621 return CONTINUE;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 dO = static_cast<face_pointer>(min_neighbor)->m_plane.signed_distance(origin);
00638 dD = static_cast<face_pointer>(min_neighbor)->m_plane.signed_distance(destination);
00639 dmin = dO + min_t*(dD-dO);
00640 if(dmin==0)
00641 {
00642 cp = origin + segment*min_t;
00643 return PENETRATION;
00644 }
00645 m_edge = (dmin>0) ? ((dO < dD) ? min_neighbor : max_neighbor) : ((dO > dD) ? min_neighbor : max_neighbor);
00646 return CONTINUE;
00647 }
00648
00649
00650
00651 real_type dmax;
00652 if(min_neighbor)
00653 {
00654 if(min_neighbor->m_type==Feature::FACE)
00655 {
00656 dO = static_cast<face_pointer>(min_neighbor)->m_plane.signed_distance(origin);
00657 dD = static_cast<face_pointer>(min_neighbor)->m_plane.signed_distance(destination);
00658 dmin = dO + min_t*(dD-dO);
00659 dmax = (max_neighbor) ? dO + max_t*(dD-dO) : dD;
00660 if(dmin==0)
00661 {
00662 cp = origin + segment*min_t;
00663 return PENETRATION;
00664 }
00665 if(((dmin>0)&&(dmin<dmax))||((dmin<0)&&(dmin>dmax)))
00666 {
00667 m_edge = min_neighbor;
00668 return CONTINUE;
00669 }
00670 }
00671 else
00672 {
00673 point = origin + segment*min_t;
00674 point -= static_cast<vertex_pointer>(min_neighbor)->m_coord;
00675 if(is_zero(point))
00676 {
00677 cp = static_cast<vertex_pointer>(min_neighbor)->m_coord;
00678 return PENETRATION;
00679 }
00680 if(point*segment>0)
00681 {
00682 m_edge = min_neighbor;
00683 return CONTINUE;
00684 }
00685 }
00686 }
00687 if(max_neighbor)
00688 {
00689 if(max_neighbor->m_type==Feature::FACE)
00690 {
00691 dO = static_cast<face_pointer>(max_neighbor)->m_plane.signed_distance(origin);
00692 dD = static_cast<face_pointer>(max_neighbor)->m_plane.signed_distance(destination);
00693 dmin = (min_neighbor) ? dO + min_t*(dD-dO) : dO;
00694 dmax = dO + max_t*(dD-dO);
00695 if(dmax==0)
00696 {
00697 cp = origin + segment*max_t;
00698 return PENETRATION;
00699 }
00700 if(((dmax>0)&&(dmax<dmin))||((dmax<0)&&(dmax>dmin)))
00701 {
00702 m_edge = max_neighbor;
00703 return CONTINUE;
00704 }
00705 }
00706 else
00707 {
00708 point = origin + segment*max_t;
00709 point -= static_cast<vertex_pointer>(max_neighbor)->m_coord;
00710 if(is_zero(point))
00711 {
00712 cp = static_cast<vertex_pointer>(max_neighbor)->m_coord;
00713 return PENETRATION;
00714 }
00715 if(point * segment<0)
00716 {
00717 m_edge = max_neighbor;
00718 return CONTINUE;
00719 }
00720 }
00721 }
00722
00723
00724 return DISJOINT;
00725 };
00726
00727 result_type edge_edge(
00728 coordsys_type const & AtoB
00729 , coordsys_type const & BtoA
00730 , vector3_type & cpA
00731 , vector3_type & cpB
00732 )
00733 {
00734 result_type result;
00735
00736 halfedge_pointer eA = static_cast<halfedge_pointer>(m_edgeA);
00737 halfedge_pointer eB = static_cast<halfedge_pointer>(m_edgeB);
00738
00739
00740 vector3_type origin = eA->get_origin_iterator()->m_coord;
00741 vector3_type destination = eA->get_destination_iterator()->m_coord;
00742 AtoB.xform_point(origin);
00743 AtoB.xform_point(destination);
00744 vector3_type segment = destination - origin;
00745
00746 m_edge = m_edgeB;
00747 if((result=edge_edge_subtest(origin,destination,segment,cpB))==PENETRATION)
00748 {
00749 cpA = cpB;
00750 BtoA.xform_point(cpA);
00751 }
00752 m_edgeB = m_edge;
00753 if(result!=DISJOINT)
00754 {
00755 return result;
00756 }
00757
00758
00759
00760 origin = eB->get_origin_iterator()->m_coord;
00761 destination = eB->get_destination_iterator()->m_coord;
00762 BtoA.xform_point(origin);
00763 BtoA.xform_point(destination);
00764 segment = destination - origin;
00765
00766 m_edge = m_edgeA;
00767 if((result=edge_edge_subtest(origin,destination,segment,cpA))==PENETRATION)
00768 {
00769 cpB = cpA;
00770 AtoB.xform_point(cpB);
00771 }
00772 m_edgeA = m_edge;
00773 if(result!=DISJOINT)
00774 {
00775 return result;
00776 }
00777
00778
00779
00780 real_type lambda;
00781 vector3_type p;
00782 vector3_type h;
00783 vector3_type h2;
00784 vector3_type xdir;
00785
00786 xdir = eB->m_u;
00787 BtoA.xform_vector(xdir);
00788
00789 real_type k = xdir * eA->m_u;
00790 h = origin - eA->get_origin_iterator()->m_coord;
00791 h2 = eA->m_u - xdir*k;
00792 real_type num = h * h2;
00793 real_type denom = 1 - k*k;
00794 if(denom==0)
00795 {
00796 if(num>0)
00797 {
00798 cpA = eA->get_destination_iterator()->m_coord;
00799 }
00800 else
00801 {
00802 cpA = eA->get_origin_iterator()->m_coord;
00803 }
00804 }
00805 else
00806 {
00807 lambda = num/denom;
00808 if(lambda<0)
00809 {
00810 lambda = static_cast<real_type>(0.0);
00811 }
00812 else if(lambda > eA->m_length)
00813 {
00814 lambda = eA->m_length;
00815 }
00816 cpA = eA->get_origin_iterator()->m_coord + eA->m_u * lambda;
00817 }
00818
00819 p = cpA;
00820 AtoB.xform_point(p);
00821 h = p - eB->get_origin_iterator()->m_coord;
00822 lambda = h * eB->m_u;
00823 cpB = eB->get_origin_iterator()->m_coord + eB->m_u*lambda;
00824 vector3_type diff = cpB - p;
00825 m_distance = std::sqrt(diff*diff);
00826 return DISJOINT;
00827 };
00828
00829 result_type edge_face(
00830 coordsys_type const & EtoF
00831 , vector3_type & cpE
00832 , vector3_type & cpF
00833 )
00834 {
00835 halfedge_pointer e = static_cast<halfedge_pointer>(m_edge);
00836 face_pointer f = static_cast<face_pointer>(m_face);
00837
00838
00839
00840
00841 unsigned int N = valency(*f);
00842 m_code.resize(N);
00843 m_parameter.resize(N);
00844
00845 vector3_type point;
00846 vector3_type origin;
00847 vector3_type destination;
00848 vector3_type segment;
00849
00850 origin = e->get_origin_iterator()->m_coord;
00851 EtoF.xform_point(origin);
00852 destination = e->get_destination_iterator()->m_coord;
00853 EtoF.xform_point(destination);
00854 segment = destination - origin;
00855
00856
00857
00858 halfedge_pointer minCn = 0;
00859 halfedge_pointer maxCn = 0;
00860 halfedge_pointer chopCn = 0;
00861
00862 real_type min_t = 0.0f;
00863 real_type max_t = 1.0f;
00864 real_type dO,dD,t;
00865
00866 face_halfedge_circulator h(*f),hend;
00867 for(int j = 0;h!=hend;++h,++j)
00868 {
00869 h->m_tag = j;
00870
00871 dO = h->m_voronoi_plane_EF.signed_distance(origin);
00872 dD = h->m_voronoi_plane_EF.signed_distance(destination);
00873 if(dO>=0)
00874 {
00875 if(dD>=0)
00876 {
00877 m_code[j] = INSIDE;
00878 }
00879 else
00880 {
00881 m_code[j] = MAX;
00882 if((m_parameter[j]=dO/(dO-dD))<max_t)
00883 {
00884 max_t = m_parameter[j];
00885 maxCn = &(*h);
00886 }
00887 }
00888 }
00889 else
00890 {
00891 if(dD<0)
00892 {
00893 m_code[j] = OUTSIDE;
00894 chopCn = &(*h);
00895 }
00896 else
00897 {
00898 m_code[j] = MIN;
00899 if((m_parameter[j]=dO/(dO-dD))>min_t)
00900 {
00901 min_t = m_parameter[j];
00902 minCn = &(*h);
00903 }
00904 }
00905 }
00906 }
00907
00908
00909
00910
00911
00912
00913
00914 halfedge_pointer curCn = 0;
00915
00916 if(chopCn ||(min_t>max_t))
00917 {
00918 if(chopCn)
00919 {
00920 curCn = chopCn;
00921 }
00922 else
00923 {
00924
00925
00926
00927 curCn = ((min_t + max_t) > 1.0) ? minCn : maxCn;
00928 }
00929 halfedge_pointer prev = 0;
00930 halfedge_pointer next = curCn;
00931 halfedge_pointer s = 0;
00932
00933 bool intersect = false;
00934
00935
00936
00937 while(next!=prev)
00938 {
00939 prev = curCn;
00940 curCn = next;
00941 s = curCn;
00942 vertex_pointer minv = 0;
00943 vertex_pointer maxv = 0;
00944
00945
00946
00947 int i = curCn->m_tag;
00948 if(m_code[i]==INSIDE)
00949 break;
00950 else if(m_code[i]==OUTSIDE)
00951 {
00952 min_t = static_cast<real_type>(0.0);
00953 max_t = static_cast<real_type>(1.0);
00954 }
00955 else if(m_code[i]==MIN)
00956 {
00957 min_t = static_cast<real_type>(0.0);
00958 max_t = m_parameter[i];
00959 }
00960 else if(m_code[i]==MAX)
00961 {
00962 min_t = m_parameter[i];
00963 max_t = static_cast<real_type>(1.0);
00964 }
00965
00966 dO = - s->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(origin);
00967 dD = - s->get_twin_iterator()->m_voronoi_plane_VE.signed_distance(destination);
00968 if(dO>=0)
00969 {
00970 if(dD<0)
00971 {
00972 if((t=dO/(dO-dD))<max_t)
00973 {
00974 max_t = t;
00975 maxv = static_cast<vertex_pointer>(&(*(s->get_origin_iterator())));
00976 if(min_t>max_t)
00977 {
00978 if(intersect)
00979 break;
00980 next = static_cast<halfedge_pointer>(&(*(s->get_prev_iterator())) );
00981 continue;
00982 }
00983 }
00984 }
00985 }
00986 else
00987 {
00988 if(dD<0)
00989 {
00990 next = static_cast<halfedge_pointer>( &(*( s->get_prev_iterator() ) ) );
00991 continue;
00992 }
00993 if((t=dO/(dO-dD))>min_t)
00994 {
00995 min_t = t;
00996 minv = static_cast<vertex_pointer> ( &(*( s->get_origin_iterator() )) );
00997 if(min_t>max_t)
00998 {
00999 if(intersect)
01000 break;
01001 next = static_cast<halfedge_pointer>( &(*(s->get_prev_iterator())) );
01002 continue;
01003 }
01004 }
01005 }
01006
01007
01008
01009
01010 dO = - s->m_voronoi_plane_VE.signed_distance(origin);
01011 dD = - s->m_voronoi_plane_VE.signed_distance(destination);
01012 if(dO>=0)
01013 {
01014 if(dD<0)
01015 {
01016 if((t=dO/(dO-dD))<max_t)
01017 {
01018 max_t = t;
01019 maxv = static_cast<vertex_pointer> ( &(*( s->get_destination_iterator() ) ) );
01020 if(min_t>max_t)
01021 {
01022 if(intersect)
01023 break;
01024 next = static_cast<halfedge_pointer> ( &(*( s->get_next_iterator() ) ) );
01025 continue;
01026 }
01027 }
01028 }
01029 }
01030 else
01031 {
01032 if(dD<0)
01033 {
01034 next = static_cast<halfedge_pointer> ( &(*(s->get_next_iterator())) );
01035 continue;
01036 }
01037 if((t=dO/(dO-dD))>min_t)
01038 {
01039 min_t = t;
01040 minv = static_cast<vertex_pointer> ( &(*( s->get_destination_iterator() )) );
01041 if(min_t>max_t)
01042 {
01043 if(intersect)
01044 break;
01045 next = static_cast<halfedge_pointer> ( &(*( s->get_next_iterator() )) );
01046 continue;
01047 }
01048 }
01049 }
01050
01051
01052 intersect = true;
01053 if(minv)
01054 {
01055 point = origin + segment* min_t;
01056 point -= minv->m_coord;
01057 if(point * segment>0)
01058 {
01059 next = ( &(*(s->get_origin_iterator()))==minv)? &(*s->get_prev_iterator()) : &(*s->get_next_iterator());
01060 continue;
01061 }
01062 }
01063 if(maxv)
01064 {
01065 point = origin + segment*max_t;
01066 point -= maxv->m_coord;
01067 if(point*segment<0)
01068 {
01069 next = ( &(*s->get_destination_iterator()) ==maxv)? &(*s->get_next_iterator()) : &(*s->get_prev_iterator());
01070 continue;
01071 }
01072 }
01073 m_face = s;
01074 return CONTINUE;
01075 }
01076 m_face = ( &(*curCn->get_next_iterator()) == prev) ? &(*s->get_destination_iterator()) : &(*s->get_origin_iterator());
01077 return CONTINUE;
01078 }
01079
01080
01081
01082
01083
01084
01085
01086 dO = f->m_plane.signed_distance(origin);
01087 dD = f->m_plane.signed_distance(destination);
01088
01089 real_type dmin = (minCn) ? (dO + min_t*(dD-dO)) : dO;
01090 real_type dmax = (maxCn) ? (dO + max_t*(dD-dO)) : dD;
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 if((dmin==0)||((dmin<0)&&(dmax>0)))
01102 {
01103 m_distance = dmin;
01104 cpE = e->get_origin_iterator()->m_coord + e->m_u * (min_t * e->m_length);
01105 cpF = origin + segment*min_t;
01106 cpF -= f->m_plane.n()*dmin;
01107 return PENETRATION;
01108 }
01109 else if((dmax==0)||((dmin>0)&&(dmax<0)))
01110 {
01111 m_distance = dmax;
01112 cpE = e->get_origin_iterator()->m_coord + e->m_u * (max_t*e->m_length);
01113 cpF = origin + segment*max_t;
01114 cpF -= f->m_plane.n()*dmax;
01115 return PENETRATION;
01116 }
01117
01118
01119
01120
01121
01122
01123 if(((dmin>0)&&(dO<=dD))||((dmin<0)&&(dO>=dD)))
01124 {
01125 if(minCn)
01126 {
01127 m_face = minCn;
01128 }
01129 else
01130 {
01131 m_edge = &(*e->get_origin_iterator());
01132 }
01133 }
01134 else
01135 {
01136 if(maxCn)
01137 {
01138 m_face = maxCn;
01139 }
01140 else
01141 {
01142 m_edge = &(*e->get_destination_iterator());
01143 }
01144 }
01145 return CONTINUE;
01146 };
01147
01148 public:
01149
01180 real_type run(
01181 vclip_mesh_type const & meshA
01182 , vclip_mesh_type const & meshB
01183 , coordsys_type const & AtoB
01184 , coordsys_type const & BtoA
01185 , feature_pointer * seedA
01186 , feature_pointer * seedB
01187 , vector3_type & cpA
01188 , vector3_type & cpB
01189 , unsigned int const max_iterations = 500
01190 )
01191 {
01192 feature_pointer witnessA = *seedA;
01193 feature_pointer witnessB = *seedB;
01194
01195 if(!witnessA)
01196 {
01197 throw std::invalid_argument("vclip(): witness A was null?");
01198 return real_type();
01199 }
01200 if(!witnessB)
01201 {
01202 throw std::invalid_argument("vclip(): witness B was null?");
01203 return real_type();
01204 }
01205
01206 if((witnessA->m_type==Feature::FACE && witnessB->m_type==Feature::FACE))
01207 {
01208 throw std::invalid_argument("vclip(): both witness' were faces?");
01209 return real_type();
01210 }
01211
01212 result_type result = CONTINUE;
01213 m_distance = static_cast<real_type>(0.0);
01214 unsigned int iteration = 0;
01215
01216 for(; (result==CONTINUE) && (iteration < max_iterations); ++iteration)
01217 {
01218 state_type state = (witnessA->m_type<<2)+witnessB->m_type;
01219 switch(state)
01220 {
01221 case vertex_vertex_state:
01222 m_vertexA = witnessA;
01223 m_vertexB = witnessB;
01224 result = vertex_vertex(AtoB,BtoA,cpA,cpB);
01225 witnessA = m_vertexA;
01226 witnessB = m_vertexB;
01227 break;
01228 case vertex_edge_state:
01229 m_vertex = witnessA;
01230 m_edge = witnessB;
01231 result = vertex_edge(AtoB,BtoA,cpA,cpB);
01232 witnessA = m_vertex;
01233 witnessB = m_edge;
01234 break;
01235 case edge_vertex_state:
01236 m_edge = witnessA;
01237 m_vertex = witnessB;
01238 result = vertex_edge(BtoA,AtoB,cpB,cpA);
01239 witnessA = m_edge;
01240 witnessB = m_vertex;
01241 break;
01242 case vertex_face_state:
01243 m_vertex = witnessA;
01244 m_face = witnessB;
01245 result = vertex_face(AtoB,cpA,cpB,const_cast< vclip_mesh_type *>( &meshB ));
01246 witnessA = m_vertex;
01247 witnessB = m_face;
01248 break;
01249 case face_vertex_state:
01250 m_face = witnessA;
01251 m_vertex = witnessB;
01252 result = vertex_face(BtoA,cpB,cpA,const_cast< vclip_mesh_type *>(&meshA));
01253 witnessA = m_face;
01254 witnessB = m_vertex;
01255 break;
01256 case edge_edge_state:
01257 m_edgeA = witnessA;
01258 m_edgeB = witnessB;
01259 result = edge_edge(AtoB,BtoA,cpA,cpB);
01260 witnessA = m_edgeA;
01261 witnessB = m_edgeB;
01262 break;
01263 case edge_face_state:
01264 m_edge = witnessA;
01265 m_face = witnessB;
01266 result = edge_face(AtoB,cpA,cpB);
01267 witnessA = m_edge;
01268 witnessB = m_face;
01269 break;
01270 case face_edge_state:
01271 m_face = witnessA;
01272 m_edge = witnessB;
01273 result = edge_face(BtoA,cpB,cpA);
01274 witnessA = m_face;
01275 witnessB = m_edge;
01276 break;
01277 default:
01278 throw std::logic_error("vclip(): unrecognized state, this should never happen!");
01279 break;
01280 }
01281 }
01282
01283 *seedA = witnessA;
01284 *seedB = witnessB;
01285
01286 return m_distance;
01287 }
01288
01289 };
01290
01291 }
01292
01293 }
01294
01295
01296 #endif