00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "stdafx.h"
00022
00023 #include "gul_types.h"
00024 #include "gul_float.h"
00025 #include "gul_vector.h"
00026 #include "guma_newton.h"
00027 #include "gunu_basics.h"
00028 #include "gunu_refine.h"
00029 #include "gunu_sample.h"
00030 #include "gunu_bezier_derivatives.h"
00031 #include "guma_random.h"
00032 #include "guma_rkdtree.h"
00033 #include "gunu_project.h"
00034
00035 #include <iostream>
00036 #include "gul_io.h"
00037
00038 namespace gunu {
00039
00040 using gul::rtr;
00041 using gul::Ptr;
00042 using gul::point;
00043 using gul::hpoint;
00044 using gul::kdpoint;
00045 using gul::List;
00046 using gul::ListNode;
00047 using gul::rel_equal;
00048 using guma::rkdtree;
00049 using guma::kdnnrec;
00050 using guma::kdrec;
00051 using guma::newton_info;
00052 using guma::random_des;
00053 using guma::Newton;
00054 using gul::distance;
00055
00056
00057
00058
00059
00060 template< class T, class HP >
00061 struct patch_ninfo : public gul::pool_object
00062 {
00063 int pu;
00064 int pv;
00065 Ptr<T> U;
00066 Ptr<T> V;
00067 Ptr< Ptr<HP> > Pw;
00068
00069 int row;
00070 int col;
00071 };
00072
00073 template< class T, class HP, class EP >
00074 class point_ninfo : public kdpoint<T,EP>
00075 {
00076 public:
00077 Ptr< patch_ninfo<T,HP> > S;
00078
00079 T u;
00080 T v;
00081
00082 point_ninfo *next;
00083 point_ninfo *prev;
00084
00085 point_ninfo( EP& inP, Ptr< patch_ninfo<T,HP> >& inS, T in_u, T in_v )
00086 : kdpoint<T,EP>( inP, 0 )
00087 {
00088 S = inS;
00089 u = in_u;
00090 v = in_v;
00091 }
00092
00093 };
00094
00095 template< class T, class HP, class EP >
00096 class bezier_ninfo : public newton_info<T>
00097 {
00098 public:
00099 T last_u;
00100 T last_v;
00101 bool last_result;
00102 const EP *P;
00103 const point_ninfo<T,HP,EP> *SP;
00104 Ptr< Ptr<EP> > SKL;
00105 T tol1;
00106 T tol2;
00107 bool init;
00108
00109 bezier_ninfo( T in_tol1, T in_tol2 )
00110 : newton_info<T>( 2, (T)0.0001, in_tol2 )
00111 {
00112 int i;
00113
00114 tol1 = in_tol1;
00115 tol2 = in_tol2;
00116
00117 init = false;
00118 P = 0;
00119 SP = 0;
00120
00121 SKL.reserve_pool(3);
00122 for( i = 0; i < 3; i++ )
00123 SKL[i].reserve_pool(3);
00124 }
00125
00126 virtual bool evaluate( const gul::Ptr<T>& dom );
00127
00128 void setCurrentPoint( const EP *inP, const point_ninfo<T,HP,EP> *inSP )
00129 {
00130 init = false;
00131
00132 P = inP;
00133 SP = inSP;
00134 }
00135 };
00136
00137
00138 template< class T, class HP, class EP >
00139 bool bezier_ninfo<T,HP,EP>::evaluate( const Ptr<T>& dom )
00140 {
00141 T u = dom[0], v = dom[1], rootPS;
00142 EP S, Su, Sv, Suu, Svv, Suv, PS;
00143 T SuSu, SvSv, b1, b2;
00144
00145 if( init && (u == last_u) && (v == last_v) )
00146 return last_result;
00147 else
00148 {
00149 init = true;
00150 last_u = u;
00151 last_v = v;
00152 }
00153
00154 if( u < 0.0 ) u = 0.0;
00155 else if( u > 1.0 ) u = 1.0;
00156
00157 if( v < 0.0 ) v = 0.0;
00158 else if( v > 1.0 ) v = 1.0;
00159
00160 BezierSurfaceDerivatives(
00161 u, v, SP->S[0].pu, SP->S[0].U, SP->S[0].pv, SP->S[0].V,
00162 SP->S[0].Pw, 2, SKL );
00163
00164 S = SKL[0][0];
00165 Su = SKL[1][0];
00166 Sv = SKL[0][1];
00167 Suu = SKL[2][0];
00168 Suv = SKL[1][1];
00169 Svv = SKL[0][2];
00170
00171 PS = S - *P;
00172 SuSu = Su*Su;
00173 SvSv = Sv*Sv;
00174
00175 fjac[0][0] = PS*Suu + SuSu;
00176 fjac[0][1] = fjac[1][0] = PS*Suv + Su*Sv;
00177 fjac[1][1] = PS*Svv + SvSv;
00178
00179 fvec[0] = Su*PS;
00180 fvec[1] = Sv*PS;
00181
00182 if( rel_equal(S,*P,tol1) )
00183 {
00184 last_result = true;
00185 return true;
00186 }
00187
00188 rootPS = rtr<T>::sqrt(PS*PS);
00189 b1 = rtr<T>::sqrt(SuSu)*rootPS;
00190 b2 = rtr<T>::sqrt(SvSv)*rootPS;
00191
00192 if( rel_equal(fvec[0]+b1,b1,tol2) &&
00193 rel_equal(fvec[1]+b2,b2,tol2) )
00194 {
00195 last_result = true;
00196 return true;
00197 }
00198
00199 last_result = false;
00200 return false;
00201 }
00202
00203
00204
00205
00206
00207 template< class T, class HP, class EP >
00208 GULAPI int ProjectToSurface(
00209 int nDatPoints, const Ptr<EP>& datPoints,
00210 int ref_nu, int ref_pu, const Ptr<T>& refU,
00211 int ref_nv, int ref_pv, const Ptr<T>& refV,
00212 const Ptr< Ptr<HP> >& refPw,
00213 Ptr< pts_point<T,EP> >& retPts )
00214 {
00215 Ptr<T> BezU,BezV;
00216 Ptr< Ptr< Ptr<HP> > > strips;
00217 Ptr< Ptr< Ptr<HP> > > segs;
00218 Ptr<T> sampU, sampV;
00219 Ptr< Ptr<EP> > sampP;
00220 int nStrips, nSegs, i, j, k, l;
00221 int nSampU, nSampV;
00222 int nKu, nKv;
00223 Ptr<int> Ku,Mu,Kv,Mv;
00224 bezier_ninfo<T,HP,EP> I((T)0.000001,(T)0.000001);
00225 Ptr< patch_ninfo<T,HP> > S;
00226 point_ninfo<T,HP,EP> *P;
00227 List< point_ninfo<T,HP,EP> > LP;
00228 rkdtree< kdpoint<T,EP>,T,random_des > KDT(3);
00229 Ptr< kdnnrec< kdpoint<T,EP>,T > > N;
00230 ListNode< kdrec< kdpoint<T,EP>,T > > *r;
00231 Ptr<T> dom,x1,x2;
00232 point_ninfo<T,HP,EP> *pi;
00233 int n;
00234 bool found;
00235 int index,nFound;
00236 T u,v,nurbs_u,nurbs_v,min_u,min_v,dist,min_dist;
00237 EP min_S;
00238 int nRetPts;
00239
00240 nRetPts = 0;
00241
00242 dom.reserve_pool(2);
00243 x1.reserve_pool(2);
00244 x2.reserve_pool(2);
00245
00246
00247
00248 BezU.reserve_pool(ref_pu+ref_pu+2);
00249 BezV.reserve_pool(ref_pv+ref_pv+2);
00250
00251 BezierKnotVector(ref_pu,BezU);
00252 BezierKnotVector(ref_pv,BezV);
00253
00254
00255
00256 nSampU = ref_pu*3;
00257 nSampV = ref_pv*3;
00258
00259 sampP.reserve_pool(nSampV);
00260 for( i = 0; i < nSampV; i++ )
00261 sampP[i].reserve_pool(nSampU);
00262
00263 sampU.reserve_pool(nSampU);
00264 sampV.reserve_pool(nSampV);
00265 EqualSpacedParameters( nSampU, BezU[0], BezU[ref_pu+1], sampU );
00266 EqualSpacedParameters( nSampV, BezV[0], BezV[ref_pv+1], sampV );
00267
00268 nKu = BezierPositions( ref_nu, ref_pu, refU, Ku, Mu );
00269 nKv = BezierPositions( ref_nv, ref_pv, refV, Kv, Mv );
00270 nStrips = nKv;
00271 nSegs = nKu;
00272
00273
00274
00275 BezierDecomposeSurfaceV( nKv, Kv, Mv, ref_nu, ref_pu, refU,
00276 ref_nv, ref_pv, refV, refPw, &strips );
00277
00278
00279
00280 segs.reserve_pool( nStrips );
00281
00282 for( i = 0; i < nStrips; i++ )
00283 {
00284 BezierDecomposeSurfaceU( nKu, Ku, Mu, ref_nu, ref_pu, refU,
00285 ref_pv, ref_pv, BezV, strips[i], &segs );
00286
00287 strips[i].reset();
00288
00289 for( j = 0; j < nSegs; j++ )
00290 {
00291 CalcSurfaceMesh( ref_pu, ref_pu, BezU, ref_pv, ref_pv, BezV, segs[j],
00292 nSampU, sampU, nSampV, sampV, sampP );
00293
00294 S.reserve_pool(1);
00295
00296 S[0].pu = ref_pu;
00297 S[0].pv = ref_pv;
00298 S[0].U = BezU;
00299 S[0].V = BezV;
00300 S[0].Pw = segs[j];
00301 S[0].row = i;
00302 S[0].col = j;
00303
00304 for( k = 0; k < nSampV; k++ )
00305 {
00306 for( l = 0; l < nSampU; l++ )
00307 {
00308 P = new point_ninfo<T,HP,EP>( sampP[k][l], S, sampU[l], sampV[k] );
00309 LP.Append( P );
00310
00311 KDT.insert( P );
00312 }
00313 }
00314 }
00315
00316
00317
00318 }
00319
00320
00321
00322
00323 x1[0] = x1[1] = (T)0;
00324 x2[0] = x2[1] = (T)1;
00325
00326 for( i = 0; i < nDatPoints; i++ )
00327 {
00328 N.reserve_pool(1);
00329
00330
00331 n = KDT.nearest_neighbors( kdpoint<T,EP>(datPoints[i],0), 1, N );
00332 if( !n ) continue;
00333
00334
00335
00336
00337
00338
00339
00340
00341 nFound = 0;
00342 for( r = N[0].m_recs.First(); r; r = r->next )
00343 {
00344 pi = (point_ninfo<T,HP,EP> *)r->el.m_base;
00345 I.setCurrentPoint( &datPoints[i], pi );
00346
00347 dom[0] = pi->u;
00348 dom[1] = pi->v;
00349 found = Newton( dom, x1, x2, I, 200 );
00350 if( !found ) continue;
00351
00352
00353
00354 u = I.last_u;
00355 v = I.last_v;
00356
00357 index = pi->S[0].row-1;
00358 if( index < 0 )
00359 nurbs_v = ((T)1-v)*refV[ref_pu] + v*refV[Kv[index+1]];
00360 else
00361 nurbs_v = ((T)1-v)*refV[Kv[index]] + v*refV[Kv[index+1]];
00362
00363 index = pi->S[0].col-1;
00364 if( index < 0 )
00365 nurbs_u = ((T)1-u)*refU[ref_pu] + u*refU[Ku[index+1]];
00366 else
00367 nurbs_u = ((T)1-u)*refU[Ku[index]] + u*refU[Ku[index+1]];
00368
00369
00370
00371 dist = distance( I.SKL[0][0], datPoints[i] );
00372
00373 if( !nFound || (dist < min_dist) )
00374 {
00375 min_dist = dist;
00376 min_u = nurbs_u;
00377 min_v = nurbs_v;
00378 min_S = I.SKL[0][0];
00379 }
00380 nFound++;
00381
00382
00383
00384
00385 }
00386
00387
00388
00389 if( nFound )
00390 {
00391 retPts[nRetPts].i = i;
00392 retPts[nRetPts].u = min_u;
00393 retPts[nRetPts].v = min_v;
00394 retPts[nRetPts].S = min_S;
00395 nRetPts++;
00396 }
00397 }
00398
00399 return nRetPts;
00400 }
00401
00402 template GULAPI int ProjectToSurface(
00403 int nDatPoints, const Ptr< point<float> >& datPoints,
00404 int ref_nu, int ref_pu, const Ptr<float>& refU,
00405 int ref_nv, int ref_pv, const Ptr<float>& refV,
00406 const Ptr< Ptr< hpoint<float> > >& Pw,
00407 Ptr< pts_point< float,point<float> > >& retPts );
00408 template GULAPI int ProjectToSurface(
00409 int nDatPoints, const Ptr< point<double> >& datPoints,
00410 int ref_nu, int ref_pu, const Ptr<double>& refU,
00411 int ref_nv, int ref_pv, const Ptr<double>& refV,
00412 const Ptr< Ptr< hpoint<double> > >& Pw,
00413 Ptr< pts_point< double,point<double> > >& retPts );
00414 template GULAPI int ProjectToSurface(
00415 int nDatPoints, const Ptr< point<float> >& datPoints,
00416 int ref_nu, int ref_pu, const Ptr<float>& refU,
00417 int ref_nv, int ref_pv, const Ptr<float>& refV,
00418 const Ptr< Ptr< point<float> > >& Pw,
00419 Ptr< pts_point< float,point<float> > >& retPts );
00420 template GULAPI int ProjectToSurface(
00421 int nDatPoints, const Ptr< point<double> >& datPoints,
00422 int ref_nu, int ref_pu, const Ptr<double>& refU,
00423 int ref_nv, int ref_pv, const Ptr<double>& refV,
00424 const Ptr< Ptr< point<double> > >& Pw,
00425 Ptr< pts_point< double,point<double> > >& retPts );
00426
00427 }