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