shape_doc 0.1
|
00001 #include <shape/ssi_dsearch.hpp> 00002 #include <shape/ssi_tri_tri.hpp> 00003 #include <shape/ssi_math.hpp> 00004 00005 namespace mmx { 00006 #define SHIFT 3 00007 00008 namespace shape_ssi { 00009 00010 static const int up_triangle_[] = { 0, 1, 3 }; 00011 static const int dw_triangle_[] = { 2, 3, 1 }; 00012 00013 #define __up__ 0 00014 #define __down__ 1 00015 /* return the up triangle of quad q */ 00016 #define __up__triangle__(q) q[0],q[3],q[2] 00017 /* return the down triangle of quad q */ 00018 #define __down__triangle__(q) q[0],q[1],q[2] 00019 /* return the parametric plane of up triangle of q */ 00020 #define __up__param_triangle__(q) q[3],q[2],q[0] 00021 /* return the parametric plane of down triangle of q */ 00022 #define __down__param_triangle__(q) q[1],q[0],q[2] 00023 #define __convert_order__(i,point) { point[(i+1)%2] = 1.0-point[(i+1)%2]; } 00024 /* check for the intersection beetween {UP,DOWN}/{UP,DOWN} triangles */ 00025 #define __triangle_triangle_case__(trig0,trig1) \ 00026 { \ 00027 if ( geom::intersectp_triangles3_isegment \ 00028 ( coplanar, seg[0], seg[1], \ 00029 trig0##triangle__(a), \ 00030 trig1##triangle__(b), point3::value_type(1e-12) )) \ 00031 { \ 00032 if ( !coplanar ) \ 00033 { \ 00034 space2prm(/* points in parameter space */ \ 00035 seg0[0], seg0[1], \ 00036 /* corresponding points in R3 */ \ 00037 seg[0], seg[1], \ 00038 /* parametric plane = base + 2 vectors */ \ 00039 trig0##param_triangle__(a) \ 00040 ); \ 00041 space2prm( seg1[0], seg1[1], \ 00042 seg[0], seg[1], \ 00043 trig1##param_triangle__(b) ); \ 00044 /* retrieve the correct offset coordinates in quad */ \ 00045 __convert_order__(trig0,seg0[0]); \ 00046 __convert_order__(trig0,seg0[1]); \ 00047 __convert_order__(trig1,seg1[0]); \ 00048 __convert_order__(trig1,seg1[1]); \ 00049 } \ 00050 else \ 00051 {\ 00052 seg0[0][0] = 1.0/3.0; seg0[0][1] = 1.0/3.0; \ 00053 seg0[1][0] = 1.0/3.0; seg0[1][0] = 1.0/3.0; \ 00054 seg1[0][0] = 1.0/3.0; seg1[0][1] = 1.0/3.0; \ 00055 seg1[1][0] = 1.0/3.0; seg1[1][1] = 1.0/3.0; \ 00056 __convert_order__(trig0,seg0[0]); \ 00057 __convert_order__(trig0,seg0[1]); \ 00058 __convert_order__(trig1,seg1[0]); \ 00059 __convert_order__(trig1,seg1[1]); \ 00060 }; \ 00061 { \ 00062 f->convert(seg0,this,2); \ 00063 s->convert(seg1,this,2); \ 00064 push( seg0[0], seg0[1], seg1[0], seg1[1], seg[0],seg[1] ); \ 00065 } \ 00066 }; \ 00067 } \ 00068 00069 // f->convert(seg0,this,2); 00070 // s->convert(seg1,this,2); 00071 00072 00073 00074 void space2prm( vector2 & pa, 00075 vector2 & pb, 00076 const vector3& sa, 00077 const vector3& sb, 00078 const vector3& base, 00079 const vector3& pu, 00080 const vector3& pv ) 00081 { 00082 /* T(u,v) = base + u*bu +v*bv 00083 => 00084 spc[0] - base[0] = delta[0] = / bu[0] bv[0]\ / u \ 00085 spc[1] - base[1] = delta[1] = | bu[1] bv[1]| | | 00086 spc[2] - base[2] = delta[2] = \ bu[2] bv[2]/ \ v / 00087 */ 00088 vector3 bu; 00089 for ( int i = 0; i < 3; i ++ ) bu[i] = pu[i]-base[i]; 00090 vector3 bv; 00091 for ( int i = 0; i < 3; i ++ ) bv[i] = pv[i]-base[i]; 00092 double muu, mvv, muv; 00093 muu = 0; 00094 for ( int i = 0; i < 3; i ++ ) muu += bu[i]*bu[i]; 00095 mvv = 0; 00096 for ( int i = 0; i < 3; i ++ ) mvv += bv[i]*bv[i]; 00097 muv = 0; 00098 for ( int i = 0; i < 3; i ++ ) muv += bu[i]*bv[i]; 00099 double detm = muu*mvv - muv*muv; 00100 vector3 delta; 00101 double x, y; 00102 for ( int k = 0; k < 3; k ++ ) delta[k] = sa[k]-base[k]; 00103 x = 0; 00104 for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k]; 00105 y = 0; 00106 for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k]; 00107 pa[0] = (mvv * x - muv * y)/detm; 00108 pa[1] = (muu * y - muv * x)/detm; 00109 for ( int k = 0; k < 3; k ++ ) delta[k] = sb[k]-base[k]; 00110 x = 0; 00111 for ( int k = 0; k < 3; k ++ ) x += bu[k]*delta[k]; 00112 y = 0; 00113 for ( int k = 0; k < 3; k ++ ) y += bv[k]*delta[k]; 00114 pb[0] = (mvv * x - muv * y)/detm; 00115 pb[1] = (muu * y - muv * x)/detm; 00116 }; 00117 00118 void dsearch::cnfpush( qtree f, qtree s ) 00119 { 00120 point3 a[4],b[4]; // point3 a[4]; point3 b[4]; 00121 f->fill(a,this); 00122 s->fill(b,this); 00123 cnfdata3.push_back( ((double)(1.0/4.0))*(a[0]+a[1]+a[2]+a[3]) ); 00124 }; 00125 00126 // push an quad / quad conflict 00127 // intersection is computed if any and added to the current conflict set of segments 00128 void dsearch::push( qtree f, qtree s ) 00129 { 00130 if ( std::abs(f->umin-s->umin)+std::abs(f->vmin-s->vmin) < SHIFT ) return; 00131 conflict_count ++; 00132 point3 a[4],b[4]; 00133 scale_conflict(a,b,f,s); 00134 { 00135 point3 seg[2]; 00136 point2 seg0[2], seg1[2]; 00137 bool coplanar; 00138 __triangle_triangle_case__(__up__,__up__); 00139 __triangle_triangle_case__(__up__,__down__); 00140 __triangle_triangle_case__(__down__,__down__); 00141 __triangle_triangle_case__(__down__,__up__); 00142 } 00143 }; 00144 /* 00145 void vector_sub( point3& r, const point3& a, const point3& b ) 00146 { 00147 for ( unsigned i = 0; i < d; i++ ) 00148 r[i] = a[i]-b[i]; 00149 }; 00150 00151 double_t vector_dotprod( const point3& a, const point3& b ) 00152 { 00153 double_t tmp = 0; 00154 for ( unsigned i = 0; i < d; i++ ) 00155 tmp += a[i]*b[i]; 00156 return tmp; 00157 }; 00158 00159 void vector_crossprod( point3& r, const point3& a, const point3& b ) 00160 { 00161 r[2] = a[0]*b[1]-a[1]*b[0]; 00162 r[0] = a[1]*b[2]-a[2]*b[1]; 00163 r[1] = a[2]*b[0]-a[0]*b[2]; 00164 }; 00165 double_t vector_nmax( const point3& a, const point3& b) 00166 { 00167 double_t m = std::abs(a[0]-b[0]); 00168 for ( unsigned i = 1; i < d; i++ ) 00169 { 00170 double_t c = std::abs(a[i]-b[i]); 00171 if ( c > m ) m = c; 00172 }; 00173 return m; 00174 }; 00175 00176 struct FirstOrderException{}; 00177 00178 void reachpt( double_t& du, double_t& dv, const point_t& delta, const point_t& Tu, const point_t& Tv ) 00179 { 00180 number_t v0,v1; 00181 number_t m00,m11,m01; 00182 v0 = vector_dotprod( delta, Tu ); 00183 v1 = vector_dotprod( delta, Tv ); 00184 m00 = vector_dotprod( Tu, Tu ); 00185 m11 = vector_dotprod( Tv, Tv ); 00186 m01 = vector_dotprod( Tu, Tv ); 00187 number_t det = m00*m11-m01*m01; 00188 if ( det < 1e-20 ) throw FirstOrderException(); 00189 du = (m11*v0-m01*v1)/det; 00190 dv = (m00*v1-m01*v0)/det; 00191 }; 00192 00193 bool hosaka_iter( number_t& du, number_t& dv, number_t& ds, number_t& dt, 00194 point_t& pA, point_t& pB, 00195 const number_t& u, const number_t& v, const number_t& s, const number_t& t ) 00196 { 00197 00198 point_t tAu,tAv,tBu,tBv; 00199 00200 m_smp->DiffUEval(tAu,u,v); m_smp->DiffVEval(tAv,u,v); 00201 m_smp->DiffUEval(tBu,s,t); m_smp->DiffVEval(tBv,s,t); 00202 00203 point_t nA,nB,nD; 00204 00205 vector_crossprod( nA, tAu, tAv ); 00206 vector_crossprod( nB, tBu, tBv ); 00207 vector_crossprod( nD, nA, nB ); 00208 00209 number_t dA,dB,dD; 00210 00211 dA = vector_dotprod( nA, pA ); 00212 dB = vector_dotprod( nB, pB ); 00213 dD = vector_dotprod( nD, pB ); 00214 00215 00216 number_t d2nD = vector_dotprod( nD, nD ) ; 00217 number_t d2nA = vector_dotprod( nA, nA ) ; 00218 number_t d2nB = vector_dotprod( nB, nB ) ; 00219 00220 if ( d2nD < 1e-6*d2nA*d2nB ) throw FirstOrderException(); 00221 00222 // plane3 00223 00224 point_t c0,c1,x; 00225 00226 vector_crossprod( c0, nB, nD ); 00227 vector_crossprod( c1, nD, nA ); 00228 00229 x[0] = c0[0]*dA+c1[0]*dB+nD[0]*dD; 00230 x[1] = c0[1]*dA+c1[1]*dB+nD[1]*dD; 00231 x[2] = c0[2]*dA+c1[2]*dB+nD[2]*dD; 00232 00233 number_t sc = 1.0/d2nD; 00234 00235 x[0] *= sc; 00236 x[1] *= sc; 00237 x[2] *= sc; 00238 00239 00240 point_t Adelta,Bdelta; 00241 00242 vector_sub(Adelta,x,pA); 00243 vector_sub(Bdelta,x,pB); 00244 00245 reachpt( du, dv, Adelta, tAu, tAv ); 00246 reachpt( ds, dt, Bdelta, tBu, tBv ); 00247 00248 }; 00249 00250 00251 bool hosaka( point2& l, point2& r ) 00252 { 00253 point3 pA,pB; 00254 number u,v,s,t; 00255 00256 const number Sdu(m_smp->du()/3.0); 00257 const number Sdv(m_smp->dv()/3.0); 00258 00259 u = l[0]*this->m_du+this->Fct->umin(); 00260 v = l[1]*m_dv+this->Fct->vmin(); 00261 00262 s = r[0]*this->m_du+this->Fct->umin(); 00263 t = r[1]*m_dv+this->Fct->vmin(); 00264 00265 this->Fct->Eval(pA,u,v); 00266 this->Fct->Eval(pB,s,t); 00267 00268 number d = vector_nmax(pA,pB); 00269 00270 #define exiting()\ 00271 {\ 00272 if ( std::abs(du) > Sdu ) return false;\ 00273 if ( std::abs(ds) > Sdu ) return false;\ 00274 if ( std::abs(dv) > Sdv ) return false;\ 00275 if ( std::abs(dt) > Sdv ) return false;\ 00276 l[0] = u;\ 00277 l[1] = v;\ 00278 r[0] = s;\ 00279 r[1] = t;\ 00280 } 00281 00282 00283 for( int it = 0; it < 8; it++ ) 00284 { 00285 number_t du,dv,ds,dt; 00286 try { hosaka_iter(du,dv,ds,dt,pA,pB,u,v,s,t); } 00287 catch( ... ) 00288 { 00289 l[0] = u; l[1] = v; 00290 r[0] = s; r[1] = t; 00291 return false; 00292 } 00293 00294 exiting(); 00295 00296 u += du; 00297 v += dv; 00298 s += ds; 00299 t += dt; 00300 00301 this->Fct->Eval(pA,u,v); 00302 this->Fct->Eval(pB,s,t); 00303 00304 number_t err = vector_nmax(pA,pB); 00305 00306 if ( err < d ) d = err; else return false; 00307 if ( err < 1e-7 ) 00308 { 00309 using namespace std; 00310 if ( abs(u-s) < 1e-8 && abs(s-t) < 1e-8 ) return false; 00311 return true; 00312 }; 00313 }; 00314 return false; 00315 }; 00316 */ 00317 00318 }; 00319 } //namespace mmx