Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
igl::copyleft::comiso::NRosyField Class Reference
+ Collaboration diagram for igl::copyleft::comiso::NRosyField:

Public Member Functions

IGL_INLINE NRosyField (const Eigen::MatrixXd &_V, const Eigen::MatrixXi &_F)
 
IGL_INLINE void solve (const int N=4)
 
IGL_INLINE void setConstraintHard (const int fid, const Eigen::Vector3d &v)
 
IGL_INLINE void setConstraintSoft (const int fid, const double w, const Eigen::Vector3d &v)
 
IGL_INLINE void setSoftAlpha (double alpha)
 
IGL_INLINE void resetConstraints ()
 
IGL_INLINE Eigen::MatrixXd getFieldPerFace ()
 
IGL_INLINE Eigen::MatrixXd getFFieldPerFace ()
 
IGL_INLINE void findCones (int N)
 
IGL_INLINE Eigen::VectorXd getSingularityIndexPerVertex ()
 

Private Member Functions

IGL_INLINE void computek ()
 
IGL_INLINE void reduceSpace ()
 
IGL_INLINE void prepareSystemMatrix (const int N)
 
IGL_INLINE void solveNoRoundings ()
 
IGL_INLINE void solveRoundings ()
 
IGL_INLINE void roundAndFixToZero ()
 
IGL_INLINE void roundAndFix ()
 
IGL_INLINE double convert3DtoLocal (unsigned fid, const Eigen::Vector3d &v)
 
IGL_INLINE Eigen::Vector3d convertLocalto3D (unsigned fid, double a)
 
IGL_INLINE Eigen::VectorXd angleDefect ()
 

Private Attributes

Eigen::VectorXd angles
 
Eigen::VectorXd hard
 
std::vector< bool > isHard
 
Eigen::VectorXd soft
 
Eigen::VectorXd wSoft
 
double softAlpha
 
Eigen::MatrixXi TT
 
Eigen::MatrixXi TTi
 
Eigen::MatrixXi EV
 
Eigen::MatrixXi FE
 
Eigen::MatrixXi EF
 
std::vector< bool > isBorderEdge
 
Eigen::VectorXd k
 
Eigen::VectorXi p
 
std::vector< bool > pFixed
 
Eigen::MatrixXd V
 
Eigen::MatrixXi F
 
Eigen::MatrixXd N
 
Eigen::VectorXd singularityIndex
 
std::vector< Eigen::MatrixXd > TPs
 
Eigen::SparseMatrix< double > A
 
Eigen::VectorXd b
 
Eigen::VectorXi tag_t
 
Eigen::VectorXi tag_p
 

Detailed Description

Constructor & Destructor Documentation

◆ NRosyField()

igl::copyleft::comiso::NRosyField::NRosyField ( const Eigen::MatrixXd &  _V,
const Eigen::MatrixXi &  _F 
)
160{
161 using namespace std;
162 using namespace Eigen;
163
164 V = _V;
165 F = _F;
166
167 assert(V.rows() > 0);
168 assert(F.rows() > 0);
169
170
171 // Generate topological relations
174
175 // Flag border edges
176 isBorderEdge.resize(EV.rows());
177 for(unsigned i=0; i<EV.rows(); ++i)
178 isBorderEdge[i] = (EF(i,0) == -1) || ((EF(i,1) == -1));
179
180 // Generate normals per face
182
183 // Generate reference frames
184 for(unsigned fid=0; fid<F.rows(); ++fid)
185 {
186 // First edge
187 Vector3d e1 = V.row(F(fid,1)) - V.row(F(fid,0));
188 e1.normalize();
189 Vector3d e2 = N.row(fid);
190 e2 = e2.cross(e1);
191 e2.normalize();
192
193 MatrixXd TP(2,3);
194 TP << e1.transpose(), e2.transpose();
195 TPs.push_back(TP);
196 }
197
198 // Alloc internal variables
199 angles = VectorXd::Zero(F.rows());
200 p = VectorXi::Zero(EV.rows());
201 pFixed.resize(EV.rows());
202 k = VectorXd::Zero(EV.rows());
203 singularityIndex = VectorXd::Zero(V.rows());
204
205 // Reset the constraints
207
208 // Compute k, differences between reference frames
209 computek();
210
211 softAlpha = 0.5;
212}
std::vector< bool > isBorderEdge
Definition nrosy.cpp:124
IGL_INLINE void computek()
Definition nrosy.cpp:579
IGL_INLINE void resetConstraints()
Definition nrosy.cpp:533
Eigen::MatrixXi FE
Definition nrosy.cpp:123
Eigen::VectorXd angles
Definition nrosy.cpp:108
Eigen::MatrixXd V
Definition nrosy.cpp:135
Eigen::MatrixXi EF
Definition nrosy.cpp:123
Eigen::MatrixXi TTi
Definition nrosy.cpp:120
double softAlpha
Definition nrosy.cpp:117
Eigen::MatrixXi F
Definition nrosy.cpp:136
Eigen::VectorXi p
Definition nrosy.cpp:131
std::vector< Eigen::MatrixXd > TPs
Definition nrosy.cpp:145
Eigen::VectorXd singularityIndex
Definition nrosy.cpp:142
Eigen::MatrixXi TT
Definition nrosy.cpp:120
Eigen::MatrixXi EV
Definition nrosy.cpp:123
std::vector< bool > pFixed
Definition nrosy.cpp:132
Eigen::VectorXd k
Definition nrosy.cpp:128
Eigen::MatrixXd N
Definition nrosy.cpp:139
Definition LDLT.h:16
IGL_INLINE void edge_topology(const Eigen::PlainObjectBase< DerivedV > &V, const Eigen::PlainObjectBase< DerivedF > &F, Eigen::MatrixXi &EV, Eigen::MatrixXi &FE, Eigen::MatrixXi &EF)
Definition edge_topology.cpp:13
IGL_INLINE void per_face_normals(const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Eigen::MatrixBase< DerivedZ > &Z, Eigen::PlainObjectBase< DerivedN > &N)
Definition per_face_normals.cpp:13
IGL_INLINE void triangle_triangle_adjacency(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedTT > &TT, Eigen::PlainObjectBase< DerivedTTi > &TTi)
Definition triangle_triangle_adjacency.cpp:116
STL namespace.

References angles, computek(), igl::edge_topology(), EF, EV, F, FE, isBorderEdge, k, N, p, igl::per_face_normals(), pFixed, resetConstraints(), singularityIndex, softAlpha, TPs, igl::triangle_triangle_adjacency(), TT, TTi, and V.

+ Here is the call graph for this function:

Member Function Documentation

◆ angleDefect()

Eigen::VectorXd igl::copyleft::comiso::NRosyField::angleDefect ( )
private
797{
798 Eigen::VectorXd A = Eigen::VectorXd::Constant(V.rows(),-2*igl::PI);
799
800 for (unsigned i=0; i < F.rows(); ++i)
801 {
802 for (int j = 0; j < 3; ++j)
803 {
804 Eigen::VectorXd a = V.row(F(i,(j+1)%3)) - V.row(F(i,j));
805 Eigen::VectorXd b = V.row(F(i,(j+2)%3)) - V.row(F(i,j));
806 double t = a.transpose()*b;
807 t /= (a.norm() * b.norm());
808 A(F(i,j)) += acos(t);
809 }
810 }
811
812 return A;
813}
EIGEN_DEVICE_FUNC const AcosReturnType acos() const
Definition ArrayCwiseUnaryOps.h:262
Eigen::VectorXd b
Definition nrosy.cpp:149
Eigen::SparseMatrix< double > A
Definition nrosy.cpp:148
const double PI
Definition PI.h:16

References acos(), and igl::PI.

+ Here is the call graph for this function:

◆ computek()

void igl::copyleft::comiso::NRosyField::computek ( )
private
580{
581 using namespace std;
582 using namespace Eigen;
583
584 // For every non-border edge
585 for (unsigned eid=0; eid<EF.rows(); ++eid)
586 {
587 if (!isBorderEdge[eid])
588 {
589 int fid0 = EF(eid,0);
590 int fid1 = EF(eid,1);
591
592 Vector3d N0 = N.row(fid0);
593 Vector3d N1 = N.row(fid1);
594
595 // find common edge on triangle 0 and 1
596 int fid0_vc = -1;
597 int fid1_vc = -1;
598 for (unsigned i=0;i<3;++i)
599 {
600 if (EV(eid,0) == F(fid0,i))
601 fid0_vc = i;
602 if (EV(eid,1) == F(fid1,i))
603 fid1_vc = i;
604 }
605 assert(fid0_vc != -1);
606 assert(fid1_vc != -1);
607
608 Vector3d common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
609 common_edge.normalize();
610
611 // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
612 MatrixXd P(3,3);
613 VectorXd o = V.row(F(fid0,fid0_vc));
614 VectorXd tmp = -N0.cross(common_edge);
615 P << common_edge, tmp, N0;
616 P.transposeInPlace();
617
618
619 MatrixXd V0(3,3);
620 V0.row(0) = V.row(F(fid0,0)).transpose() -o;
621 V0.row(1) = V.row(F(fid0,1)).transpose() -o;
622 V0.row(2) = V.row(F(fid0,2)).transpose() -o;
623
624 V0 = (P*V0.transpose()).transpose();
625
626 assert(V0(0,2) < 10e-10);
627 assert(V0(1,2) < 10e-10);
628 assert(V0(2,2) < 10e-10);
629
630 MatrixXd V1(3,3);
631 V1.row(0) = V.row(F(fid1,0)).transpose() -o;
632 V1.row(1) = V.row(F(fid1,1)).transpose() -o;
633 V1.row(2) = V.row(F(fid1,2)).transpose() -o;
634 V1 = (P*V1.transpose()).transpose();
635
636 assert(V1(fid1_vc,2) < 10e-10);
637 assert(V1((fid1_vc+1)%3,2) < 10e-10);
638
639 // compute rotation R such that R * N1 = N0
640 // i.e. map both triangles to the same plane
641 double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
642
643 MatrixXd R(3,3);
644 R << 1, 0, 0,
645 0, cos(alpha), -sin(alpha) ,
646 0, sin(alpha), cos(alpha);
647 V1 = (R*V1.transpose()).transpose();
648
649 assert(V1(0,2) < 10e-10);
650 assert(V1(1,2) < 10e-10);
651 assert(V1(2,2) < 10e-10);
652
653 // measure the angle between the reference frames
654 // k_ij is the angle between the triangle on the left and the one on the right
655 VectorXd ref0 = V0.row(1) - V0.row(0);
656 VectorXd ref1 = V1.row(1) - V1.row(0);
657
658 ref0.normalize();
659 ref1.normalize();
660
661 double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
662
663 // just to be sure, rotate ref0 using angle ktemp...
664 MatrixXd R2(2,2);
665 R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
666
667 tmp = R2*ref0.head<2>();
668
669 assert(tmp(0) - ref1(0) < 10^10);
670 assert(tmp(1) - ref1(1) < 10^10);
671
672 k[eid] = ktemp;
673 }
674 }
675
676}
EIGEN_DEVICE_FUNC const CosReturnType cos() const
Definition ArrayCwiseUnaryOps.h:202
EIGEN_DEVICE_FUNC const SinReturnType sin() const
Definition ArrayCwiseUnaryOps.h:220

References cos(), and sin().

Referenced by NRosyField().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ convert3DtoLocal()

double igl::copyleft::comiso::NRosyField::convert3DtoLocal ( unsigned  fid,
const Eigen::Vector3d &  v 
)
private
776{
777 using namespace std;
778 using namespace Eigen;
779
780 // Project onto the tangent plane
781 Vector2d vp = TPs[fid] * v;
782
783 // Convert to angle
784 return atan2(vp(1),vp(0));
785}

◆ convertLocalto3D()

Eigen::Vector3d igl::copyleft::comiso::NRosyField::convertLocalto3D ( unsigned  fid,
double  a 
)
private
788{
789 using namespace std;
790 using namespace Eigen;
791
792 Vector2d vp(cos(a),sin(a));
793 return vp.transpose() * TPs[fid];
794}

References cos(), and sin().

+ Here is the call graph for this function:

◆ findCones()

void igl::copyleft::comiso::NRosyField::findCones ( int  N)
816{
817 // Compute I0, see http://www.graphics.rwth-aachen.de/media/papers/bommes_zimmer_2009_siggraph_011.pdf for details
818
819 Eigen::VectorXd I0 = Eigen::VectorXd::Zero(V.rows());
820
821 // first the k
822 for (unsigned i=0; i < EV.rows(); ++i)
823 {
824 if (!isBorderEdge[i])
825 {
826 I0(EV(i,0)) -= k(i);
827 I0(EV(i,1)) += k(i);
828 }
829 }
830
831 // then the A
832 Eigen::VectorXd A = angleDefect();
833
834 I0 = I0 + A;
835
836 // normalize
837 I0 = I0 / (2*igl::PI);
838
839 // round to integer (remove numerical noise)
840 for (unsigned i=0; i < I0.size(); ++i)
841 I0(i) = round(I0(i));
842
843 // compute I
844 Eigen::VectorXd I = I0;
845
846 for (unsigned i=0; i < EV.rows(); ++i)
847 {
848 if (!isBorderEdge[i])
849 {
850 I(EV(i,0)) -= double(p(i))/double(N);
851 I(EV(i,1)) += double(p(i))/double(N);
852 }
853 }
854
855 // Clear the vertices on the edges
856 for (unsigned i=0; i < EV.rows(); ++i)
857 {
858 if (isBorderEdge[i])
859 {
860 I0(EV(i,0)) = 0;
861 I0(EV(i,1)) = 0;
862 I(EV(i,0)) = 0;
863 I(EV(i,1)) = 0;
864 A(EV(i,0)) = 0;
865 A(EV(i,1)) = 0;
866 }
867 }
868
870}
EIGEN_DEVICE_FUNC const RoundReturnType round() const
Definition ArrayCwiseUnaryOps.h:374
IGL_INLINE Eigen::VectorXd angleDefect()
Definition nrosy.cpp:796

References igl::PI, and round().

+ Here is the call graph for this function:

◆ getFFieldPerFace()

Eigen::MatrixXd igl::copyleft::comiso::NRosyField::getFFieldPerFace ( )
559{
560 using namespace std;
561 using namespace Eigen;
562
563 MatrixXd result(F.rows(),6);
564 for(unsigned i=0; i<F.rows(); ++i)
565 {
566 Vector3d v1 = convertLocalto3D(i, angles(i));
567 Vector3d n = N.row(i);
568 Vector3d v2 = n.cross(v1);
569 v1.normalize();
570 v2.normalize();
571
572 result.block(i,0,1,3) = v1.transpose();
573 result.block(i,3,1,3) = v2.transpose();
574 }
575 return result;
576}
IGL_INLINE Eigen::Vector3d convertLocalto3D(unsigned fid, double a)
Definition nrosy.cpp:787

◆ getFieldPerFace()

Eigen::MatrixXd igl::copyleft::comiso::NRosyField::getFieldPerFace ( )
548{
549 using namespace std;
550 using namespace Eigen;
551
552 MatrixXd result(F.rows(),3);
553 for(unsigned i=0; i<F.rows(); ++i)
554 result.row(i) = convertLocalto3D(i, angles(i));
555 return result;
556}

Referenced by igl::copyleft::comiso::nrosy(), and igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ getSingularityIndexPerVertex()

Eigen::VectorXd igl::copyleft::comiso::NRosyField::getSingularityIndexPerVertex ( )
873{
874 return singularityIndex;
875}

Referenced by igl::copyleft::comiso::nrosy(), and igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ prepareSystemMatrix()

void igl::copyleft::comiso::NRosyField::prepareSystemMatrix ( const int  N)
private
222{
223 using namespace std;
224 using namespace Eigen;
225
226 double Nd = N;
227
228 // Minimize the MIQ energy
229 // Energy on edge ij is
230 // (t_i - t_j + kij + pij*(2*pi/N))^2
231 // Partial derivatives:
232 // t_i: 2 ( t_i - t_j + kij + pij*(2*pi/N)) = 0
233 // t_j: 2 (-t_i + t_j - kij - pij*(2*pi/N)) = 0
234 // pij: 4pi/N ( t_i - t_j + kij + pij*(2*pi/N)) = 0
235 //
236 // t_i t_j pij kij
237 // t_i [ 2 -2 4pi/N 2 ]
238 // t_j [ -2 2 -4pi/N -2 ]
239 // pij [ 4pi/N -4pi/N 2*(2pi/N)^2 4pi/N ]
240
241 // Count and tag the variables
242 tag_t = VectorXi::Constant(F.rows(),-1);
243 vector<int> id_t;
244 int count = 0;
245 for(unsigned i=0; i<F.rows(); ++i)
246 if (!isHard[i])
247 {
248 tag_t(i) = count++;
249 id_t.push_back(i);
250 }
251
252 unsigned count_t = id_t.size();
253
254 tag_p = VectorXi::Constant(EF.rows(),-1);
255 vector<int> id_p;
256 for(unsigned i=0; i<EF.rows(); ++i)
257 {
258 if (!pFixed[i])
259 {
260 // if it is not fixed then it is a variable
261 tag_p(i) = count++;
262 }
263
264 // if it is not a border edge,
265 if (!isBorderEdge[i])
266 {
267 // and it is not between two fixed faces
268 if (!(isHard[EF(i,0)] && isHard[EF(i,1)]))
269 {
270 // then it participates in the energy!
271 id_p.push_back(i);
272 }
273 }
274 }
275
276 unsigned count_p = count - count_t;
277 // System sizes: A (count_t + count_p) x (count_t + count_p)
278 // b (count_t + count_p)
279
280 b = VectorXd::Zero(count_t + count_p);
281
282 std::vector<Eigen::Triplet<double> > T;
283 T.reserve(3 * 4 * count_p);
284
285 for(unsigned r=0; r<id_p.size(); ++r)
286 {
287 int eid = id_p[r];
288 int i = EF(eid,0);
289 int j = EF(eid,1);
290 bool isFixed_i = isHard[i];
291 bool isFixed_j = isHard[j];
292 bool isFixed_p = pFixed[eid];
293 int row;
294 // (i)-th row: t_i [ 2 -2 4pi/N 2 ]
295 if (!isFixed_i)
296 {
297 row = tag_t[i];
298 if (isFixed_i) b(row) += -2 * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i] , 2 ));
299 if (isFixed_j) b(row) += 2 * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j] ,-2 ));
300 if (isFixed_p) b(row) += -((4 * igl::PI)/Nd) * p[eid] ; else T.push_back(Eigen::Triplet<double>(row,tag_p[eid],((4 * igl::PI)/Nd)));
301 b(row) += -2 * k[eid];
302 assert(hard[i] == hard[i]);
303 assert(hard[j] == hard[j]);
304 assert(p[eid] == p[eid]);
305 assert(k[eid] == k[eid]);
306 assert(b(row) == b(row));
307 }
308 // (j)+1 -th row: t_j [ -2 2 -4pi/N -2 ]
309 if (!isFixed_j)
310 {
311 row = tag_t[j];
312 if (isFixed_i) b(row) += 2 * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i] , -2 ));
313 if (isFixed_j) b(row) += -2 * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j] , 2 ));
314 if (isFixed_p) b(row) += ((4 * igl::PI)/Nd) * p[eid] ; else T.push_back(Eigen::Triplet<double>(row,tag_p[eid],-((4 * igl::PI)/Nd)));
315 b(row) += 2 * k[eid];
316 assert(k[eid] == k[eid]);
317 assert(b(row) == b(row));
318 }
319 // (r*3)+2 -th row: pij [ 4pi/N -4pi/N 2*(2pi/N)^2 4pi/N ]
320 if (!isFixed_p)
321 {
322 row = tag_p[eid];
323 if (isFixed_i) b(row) += -(4 * igl::PI)/Nd * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i] , (4 * igl::PI)/Nd ));
324 if (isFixed_j) b(row) += (4 * igl::PI)/Nd * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j] , -(4 * igl::PI)/Nd ));
325 if (isFixed_p) b(row) += -(2 * pow(((2*igl::PI)/Nd),2)) * p[eid] ; else T.push_back(Eigen::Triplet<double>(row,tag_p[eid], (2 * pow(((2*igl::PI)/Nd),2))));
326 b(row) += - (4 * igl::PI)/Nd * k[eid];
327 assert(k[eid] == k[eid]);
328 assert(b(row) == b(row));
329 }
330
331 }
332
333 A = SparseMatrix<double>(count_t + count_p, count_t + count_p);
334 A.setFromTriplets(T.begin(), T.end());
335
336 // Soft constraints
337 bool addSoft = false;
338
339 for(unsigned i=0; i<wSoft.size();++i)
340 if (wSoft[i] != 0)
341 addSoft = true;
342
343 if (addSoft)
344 {
345 cerr << " Adding soft here: " << endl;
346 cerr << " softAplha: " << softAlpha << endl;
347 VectorXd bSoft = VectorXd::Zero(count_t + count_p);
348
349 std::vector<Eigen::Triplet<double> > TSoft;
350 TSoft.reserve(2 * count_p);
351
352 for(unsigned i=0; i<F.rows(); ++i)
353 {
354 int varid = tag_t[i];
355 if (varid != -1) // if it is a variable in the system
356 {
357 TSoft.push_back(Eigen::Triplet<double>(varid,varid,wSoft[i]));
358 bSoft[varid] += wSoft[i] * soft[i];
359 }
360 }
361 SparseMatrix<double> ASoft(count_t + count_p, count_t + count_p);
362 ASoft.setFromTriplets(TSoft.begin(), TSoft.end());
363
364// ofstream s("/Users/daniele/As.txt");
365// for(unsigned i=0; i<TSoft.size(); ++i)
366// s << TSoft[i].row() << " " << TSoft[i].col() << " " << TSoft[i].value() << endl;
367// s.close();
368
369// ofstream s2("/Users/daniele/bs.txt");
370// for(unsigned i=0; i<bSoft.rows(); ++i)
371// s2 << bSoft(i) << endl;
372// s2.close();
373
374 // Stupid Eigen bug
375 SparseMatrix<double> Atmp (count_t + count_p, count_t + count_p);
376 SparseMatrix<double> Atmp2(count_t + count_p, count_t + count_p);
377 SparseMatrix<double> Atmp3(count_t + count_p, count_t + count_p);
378
379 // Merge the two part of the energy
380 Atmp = (1.0 - softAlpha)*A;
381 Atmp2 = softAlpha * ASoft;
382 Atmp3 = Atmp+Atmp2;
383
384 A = Atmp3;
385 b = b*(1.0 - softAlpha) + bSoft * softAlpha;
386 }
387
388// ofstream s("/Users/daniele/A.txt");
389// for (int k=0; k<A.outerSize(); ++k)
390// for (SparseMatrix<double>::InnerIterator it(A,k); it; ++it)
391// {
392// s << it.row() << " " << it.col() << " " << it.value() << endl;
393// }
394// s.close();
395//
396// ofstream s2("/Users/daniele/b.txt");
397// for(unsigned i=0; i<b.rows(); ++i)
398// s2 << b(i) << endl;
399// s2.close();
400}
EIGEN_DEVICE_FUNC RowXpr row(Index i)
This is the const version of row(). *‍/.
Definition BlockMethods.h:859
A versatible sparse matrix representation.
Definition SparseMatrix.h:98
void setFromTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:993
A small structure to hold a non zero as a triplet (i,j,value).
Definition SparseUtil.h:155
Eigen::VectorXd wSoft
Definition nrosy.cpp:116
Eigen::VectorXi tag_p
Definition nrosy.cpp:151
Eigen::VectorXd hard
Definition nrosy.cpp:111
std::vector< bool > isHard
Definition nrosy.cpp:112
Eigen::VectorXi tag_t
Definition nrosy.cpp:150
Eigen::VectorXd soft
Definition nrosy.cpp:115
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC half pow(const half &a, const half &b)
Definition Half.h:477
IGL_INLINE void count(const Eigen::SparseMatrix< XType > &X, const int dim, Eigen::SparseVector< SType > &S)
Definition count.cpp:12

References igl::count(), igl::PI, row(), and Eigen::SparseMatrix< _Scalar, _Options, _StorageIndex >::setFromTriplets().

+ Here is the call graph for this function:

◆ reduceSpace()

void igl::copyleft::comiso::NRosyField::reduceSpace ( )
private
679{
680 using namespace std;
681 using namespace Eigen;
682
683 // All variables are free in the beginning
684 for(unsigned i=0; i<EV.rows(); ++i)
685 pFixed[i] = false;
686
687 vector<VectorXd> debug;
688
689 // debug
690// MatrixXd B(F.rows(),3);
691// for(unsigned i=0; i<F.rows(); ++i)
692// B.row(i) = 1./3. * (V.row(F(i,0)) + V.row(F(i,1)) + V.row(F(i,2)));
693
694 vector<bool> visited(EV.rows());
695 for(unsigned i=0; i<EV.rows(); ++i)
696 visited[i] = false;
697
698 vector<bool> starting(EV.rows());
699 for(unsigned i=0; i<EV.rows(); ++i)
700 starting[i] = false;
701
702 queue<int> q;
703 for(unsigned i=0; i<F.rows(); ++i)
704 if (isHard[i] || wSoft[i] != 0)
705 {
706 q.push(i);
707 starting[i] = true;
708 }
709
710 // Reduce the search space (see MI paper)
711 while (!q.empty())
712 {
713 int c = q.front();
714 q.pop();
715
716 visited[c] = true;
717 for(int i=0; i<3; ++i)
718 {
719 int eid = FE(c,i);
720 int fid = TT(c,i);
721
722 // skip borders
723 if (fid != -1)
724 {
725 assert((EF(eid,0) == c && EF(eid,1) == fid) || (EF(eid,1) == c && EF(eid,0) == fid));
726 // for every neighbouring face
727 if (!visited[fid] && !starting[fid])
728 {
729 pFixed[eid] = true;
730 p[eid] = 0;
731 visited[fid] = true;
732 q.push(fid);
733
734 }
735 }
736 else
737 {
738 // fix borders
739 pFixed[eid] = true;
740 p[eid] = 0;
741 }
742 }
743
744 }
745
746 // Force matchings between fixed faces
747 for(unsigned i=0; i<F.rows();++i)
748 {
749 if (isHard[i])
750 {
751 for(unsigned int j=0; j<3; ++j)
752 {
753 int fid = TT(i,j);
754 if ((fid!=-1) && (isHard[fid]))
755 {
756 // i and fid are adjacent and fixed
757 int eid = FE(i,j);
758 int fid0 = EF(eid,0);
759 int fid1 = EF(eid,1);
760
761 pFixed[eid] = true;
762 p[eid] = roundl(2.0/igl::PI*(hard(fid1) - hard(fid0) - k(eid)));
763 }
764 }
765 }
766 }
767
768// std::ofstream s("/Users/daniele/debug.txt");
769// for(unsigned i=0; i<debug.size(); i += 2)
770// s << debug[i].transpose() << " " << debug[i+1].transpose() << endl;
771// s.close();
772
773}

References igl::PI.

◆ resetConstraints()

void igl::copyleft::comiso::NRosyField::resetConstraints ( )
534{
535 using namespace std;
536 using namespace Eigen;
537
538 isHard.resize(F.rows());
539 for(unsigned i=0; i<F.rows(); ++i)
540 isHard[i] = false;
541 hard = VectorXd::Zero(F.rows());
542
543 wSoft = VectorXd::Zero(F.rows());
544 soft = VectorXd::Zero(F.rows());
545}

Referenced by NRosyField().

+ Here is the caller graph for this function:

◆ roundAndFix()

void igl::copyleft::comiso::NRosyField::roundAndFix ( )
private
479{
480 for(unsigned i=0; i<p.rows(); ++i)
481 pFixed[i] = true;
482}

◆ roundAndFixToZero()

void igl::copyleft::comiso::NRosyField::roundAndFixToZero ( )
private
485{
486 for(unsigned i=0; i<p.rows(); ++i)
487 {
488 pFixed[i] = true;
489 p[i] = 0;
490 }
491}

◆ setConstraintHard()

void igl::copyleft::comiso::NRosyField::setConstraintHard ( const int  fid,
const Eigen::Vector3d &  v 
)
522{
523 isHard[fid] = true;
524 hard(fid) = convert3DtoLocal(fid, v);
525}
IGL_INLINE double convert3DtoLocal(unsigned fid, const Eigen::Vector3d &v)
Definition nrosy.cpp:775

Referenced by igl::copyleft::comiso::nrosy(), and igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ setConstraintSoft()

void igl::copyleft::comiso::NRosyField::setConstraintSoft ( const int  fid,
const double  w,
const Eigen::Vector3d &  v 
)
528{
529 wSoft(fid) = w;
530 soft(fid) = convert3DtoLocal(fid, v);
531}

Referenced by igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ setSoftAlpha()

void igl::copyleft::comiso::NRosyField::setSoftAlpha ( double  alpha)
215{
216 assert(alpha >= 0 && alpha < 1);
217 softAlpha = alpha;
218}

Referenced by igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ solve()

void igl::copyleft::comiso::NRosyField::solve ( const int  N = 4)
494{
495 // Reduce the search space by fixing matchings
496 reduceSpace();
497
498 // Build the system
500
501 // Solve with integer roundings
503
504 // This is a very greedy solving strategy
505 // // Solve with no roundings
506 // solveNoRoundings();
507 //
508 // // Round all p and fix them
509 // roundAndFix();
510 //
511 // // Build the system
512 // prepareSystemMatrix(N);
513 //
514 // // Solve with no roundings (they are all fixed)
515 // solveNoRoundings();
516
517 // Find the cones
518 findCones(N);
519}
IGL_INLINE void reduceSpace()
Definition nrosy.cpp:678
IGL_INLINE void prepareSystemMatrix(const int N)
Definition nrosy.cpp:221
IGL_INLINE void findCones(int N)
Definition nrosy.cpp:815
IGL_INLINE void solveRoundings()
Definition nrosy.cpp:424

Referenced by igl::copyleft::comiso::nrosy(), and igl::copyleft::comiso::nrosy().

+ Here is the caller graph for this function:

◆ solveNoRoundings()

void igl::copyleft::comiso::NRosyField::solveNoRoundings ( )
private
403{
404 using namespace std;
405 using namespace Eigen;
406
407 // Solve the linear system
409 solver.compute(A);
410 VectorXd x = solver.solve(b);
411
412 // Copy the result back
413 for(unsigned i=0; i<F.rows(); ++i)
414 if (tag_t[i] != -1)
415 angles[i] = x(tag_t[i]);
416 else
417 angles[i] = hard[i];
418
419 for(unsigned i=0; i<EF.rows(); ++i)
420 if(tag_p[i] != -1)
421 p[i] = roundl(x[tag_p[i]]);
422}
A direct sparse LDLT Cholesky factorizations without square root.
Definition SimplicialCholesky.h:422
SimplicialLDLT & compute(const MatrixType &matrix)
Definition SimplicialCholesky.h:461
const Solve< Derived, Rhs > solve(const MatrixBase< Rhs > &b) const
Definition SparseSolverBase.h:88
TCoord< P > x(const P &p)
Definition geometry_traits.hpp:297

References Eigen::SimplicialLDLT< _MatrixType, _UpLo, _Ordering >::compute(), and Eigen::SparseSolverBase< Derived >::solve().

+ Here is the call graph for this function:

◆ solveRoundings()

void igl::copyleft::comiso::NRosyField::solveRoundings ( )
private
425{
426 using namespace std;
427 using namespace Eigen;
428
429 unsigned n = A.rows();
430
431 gmm::col_matrix< gmm::wsvector< double > > gmm_A;
432 std::vector<double> gmm_b;
433 std::vector<int> ids_to_round;
434 std::vector<double> x;
435
436 gmm_A.resize(n,n);
437 gmm_b.resize(n);
438 x.resize(n);
439
440 // Copy A
441 for (int k=0; k<A.outerSize(); ++k)
442 for (SparseMatrix<double>::InnerIterator it(A,k); it; ++it)
443 {
444 gmm_A(it.row(),it.col()) += it.value();
445 }
446
447 // Copy b
448 for(unsigned i=0; i<n;++i)
449 gmm_b[i] = b[i];
450
451 // Set variables to round
452 ids_to_round.clear();
453 for(unsigned i=0; i<tag_p.size();++i)
454 if(tag_p[i] != -1)
455 ids_to_round.push_back(tag_p[i]);
456
457 // Empty constraints
458 gmm::row_matrix< gmm::wsvector< double > > gmm_C(0, n);
459
460 COMISO::ConstrainedSolver cs;
461 //print_miso_settings(cs.misolver());
462 cs.solve(gmm_C, gmm_A, x, gmm_b, ids_to_round, 0.0, false, true);
463
464 // Copy the result back
465 for(unsigned i=0; i<F.rows(); ++i)
466 if (tag_t[i] != -1)
467 angles[i] = x[tag_t[i]];
468 else
469 angles[i] = hard[i];
470
471 for(unsigned i=0; i<EF.rows(); ++i)
472 if(tag_p[i] != -1)
473 p[i] = roundl(x[tag_p[i]]);
474
475}
Definition SparseCompressedBase.h:137
Index outerSize() const
Definition SparseMatrix.h:143
Index rows() const
Definition SparseMatrix.h:136

Member Data Documentation

◆ A

Eigen::SparseMatrix<double> igl::copyleft::comiso::NRosyField::A
private

◆ angles

Eigen::VectorXd igl::copyleft::comiso::NRosyField::angles
private

Referenced by NRosyField().

◆ b

Eigen::VectorXd igl::copyleft::comiso::NRosyField::b
private

◆ EF

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::EF
private

Referenced by NRosyField().

◆ EV

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::EV
private

Referenced by NRosyField().

◆ F

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::F
private

Referenced by NRosyField().

◆ FE

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::FE
private

Referenced by NRosyField().

◆ hard

Eigen::VectorXd igl::copyleft::comiso::NRosyField::hard
private

◆ isBorderEdge

std::vector<bool> igl::copyleft::comiso::NRosyField::isBorderEdge
private

Referenced by NRosyField().

◆ isHard

std::vector<bool> igl::copyleft::comiso::NRosyField::isHard
private

◆ k

Eigen::VectorXd igl::copyleft::comiso::NRosyField::k
private

Referenced by NRosyField().

◆ N

Eigen::MatrixXd igl::copyleft::comiso::NRosyField::N
private

Referenced by NRosyField().

◆ p

Eigen::VectorXi igl::copyleft::comiso::NRosyField::p
private

Referenced by NRosyField().

◆ pFixed

std::vector<bool> igl::copyleft::comiso::NRosyField::pFixed
private

Referenced by NRosyField().

◆ singularityIndex

Eigen::VectorXd igl::copyleft::comiso::NRosyField::singularityIndex
private

Referenced by NRosyField().

◆ soft

Eigen::VectorXd igl::copyleft::comiso::NRosyField::soft
private

◆ softAlpha

double igl::copyleft::comiso::NRosyField::softAlpha
private

Referenced by NRosyField().

◆ tag_p

Eigen::VectorXi igl::copyleft::comiso::NRosyField::tag_p
private

◆ tag_t

Eigen::VectorXi igl::copyleft::comiso::NRosyField::tag_t
private

◆ TPs

std::vector<Eigen::MatrixXd> igl::copyleft::comiso::NRosyField::TPs
private

Referenced by NRosyField().

◆ TT

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::TT
private

Referenced by NRosyField().

◆ TTi

Eigen::MatrixXi igl::copyleft::comiso::NRosyField::TTi
private

Referenced by NRosyField().

◆ V

Eigen::MatrixXd igl::copyleft::comiso::NRosyField::V
private

Referenced by NRosyField().

◆ wSoft

Eigen::VectorXd igl::copyleft::comiso::NRosyField::wSoft
private

The documentation for this class was generated from the following file: