mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-25 01:31:14 -06:00
Merged branch 'dev_native' into lm_sla_supports_auto
Added igl library files
This commit is contained in:
commit
7681d00ee5
2865 changed files with 142806 additions and 22325 deletions
394
src/igl/collapse_edge.cpp
Normal file
394
src/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