1 // This file is part of libigl, a simple c++ geometry processing library.
2 //
3 // Copyright (C) 2015 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_angles.h"
9 #include "LinSpaced.h"
10 #include <algorithm>
11 
12 template <typename DerivedM, typename DerivedR>
sort_angles(const Eigen::PlainObjectBase<DerivedM> & M,Eigen::PlainObjectBase<DerivedR> & R)13 IGL_INLINE void igl::sort_angles(
14         const Eigen::PlainObjectBase<DerivedM>& M,
15         Eigen::PlainObjectBase<DerivedR>& R) {
16     const size_t num_rows = M.rows();
17     const size_t num_cols = M.cols();
18     assert(num_cols >= 2);
19 
20     R.resize(num_rows);
21     // Have to use << instead of = because Eigen's PlainObjectBase is annoying
22     R << igl::LinSpaced<
23       Eigen::Matrix<typename DerivedR::Scalar, Eigen::Dynamic, 1> >
24       (num_rows, 0, num_rows-1);
25 
26     //              |
27     // (pi/2, pi)   | (0, pi/2)
28     //              |
29     // -------------+--------------
30     //              |
31     // (-pi, -pi/2) | (-pi/2, 0)
32     //              |
33     auto comp = [&](size_t i, size_t j) {
34         auto yi = M(i, 0);
35         auto xi = M(i, 1);
36         auto yj = M(j, 0);
37         auto xj = M(j, 1);
38 
39         if (xi == xj && yi == yj) {
40             for (size_t idx=2; idx<num_cols; idx++) {
41                 auto i_val = M(i, idx);
42                 auto j_val = M(j, idx);
43                 if (i_val != j_val) {
44                     return i_val < j_val;
45                 }
46             }
47             // If the entire rows are equal, use the row index.
48             return i < j;
49         }
50 
51         if (xi >= 0 && yi >= 0) {
52             if (xj >=0 && yj >= 0) {
53                 if (xi != xj) {
54                     return xi > xj;
55                 } else {
56                     return yi < yj;
57                 }
58             } else if (xj < 0 && yj >= 0) {
59                 return true;
60             } else if (xj < 0 && yj < 0) {
61                 return false;
62             } else {
63                 return false;
64             }
65         } else if (xi < 0 && yi >= 0) {
66             if (xj >= 0 && yj >= 0) {
67                 return false;
68             } else if (xj < 0 && yj >= 0) {
69                 if (xi != xj) {
70                     return xi > xj;
71                 } else {
72                     return yi > yj;
73                 }
74             } else if (xj < 0 && yj < 0) {
75                 return false;
76             } else {
77                 return false;
78             }
79         } else if (xi < 0 && yi < 0) {
80             if (xj >= 0 && yj >= 0) {
81                 return true;
82             } else if (xj < 0 && yj >= 0) {
83                 return true;
84             } else if (xj < 0 && yj < 0) {
85                 if (xi != xj) {
86                     return xi < xj;
87                 } else {
88                     return yi > yj;
89                 }
90             } else {
91                 return true;
92             }
93         } else {
94             if (xj >= 0 && yj >= 0) {
95                 return true;
96             } else if (xj < 0 && yj >= 0) {
97                 return true;
98             } else if (xj < 0 && yj < 0) {
99                 return false;
100             } else {
101                 if (xi != xj) {
102                     return xi < xj;
103                 } else {
104                     return yi < yj;
105                 }
106             }
107         }
108     };
109     std::sort(R.data(), R.data() + num_rows, comp);
110 }
111 
112 #ifdef IGL_STATIC_LIBRARY
113 template void igl::sort_angles<Eigen::Matrix<double, -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> >&);
114 #endif
115