mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-24 09:11:23 -06:00
Building igl statically and moving to the dep scripts
Fixing dep build script on Windows and removing some warnings. Use bundled igl by default. Not building with the dependency scripts if not explicitly stated. This way, it will stay in Fix the libigl patch to include C source files in header only mode.
This commit is contained in:
parent
89e39e3895
commit
2ae2672ee9
1095 changed files with 181 additions and 5 deletions
394
src/libigl/igl/collapse_edge.cpp
Normal file
394
src/libigl/igl/collapse_edge.cpp
Normal file
|
|
@ -0,0 +1,394 @@
|
|||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "collapse_edge.h"
|
||||
#include "circulation.h"
|
||||
#include "edge_collapse_is_valid.h"
|
||||
#include <vector>
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
int & a_e1,
|
||||
int & a_e2,
|
||||
int & a_f1,
|
||||
int & a_f2)
|
||||
{
|
||||
// Assign this to 0 rather than, say, -1 so that deleted elements will get
|
||||
// draw as degenerate elements at vertex 0 (which should always exist and
|
||||
// never get collapsed to anything else since it is the smallest index)
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
const int eflip = E(e,0)>E(e,1);
|
||||
// source and destination
|
||||
const int s = eflip?E(e,1):E(e,0);
|
||||
const int d = eflip?E(e,0):E(e,1);
|
||||
|
||||
if(!edge_collapse_is_valid(e,F,E,EMAP,EF,EI))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Important to grab neighbors of d before monkeying with edges
|
||||
const std::vector<int> nV2Fd = circulation(e,!eflip,F,E,EMAP,EF,EI);
|
||||
|
||||
// The following implementation strongly relies on s<d
|
||||
assert(s<d && "s should be less than d");
|
||||
// move source and destination to midpoint
|
||||
V.row(s) = p;
|
||||
V.row(d) = p;
|
||||
|
||||
// Helper function to replace edge and associate information with NULL
|
||||
const auto & kill_edge = [&E,&EI,&EF](const int e)
|
||||
{
|
||||
E(e,0) = IGL_COLLAPSE_EDGE_NULL;
|
||||
E(e,1) = IGL_COLLAPSE_EDGE_NULL;
|
||||
EF(e,0) = IGL_COLLAPSE_EDGE_NULL;
|
||||
EF(e,1) = IGL_COLLAPSE_EDGE_NULL;
|
||||
EI(e,0) = IGL_COLLAPSE_EDGE_NULL;
|
||||
EI(e,1) = IGL_COLLAPSE_EDGE_NULL;
|
||||
};
|
||||
|
||||
// update edge info
|
||||
// for each flap
|
||||
const int m = F.rows();
|
||||
for(int side = 0;side<2;side++)
|
||||
{
|
||||
const int f = EF(e,side);
|
||||
const int v = EI(e,side);
|
||||
const int sign = (eflip==0?1:-1)*(1-2*side);
|
||||
// next edge emanating from d
|
||||
const int e1 = EMAP(f+m*((v+sign*1+3)%3));
|
||||
// prev edge pointing to s
|
||||
const int e2 = EMAP(f+m*((v+sign*2+3)%3));
|
||||
assert(E(e1,0) == d || E(e1,1) == d);
|
||||
assert(E(e2,0) == s || E(e2,1) == s);
|
||||
// face adjacent to f on e1, also incident on d
|
||||
const bool flip1 = EF(e1,1)==f;
|
||||
const int f1 = flip1 ? EF(e1,0) : EF(e1,1);
|
||||
assert(f1!=f);
|
||||
assert(F(f1,0)==d || F(f1,1)==d || F(f1,2) == d);
|
||||
// across from which vertex of f1 does e1 appear?
|
||||
const int v1 = flip1 ? EI(e1,0) : EI(e1,1);
|
||||
// Kill e1
|
||||
kill_edge(e1);
|
||||
// Kill f
|
||||
F(f,0) = IGL_COLLAPSE_EDGE_NULL;
|
||||
F(f,1) = IGL_COLLAPSE_EDGE_NULL;
|
||||
F(f,2) = IGL_COLLAPSE_EDGE_NULL;
|
||||
// map f1's edge on e1 to e2
|
||||
assert(EMAP(f1+m*v1) == e1);
|
||||
EMAP(f1+m*v1) = e2;
|
||||
// side opposite f2, the face adjacent to f on e2, also incident on s
|
||||
const int opp2 = (EF(e2,0)==f?0:1);
|
||||
assert(EF(e2,opp2) == f);
|
||||
EF(e2,opp2) = f1;
|
||||
EI(e2,opp2) = v1;
|
||||
// remap e2 from d to s
|
||||
E(e2,0) = E(e2,0)==d ? s : E(e2,0);
|
||||
E(e2,1) = E(e2,1)==d ? s : E(e2,1);
|
||||
if(side==0)
|
||||
{
|
||||
a_e1 = e1;
|
||||
a_f1 = f;
|
||||
}else
|
||||
{
|
||||
a_e2 = e1;
|
||||
a_f2 = f;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, reindex faces and edges incident on d. Do this last so asserts
|
||||
// make sense.
|
||||
//
|
||||
// Could actually skip first and last, since those are always the two
|
||||
// collpased faces.
|
||||
for(auto f : nV2Fd)
|
||||
{
|
||||
for(int v = 0;v<3;v++)
|
||||
{
|
||||
if(F(f,v) == d)
|
||||
{
|
||||
const int flip1 = (EF(EMAP(f+m*((v+1)%3)),0)==f)?1:0;
|
||||
const int flip2 = (EF(EMAP(f+m*((v+2)%3)),0)==f)?0:1;
|
||||
assert(
|
||||
E(EMAP(f+m*((v+1)%3)),flip1) == d ||
|
||||
E(EMAP(f+m*((v+1)%3)),flip1) == s);
|
||||
E(EMAP(f+m*((v+1)%3)),flip1) = s;
|
||||
assert(
|
||||
E(EMAP(f+m*((v+2)%3)),flip2) == d ||
|
||||
E(EMAP(f+m*((v+2)%3)),flip2) == s);
|
||||
E(EMAP(f+m*((v+2)%3)),flip2) = s;
|
||||
F(f,v) = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finally, "remove" this edge and its information
|
||||
kill_edge(e);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI)
|
||||
{
|
||||
int e1,e2,f1,f2;
|
||||
return collapse_edge(e,p,V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const std::function<void(
|
||||
const int,
|
||||
const Eigen::MatrixXd &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::VectorXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
double &,
|
||||
Eigen::RowVectorXd &)> & cost_and_placement,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
std::set<std::pair<double,int> > & Q,
|
||||
std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
|
||||
Eigen::MatrixXd & C)
|
||||
{
|
||||
int e,e1,e2,f1,f2;
|
||||
const auto always_try = [](
|
||||
const Eigen::MatrixXd & ,/*V*/
|
||||
const Eigen::MatrixXi & ,/*F*/
|
||||
const Eigen::MatrixXi & ,/*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & ,/*EF*/
|
||||
const Eigen::MatrixXi & ,/*EI*/
|
||||
const std::set<std::pair<double,int> > & ,/*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
|
||||
const Eigen::MatrixXd & ,/*C*/
|
||||
const int /*e*/
|
||||
) -> bool { return true;};
|
||||
const auto never_care = [](
|
||||
const Eigen::MatrixXd & , /*V*/
|
||||
const Eigen::MatrixXi & , /*F*/
|
||||
const Eigen::MatrixXi & , /*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & , /*EF*/
|
||||
const Eigen::MatrixXi & , /*EI*/
|
||||
const std::set<std::pair<double,int> > & , /*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
|
||||
const Eigen::MatrixXd & , /*C*/
|
||||
const int , /*e*/
|
||||
const int , /*e1*/
|
||||
const int , /*e2*/
|
||||
const int , /*f1*/
|
||||
const int , /*f2*/
|
||||
const bool /*collapsed*/
|
||||
)-> void { };
|
||||
return
|
||||
collapse_edge(
|
||||
cost_and_placement,always_try,never_care,
|
||||
V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const std::function<void(
|
||||
const int,
|
||||
const Eigen::MatrixXd &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::VectorXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
double &,
|
||||
Eigen::RowVectorXd &)> & cost_and_placement,
|
||||
const std::function<bool(
|
||||
const Eigen::MatrixXd & ,/*V*/
|
||||
const Eigen::MatrixXi & ,/*F*/
|
||||
const Eigen::MatrixXi & ,/*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & ,/*EF*/
|
||||
const Eigen::MatrixXi & ,/*EI*/
|
||||
const std::set<std::pair<double,int> > & ,/*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
|
||||
const Eigen::MatrixXd & ,/*C*/
|
||||
const int /*e*/
|
||||
)> & pre_collapse,
|
||||
const std::function<void(
|
||||
const Eigen::MatrixXd & , /*V*/
|
||||
const Eigen::MatrixXi & , /*F*/
|
||||
const Eigen::MatrixXi & , /*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & , /*EF*/
|
||||
const Eigen::MatrixXi & , /*EI*/
|
||||
const std::set<std::pair<double,int> > & , /*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
|
||||
const Eigen::MatrixXd & , /*C*/
|
||||
const int , /*e*/
|
||||
const int , /*e1*/
|
||||
const int , /*e2*/
|
||||
const int , /*f1*/
|
||||
const int , /*f2*/
|
||||
const bool /*collapsed*/
|
||||
)> & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
std::set<std::pair<double,int> > & Q,
|
||||
std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
|
||||
Eigen::MatrixXd & C)
|
||||
{
|
||||
int e,e1,e2,f1,f2;
|
||||
return
|
||||
collapse_edge(
|
||||
cost_and_placement,pre_collapse,post_collapse,
|
||||
V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const std::function<void(
|
||||
const int,
|
||||
const Eigen::MatrixXd &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::VectorXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
const Eigen::MatrixXi &,
|
||||
double &,
|
||||
Eigen::RowVectorXd &)> & cost_and_placement,
|
||||
const std::function<bool(
|
||||
const Eigen::MatrixXd & ,/*V*/
|
||||
const Eigen::MatrixXi & ,/*F*/
|
||||
const Eigen::MatrixXi & ,/*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & ,/*EF*/
|
||||
const Eigen::MatrixXi & ,/*EI*/
|
||||
const std::set<std::pair<double,int> > & ,/*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
|
||||
const Eigen::MatrixXd & ,/*C*/
|
||||
const int /*e*/
|
||||
)> & pre_collapse,
|
||||
const std::function<void(
|
||||
const Eigen::MatrixXd & , /*V*/
|
||||
const Eigen::MatrixXi & , /*F*/
|
||||
const Eigen::MatrixXi & , /*E*/
|
||||
const Eigen::VectorXi & ,/*EMAP*/
|
||||
const Eigen::MatrixXi & , /*EF*/
|
||||
const Eigen::MatrixXi & , /*EI*/
|
||||
const std::set<std::pair<double,int> > & , /*Q*/
|
||||
const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
|
||||
const Eigen::MatrixXd & , /*C*/
|
||||
const int , /*e*/
|
||||
const int , /*e1*/
|
||||
const int , /*e2*/
|
||||
const int , /*f1*/
|
||||
const int , /*f2*/
|
||||
const bool /*collapsed*/
|
||||
)> & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
std::set<std::pair<double,int> > & Q,
|
||||
std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
|
||||
Eigen::MatrixXd & C,
|
||||
int & e,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2)
|
||||
{
|
||||
using namespace Eigen;
|
||||
if(Q.empty())
|
||||
{
|
||||
// no edges to collapse
|
||||
return false;
|
||||
}
|
||||
std::pair<double,int> p = *(Q.begin());
|
||||
if(p.first == std::numeric_limits<double>::infinity())
|
||||
{
|
||||
// min cost edge is infinite cost
|
||||
return false;
|
||||
}
|
||||
Q.erase(Q.begin());
|
||||
e = p.second;
|
||||
Qit[e] = Q.end();
|
||||
std::vector<int> N = circulation(e, true,F,E,EMAP,EF,EI);
|
||||
std::vector<int> Nd = circulation(e,false,F,E,EMAP,EF,EI);
|
||||
N.insert(N.begin(),Nd.begin(),Nd.end());
|
||||
bool collapsed = true;
|
||||
if(pre_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e))
|
||||
{
|
||||
collapsed = collapse_edge(e,C.row(e),V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}else
|
||||
{
|
||||
// Aborted by pre collapse callback
|
||||
collapsed = false;
|
||||
}
|
||||
post_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2,collapsed);
|
||||
if(collapsed)
|
||||
{
|
||||
// Erase the two, other collapsed edges
|
||||
Q.erase(Qit[e1]);
|
||||
Qit[e1] = Q.end();
|
||||
Q.erase(Qit[e2]);
|
||||
Qit[e2] = Q.end();
|
||||
// update local neighbors
|
||||
// loop over original face neighbors
|
||||
for(auto n : N)
|
||||
{
|
||||
if(F(n,0) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,1) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,2) != IGL_COLLAPSE_EDGE_NULL)
|
||||
{
|
||||
for(int v = 0;v<3;v++)
|
||||
{
|
||||
// get edge id
|
||||
const int ei = EMAP(v*F.rows()+n);
|
||||
// erase old entry
|
||||
Q.erase(Qit[ei]);
|
||||
// compute cost and potential placement
|
||||
double cost;
|
||||
RowVectorXd place;
|
||||
cost_and_placement(ei,V,F,E,EMAP,EF,EI,cost,place);
|
||||
// Replace in queue
|
||||
Qit[ei] = Q.insert(std::pair<double,int>(cost,ei)).first;
|
||||
C.row(ei) = place;
|
||||
}
|
||||
}
|
||||
}
|
||||
}else
|
||||
{
|
||||
// reinsert with infinite weight (the provided cost function must **not**
|
||||
// have given this un-collapsable edge inf cost already)
|
||||
p.first = std::numeric_limits<double>::infinity();
|
||||
Qit[e] = Q.insert(p).first;
|
||||
}
|
||||
return collapsed;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue