Utils3d.cpp
上传用户:hcfgz168
上传日期:2011-09-11
资源大小:116k
文件大小:26k
源码类别:

OpenGL

开发平台:

WINDOWS

  1. //********************************************
  2. // Utils3d.cpp
  3. //********************************************
  4. // pierre.alliez@cnet.francetelecom.fr
  5. // Created : 29/01/97
  6. // Modified : 14/09/98
  7. //********************************************
  8. #include "stdafx.h"
  9. #include "math.h"
  10. #include "Utils3d.h"
  11. int round(double x)
  12. {
  13. int _ceil = (int)ceil(x);
  14. int _floor = (int)floor(x);
  15. if((_ceil-x) < (x-_floor))
  16. return _ceil;
  17. else
  18. return _floor;
  19. }
  20. //**************************************
  21. // SinAngle between two faces
  22. // u  ^ v  = w
  23. // |w| = |u||v| |sin(u,v)|
  24. //**************************************
  25. double SinAngle(CFace3d *pFace1,
  26.   CFace3d *pFace2)
  27. {
  28. ASSERT(pFace1 != NULL);
  29. ASSERT(pFace2 != NULL);
  30. pFace1->CalculateNormal();
  31. pFace2->CalculateNormal();
  32. if(!pFace1->HasNormal() || !pFace2->HasNormal())
  33. return 0.0f;
  34. // Avoid illegal call of non-static function
  35. CVector3d w = CVector3d::Inner(pFace1->GetNormal(),pFace2->GetNormal());
  36. double Norm1 = pFace1->GetNormal()->GetNormL2();
  37. double Norm2 = pFace2->GetNormal()->GetNormL2();
  38. double Norm_w = w.GetNormL2();
  39. if(Norm1 * Norm2)
  40. return (Norm_w / (Norm1 * Norm2));
  41. else
  42. {
  43. TRACE("** Norms : %g %gn",Norm1,Norm2);
  44. return 0.0;
  45. }
  46. }
  47. //**************************************
  48. // CosAngle between two faces
  49. // uv = |u||v| cos(u,v)
  50. //**************************************
  51. double CosAngle(CFace3d *pFace1,
  52.   CFace3d *pFace2)
  53. {
  54. ASSERT(pFace1 != NULL);
  55. ASSERT(pFace2 != NULL);
  56. pFace1->CalculateNormal();
  57. pFace2->CalculateNormal();
  58. if(!pFace1->HasNormal() || !pFace2->HasNormal())
  59. return 0.0f;
  60. CVector3d *pU = pFace1->GetNormal();
  61. CVector3d *pV = pFace2->GetNormal();
  62. double NormU = pU->GetNormL2();
  63. double NormV = pV->GetNormL2();
  64. double product = NormU*NormV;
  65. // Check
  66. if(product == 0)
  67. {
  68. TRACE("** Norms : %g %gn",NormU,NormV);
  69. return 0.0;
  70. }
  71. double scalar = ::Scalar(pU,pV);
  72. return (scalar / product);
  73. }
  74. //**************************************
  75. // Angle between two faces (in radians)
  76. // we use this formula
  77. // uv = |u||v| cos(u,v)
  78. // u  ^ v  = w
  79. // |w| = |u||v| |sin(u,v)|
  80. //**************************************
  81. double Angle(CFace3d *pFace1,
  82.  CFace3d *pFace2)
  83. {
  84. ASSERT(pFace1 != NULL);
  85. ASSERT(pFace2 != NULL);
  86. pFace1->CalculateNormal();
  87. pFace2->CalculateNormal();
  88. if(!pFace1->HasNormal() || !pFace2->HasNormal())
  89. return 0.0f;
  90. CVector3d *pU = pFace1->GetNormal();
  91. CVector3d *pV = pFace2->GetNormal();
  92. return Angle(pU,pV);
  93. }
  94. //**************************************
  95. // Angle between two vectors (in radians)
  96. // we use this formula
  97. // uv = |u||v| cos(u,v)
  98. // u  ^ v  = w
  99. // |w| = |u||v| |sin(u,v)|
  100. //**************************************
  101. double Angle(CVector3d *pU,
  102.  CVector3d *pV)
  103. {
  104. double NormU = pU->GetNormL2();
  105. double NormV = pV->GetNormL2();
  106. double product = NormU*NormV;
  107. // Check
  108. if(product == 0)
  109. {
  110. TRACE("** Norms : %g %gn",NormU,NormV);
  111. return 0.0;
  112. }
  113. double scalar = ::Scalar(pU,pV);
  114. ASSERT(product != 0);
  115. double cosinus = scalar / product;
  116. // Sinus
  117. CVector3d w = CVector3d::Inner(pU,pV);
  118. double Norm_w = w.GetNormL2();
  119. double AbsSinus = Norm_w / product;
  120. // Remove degeneracy
  121. AbsSinus = (AbsSinus > 1) ? 1 : AbsSinus;
  122. AbsSinus = (AbsSinus < -1) ? -1 : AbsSinus;
  123. if(AbsSinus > 1)
  124. {
  125. TRACE("Remove degeneracy (AbsSinus : %lg)n",AbsSinus);
  126. }
  127. if(cosinus >= 0)
  128. return asin(AbsSinus);
  129. else
  130. return (PI-asin(AbsSinus));
  131. }
  132. //**************************************
  133. // AddFaceNoDuplicate
  134. //**************************************
  135. int AddFaceNoDuplicate(CArray3d<CFace3d> &array,
  136.  CFace3d *pFace)
  137. {
  138. int size = array.GetSize();
  139. for(int i=0;i<size;i++)
  140. {
  141. if(array[i] == pFace)
  142. return 0;
  143. }
  144. array.Add(pFace);
  145. //TRACE("** AddFaceNoDuplicate : %xn",pFace);
  146. return 1;
  147. }
  148. //**************************************
  149. // AddFaceNoDuplicate
  150. //**************************************
  151. int AddFaceRecursive(CArray3d<CFace3d> &array,
  152.  CFace3d *pFace,
  153.  CVertex3d *pVertex)
  154. {
  155. // Add vertex, if needed
  156. if(pFace->HasVertex(pVertex))
  157. {
  158. if(!AddFaceNoDuplicate(array,pFace))
  159. return 0;
  160. }
  161. else
  162. return 0;
  163. // Search in neighbors
  164. for(int i=0;i<3;i++)
  165. {
  166. CFace3d *pFaceNeighbor = pFace->f(i);
  167. if(pFaceNeighbor != NULL)
  168. if(pFaceNeighbor->HasVertex(pVertex))
  169. AddFaceRecursive(array,pFaceNeighbor,pVertex);
  170. }
  171. return 1;
  172. }
  173. //**************************************
  174. // NbSharpEdge
  175. //**************************************
  176. int NbSharpEdge(CArray3d<CFace3d> &array,
  177. double threshold)
  178. {
  179. int size = array.GetSize();
  180. // Check 
  181. if(size == 0)
  182. return 0;
  183. // Only one face, 2 sharp edges
  184. if(size == 1)
  185. return 2;
  186. int NbSharp = 0;
  187. for(int i=0;i<size-1;i++)
  188. {
  189. CFace3d *pFace = array[i];
  190. for(int j=i+1;j<size;j++)
  191. {
  192. CFace3d *pFaceTest = array[j];
  193. if(pFace->HasNeighbor(pFaceTest))
  194. NbSharp += (SinAngle(pFace,pFaceTest) >= threshold);
  195. }
  196. }
  197. return NbSharp;
  198. }
  199. //**************************************
  200. // NormalSum
  201. //**************************************
  202. int NormalSum(CArray3d<CFace3d> &array,
  203. double *pSum)
  204. {
  205. int size = array.GetSize();
  206. // Check 
  207. if(size == 0)
  208. return 0;
  209. // Only one face
  210. if(size == 1)
  211. return 0;
  212. double sum = 0;
  213. for(int i=0;i<size-1;i++)
  214. {
  215. CFace3d *pFace = array[i];
  216. for(int j=i+1;j<size;j++)
  217. {
  218. CFace3d *pFaceTest = array[j];
  219. if(pFace->HasNeighbor(pFaceTest))
  220. sum += SinAngle(pFace,pFaceTest);
  221. }
  222. }
  223. *pSum = sum;
  224. //TRACE("Value : %gn",sum);
  225. return 1;
  226. }
  227. //**************************************
  228. // NormalMax
  229. // (in radians)
  230. //**************************************
  231. int NormalMax(CArray3d<CFace3d> &array,
  232. double *pMax)
  233. {
  234. int size = array.GetSize();
  235. // Check 
  236. if(size == 0)
  237. return 0;
  238. // Only one face
  239. if(size == 1)
  240. return 0;
  241. double max = 0;
  242. for(int i=0;i<size-1;i++)
  243. {
  244. CFace3d *pFace = array[i];
  245. for(int j=i+1;j<size;j++)
  246. {
  247. CFace3d *pFaceTest = array[j];
  248. if(pFace->HasNeighbor(pFaceTest))
  249. {
  250. double sin = SinAngle(pFace,pFaceTest);
  251. max = (sin > max) ? sin : max;
  252. }
  253. }
  254. }
  255. *pMax = max;
  256. max = (max > 1) ? 1 : max; // precision work-around
  257. //TRACE("Value : %gn",max);
  258. return 1;
  259. }
  260. int MaxAngleBetweenFaces(CArray3d<CFace3d> &array,
  261.  double *pMax)
  262. {
  263. int size = array.GetSize();
  264. // Check 
  265. if(size == 0)
  266. return 0;
  267. // Only one face
  268. if(size == 1)
  269. return 0;
  270. double max = 0;
  271. for(int i=0;i<size-1;i++)
  272. {
  273. CFace3d *pFace = array[i];
  274. for(int j=i+1;j<size;j++)
  275. {
  276. CFace3d *pFaceTest = array[j];
  277. if(pFace->HasNeighbor(pFaceTest))
  278. {
  279. double angle = ::Angle(pFace,pFaceTest);
  280. max = (angle > max) ? angle : max;
  281. }
  282. }
  283. }
  284. *pMax = max;
  285. return 1;
  286. }
  287. //**************************************
  288. // DistanceSquare
  289. //**************************************
  290. double DistanceSquare(CVertex3d *pVertex1,
  291.  CVertex3d *pVertex2)
  292. {
  293. return ( (double)(pVertex1->x() - pVertex2->x()) * 
  294.        (double)(pVertex1->x() - pVertex2->x()) +
  295.    (double)(pVertex1->y() - pVertex2->y()) * 
  296.  (double)(pVertex1->y() - pVertex2->y()) +
  297.    (double)(pVertex1->z() - pVertex2->z()) * 
  298.  (double)(pVertex1->z() - pVertex2->z()) );
  299. }
  300. //**************************************
  301. // Distance
  302. //**************************************
  303. double Distance(CVertex3d *pVertex1,
  304.   CVertex3d *pVertex2)
  305. {
  306. return sqrt(DistanceSquare(pVertex1,pVertex2));
  307. }
  308. //**************************************
  309. // DistanceVertexToLine
  310. // Line go through Va and Vb
  311. // Projected vertex is stored in 
  312. // pVertexProjected
  313. //**************************************
  314. double DistanceVertexToLine(CVertex3d *pVertex,
  315.  CVertex3d *pVa,
  316.  CVertex3d *pVb,
  317.  CVertex3d *pVertexProjected)
  318. {
  319. CVector3d VectorAC(pVa,pVertex);
  320. CVector3d VectorAB(pVa,pVb);
  321. double DistanceSquareAB = DistanceSquare(pVa,pVb);
  322. double temp = Scalar(&VectorAC,&VectorAB) / DistanceSquareAB;
  323. VectorAB *= (float)temp;
  324. pVertexProjected->Set(pVa);
  325. pVertexProjected->Move(&VectorAB);
  326. return Distance(pVertexProjected,pVertex);
  327. }
  328. //**************************************
  329. // DistanceVertexToLine
  330. // Line go through Va and Vb
  331. // Projected vertex is stored in 
  332. // pVertexProjected
  333. //**************************************
  334. int ProjectVertexOnLine(CVertex3d *pVertex,
  335.    CVertex3d *pVa,
  336.  CVertex3d *pVb,
  337.  CVertex3d *pVertexProjected)
  338. {
  339. CVector3d VectorAC(pVa,pVertex);
  340. CVector3d VectorAB(pVa,pVb);
  341. double DistanceSquareAB = DistanceSquare(pVa,pVb);
  342. if(DistanceSquareAB == 0.0f)
  343. return 0; // no line
  344. double temp = Scalar(&VectorAC,&VectorAB) / DistanceSquareAB;
  345. VectorAB *= (float)temp;
  346. pVertexProjected->Set(pVa);
  347. pVertexProjected->Move(&VectorAB);
  348. return 1;
  349. }
  350. //**************************************
  351. // DistanceVertexToFace
  352. // Projected vertex is stored in 
  353. // pVertexProjected
  354. //**************************************
  355. double SquareDistanceVertexToFaceIfInf(CVertex3d *pVertex,
  356. CFace3d *pFace,
  357. CVertex3d *pVertexProjected,
  358. double OldDistance)
  359. {
  360. // Project point on triangle's plane
  361. ProjectPointOnFace(pVertex,pFace,pVertexProjected);
  362. if(DistanceSquare(pVertexProjected,pVertex) > OldDistance && 
  363.  !VertexInFace(pVertexProjected,pFace))
  364. return -1.0; // flag
  365. else
  366. return SquareDistanceVertexToFace(pVertex,pFace,pVertexProjected);
  367. }
  368. //**************************************
  369. // DistanceVertexToFace
  370. // Projected vertex is stored in 
  371. // pVertexProjected
  372. //**************************************
  373. double SquareDistanceVertexToFace(CVertex3d *pVertex,
  374.  CFace3d *pFace,
  375.  CVertex3d *pVertexProjected)
  376. {
  377. // ** DEBUG **
  378. // Project point on triangle's plane
  379. ProjectPointOnFace(pVertex,pFace,pVertexProjected);
  380. // Is point in triangle  ?
  381. if(VertexInFace(pVertexProjected,pFace))
  382. {
  383. // TRACE(" vertex in face... (projected : %g %g %g)n",pVertexProjected->x(),pVertexProjected->y(),pVertexProjected->z());
  384. return DistanceSquare(pVertexProjected,pVertex);
  385. }
  386. // Out, also project "projected vertex" on 3 lines
  387. CVertex3d VertexProjectedOnLine[3];
  388. for(int i=0;i<3;i++)
  389. {
  390. ProjectVertexOnLine(pVertexProjected,pFace->v(i),pFace->v((i+1)%3),&VertexProjectedOnLine[i]);
  391. //// TRACE("  ProjectVertexOnLine : (%g %g %g)...n",VertexProjectedOnLine[i].x(),VertexProjectedOnLine[i].y(),VertexProjectedOnLine[i].z());
  392. }
  393. // Is point on segment of face ?
  394. int success = 0;
  395. for(i=0;i<3;i++)
  396. if(VertexOnSegment(&VertexProjectedOnLine[i],pFace->v(i),pFace->v((i+1)%3)))
  397. {
  398. success = 1;
  399. VertexProjectedOnLine[i].SetFlag(1);
  400. //// TRACE("  vertex on segment of face (%g %g %g)...n",VertexProjectedOnLine[i].x(),VertexProjectedOnLine[i].y(),VertexProjectedOnLine[i].z());
  401. }
  402. // At least one vertex on segment
  403. if(success)
  404. {
  405. // Compare with projected points in segment and vertices of triangle
  406. // Get nearest vertex
  407. CVertex3d *pVertexTmp = pFace->FindNearestVertex(pVertexProjected);
  408. CVertex3d VertexProjectedFinal(pVertexTmp);
  409. double MinDistance = DistanceSquare(pVertexProjected,pVertexTmp);
  410. for(i=0;i<3;i++)
  411. if(VertexProjectedOnLine[i].GetFlag())
  412. {
  413. VertexProjectedOnLine[i].SetFlag(0); // Restore
  414. double tmp = DistanceSquare(pVertexProjected,&VertexProjectedOnLine[i]);
  415. if(tmp <= MinDistance)
  416. {
  417. VertexProjectedFinal.Set(VertexProjectedOnLine[i]);
  418. MinDistance = tmp;
  419. }
  420. }
  421. pVertexProjected->Set(VertexProjectedFinal);
  422. // TRACE("  nearest vertex on face (%g %g %g)...n",VertexProjectedFinal.x(),VertexProjectedFinal.y(),VertexProjectedFinal.z());
  423. return DistanceSquare(&VertexProjectedFinal,pVertex);
  424. }
  425. // Out, we must search nearest vertex
  426. CVertex3d *pVertexProjectedFinal = pFace->FindNearestVertex(pVertexProjected);
  427. pVertexProjected->Set(pVertexProjectedFinal);
  428. // TRACE("  nearest vertex on face (%g %g %g)...n",pVertexProjectedFinal->x(),pVertexProjectedFinal->y(),pVertexProjectedFinal->z());
  429. return DistanceSquare(pVertexProjectedFinal,pVertex);
  430. }
  431. //********************************************
  432. // SquareDistanceToFaceFast
  433. //********************************************
  434. // Search min distance between pVertex and 
  435. // mesh's faces around pFace
  436. //********************************************
  437. double SquareDistanceToSetOfFace(CVertex3d *pVertex,
  438. CVertex3d *pVertexRef,
  439. CFace3d **ppFace,
  440. CArray3d<CFace3d> &ArrayFace)
  441. {
  442. ASSERT(pVertex != NULL);
  443. ASSERT(pVertexRef != NULL);
  444. int size = ArrayFace.GetSize();
  445. ASSERT(size != 0);
  446. // For each face in set
  447. CVertex3d vertex;
  448. double distance = MAX_DOUBLE;
  449. for(int i=0;i<size;i++)
  450. {
  451. double tmp = SquareDistanceVertexToFaceIfInf(pVertex,ArrayFace[i],&vertex,distance);
  452. if(tmp < distance && tmp != -1.0f)
  453. {
  454. distance = tmp;
  455. pVertexRef->Set(vertex);
  456. *ppFace = ArrayFace[i];
  457. }
  458. }
  459. //TRACE("Dist : %g vertex(%g,%g,%g)",distance,pVertex->x(),pVertex->y(),pVertex->z());
  460. return distance;
  461. }
  462. //********************************************
  463. // MaxSquareDistanceVertexFace
  464. // For each vertex, search smallest distance 
  465. // to set of faces (pArrayFace)
  466. // Return max founded
  467. //********************************************
  468. double MaxSquareDistanceVertexFace(CArray3d<CVertex3d> *pArrayVertex,
  469.      CArray3d<CFace3d> *pArrayFace,
  470. CVertex3d **ppVertex,
  471. CFace3d **ppFace)
  472. {
  473. int NbVertex = pArrayVertex->GetSize();
  474. int NbFace = pArrayFace->GetSize();
  475. // Check
  476. ASSERT(NbVertex != 0 && NbFace != 0);
  477. // Non-optimized
  478. CVertex3d v;
  479. double max = 0.0;
  480. double distance;
  481. for(int i=0;i<NbVertex;i++)
  482. {
  483. // Get distance to set of faces
  484. distance = MAX_FLOAT;
  485. for(int j=0;j<NbFace;j++)
  486. {
  487. double d = ::SquareDistanceVertexToFace(pArrayVertex->GetAt(i),
  488.                                       pArrayFace->GetAt(j),&v);
  489. if(d < distance)
  490. distance = d;
  491. }
  492. // Get max for each vertex
  493.   if(distance > max)
  494. {
  495. max = distance;
  496. if(ppFace != NULL && ppVertex != NULL)
  497. {
  498. *ppFace = pArrayFace->GetAt(j);
  499. *ppVertex = pArrayVertex->GetAt(i);
  500. }
  501. }
  502. }
  503. return max;
  504. }
  505. //**************************************
  506. // Scalar product
  507. //**************************************
  508. double Scalar(CVector3d *pV1,
  509. CVector3d *pV2)
  510. {
  511. return ((double)pV1->x()*(double)pV2->x() +  
  512.       (double)pV1->y()*(double)pV2->y() + 
  513. (double)pV1->z()*(double)pV2->z());
  514. }
  515. //**************************************
  516. // Opposite per coord
  517. //**************************************
  518. int OppositePerCoord(CVector3d *pV1,
  519.  CVector3d *pV2)
  520. {
  521. return (pV1->x()*pV2->x() < 0.0f &&  
  522.       pV1->y()*pV2->y() < 0.0f &&  
  523. pV1->z()*pV2->z() < 0.0f);
  524. }
  525. //**************************************
  526. // Scalar product
  527. //**************************************
  528. double Scalar(CVector3d &v1,
  529. CVector3d &v2)
  530. {
  531. return ((double)v1.x() * (double)v2.x() +  
  532.       (double)v1.y() * (double)v2.y() + 
  533. (double)v1.z() * (double)v2.z());
  534. }
  535. //********************************************
  536. // Inner
  537. //********************************************
  538. CVector3d Inner(CVector3d* u,
  539. CVector3d* v)
  540. {
  541. // w = u ^ v
  542. CVector3d w;
  543. w.Set((float)((double)u->y()*(double)v->z()-(double)u->z()*(double)v->y()),
  544.     (float)((double)u->z()*(double)v->x()-(double)u->x()*(double)v->z()),
  545.     (float)((double)u->x()*(double)v->y()-(double)u->y()*(double)v->x()));
  546. return w;
  547. }
  548. //**************************************
  549. // PlaneEquation
  550. // Plane : ax + by + cz + d = 0
  551. // Normal : a,b,c
  552. // d : distance from origin along normal 
  553. //     to the plane
  554. //**************************************
  555. int PlaneEquationFromFace(CFace3d *pFace,
  556. float *a,
  557. float *b,
  558. float *c,
  559. float *d)
  560. {
  561. ASSERT(a != NULL);
  562. ASSERT(b != NULL);
  563. ASSERT(c != NULL);
  564. ASSERT(d != NULL);
  565. pFace->CalculateNormal();
  566. if(!pFace->HasNormal())
  567. return 0;
  568. CVector3d *pNormal = pFace->GetNormal();
  569. CVertex3d *pVertex = pFace->v1();
  570. ASSERT(pNormal != NULL);
  571. ASSERT(pVertex != NULL);
  572. // Store coeff
  573. *a = pNormal->x();
  574. *b = pNormal->y();
  575. *c = pNormal->z();
  576. *d = -(pNormal->x()*pVertex->x()+
  577.      pNormal->y()*pVertex->y()+
  578.  pNormal->z()*pVertex->z());
  579. return 1;
  580. }
  581. //**************************************
  582. // VertexOnSegment
  583. //**************************************
  584. int VertexOnSegment(CVertex3d *pVertex,
  585. CVertex3d *pV1,
  586. CVertex3d *pV2)
  587. {
  588. CVector3d v1(pV1,pVertex);
  589. CVector3d v2(pV2,pVertex);
  590. return (Scalar(v1,v2) <= 0);
  591. }
  592. //**************************************
  593. // ProjectPointOnPlane
  594. // Plane : ax + by + cz + d = 0
  595. // We store projected vertex coordinates 
  596. // in pVertexProjected
  597. //**************************************
  598. int ProjectPointOnPlane(CVertex3d *pVertex,
  599. CVertex3d *pVertexProjected,
  600. float a,
  601. float b,
  602. float c,
  603. float d)
  604. {
  605. // We need valid plane
  606. float div = a*a+b*b+c*c;
  607. ASSERT(div != 0.0f);
  608. if(div == 0.0f)
  609. return 0;
  610. float x = pVertex->x();
  611. float y = pVertex->y();
  612. float z = pVertex->z();
  613. float t = -(a*x + b*y + c*z + d) / div;
  614. pVertexProjected->Set(a*t+x,b*t+y,c*t+z);
  615. return 1;
  616. }
  617. //**************************************
  618. // ProjectPointOnFace
  619. // We store projected vertex coordinates 
  620. // in pVertexProjected
  621. //**************************************
  622. int ProjectPointOnFace(CVertex3d *pVertex,
  623. CFace3d *pFace,
  624. CVertex3d *pVertexProjected)
  625. {
  626. // Get plane coeff
  627. float a,b,c,d;
  628. if(PlaneEquationFromFace(pFace,&a,&b,&c,&d))
  629. return ProjectPointOnPlane(pVertex,pVertexProjected,a,b,c,d);
  630. else
  631. return 0;
  632. //TRACE("** Plane equation : %f %f %f %fn",a,b,c,d);
  633. // Project point on triangle's plane
  634. }
  635. //**************************************
  636. // IsVertexInFace
  637. // We know vertex is in plane of
  638. // triangle, and just test whenever
  639. // vertex V is in triangular face F
  640. //**************************************
  641. int VertexInFace(CVertex3d *pVertex,
  642.  CFace3d *pFace)
  643. {
  644. CVector3d vv1(pVertex,pFace->v1());
  645. CVector3d vv2(pVertex,pFace->v2());
  646. CVector3d vv3(pVertex,pFace->v3());
  647. CVector3d w1 = CVector3d::Inner(&vv1,&vv2);
  648. CVector3d w2 = CVector3d::Inner(&vv2,&vv3);
  649. CVector3d w3 = CVector3d::Inner(&vv3,&vv1);
  650. return (Scalar(&w1,&w2) >= 0 && 
  651.       Scalar(&w2,&w3) >= 0 && 
  652. Scalar(&w1,&w3) >= 0);
  653. }
  654. //**************************************
  655. // Spring term 
  656. // SIGMA(j,k)(k|Vj - Vk|^2);
  657. //**************************************
  658. double Spring(CVertex3d *pVertex,
  659.   double k)
  660. {
  661. // Check
  662. int NbVertexNeighbor = pVertex->NbVertexNeighbor();
  663. if(NbVertexNeighbor == 0)
  664. return 0.0f;
  665. double sum = 0.0f;
  666. for(int i=0;i<NbVertexNeighbor;i++)
  667. sum += DistanceSquare(pVertex,pVertex->GetVertexNeighbor(i));
  668. return (sum*k);
  669. }
  670. //**************************************
  671. // Area
  672. //**************************************
  673. double Area(CVertex3d *pV0,
  674. CVertex3d *pV1,
  675. CVertex3d *pV2)
  676. {
  677. ASSERT(pV0 != NULL);
  678. ASSERT(pV1 != NULL);
  679. ASSERT(pV2 != NULL);
  680. CVector3d bc(pV1,pV2);
  681. CVector3d ba(pV1,pV0);
  682. //bc.Trace();
  683. //ba.Trace();
  684. CVector3d v = ::Inner(&bc,&ba);
  685. //v.Trace();
  686. return v.GetNormL2()/2.0;
  687. }
  688. //**************************************
  689. // GetMeanArea
  690. //**************************************
  691. double GetMeanArea(CArray3d<CFace3d> *pArrayFace)
  692. {
  693. int size = pArrayFace->GetSize();
  694. ASSERT(size > 0);
  695. double sum = 0.0f;
  696. for(int i=0;i<size;i++)
  697. sum += pArrayFace->GetAt(i)->Area();
  698. return (sum/(double)size);
  699. }
  700. //**************************************
  701. // GetMinArea
  702. //**************************************
  703. double GetMinArea(CArray3d<CFace3d> *pArrayFace)
  704. {
  705. int size = pArrayFace->GetSize();
  706. ASSERT(size > 0);
  707. double min = MAX_DOUBLE;
  708. for(int i=0;i<size;i++)
  709. {
  710. double area = pArrayFace->GetAt(i)->Area();
  711. //TRACE("Area : %gn",area);
  712. min = (area < min) ? area : min;
  713. }
  714. return min;
  715. }
  716. //**************************************
  717. // FormFunction
  718. //**************************************
  719. // Ratio (area(013)/area(012))
  720. // Triangle : 012
  721. // Vertex on which we want to evaluate 
  722. // form function : 3
  723. //**************************************
  724. double FormFunction(CVertex3d *pV0,
  725. CVertex3d *pV1,
  726. CVertex3d *pV2,
  727. CVertex3d *pV3)
  728. {
  729. double area = Area(pV0,pV1,pV2);
  730. ASSERT(area != 0.0);
  731. return Area(pV0,pV1,pV3)/area;
  732. }
  733. //**************************************
  734. // IntersectionLineFace
  735. //**************************************
  736. int IntersectionLineFace(CVertex3d *pV0,
  737.  CVertex3d *pV1,
  738.  CFace3d *pFace,
  739.  CVertex3d *pVertexResult)
  740. {
  741. float a,b,c,d;
  742. PlaneEquationFromFace(pFace,&a,&b,&c,&d);
  743. float i = pV1->x()-pV0->x();
  744. float j = pV1->y()-pV0->y();
  745. float k = pV1->z()-pV0->z();
  746. float den = a*i + b*j + c*k;
  747. float num = -(a * pV0->x() + b * pV0->y() + c * pV0->z() + d);
  748. // parallel or face contain line
  749. if(den == 0.0f)
  750. return 0;
  751. float t = num / den;
  752. pVertexResult->Set(pV0->x()+t*i,pV0->y()+t*j,pV0->z()+t*k);
  753. return VertexInFace(pVertexResult,pFace);
  754. }
  755. //********************************************
  756. // IntersectionLineFaceRecursive
  757. // (propagation from pFaceStart)
  758. //********************************************
  759. int IntersectionLineFaceRecursive(CVertex3d *pV0,
  760. CVertex3d *pV1,
  761. CFace3d *pFaceStart,
  762. CVertex3d *pVertexResult,
  763. CFace3d **ppFaceResult,
  764. CArray3d<CFace3d> *pArrayFace,
  765. int MaxNbFace)
  766. {
  767. if(pArrayFace->GetSize() >= MaxNbFace)
  768. return 0;
  769. pArrayFace->Add(pFaceStart);
  770. if(IntersectionLineFace(pV0,pV1,pFaceStart,pVertexResult))
  771. {
  772. *ppFaceResult = pFaceStart;
  773. return 1;
  774. }
  775. //TRACE("Size : %d (max : %d)n",pArrayFace->GetSize(),MaxNbFace);
  776. pFaceStart->SetFlag(1);
  777. // neighboring
  778. for(int i=0;i<3;i++)
  779. {
  780. CFace3d *pFace = pFaceStart->f(i);
  781. if(pFace != NULL)  // neighbor exists
  782. if(pFace->GetFlag() != 1) // not yet
  783. if(IntersectionLineFaceRecursive(pV0,pV1,pFace,
  784.              pVertexResult,ppFaceResult,pArrayFace,MaxNbFace))
  785. return 1;
  786. }
  787. return 0;
  788. }
  789. //********************************************
  790. // NearestIntersectionWithLine
  791. // First intersection founded (propagation
  792. // from pFaceStart)
  793. //********************************************
  794. int NearestIntersectionWithLine(CVertex3d *pV0,
  795. CVertex3d *pV1,
  796. CFace3d *pFaceStart,
  797. CVertex3d *pVertexResult,
  798. CFace3d **ppFaceResult,
  799. int MaxNbFace)
  800. {
  801. // Check
  802. ASSERT(pV0 != NULL);
  803. ASSERT(pV1 != NULL);
  804. ASSERT(pFaceStart != NULL);
  805. ASSERT(pVertexResult != NULL);
  806. // Use flag
  807. CArray3d<CFace3d> ArrayFace;
  808. int success = IntersectionLineFaceRecursive(pV0,pV1,pFaceStart,
  809.                                           pVertexResult,ppFaceResult,&ArrayFace,MaxNbFace);
  810. for(int i=0;i<ArrayFace.GetSize();i++)
  811. ArrayFace[i]->SetFlag(0);
  812. //TRACE("NbFace : %dn",ArrayFace.GetSize());
  813. ArrayFace.SetSize(0);
  814. return success;
  815. }
  816. //********************************************
  817. // NearestIntersectionWithLine
  818. // Only search in pArrayFace
  819. //********************************************
  820. int NearestIntersectionWithLine(CArray3d<CFace3d> *pArrayFace,
  821. CVertex3d *pV0,
  822. CVertex3d *pV1,
  823. CVertex3d *pVertexResult,
  824. CFace3d **ppFaceResult,
  825. int *pNbVisitedFace)
  826. {
  827. int success = 0;
  828. *ppFaceResult = NULL;
  829. int size = pArrayFace->GetSize();
  830. *pNbVisitedFace = size;
  831. double SqDistance = MAX_DOUBLE;
  832. // For each face
  833. for(int i=0;i<size;i++)
  834. {
  835. CVertex3d v;
  836. if(IntersectionLineFace(pV0,pV1,pArrayFace->GetAt(i),&v))
  837. {
  838. success++;
  839. double d = ::DistanceSquare(pV0,&v);
  840. if(d < SqDistance)
  841. {
  842. SqDistance = d;
  843. pVertexResult->Set(v);
  844. // this face contains intersection
  845. *ppFaceResult = pArrayFace->GetAt(i);
  846. }
  847. }
  848. }
  849. //TRACE("NbIntersection : %dn",success);
  850. if(success)
  851. {
  852. ASSERT(ppFaceResult != NULL);
  853. }
  854. return success; // NbIntersection
  855. }
  856. //********************************************
  857. // NearestIntersectionWithLine
  858. // Only search in pFace and its neighbors
  859. //********************************************
  860. int NearestIntersectionWithLineFromFaceAndNeighbors(CFace3d *pFace,
  861. CVertex3d *pV0,
  862. CVertex3d *pV1,
  863. CVertex3d *pVertexResult,
  864. CFace3d **ppFaceResult)
  865. {
  866. int success = 0;
  867. *ppFaceResult = NULL;
  868. double SqDistance = MAX_DOUBLE;
  869. CVertex3d v;
  870. // pFace alone
  871. if(IntersectionLineFace(pV0,pV1,pFace,&v))
  872. {
  873. success++;
  874. double d = ::DistanceSquare(pV0,&v);
  875. if(d < SqDistance)
  876. {
  877. SqDistance = d;
  878. pVertexResult->Set(v);
  879. *ppFaceResult = pFace;
  880. }
  881. }
  882. // Its neighbors
  883. for(int i=0;i<3;i++)
  884. {
  885. CFace3d *pFaceNeighbor = pFace->f(i);
  886. if(pFaceNeighbor != NULL) // neighbor
  887. if(IntersectionLineFace(pV0,pV1,pFaceNeighbor,&v))
  888. {
  889. success++;
  890. double d = ::DistanceSquare(pV0,&v);
  891. if(d < SqDistance)
  892. {
  893. SqDistance = d;
  894. pVertexResult->Set(v);
  895. *ppFaceResult = pFaceNeighbor;
  896. }
  897. }
  898. }
  899. if(success) { ASSERT((*ppFaceResult) != NULL); }
  900. return success;
  901. }
  902. int GravityCenter(CArray3d<CVertex3d> *pArray,
  903. CVertex3d *pVertexCenter)
  904. {
  905. int size = pArray->GetSize();
  906. for(int j=0;j<3;j++)
  907. {
  908. float v = 0.0f;
  909. for(int i=0;i<size;i++)
  910. v += pArray->GetAt(i)->Get(j);
  911. v /= size;
  912. pVertexCenter->Set(j,v);
  913. }
  914. return 1;
  915. }
  916. // ** EOF **