diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc index 35a73d9f308..0eeba8ab6c2 100644 --- a/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc +++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/arg_parser.cc @@ -221,9 +221,8 @@ namespace lemon { const std::string &opt) { Opts::iterator o = _opts.find(opt); - Opts::iterator s = _opts.find(syn); LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'"); - LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'"); + LEMON_ASSERT(_opts.find(syn)==_opts.end(), "Option already used: '"+syn+"'"); ParData p; p.help=opt; p.mandatory=false; diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h index 355ee008246..a770bbee60c 100644 --- a/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h +++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/bits/array_map.h @@ -88,7 +88,7 @@ namespace lemon { Item it; for (nf->first(it); it != INVALID; nf->next(it)) { int id = nf->id(it);; - allocator.construct(&(values[id]), Value()); + std::allocator_traits::construct(allocator, &(values[id]), Value()); } } @@ -218,15 +218,15 @@ namespace lemon { for (nf->first(it); it != INVALID; nf->next(it)) { int jd = nf->id(it);; if (id != jd) { - allocator.construct(&(new_values[jd]), values[jd]); - allocator.destroy(&(values[jd])); + std::allocator_traits::construct(allocator, &(new_values[jd]), values[jd]); + std::allocator_traits::destroy(allocator, &(values[jd])); } } if (capacity != 0) allocator.deallocate(values, capacity); values = new_values; capacity = new_capacity; } - allocator.construct(&(values[id]), Value()); + std::allocator_traits::construct(allocator, &(values[id]), Value()); } // \brief Adds more new keys to the map. @@ -260,8 +260,8 @@ namespace lemon { } } if (found) continue; - allocator.construct(&(new_values[id]), values[id]); - allocator.destroy(&(values[id])); + std::allocator_traits::construct(allocator, &(new_values[id]), values[id]); + std::allocator_traits::destroy(allocator, &(values[id])); } if (capacity != 0) allocator.deallocate(values, capacity); values = new_values; @@ -269,7 +269,7 @@ namespace lemon { } for (int i = 0; i < int(keys.size()); ++i) { int id = nf->id(keys[i]); - allocator.construct(&(values[id]), Value()); + std::allocator_traits::construct(allocator, &(values[id]), Value()); } } @@ -279,7 +279,7 @@ namespace lemon { // and it overrides the erase() member function of the observer base. virtual void erase(const Key& key) { int id = Parent::notifier()->id(key); - allocator.destroy(&(values[id])); + std::allocator_traits::destroy(allocator, &(values[id])); } // \brief Erase more keys from the map. @@ -289,7 +289,7 @@ namespace lemon { virtual void erase(const std::vector& keys) { for (int i = 0; i < int(keys.size()); ++i) { int id = Parent::notifier()->id(keys[i]); - allocator.destroy(&(values[id])); + std::allocator_traits::destroy(allocator, &(values[id])); } } @@ -303,7 +303,7 @@ namespace lemon { Item it; for (nf->first(it); it != INVALID; nf->next(it)) { int id = nf->id(it);; - allocator.construct(&(values[id]), Value()); + std::allocator_traits::construct(allocator, &(values[id]), Value()); } } @@ -317,7 +317,7 @@ namespace lemon { Item it; for (nf->first(it); it != INVALID; nf->next(it)) { int id = nf->id(it); - allocator.destroy(&(values[id])); + std::allocator_traits::destroy(allocator, &(values[id])); } allocator.deallocate(values, capacity); capacity = 0; diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h index 6ccad33e68e..388e990ec3b 100644 --- a/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h +++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/network_simplex.h @@ -234,7 +234,7 @@ namespace lemon { int in_arc, join, u_in, v_in, u_out, v_out; Value delta; - const Value MAX; + const Value MAX_VALUE; public: @@ -649,9 +649,9 @@ namespace lemon { NetworkSimplex(const GR& graph, bool arc_mixing = true) : _graph(graph), _node_id(graph), _arc_id(graph), _arc_mixing(arc_mixing), - MAX(std::numeric_limits::max()), + MAX_VALUE(std::numeric_limits::max()), INF(std::numeric_limits::has_infinity ? - std::numeric_limits::infinity() : MAX) + std::numeric_limits::infinity() : MAX_VALUE) { // Check the number types LEMON_ASSERT(std::numeric_limits::is_signed, @@ -1076,9 +1076,9 @@ namespace lemon { for (int i = 0; i != _arc_num; ++i) { Value c = _lower[i]; if (c >= 0) { - _cap[i] = _upper[i] < MAX ? _upper[i] - c : INF; + _cap[i] = _upper[i] < MAX_VALUE ? _upper[i] - c : INF; } else { - _cap[i] = _upper[i] < MAX + c ? _upper[i] - c : INF; + _cap[i] = _upper[i] < MAX_VALUE + c ? _upper[i] - c : INF; } _supply[_source[i]] -= c; _supply[_target[i]] += c; @@ -1282,7 +1282,7 @@ namespace lemon { d = _flow[e]; if (_pred_dir[u] == DIR_DOWN) { c = _cap[e]; - d = c >= MAX ? INF : c - d; + d = c >= MAX_VALUE ? INF : c - d; } if (d < delta) { delta = d; @@ -1297,7 +1297,7 @@ namespace lemon { d = _flow[e]; if (_pred_dir[u] == DIR_UP) { c = _cap[e]; - d = c >= MAX ? INF : c - d; + d = c >= MAX_VALUE ? INF : c - d; } if (d <= delta) { delta = d; @@ -1559,7 +1559,7 @@ namespace lemon { _pi[_target[in_arc]]) >= 0) continue; findJoinNode(); bool change = findLeavingArc(); - if (delta >= MAX) return false; + if (delta >= MAX_VALUE) return false; changeFlow(change); if (change) { updateTreeStructure(); @@ -1598,7 +1598,7 @@ namespace lemon { while (pivot.findEnteringArc()) { findJoinNode(); bool change = findLeavingArc(); - if (delta >= MAX) return UNBOUNDED; + if (delta >= MAX_VALUE) return UNBOUNDED; changeFlow(change); if (change) { updateTreeStructure(); diff --git a/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h index 8de74ede8a9..f9861f39169 100644 --- a/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h +++ b/extern/quadriflow/3rd/lemon-1.3.1/lemon/random.h @@ -249,8 +249,8 @@ namespace lemon { current = state + length; - register Word *curr = state + length - 1; - register long num; + Word *curr = state + length - 1; + long num; num = length - shift; while (num--) { diff --git a/extern/quadriflow/src/hierarchy.cpp b/extern/quadriflow/src/hierarchy.cpp index c333256a139..70a9628320f 100644 --- a/extern/quadriflow/src/hierarchy.cpp +++ b/extern/quadriflow/src/hierarchy.cpp @@ -269,7 +269,13 @@ void Hierarchy::DownsampleGraph(const AdjacentMatrix adj, const MatrixXd& V, con for (auto it = ad.begin(); it != ad.end(); ++it, ++entry_it) { int k = it->id; double dp = N.col(i).dot(N.col(k)); - double ratio = A[i] > A[k] ? (A[i] / A[k]) : (A[k] / A[i]); + double ratio; + if (A[i] > A[k]) { + ratio = (A[k] == 0.0f) ? 1.0f : A[i] / A[k]; + } + else { + ratio = (A[i] == 0.0f) ? 1.0f : A[k] / A[i]; + } *entry_it = Entry(i, k, dp * ratio); } } @@ -1133,7 +1139,8 @@ void Hierarchy::propagateConstraints() { auto& COw = mCOw[l]; auto& COw_next = mCOw[l + 1]; auto& toUpper = mToUpper[l]; - MatrixXd& S = mS[l]; + // FIXME + // MatrixXd& S = mS[l]; for (uint32_t i = 0; i != mV[l + 1].cols(); ++i) { Vector2i upper = toUpper.col(i); diff --git a/extern/quadriflow/src/loader.cpp b/extern/quadriflow/src/loader.cpp index aa27066e6e4..5b9d717db71 100644 --- a/extern/quadriflow/src/loader.cpp +++ b/extern/quadriflow/src/loader.cpp @@ -8,6 +8,7 @@ #include "loader.hpp" +#include #include #include @@ -69,7 +70,7 @@ void load(const char* filename, MatrixXd& V, MatrixXi& F) }; /// Hash function for obj_vertex - struct obj_vertexHash : std::unary_function { + struct obj_vertexHash { std::size_t operator()(const obj_vertex &v) const { size_t hash = std::hash()(v.p); hash = hash * 37 + std::hash()(v.uv); diff --git a/extern/quadriflow/src/flow.hpp b/extern/quadriflow/src/flow.hpp index ab4a01c..a77f7ae 100644 --- a/extern/quadriflow/src/flow.hpp +++ b/extern/quadriflow/src/flow.hpp @@ -7,17 +7,12 @@ #include #include "config.hpp" - -#include -#include -#include -#include +#include "../patches/boykov_kolmogorov_max_flow.hpp" #include #include #include -using namespace boost; using namespace Eigen; namespace qflow { @@ -34,78 +29,52 @@ class MaxFlowHelper { class BoykovMaxFlowHelper : public MaxFlowHelper { public: - typedef int EdgeWeightType; - typedef adjacency_list_traits Traits; - // clang-format off - typedef adjacency_list < vecS, vecS, directedS, - property < vertex_name_t, std::string, - property < vertex_index_t, long, - property < vertex_color_t, boost::default_color_type, - property < vertex_distance_t, long, - property < vertex_predecessor_t, Traits::edge_descriptor > > > > >, - - property < edge_capacity_t, EdgeWeightType, - property < edge_residual_capacity_t, EdgeWeightType, - property < edge_reverse_t, Traits::edge_descriptor > > > > Graph; - // clang-format on - - public: - BoykovMaxFlowHelper() { rev = get(edge_reverse, g); } - void resize(int n, int m) { - vertex_descriptors.resize(n); - for (int i = 0; i < n; ++i) vertex_descriptors[i] = add_vertex(g); - } - int compute() { - EdgeWeightType flow = - boykov_kolmogorov_max_flow(g, vertex_descriptors.front(), vertex_descriptors.back()); - return flow; + BoykovMaxFlowHelper() = default; + void resize(int n, int m) override { + num_verts = n; + num_edges = 0; + flow.resize(num_verts, m * 2); } - void addDirectEdge(Traits::vertex_descriptor& v1, Traits::vertex_descriptor& v2, - property_map::type& rev, const int capacity, - const int inv_capacity, Graph& g, Traits::edge_descriptor& e1, - Traits::edge_descriptor& e2) { - e1 = add_edge(v1, v2, g).first; - e2 = add_edge(v2, v1, g).first; - put(edge_capacity, g, e1, capacity); - put(edge_capacity, g, e2, inv_capacity); - - rev[e1] = e2; - rev[e2] = e1; + int compute() override { + return flow.max_flow(0, num_verts - 1); } - void addEdge(int x, int y, int c, int rc, int v, int cost = 1) { - Traits::edge_descriptor e1, e2; - addDirectEdge(vertex_descriptors[x], vertex_descriptors[y], rev, c, rc, g, e1, e2); + void addEdge(int x, int y, int c, int rc, int v, int cost = 1) override { + const int e1 = num_edges++; + const int e2 = num_edges++; + flow.set_edge(e1, e2, x, y, c); + flow.set_edge(e2, e1, y, x, rc); if (v != -1) { - edge_to_variables[e1] = std::make_pair(v, -1); - edge_to_variables[e2] = std::make_pair(v, 1); + edge_to_variables.emplace_back(v, -1); + edge_to_variables.emplace_back(v, 1); + } + else { + edge_to_variables.emplace_back(-1, -1); + edge_to_variables.emplace_back(-1, -1); } } - void applyTo(std::vector& edge_diff) { - property_map::type capacity = get(edge_capacity, g); - property_map::type residual_capacity = - get(edge_residual_capacity, g); - - graph_traits::vertex_iterator u_iter, u_end; - graph_traits::out_edge_iterator ei, e_end; - for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) - for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) - if (capacity[*ei] > 0) { - int flow = (capacity[*ei] - residual_capacity[*ei]); + void applyTo(std::vector& edge_diff) override { + for (int vert = 0; vert < num_verts; vert++) { + for (int edge : flow.vertex_out_edges(vert)) { + const int capacity = flow.edge_capacity(edge); + const int residual_capacity = flow.edge_residual_capacity(edge); + if (capacity > 0) { + int flow = (capacity - residual_capacity); if (flow > 0) { - auto it = edge_to_variables.find(*ei); - if (it != edge_to_variables.end()) { - edge_diff[it->second.first / 2][it->second.first % 2] += - it->second.second * flow; + std::pair e2v = edge_to_variables[edge]; + if (e2v.first != -1) { + edge_diff[e2v.first / 2][e2v.first % 2] += e2v.second * flow; } } } + } + } } private: - Graph g; - property_map::type rev; - std::vector vertex_descriptors; - std::map> edge_to_variables; + BoykovKolmogorovMaxFlow flow; + std::vector> edge_to_variables; + int num_verts = 0; + int num_edges = 0; }; class NetworkSimplexFlowHelper : public MaxFlowHelper { diff --git a/extern/quadriflow/src/main.cpp b/extern/quadriflow/src/main.cpp index 18bc4063c42..63c9e61b8c9 100644 --- a/extern/quadriflow/src/main.cpp +++ b/extern/quadriflow/src/main.cpp @@ -110,7 +110,10 @@ int main(int argc, char** argv) { printf("Use %lf seconds\n", (t2 - t1) * 1e-3); t1 = GetCurrentTime64(); printf("Solve index map...\n"); - field.ComputeIndexMap(); + if (!field.ComputeIndexMap()) { + fprintf(stderr, "Failed to solve result, exiting!\n"); + return 1; + } t2 = GetCurrentTime64(); printf("Indexmap Use %lf seconds\n", (t2 - t1) * 1e-3); printf("Writing the file...\n"); diff --git a/extern/quadriflow/src/parametrizer.cpp b/extern/quadriflow/src/parametrizer.cpp index b85383566c9..3dbdc386eca 100644 --- a/extern/quadriflow/src/parametrizer.cpp +++ b/extern/quadriflow/src/parametrizer.cpp @@ -18,7 +18,7 @@ namespace qflow { -void Parametrizer::ComputeIndexMap(int with_scale) { +bool Parametrizer::ComputeIndexMap(int with_scale) { // build edge info auto& V = hierarchy.mV[0]; auto& F = hierarchy.mF; @@ -80,9 +80,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) { #ifdef LOG_OUTPUT printf("subdivide...\n"); #endif - subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold, - edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges, - singularities, 1); + if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold, + edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges, + singularities, 1)) + { + return false; + } allow_changes.clear(); allow_changes.resize(edge_diff.size() * 2, 1); @@ -99,9 +102,12 @@ void Parametrizer::ComputeIndexMap(int with_scale) { int t1 = GetCurrentTime64(); #endif FixFlipHierarchy(); - subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold, + if (!subdivide_edgeDiff(F, V, N, Q, O, &hierarchy.mS[0], V2E, hierarchy.mE2E, boundary, nonManifold, edge_diff, edge_values, face_edgeOrients, face_edgeIds, sharp_edges, - singularities, 1); + singularities, 1)) + { + return false; + } FixFlipSat(); #ifdef LOG_OUTPUT @@ -242,6 +248,7 @@ void Parametrizer::ComputeIndexMap(int with_scale) { // E2E_compact, // V, N, Q, O, F, V2E, hierarchy.mE2E, disajoint_tree, // hierarchy.mScale, false); + return true; } } // namespace qflow diff --git a/extern/quadriflow/src/parametrizer.hpp b/extern/quadriflow/src/parametrizer.hpp index 1f4a02be6c2..9703ebbfff6 100644 --- a/extern/quadriflow/src/parametrizer.hpp +++ b/extern/quadriflow/src/parametrizer.hpp @@ -54,7 +54,8 @@ class Parametrizer { void ComputePositionSingularities(); // Integer Grid Map Pipeline - void ComputeIndexMap(int with_scale = 0); + // Return false when the solver fails. + bool ComputeIndexMap(int with_scale = 0); void BuildEdgeInfo(); void ComputeMaxFlow(); void MarkInteger(); diff --git a/extern/quadriflow/src/post-solver.cpp b/extern/quadriflow/src/post-solver.cpp index 6027ddd..ccefd15 100644 --- a/extern/quadriflow/src/post-solver.cpp +++ b/extern/quadriflow/src/post-solver.cpp @@ -5,7 +5,9 @@ // Created by Jingwei on 2/5/18. // #include +#ifdef POST_SOLVER #include +#endif #include #include #include diff --git a/extern/quadriflow/src/subdivide.cpp b/extern/quadriflow/src/subdivide.cpp index c408bbc6394..babff96ccb4 100644 --- a/extern/quadriflow/src/subdivide.cpp +++ b/extern/quadriflow/src/subdivide.cpp @@ -145,7 +145,7 @@ void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi E2E.conservativeResize(nF * 3); } -void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S, +bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold, std::vector &edge_diff, std::vector &edge_values, std::vector &face_edgeOrients, std::vector &face_edgeIds, @@ -500,17 +500,18 @@ void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, Matr for (int j = 0; j < 3; ++j) { auto diff = edge_diff[face_edgeIds[i][j]]; if (abs(diff[0]) > 1 || abs(diff[1]) > 1) { - printf("wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j); - exit(0); + fprintf(stderr, "wrong init %d %d!\n", face_edgeIds[i][j], i * 3 + j); + return false; } } } for (int i = 0; i < edge_diff.size(); ++i) { if (abs(edge_diff[i][0]) > 1 || abs(edge_diff[i][1]) > 1) { - printf("wrong...\n"); - exit(0); + fprintf(stderr, "wrong...\n"); + return false; } } + return true; } } // namespace qflow diff --git a/extern/quadriflow/src/subdivide.hpp b/extern/quadriflow/src/subdivide.hpp index a93c58ac2a7..8c682b6d9f2 100644 --- a/extern/quadriflow/src/subdivide.hpp +++ b/extern/quadriflow/src/subdivide.hpp @@ -9,7 +9,8 @@ namespace qflow { void subdivide(MatrixXi &F, MatrixXd &V, VectorXd& rho, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold, double maxLength); -void subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S, +// Return false when solving fails. +bool subdivide_edgeDiff(MatrixXi &F, MatrixXd &V, MatrixXd &N, MatrixXd &Q, MatrixXd &O, MatrixXd* S, VectorXi &V2E, VectorXi &E2E, VectorXi &boundary, VectorXi &nonmanifold, std::vector &edge_diff, std::vector &edge_values, std::vector &face_edgeOrients, std::vector &face_edgeIds, diff --git a/extern/quadriflow/src/optimizer.cpp b/extern/quadriflow/src/optimizer.cpp index 1c59ad0f70c..f8836ed0d0e 100644 --- a/extern/quadriflow/src/optimizer.cpp +++ b/extern/quadriflow/src/optimizer.cpp @@ -1296,7 +1296,9 @@ void Optimizer::optimize_integer_constraints(Hierarchy& mRes, std::map solver = std::make_unique(); } #endif - solver->resize(initial.size() + 2, arc_ids.size()); + /* This used to be arc_ids.size() which is wrong, the loop below adds + * exactly arcs.size() edges. */ + solver->resize(initial.size() + 2, arcs.size()); std::set ids; for (int i = 0; i < arcs.size(); ++i) { diff --git a/extern/quadriflow/src/field-math.hpp b/extern/quadriflow/src/field-math.hpp index 86ed4b2b1f4..3f4fe3fa097 100644 --- a/extern/quadriflow/src/field-math.hpp +++ b/extern/quadriflow/src/field-math.hpp @@ -292,7 +292,6 @@ inline Vector3d Travel(Vector3d p, const Vector3d &dir, double &len, int &f, Vec double max_len = 1e30; bool found = false; int next_id, next_f; - Vector3d next_q; Matrix3d m, n; m.col(0) = t1; m.col(1) = t2; @@ -399,7 +398,6 @@ inline Vector3d TravelField(Vector3d p, Vector3d &pt, double &len, int &f, Vecto double max_len = 1e30; bool found = false; int next_id = -1, next_f = -1; - Vector3d next_q; Matrix3d m, n; m.col(0) = t1; m.col(1) = t2;