sort_triangles.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "sort_triangles.h"
  9. #include "barycenter.h"
  10. #include "sort.h"
  11. #include "sortrows.h"
  12. #include "slice.h"
  13. #include "round.h"
  14. #include "colon.h"
  15. #include "matlab_format.h"
  16. #include <iostream>
  17. template <
  18. typename DerivedV,
  19. typename DerivedF,
  20. typename DerivedMV,
  21. typename DerivedP,
  22. typename DerivedFF,
  23. typename DerivedI>
  24. IGL_INLINE void igl::sort_triangles(
  25. const Eigen::PlainObjectBase<DerivedV> & V,
  26. const Eigen::PlainObjectBase<DerivedF> & F,
  27. const Eigen::PlainObjectBase<DerivedMV> & MV,
  28. const Eigen::PlainObjectBase<DerivedP> & P,
  29. Eigen::PlainObjectBase<DerivedFF> & FF,
  30. Eigen::PlainObjectBase<DerivedI> & I)
  31. {
  32. using namespace Eigen;
  33. using namespace std;
  34. // Barycenter, centroid
  35. Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
  36. Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> BC,PBC;
  37. barycenter(V,F,BC);
  38. D = BC*(MV.transpose()*P.transpose().eval().col(2));
  39. sort(D,1,false,sD,I);
  40. //// Closest corner
  41. //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
  42. //D.setConstant(F.rows(),1,-1e26);
  43. //for(int c = 0;c<3;c++)
  44. //{
  45. // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
  46. // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> DC;
  47. // C.resize(F.rows(),4);
  48. // for(int f = 0;f<F.rows();f++)
  49. // {
  50. // C(f,0) = V(F(f,c),0);
  51. // C(f,1) = V(F(f,c),1);
  52. // C(f,2) = V(F(f,c),2);
  53. // C(f,3) = 1;
  54. // }
  55. // DC = C*(MV.transpose()*P.transpose().eval().col(2));
  56. // D = (DC.array()>D.array()).select(DC,D).eval();
  57. //}
  58. //sort(D,1,false,sD,I);
  59. //// Closest corner with tie breaks
  60. //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,3> D,sD,ssD;
  61. //D.resize(F.rows(),3);
  62. //for(int c = 0;c<3;c++)
  63. //{
  64. // Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
  65. // C.resize(F.rows(),4);
  66. // for(int f = 0;f<F.rows();f++)
  67. // {
  68. // C(f,0) = V(F(f,c),0);
  69. // C(f,1) = V(F(f,c),1);
  70. // C(f,2) = V(F(f,c),2);
  71. // C(f,3) = 1;
  72. // }
  73. // D.col(c) = C*(MV.transpose()*P.transpose().eval().col(2));
  74. //}
  75. //VectorXi _;
  76. //sort(D,2,false,sD,_);
  77. //sortrows(sD,false,ssD,I);
  78. slice(F,I,1,FF);
  79. }
  80. //#include "EPS.h"
  81. //#include <functional>
  82. //#include <algorithm>
  83. //
  84. //static int tough_count = 0;
  85. //template <typename Vec3>
  86. //class Triangle
  87. //{
  88. // public:
  89. // static inline bool z_comp(const Vec3 & A, const Vec3 & B)
  90. // {
  91. // return A(2) > B(2);
  92. // }
  93. // static typename Vec3::Scalar ZERO()
  94. // {
  95. // return igl::EPS<typename Vec3::Scalar>();
  96. // return 0;
  97. // }
  98. // public:
  99. // int id;
  100. // // Sorted projected coners: c[0] has smallest z value
  101. // Vec3 c[3];
  102. // Vec3 n;
  103. // public:
  104. // Triangle():id(-1) { };
  105. // Triangle(int id, const Vec3 c0, const Vec3 c1, const Vec3 c2):
  106. // id(id)
  107. // {
  108. // using namespace std;
  109. // c[0] = c0;
  110. // c[1] = c1;
  111. // c[2] = c2;
  112. // sort(c,c+3,Triangle<Vec3>::z_comp);
  113. // // normal pointed toward viewpoint
  114. // n = (c0-c1).cross(c2-c0);
  115. // if(n(2) < 0)
  116. // {
  117. // n *= -1.0;
  118. // }
  119. // // Avoid NaNs
  120. // typename Vec3::Scalar len = n.norm();
  121. // if(len == 0)
  122. // {
  123. // cout<<"avoid NaN"<<endl;
  124. // assert(false);
  125. // len = 1;
  126. // }
  127. // n /= len;
  128. // };
  129. //
  130. // typename Vec3::Scalar project(const Vec3 & r) const
  131. // {
  132. // //return n.dot(r-c[2]);
  133. // int closest = -1;
  134. // typename Vec3::Scalar min_dist = 1e26;
  135. // for(int ci = 0;ci<3;ci++)
  136. // {
  137. // typename Vec3::Scalar dist = (c[ci]-r).norm();
  138. // if(dist < min_dist)
  139. // {
  140. // min_dist = dist;
  141. // closest = ci;
  142. // }
  143. // }
  144. // assert(closest>=0);
  145. // return n.dot(r-c[closest]);
  146. // }
  147. //
  148. // // Z-values of this are < z-values of that
  149. // bool is_completely_behind(const Triangle & that) const
  150. // {
  151. // const typename Vec3::Scalar ac0 = that.c[0](2);
  152. // const typename Vec3::Scalar ac1 = that.c[1](2);
  153. // const typename Vec3::Scalar ac2 = that.c[2](2);
  154. // const typename Vec3::Scalar ic0 = this->c[0](2);
  155. // const typename Vec3::Scalar ic1 = this->c[1](2);
  156. // const typename Vec3::Scalar ic2 = this->c[2](2);
  157. // return
  158. // (ic0 < ac2 && ic1 <= ac2 && ic2 <= ac2) ||
  159. // (ic0 <= ac2 && ic1 < ac2 && ic2 <= ac2) ||
  160. // (ic0 <= ac2 && ic1 <= ac2 && ic2 < ac2);
  161. // }
  162. //
  163. // bool is_behind_plane(const Triangle &that) const
  164. // {
  165. // using namespace std;
  166. // const typename Vec3::Scalar apc0 = that.project(this->c[0]);
  167. // const typename Vec3::Scalar apc1 = that.project(this->c[1]);
  168. // const typename Vec3::Scalar apc2 = that.project(this->c[2]);
  169. // cout<<" "<<
  170. // apc0<<", "<<
  171. // apc1<<", "<<
  172. // apc2<<", "<<endl;
  173. // return (apc0 < ZERO() && apc1 < ZERO() && apc2 < ZERO());
  174. // }
  175. //
  176. // bool is_in_front_of_plane(const Triangle &that) const
  177. // {
  178. // using namespace std;
  179. // const typename Vec3::Scalar apc0 = that.project(this->c[0]);
  180. // const typename Vec3::Scalar apc1 = that.project(this->c[1]);
  181. // const typename Vec3::Scalar apc2 = that.project(this->c[2]);
  182. // cout<<" "<<
  183. // apc0<<", "<<
  184. // apc1<<", "<<
  185. // apc2<<", "<<endl;
  186. // return (apc0 > ZERO() && apc1 > ZERO() && apc2 > ZERO());
  187. // }
  188. //
  189. // bool is_coplanar(const Triangle &that) const
  190. // {
  191. // using namespace std;
  192. // const typename Vec3::Scalar apc0 = that.project(this->c[0]);
  193. // const typename Vec3::Scalar apc1 = that.project(this->c[1]);
  194. // const typename Vec3::Scalar apc2 = that.project(this->c[2]);
  195. // return (fabs(apc0)<=ZERO() && fabs(apc1)<=ZERO() && fabs(apc2)<=ZERO());
  196. // }
  197. //
  198. // // http://stackoverflow.com/a/14561664/148668
  199. // // a1 is line1 start, a2 is line1 end, b1 is line2 start, b2 is line2 end
  200. // static bool seg_seg_intersect(const Vec3 & a1, const Vec3 & a2, const Vec3 & b1, const Vec3 & b2)
  201. // {
  202. // Vec3 b = a2-a1;
  203. // Vec3 d = b2-b1;
  204. // typename Vec3::Scalar bDotDPerp = b(0) * d(1) - b(1) * d(0);
  205. //
  206. // // if b dot d == 0, it means the lines are parallel so have infinite intersection points
  207. // if (bDotDPerp == 0)
  208. // return false;
  209. //
  210. // Vec3 c = b1-a1;
  211. // typename Vec3::Scalar t = (c(0) * d(1) - c(1) * d(0)) / bDotDPerp;
  212. // if (t < 0 || t > 1)
  213. // return false;
  214. //
  215. // typename Vec3::Scalar u = (c(0) * b(1) - c(1) * b(0)) / bDotDPerp;
  216. // if (u < 0 || u > 1)
  217. // return false;
  218. //
  219. // return true;
  220. // }
  221. // bool has_corner_inside(const Triangle & that) const
  222. // {
  223. // // http://www.blackpawn.com/texts/pointinpoly/
  224. // // Compute vectors
  225. // Vec3 A = that.c[0];
  226. // Vec3 B = that.c[1];
  227. // Vec3 C = that.c[2];
  228. // A(2) = B(2) = C(2) = 0;
  229. // for(int ci = 0;ci<3;ci++)
  230. // {
  231. // Vec3 P = this->c[ci];
  232. // P(2) = 0;
  233. //
  234. // Vec3 v0 = C - A;
  235. // Vec3 v1 = B - A;
  236. // Vec3 v2 = P - A;
  237. //
  238. // // Compute dot products
  239. // typename Vec3::Scalar dot00 = v0.dot(v0);
  240. // typename Vec3::Scalar dot01 = v0.dot(v1);
  241. // typename Vec3::Scalar dot02 = v0.dot(v2);
  242. // typename Vec3::Scalar dot11 = v1.dot(v1);
  243. // typename Vec3::Scalar dot12 = v1.dot(v2);
  244. //
  245. // // Compute barycentric coordinates
  246. // typename Vec3::Scalar invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
  247. // typename Vec3::Scalar u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  248. // typename Vec3::Scalar v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  249. //
  250. // // Check if point is in triangle
  251. // if((u >= 0) && (v >= 0) && (u + v < 1))
  252. // {
  253. // return true;
  254. // }
  255. // }
  256. // return false;
  257. // }
  258. //
  259. // bool overlaps(const Triangle &that) const
  260. // {
  261. // // Edges cross
  262. // for(int e = 0;e<3;e++)
  263. // {
  264. // for(int f = 0;f<3;f++)
  265. // {
  266. // if(seg_seg_intersect(
  267. // this->c[e],this->c[(e+1)%3],
  268. // that.c[e],that.c[(e+1)%3]))
  269. // {
  270. // return true;
  271. // }
  272. // }
  273. // }
  274. // // This could be entirely inside that
  275. // if(this->has_corner_inside(that))
  276. // {
  277. // return true;
  278. // }
  279. // // vice versa
  280. // if(that.has_corner_inside(*this))
  281. // {
  282. // return true;
  283. // }
  284. // return false;
  285. // }
  286. //
  287. //
  288. // bool operator< (const Triangle &that) const
  289. // {
  290. // // THIS < THAT if "depth" of THIS < "depth" of THAT
  291. // // " if THIS should be draw before THAT
  292. // using namespace std;
  293. // bool ret = false;
  294. // // Self compare
  295. // if(that.id == this->id)
  296. // {
  297. // ret = false;
  298. // }
  299. // if(this->is_completely_behind(that))
  300. // {
  301. // cout<<" "<<this->id<<" completely behind "<<that.id<<endl;
  302. // ret = false;
  303. // }else if(that.is_completely_behind(*this))
  304. // {
  305. // cout<<" "<<that.id<<" completely behind "<<this->id<<endl;
  306. // ret = true;
  307. // }else
  308. // {
  309. // if(!this->overlaps(that))
  310. // {
  311. // assert(!that.overlaps(*this));
  312. // cout<<" THIS does not overlap THAT"<<endl;
  313. // // No overlap use barycenter
  314. // return
  315. // 1./3.*(this->c[0](2) + this->c[1](2) + this->c[2](2)) >
  316. // 1./3.*(that.c[0](2) + that.c[1](2) + that.c[2](2));
  317. // }else
  318. // {
  319. // if(this->is_coplanar(that) || that.is_coplanar(*this))
  320. // {
  321. // cout<<" coplanar"<<endl;
  322. // // co-planar: decide based on barycenter depth
  323. // ret =
  324. // 1./3.*(this->c[0](2) + this->c[1](2) + this->c[2](2)) >
  325. // 1./3.*(that.c[0](2) + that.c[1](2) + that.c[2](2));
  326. // }else if(this->is_behind_plane(that))
  327. // {
  328. // cout<<" THIS behind plane of THAT"<<endl;
  329. // ret = true;
  330. // }else if(that.is_behind_plane(*this))
  331. // {
  332. // cout<<" THAT behind of plane of THIS"<<endl;
  333. // ret = false;
  334. // // THAT is in front of plane of THIS
  335. // }else if(that.is_in_front_of_plane(*this))
  336. // {
  337. // cout<<" THAT in front of plane of THIS"<<endl;
  338. // ret = true;
  339. // // THIS is in front of plane of THAT
  340. // }else if(this->is_in_front_of_plane(that))
  341. // {
  342. // cout<<" THIS in front plane of THAT"<<endl;
  343. // ret = false;
  344. // }else
  345. // {
  346. // cout<<" compare bary"<<endl;
  347. // ret =
  348. // 1./3.*(this->c[0](2) + this->c[1](2) + this->c[2](2)) >
  349. // 1./3.*(that.c[0](2) + that.c[1](2) + that.c[2](2));
  350. // }
  351. // }
  352. // }
  353. // if(ret)
  354. // {
  355. // // THIS < THAT so better not be THAT < THIS
  356. // cout<<this->id<<" < "<<that.id<<endl;
  357. // assert(!(that < *this));
  358. // }else
  359. // {
  360. // // THIS >= THAT so could be THAT < THIS or THAT == THIS
  361. // }
  362. // return ret;
  363. // }
  364. //};
  365. //#include <igl/matlab/MatlabWorkspace.h>
  366. //
  367. //template <
  368. // typename DerivedV,
  369. // typename DerivedF,
  370. // typename DerivedMV,
  371. // typename DerivedP,
  372. // typename DerivedFF,
  373. // typename DerivedI>
  374. //IGL_INLINE void igl::sort_triangles_robust(
  375. // const Eigen::PlainObjectBase<DerivedV> & V,
  376. // const Eigen::PlainObjectBase<DerivedF> & F,
  377. // const Eigen::PlainObjectBase<DerivedMV> & MV,
  378. // const Eigen::PlainObjectBase<DerivedP> & P,
  379. // Eigen::PlainObjectBase<DerivedFF> & FF,
  380. // Eigen::PlainObjectBase<DerivedI> & I)
  381. //{
  382. // assert(false &&
  383. // "THIS WILL NEVER WORK because depth sorting is not a numerical sort where"
  384. // "pairwise comparisons of triangles are transitive. Rather it is a"
  385. // "topological sort on a dependecy graph. Dependency encodes 'This triangle"
  386. // "must be drawn before that one'");
  387. // using namespace std;
  388. // using namespace Eigen;
  389. // typedef Matrix<typename DerivedV::Scalar,3,1> Vec3;
  390. // assert(V.cols() == 4);
  391. // Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime,3> VMVP =
  392. // V*(MV.transpose()*P.transpose().eval().block(0,0,4,3));
  393. //
  394. // MatrixXd projV(V.rows(),3);
  395. // for(int v = 0;v<V.rows();v++)
  396. // {
  397. // Vector3d vv;
  398. // vv(0) = V(v,0);
  399. // vv(1) = V(v,1);
  400. // vv(2) = V(v,2);
  401. // Vector3d p;
  402. // project(vv,p);
  403. // projV.row(v) = p;
  404. // }
  405. //
  406. // vector<Triangle<Vec3> > vF(F.rows());
  407. // MatrixXd N(F.rows(),3);
  408. // MatrixXd C(F.rows()*3,3);
  409. // for(int f = 0;f<F.rows();f++)
  410. // {
  411. // vF[f] =
  412. // //Triangle<Vec3>(f,VMVP.row(F(f,0)),VMVP.row(F(f,1)),VMVP.row(F(f,2)));
  413. // Triangle<Vec3>(f,projV.row(F(f,0)),projV.row(F(f,1)),projV.row(F(f,2)));
  414. // N.row(f) = vF[f].n;
  415. // for(int c = 0;c<3;c++)
  416. // for(int d = 0;d<3;d++)
  417. // C(f*3+c,d) = vF[f].c[c](d);
  418. // }
  419. // MatlabWorkspace mw;
  420. // mw.save_index(F,"F");
  421. // mw.save(V,"V");
  422. // mw.save(MV,"MV");
  423. // mw.save(P,"P");
  424. // Vector4i VP;
  425. // glGetIntegerv(GL_VIEWPORT, VP.data());
  426. // mw.save(projV,"projV");
  427. // mw.save(VP,"VP");
  428. // mw.save(VMVP,"VMVP");
  429. // mw.save(N,"N");
  430. // mw.save(C,"C");
  431. // mw.write("ao.mat");
  432. // sort(vF.begin(),vF.end());
  433. //
  434. // // check
  435. // for(int f = 0;f<F.rows();f++)
  436. // {
  437. // for(int g = f+1;g<F.rows();g++)
  438. // {
  439. // assert(!(vF[g] < vF[f])); // should never happen
  440. // }
  441. // }
  442. // FF.resize(F.rows(),3);
  443. // I.resize(F.rows(),1);
  444. // for(int f = 0;f<F.rows();f++)
  445. // {
  446. // FF.row(f) = F.row(vF[f].id);
  447. // I(f) = vF[f].id;
  448. // }
  449. //
  450. // mw.save_index(FF,"FF");
  451. // mw.save_index(I,"I");
  452. // mw.write("ao.mat");
  453. //}
  454. //template <
  455. // typename DerivedV,
  456. // typename DerivedF,
  457. // typename DerivedFF,
  458. // typename DerivedI>
  459. //IGL_INLINE void igl::sort_triangles_robust(
  460. // const Eigen::PlainObjectBase<DerivedV> & V,
  461. // const Eigen::PlainObjectBase<DerivedF> & F,
  462. // Eigen::PlainObjectBase<DerivedFF> & FF,
  463. // Eigen::PlainObjectBase<DerivedI> & I)
  464. //{
  465. // using namespace Eigen;
  466. // using namespace std;
  467. // // Put model, projection, and viewport matrices into double arrays
  468. // Matrix4d MV;
  469. // Matrix4d P;
  470. // glGetDoublev(GL_MODELVIEW_MATRIX, MV.data());
  471. // glGetDoublev(GL_PROJECTION_MATRIX, P.data());
  472. // if(V.cols() == 3)
  473. // {
  474. // Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime,4> hV;
  475. // hV.resize(V.rows(),4);
  476. // hV.block(0,0,V.rows(),V.cols()) = V;
  477. // hV.col(3).setConstant(1);
  478. // return sort_triangles_robust(hV,F,MV,P,FF,I);
  479. // }else
  480. // {
  481. // return sort_triangles_robust(V,F,MV,P,FF,I);
  482. // }
  483. //}
  484. #ifdef IGL_STATIC_LIBRARY
  485. // Explicit template specialization
  486. template void igl::sort_triangles<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  487. template void igl::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  488. #endif