diff options
Diffstat (limited to 'extern/carve/include/carve/mesh_simplify.hpp')
-rw-r--r-- | extern/carve/include/carve/mesh_simplify.hpp | 1599 |
1 files changed, 0 insertions, 1599 deletions
diff --git a/extern/carve/include/carve/mesh_simplify.hpp b/extern/carve/include/carve/mesh_simplify.hpp deleted file mode 100644 index 9c7371b3df5..00000000000 --- a/extern/carve/include/carve/mesh_simplify.hpp +++ /dev/null @@ -1,1599 +0,0 @@ -// Begin License: -// Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com). -// All rights reserved. -// -// This file is part of the Carve CSG Library (http://carve-csg.com/) -// -// This file may be used under the terms of either the GNU General -// Public License version 2 or 3 (at your option) as published by the -// Free Software Foundation and appearing in the files LICENSE.GPL2 -// and LICENSE.GPL3 included in the packaging of this file. -// -// This file is provided "AS IS" with NO WARRANTY OF ANY KIND, -// INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE. -// End: - - -#pragma once - -#include <carve/carve.hpp> -#include <carve/mesh.hpp> -#include <carve/mesh_ops.hpp> -#include <carve/geom2d.hpp> -#include <carve/heap.hpp> -#include <carve/rtree.hpp> -#include <carve/triangle_intersection.hpp> - -#include <fstream> -#include <string> -#include <utility> -#include <set> -#include <algorithm> -#include <vector> - - -namespace carve { - namespace mesh { - - - class MeshSimplifier { - typedef carve::mesh::MeshSet<3> meshset_t; - typedef carve::mesh::Mesh<3> mesh_t; - typedef mesh_t::vertex_t vertex_t; - typedef vertex_t::vector_t vector_t; - typedef mesh_t::edge_t edge_t; - typedef mesh_t::face_t face_t; - typedef face_t::aabb_t aabb_t; - - typedef carve::geom::RTreeNode<3, carve::mesh::Face<3> *> face_rtree_t; - - - struct EdgeInfo { - edge_t *edge; - double delta_v; - - double c[4]; - double l[2], t1[2], t2[2]; - size_t heap_idx; - - void update() { - const vertex_t *v1 = edge->vert; - const vertex_t *v2 = edge->next->vert; - const vertex_t *v3 = edge->next->next->vert; - const vertex_t *v4 = edge->rev ? edge->rev->next->next->vert : NULL; - - l[0] = (v1->v - v2->v).length(); - - t1[0] = (v3->v - v1->v).length(); - t1[1] = (v3->v - v2->v).length(); - - c[0] = std::max((t1[0] + t1[1]) / l[0] - 1.0, 0.0); - - if (v4) { - l[1] = (v3->v - v4->v).length(); - t2[0] = (v4->v - v1->v).length(); - t2[1] = (v4->v - v2->v).length(); - c[1] = std::max((t2[0] + t2[1]) / l[0] - 1.0, 0.0); - c[2] = std::max((t1[0] + t2[0]) / l[1] - 1.0, 0.0); - c[3] = std::max((t1[1] + t2[1]) / l[1] - 1.0, 0.0); - delta_v = carve::geom3d::tetrahedronVolume(v1->v, v2->v, v3->v, v4->v); - } else { - l[1] = 0.0; - t2[0] = t2[1] = 0.0; - c[1] = c[2] = c[3] = 0.0; - delta_v = 0.0; - } - } - - EdgeInfo(edge_t *e) : edge(e) { - update(); - } - - EdgeInfo() : edge(NULL) { - delta_v = 0.0; - c[0] = c[1] = c[2] = c[3] = 0.0; - l[0] = l[1] = 0.0; - t1[0] = t1[1] = 0.0; - t2[0] = t2[1] = 0.0; - } - - struct NotifyPos { - void operator()(EdgeInfo *edge, size_t pos) const { edge->heap_idx = pos; } - void operator()(EdgeInfo &edge, size_t pos) const { edge.heap_idx = pos; } - }; - }; - - - - struct FlippableBase { - double min_dp; - - FlippableBase(double _min_dp = 0.0) : min_dp(_min_dp) { - } - - bool open(const EdgeInfo *e) const { - return e->edge->rev == NULL; - } - - bool wouldCreateDegenerateEdge(const EdgeInfo *e) const { - return e->edge->prev->vert == e->edge->rev->prev->vert; - } - - bool flippable_DotProd(const EdgeInfo *e) const { - using carve::geom::dot; - using carve::geom::cross; - - if (open(e)) return false; - - edge_t *edge = e->edge; - - const vertex_t *v1 = edge->vert; - const vertex_t *v2 = edge->next->vert; - const vertex_t *v3 = edge->next->next->vert; - const vertex_t *v4 = edge->rev->next->next->vert; - - if (dot(cross(v3->v - v2->v, v1->v - v2->v).normalized(), - cross(v4->v - v1->v, v2->v - v1->v).normalized()) < min_dp) return false; - - if (dot(cross(v3->v - v4->v, v1->v - v4->v).normalized(), - cross(v4->v - v3->v, v2->v - v3->v).normalized()) < min_dp) return false; - - return true; - } - - virtual bool canFlip(const EdgeInfo *e) const { - return !open(e) && !wouldCreateDegenerateEdge(e) && score(e) > 0.0; - } - - virtual double score(const EdgeInfo *e) const { - return std::min(e->c[2], e->c[3]) - std::min(e->c[0], e->c[1]); - } - - class Priority { - Priority &operator=(const Priority &); - const FlippableBase &flip; - - public: - Priority(const FlippableBase &_flip) : flip(_flip) {} - bool operator()(const EdgeInfo *a, const EdgeInfo *b) const { return flip.score(a) > flip.score(b); } - }; - - Priority priority() const { - return Priority(*this); - } - }; - - - - struct FlippableConservative : public FlippableBase { - FlippableConservative() : FlippableBase(0.0) { - } - - bool connectsAlmostCoplanarFaces(const EdgeInfo *e) const { - // XXX: remove hard coded constants. - if (e->c[0] < 1e-10 || e->c[1] < 1e-10) return true; - return fabs(carve::geom::dot(e->edge->face->plane.N, e->edge->rev->face->plane.N) - 1.0) < 1e-10; - } - - bool connectsExactlyCoplanarFaces(const EdgeInfo *e) const { - edge_t *edge = e->edge; - return - carve::geom3d::orient3d(edge->vert->v, - edge->next->vert->v, - edge->next->next->vert->v, - edge->rev->next->next->vert->v) == 0.0 && - carve::geom3d::orient3d(edge->rev->vert->v, - edge->rev->next->vert->v, - edge->rev->next->next->vert->v, - edge->next->next->vert->v) == 0.0; - } - - virtual bool canFlip(const EdgeInfo *e) const { - return FlippableBase::canFlip(e) && connectsExactlyCoplanarFaces(e) && flippable_DotProd(e); - } - }; - - - - struct FlippableColinearPair : public FlippableBase { - - FlippableColinearPair() { - } - - - virtual double score(const EdgeInfo *e) const { - return e->l[0] - e->l[1]; - } - - virtual bool canFlip(const EdgeInfo *e) const { - if (!FlippableBase::canFlip(e)) return false; - - if (e->c[0] > 1e-3 || e->c[1] > 1e-3) return false; - - return true; - } - }; - - - - struct Flippable : public FlippableBase { - double min_colinearity; - double min_delta_v; - - Flippable(double _min_colinearity, - double _min_delta_v, - double _min_normal_angle) : - FlippableBase(cos(_min_normal_angle)), - min_colinearity(_min_colinearity), - min_delta_v(_min_delta_v) { - } - - - virtual bool canFlip(const EdgeInfo *e) const { - if (!FlippableBase::canFlip(e)) return false; - - if (fabs(e->delta_v) > min_delta_v) return false; - - // if (std::min(e->c[0], e->c[1]) > min_colinearity) return false; - - return flippable_DotProd(e); - } - }; - - - - struct EdgeMerger { - double min_edgelen; - - virtual bool canMerge(const EdgeInfo *e) const { - return e->l[0] <= min_edgelen; - } - - EdgeMerger(double _min_edgelen) : min_edgelen(_min_edgelen) { - } - - double score(const EdgeInfo *e) const { - return min_edgelen - e->l[0]; - } - - class Priority { - Priority &operator=(const Priority &); - - public: - const EdgeMerger &merger; - Priority(const EdgeMerger &_merger) : merger(_merger) { - } - bool operator()(const EdgeInfo *a, const EdgeInfo *b) const { - // collapse edges in order from shortest to longest. - return merger.score(a) < merger.score(b); - } - }; - - Priority priority() const { - return Priority(*this); - } - }; - - - - typedef std::unordered_map<edge_t *, EdgeInfo *> edge_info_map_t; - std::unordered_map<edge_t *, EdgeInfo *> edge_info; - - - - void initEdgeInfo(mesh_t *mesh) { - for (size_t i = 0; i < mesh->faces.size(); ++i) { - edge_t *e = mesh->faces[i]->edge; - do { - edge_info[e] = new EdgeInfo(e); - e = e->next; - } while (e != mesh->faces[i]->edge); - } - } - - - - void initEdgeInfo(meshset_t *meshset) { - for (size_t m = 0; m < meshset->meshes.size(); ++m) { - mesh_t *mesh = meshset->meshes[m]; - initEdgeInfo(mesh); - } - } - - - - void clearEdgeInfo() { - for (edge_info_map_t::iterator i = edge_info.begin(); i != edge_info.end(); ++i) { - delete (*i).second; - } - } - - - - void updateEdgeFlipHeap(std::vector<EdgeInfo *> &edge_heap, - edge_t *edge, - const FlippableBase &flipper) { - std::unordered_map<edge_t *, EdgeInfo *>::const_iterator i = edge_info.find(edge); - CARVE_ASSERT(i != edge_info.end()); - EdgeInfo *e = (*i).second; - - bool heap_pre = e->heap_idx != ~0U; - (*i).second->update(); - bool heap_post = edge->v1() < edge->v2() && flipper.canFlip(e); - - if (!heap_pre && heap_post) { - edge_heap.push_back(e); - carve::heap::push_heap(edge_heap.begin(), - edge_heap.end(), - flipper.priority(), - EdgeInfo::NotifyPos()); - } else if (heap_pre && !heap_post) { - CARVE_ASSERT(edge_heap[e->heap_idx] == e); - carve::heap::remove_heap(edge_heap.begin(), - edge_heap.end(), - edge_heap.begin() + e->heap_idx, - flipper.priority(), - EdgeInfo::NotifyPos()); - CARVE_ASSERT(edge_heap.back() == e); - edge_heap.pop_back(); - e->heap_idx = ~0U; - } else if (heap_pre && heap_post) { - CARVE_ASSERT(edge_heap[e->heap_idx] == e); - carve::heap::adjust_heap(edge_heap.begin(), - edge_heap.end(), - edge_heap.begin() + e->heap_idx, - flipper.priority(), - EdgeInfo::NotifyPos()); - CARVE_ASSERT(edge_heap[e->heap_idx] == e); - } - } - - - std::string vk(const vertex_t *v1, - const vertex_t *v2, - const vertex_t *v3) { - const vertex_t *v[3]; - v[0] = v1; v[1] = v2; v[2] = v3; - std::sort(v, v+3); - std::ostringstream s; - s << v[0] << ";" << v[1] << ";" << v[2]; - return s.str(); - } - - std::string vk(const face_t *f) { return vk(f->edge->vert, f->edge->next->vert, f->edge->next->next->vert); } - - int mapTriangle(const face_t *face, - const vertex_t *remap1, const vertex_t *remap2, - const vector_t &tgt, - vector_t tri[3]) { - edge_t *edge = face->edge; - int n_remaps = 0; - for (size_t i = 0; i < 3; edge = edge->next, ++i) { - if (edge->vert == remap1) { tri[i] = tgt; ++n_remaps; } - else if (edge->vert == remap2) { tri[i] = tgt; ++n_remaps; } - else { tri[i] = edge->vert->v; } - } - return n_remaps; - } - - template<typename iter1_t, typename iter2_t> - int countIntersectionPairs(iter1_t fabegin, iter1_t faend, - iter2_t fbbegin, iter2_t fbend, - const vertex_t *remap1, const vertex_t *remap2, - const vector_t &tgt) { - vector_t tri_a[3], tri_b[3]; - int remap_a, remap_b; - std::set<std::pair<const face_t *, const face_t *> > ints; - - for (iter1_t i = fabegin; i != faend; ++i) { - remap_a = mapTriangle(*i, remap1, remap2, tgt, tri_a); - if (remap_a >= 2) continue; - for (iter2_t j = fbbegin; j != fbend; ++j) { - remap_b = mapTriangle(*j, remap1, remap2, tgt, tri_b); - if (remap_b >= 2) continue; - if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) { - ints.insert(std::make_pair(std::min(*i, *j), std::max(*i, *j))); - } - } - } - - return ints.size(); - } - - int countIntersections(const vertex_t *v1, - const vertex_t *v2, - const vertex_t *v3, - const std::vector<face_t *> &faces) { - int n_int = 0; - vector_t tri_a[3], tri_b[3]; - tri_a[0] = v1->v; - tri_a[1] = v2->v; - tri_a[2] = v3->v; - - for (std::vector<face_t *>::const_iterator i = faces.begin(); i != faces.end(); ++i) { - face_t *fb = *i; - if (fb->nEdges() != 3) continue; - tri_b[0] = fb->edge->vert->v; - tri_b[1] = fb->edge->next->vert->v; - tri_b[2] = fb->edge->next->next->vert->v; - - if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) { - n_int++; - } - } - return n_int; - } - - - - int _findSelfIntersections(const face_rtree_t *a_node, - const face_rtree_t *b_node, - bool descend_a = true) { - int r = 0; - - if (!a_node->bbox.intersects(b_node->bbox)) { - return 0; - } - - if (a_node->child && (descend_a || !b_node->child)) { - for (face_rtree_t *node = a_node->child; node; node = node->sibling) { - r += _findSelfIntersections(node, b_node, false); - } - } else if (b_node->child) { - for (face_rtree_t *node = b_node->child; node; node = node->sibling) { - r += _findSelfIntersections(a_node, node, true); - } - } else { - for (size_t i = 0; i < a_node->data.size(); ++i) { - face_t *fa = a_node->data[i]; - if (fa->nVertices() != 3) continue; - - aabb_t aabb_a = fa->getAABB(); - - vector_t tri_a[3]; - tri_a[0] = fa->edge->vert->v; - tri_a[1] = fa->edge->next->vert->v; - tri_a[2] = fa->edge->next->next->vert->v; - - if (!aabb_a.intersects(b_node->bbox)) continue; - - for (size_t j = 0; j < b_node->data.size(); ++j) { - face_t *fb = b_node->data[j]; - if (fb->nVertices() != 3) continue; - - vector_t tri_b[3]; - tri_b[0] = fb->edge->vert->v; - tri_b[1] = fb->edge->next->vert->v; - tri_b[2] = fb->edge->next->next->vert->v; - - if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) { - ++r; - } - } - } - } - - return r; - } - - - - int countSelfIntersections(meshset_t *meshset) { - int n_ints = 0; - face_rtree_t *tree = face_rtree_t::construct_STR(meshset->faceBegin(), meshset->faceEnd(), 4, 4); - - for (meshset_t::face_iter f = meshset->faceBegin(); f != meshset->faceEnd(); ++f) { - face_t *fa = *f; - if (fa->nVertices() != 3) continue; - - vector_t tri_a[3]; - tri_a[0] = fa->edge->vert->v; - tri_a[1] = fa->edge->next->vert->v; - tri_a[2] = fa->edge->next->next->vert->v; - - std::vector<face_t *> near_faces; - tree->search(fa->getAABB(), std::back_inserter(near_faces)); - - for (size_t f2 = 0; f2 < near_faces.size(); ++f2) { - const face_t *fb = near_faces[f2]; - if (fb->nVertices() != 3) continue; - - if (fa >= fb) continue; - - vector_t tri_b[3]; - tri_b[0] = fb->edge->vert->v; - tri_b[1] = fb->edge->next->vert->v; - tri_b[2] = fb->edge->next->next->vert->v; - - if (carve::geom::triangle_intersection_exact(tri_a, tri_b) == carve::geom::TR_TYPE_INT) { - ++n_ints; - } - } - } - - delete tree; - - return n_ints; - } - - size_t flipEdges(meshset_t *mesh, - const FlippableBase &flipper) { - face_rtree_t *tree = face_rtree_t::construct_STR(mesh->faceBegin(), mesh->faceEnd(), 4, 4); - - size_t n_mods = 0; - - std::vector<EdgeInfo *> edge_heap; - - edge_heap.reserve(edge_info.size()); - - for (edge_info_map_t::iterator i = edge_info.begin(); - i != edge_info.end(); - ++i) { - EdgeInfo *e = (*i).second; - e->update(); - if (e->edge->v1() < e->edge->v2() && flipper.canFlip(e)) { - edge_heap.push_back(e); - } else { - e->heap_idx = ~0U; - } - } - - carve::heap::make_heap(edge_heap.begin(), - edge_heap.end(), - flipper.priority(), - EdgeInfo::NotifyPos()); - - while (edge_heap.size()) { -// std::cerr << "test" << std::endl; -// for (size_t m = 0; m < mesh->meshes.size(); ++m) { -// for (size_t f = 0; f < mesh->meshes[m]->faces.size(); ++f) { -// if (mesh->meshes[m]->faces[f]->edge) mesh->meshes[m]->faces[f]->edge->validateLoop(); -// } -// } - - carve::heap::pop_heap(edge_heap.begin(), - edge_heap.end(), - flipper.priority(), - EdgeInfo::NotifyPos()); - EdgeInfo *e = edge_heap.back(); -// std::cerr << "flip " << e << std::endl; - edge_heap.pop_back(); - e->heap_idx = ~0U; - - aabb_t aabb; - aabb = e->edge->face->getAABB(); - aabb.unionAABB(e->edge->rev->face->getAABB()); - - std::vector<face_t *> overlapping; - tree->search(aabb, std::back_inserter(overlapping)); - - // overlapping.erase(e->edge->face); - // overlapping.erase(e->edge->rev->face); - - const vertex_t *v1 = e->edge->vert; - const vertex_t *v2 = e->edge->next->vert; - const vertex_t *v3 = e->edge->next->next->vert; - const vertex_t *v4 = e->edge->rev->next->next->vert; - - int n_int1 = countIntersections(v1, v2, v3, overlapping); - int n_int2 = countIntersections(v2, v1, v4, overlapping); - int n_int3 = countIntersections(v3, v4, v2, overlapping); - int n_int4 = countIntersections(v4, v3, v1, overlapping); - - if ((n_int3 + n_int4) - (n_int1 + n_int2) > 0) { - std::cerr << "delta[ints] = " << (n_int3 + n_int4) - (n_int1 + n_int2) << std::endl; - // avoid creating a self intersection. - continue; - } - - n_mods++; - CARVE_ASSERT(flipper.canFlip(e)); - edge_info[e->edge]->update(); - edge_info[e->edge->rev]->update(); - - carve::mesh::flipTriEdge(e->edge); - - tree->updateExtents(aabb); - - updateEdgeFlipHeap(edge_heap, e->edge, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->rev, flipper); - - CARVE_ASSERT(!flipper.canFlip(e)); - - updateEdgeFlipHeap(edge_heap, e->edge->next, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->next->next, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->rev->next, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->rev->next->next, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->next->rev, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->next->next->rev, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->rev->next->rev, flipper); - updateEdgeFlipHeap(edge_heap, e->edge->rev->next->next->rev, flipper); - } - - delete tree; - - return n_mods; - } - - - - void removeFromEdgeMergeHeap(std::vector<EdgeInfo *> &edge_heap, - EdgeInfo *edge, - const EdgeMerger &merger) { - if (edge->heap_idx != ~0U) { - CARVE_ASSERT(edge_heap[edge->heap_idx] == edge); - carve::heap::remove_heap(edge_heap.begin(), - edge_heap.end(), - edge_heap.begin() + edge->heap_idx, - merger.priority(), - EdgeInfo::NotifyPos()); - CARVE_ASSERT(edge_heap.back() == edge); - edge_heap.pop_back(); - edge->heap_idx = ~0U; - } - } - - void updateEdgeMergeHeap(std::vector<EdgeInfo *> &edge_heap, - EdgeInfo *edge, - const EdgeMerger &merger) { - bool heap_pre = edge->heap_idx != ~0U; - edge->update(); - bool heap_post = merger.canMerge(edge); - - if (!heap_pre && heap_post) { - edge_heap.push_back(edge); - carve::heap::push_heap(edge_heap.begin(), - edge_heap.end(), - merger.priority(), - EdgeInfo::NotifyPos()); - } else if (heap_pre && !heap_post) { - CARVE_ASSERT(edge_heap[edge->heap_idx] == edge); - carve::heap::remove_heap(edge_heap.begin(), - edge_heap.end(), - edge_heap.begin() + edge->heap_idx, - merger.priority(), - EdgeInfo::NotifyPos()); - CARVE_ASSERT(edge_heap.back() == edge); - edge_heap.pop_back(); - edge->heap_idx = ~0U; - } else if (heap_pre && heap_post) { - CARVE_ASSERT(edge_heap[edge->heap_idx] == edge); - carve::heap::adjust_heap(edge_heap.begin(), - edge_heap.end(), - edge_heap.begin() + edge->heap_idx, - merger.priority(), - EdgeInfo::NotifyPos()); - CARVE_ASSERT(edge_heap[edge->heap_idx] == edge); - } - } - - - - // collapse edges edges based upon the predicate implemented by EdgeMerger. - size_t collapseEdges(meshset_t *mesh, - const EdgeMerger &merger) { - face_rtree_t *tree = face_rtree_t::construct_STR(mesh->faceBegin(), mesh->faceEnd(), 4, 4); - - size_t n_mods = 0; - - std::vector<EdgeInfo *> edge_heap; - std::unordered_map<vertex_t *, std::set<EdgeInfo *> > vert_to_edges; - - edge_heap.reserve(edge_info.size()); - - for (edge_info_map_t::iterator i = edge_info.begin(); - i != edge_info.end(); - ++i) { - EdgeInfo *e = (*i).second; - - vert_to_edges[e->edge->v1()].insert(e); - vert_to_edges[e->edge->v2()].insert(e); - - if (merger.canMerge(e)) { - edge_heap.push_back(e); - } else { - e->heap_idx = ~0U; - } - } - - carve::heap::make_heap(edge_heap.begin(), - edge_heap.end(), - merger.priority(), - EdgeInfo::NotifyPos()); - - while (edge_heap.size()) { -// std::cerr << "test" << std::endl; -// for (size_t m = 0; m < mesh->meshes.size(); ++m) { -// for (size_t f = 0; f < mesh->meshes[m]->faces.size(); ++f) { -// if (mesh->meshes[m]->faces[f]->edge) mesh->meshes[m]->faces[f]->edge->validateLoop(); -// } -// } - carve::heap::pop_heap(edge_heap.begin(), - edge_heap.end(), - merger.priority(), - EdgeInfo::NotifyPos()); - EdgeInfo *e = edge_heap.back(); - edge_heap.pop_back(); - e->heap_idx = ~0U; - - edge_t *edge = e->edge; - vertex_t *v1 = edge->v1(); - vertex_t *v2 = edge->v2(); - - std::set<face_t *> affected_faces; - for (std::set<EdgeInfo *>::iterator f = vert_to_edges[v1].begin(); - f != vert_to_edges[v1].end(); - ++f) { - affected_faces.insert((*f)->edge->face); - affected_faces.insert((*f)->edge->rev->face); - } - for (std::set<EdgeInfo *>::iterator f = vert_to_edges[v2].begin(); - f != vert_to_edges[v2].end(); - ++f) { - affected_faces.insert((*f)->edge->face); - affected_faces.insert((*f)->edge->rev->face); - } - - std::vector<EdgeInfo *> edges_to_merge; - std::vector<EdgeInfo *> v1_incident; - std::vector<EdgeInfo *> v2_incident; - - std::set_intersection(vert_to_edges[v1].begin(), vert_to_edges[v1].end(), - vert_to_edges[v2].begin(), vert_to_edges[v2].end(), - std::back_inserter(edges_to_merge)); - - CARVE_ASSERT(edges_to_merge.size() > 0); - - std::set_difference(vert_to_edges[v1].begin(), vert_to_edges[v1].end(), - edges_to_merge.begin(), edges_to_merge.end(), - std::back_inserter(v1_incident)); - std::set_difference(vert_to_edges[v2].begin(), vert_to_edges[v2].end(), - edges_to_merge.begin(), edges_to_merge.end(), - std::back_inserter(v2_incident)); - - vector_t aabb_min, aabb_max; - assign_op(aabb_min, v1->v, v2->v, carve::util::min_functor()); - assign_op(aabb_max, v1->v, v2->v, carve::util::max_functor()); - - for (size_t i = 0; i < v1_incident.size(); ++i) { - assign_op(aabb_min, aabb_min, v1_incident[i]->edge->v1()->v, carve::util::min_functor()); - assign_op(aabb_max, aabb_max, v1_incident[i]->edge->v1()->v, carve::util::max_functor()); - assign_op(aabb_min, aabb_min, v1_incident[i]->edge->v2()->v, carve::util::min_functor()); - assign_op(aabb_max, aabb_max, v1_incident[i]->edge->v2()->v, carve::util::max_functor()); - } - - for (size_t i = 0; i < v2_incident.size(); ++i) { - assign_op(aabb_min, aabb_min, v2_incident[i]->edge->v1()->v, carve::util::min_functor()); - assign_op(aabb_max, aabb_max, v2_incident[i]->edge->v1()->v, carve::util::max_functor()); - assign_op(aabb_min, aabb_min, v2_incident[i]->edge->v2()->v, carve::util::min_functor()); - assign_op(aabb_max, aabb_max, v2_incident[i]->edge->v2()->v, carve::util::max_functor()); - } - - aabb_t aabb; - aabb.fit(aabb_min, aabb_max); - - std::vector<face_t *> near_faces; - tree->search(aabb, std::back_inserter(near_faces)); - - double frac = 0.5; // compute this based upon v1_incident and v2_incident? - vector_t merge = frac * v1->v + (1 - frac) * v2->v; - - int i1 = countIntersectionPairs(affected_faces.begin(), affected_faces.end(), - near_faces.begin(), near_faces.end(), - NULL, NULL, merge); - int i2 = countIntersectionPairs(affected_faces.begin(), affected_faces.end(), - near_faces.begin(), near_faces.end(), - v1, v2, merge); - if (i2 != i1) { - std::cerr << "near faces: " << near_faces.size() << " affected faces: " << affected_faces.size() << std::endl; - std::cerr << "merge delta[ints] = " << i2 - i1 << " pre: " << i1 << " post: " << i2 << std::endl; - if (i2 > i1) continue; - } - - std::cerr << "collapse " << e << std::endl; - - v2->v = merge; - ++n_mods; - - for (size_t i = 0; i < v1_incident.size(); ++i) { - if (v1_incident[i]->edge->vert == v1) { - v1_incident[i]->edge->vert = v2; - } - } - - for (size_t i = 0; i < v1_incident.size(); ++i) { - updateEdgeMergeHeap(edge_heap, v1_incident[i], merger); - } - - for (size_t i = 0; i < v2_incident.size(); ++i) { - updateEdgeMergeHeap(edge_heap, v2_incident[i], merger); - } - - vert_to_edges[v2].insert(vert_to_edges[v1].begin(), vert_to_edges[v1].end()); - vert_to_edges.erase(v1); - - for (size_t i = 0; i < edges_to_merge.size(); ++i) { - EdgeInfo *e = edges_to_merge[i]; - - removeFromEdgeMergeHeap(edge_heap, e, merger); - edge_info.erase(e->edge); - - vert_to_edges[v1].erase(e); - vert_to_edges[v2].erase(e); - - face_t *f1 = e->edge->face; - - e->edge->removeHalfEdge(); - - if (f1->n_edges == 2) { - edge_t *e1 = f1->edge; - edge_t *e2 = f1->edge->next; - if (e1->rev) e1->rev->rev = e2->rev; - if (e2->rev) e2->rev->rev = e1->rev; - EdgeInfo *e1i = edge_info[e1]; - EdgeInfo *e2i = edge_info[e2]; - CARVE_ASSERT(e1i != NULL); - CARVE_ASSERT(e2i != NULL); - vert_to_edges[e1->v1()].erase(e1i); - vert_to_edges[e1->v2()].erase(e1i); - vert_to_edges[e2->v1()].erase(e2i); - vert_to_edges[e2->v2()].erase(e2i); - removeFromEdgeMergeHeap(edge_heap, e1i, merger); - removeFromEdgeMergeHeap(edge_heap, e2i, merger); - edge_info.erase(e1); - edge_info.erase(e2); - f1->clearEdges(); - tree->remove(f1, aabb); - - delete e1i; - delete e2i; - } - delete e; - } - - tree->updateExtents(aabb); - } - - delete tree; - - return n_mods; - } - - - - size_t mergeCoplanarFaces(mesh_t *mesh, double min_normal_angle) { - std::unordered_set<edge_t *> coplanar_face_edges; - double min_dp = cos(min_normal_angle); - size_t n_merge = 0; - - for (size_t i = 0; i < mesh->closed_edges.size(); ++i) { - edge_t *e = mesh->closed_edges[i]; - face_t *f1 = e->face; - face_t *f2 = e->rev->face; - - if (carve::geom::dot(f1->plane.N, f2->plane.N) < min_dp) { - continue; - } - - coplanar_face_edges.insert(std::min(e, e->rev)); - } - - while (coplanar_face_edges.size()) { - edge_t *edge = *coplanar_face_edges.begin(); - if (edge->face == edge->rev->face) { - coplanar_face_edges.erase(edge); - continue; - } - - edge_t *removed = edge->mergeFaces(); - if (removed == NULL) { - coplanar_face_edges.erase(edge); - ++n_merge; - } else { - edge_t *e = removed; - do { - edge_t *n = e->next; - coplanar_face_edges.erase(std::min(e, e->rev)); - delete e->rev; - delete e; - e = n; - } while (e != removed); - } - } - return n_merge; - } - - - - uint8_t affected_axes(const face_t *face) { - uint8_t r = 0; - if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(1,0,0))) > 0.001) r |= 1; - if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(0,1,0))) > 0.001) r |= 2; - if (fabs(carve::geom::dot(face->plane.N, carve::geom::VECTOR(0,0,1))) > 0.001) r |= 4; - return r; - } - - - - double median(std::vector<double> &v) { - if (v.size() & 1) { - size_t N = v.size() / 2 + 1; - std::nth_element(v.begin(), v.begin() + N, v.end()); - return v[N]; - } else { - size_t N = v.size() / 2; - std::nth_element(v.begin(), v.begin() + N, v.end()); - return (v[N] + *std::min_element(v.begin() + N + 1, v.end())) / 2.0; - } - } - - - - double harmonicmean(const std::vector<double> &v) { - double m = 0.0; - for (size_t i = 0; i < v.size(); ++i) { - m *= v[i]; - } - return pow(m, 1.0 / v.size()); - } - - - - double mean(const std::vector<double> &v) { - double m = 0.0; - for (size_t i = 0; i < v.size(); ++i) { - m += v[i]; - } - return m / v.size(); - } - - - - template<typename iter_t> - void snapFaces(iter_t begin, iter_t end, double grid, int axis) { - std::set<vertex_t *> vertices; - for (iter_t i = begin; i != end; ++i) { - face_t *face = *i; - edge_t *edge = face->edge; - do { - vertices.insert(edge->vert); - edge = edge->next; - } while (edge != face->edge); - } - - std::vector<double> pos; - pos.reserve(vertices.size()); - for (std::set<vertex_t *>::iterator i = vertices.begin(); i != vertices.end(); ++i) { - pos.push_back((*i)->v.v[axis]); - } - - double med = median(pos); - - double snap_pos = med; - if (grid) snap_pos = round(snap_pos / grid) * grid; - - for (std::set<vertex_t *>::iterator i = vertices.begin(); i != vertices.end(); ++i) { - (*i)->v.v[axis] = snap_pos; - } - - for (iter_t i = begin; i != end; ++i) { - face_t *face = *i; - face->recalc(); - edge_t *edge = face->edge; - do { - if (edge->rev && edge->rev->face) edge->rev->face->recalc(); - edge = edge->next; - } while (edge != face->edge); - } - } - - carve::geom::plane<3> quantizePlane(const face_t *face, - int angle_xy_quantization, - int angle_z_quantization) { - if (!angle_xy_quantization && !angle_z_quantization) { - return face->plane; - } - carve::geom::vector<3> normal = face->plane.N; - - if (angle_z_quantization) { - if (normal.x || normal.y) { - double a = asin(std::min(std::max(normal.z, 0.0), 1.0)); - a = round(a * angle_z_quantization / (M_PI * 2)) * (M_PI * 2) / angle_z_quantization; - normal.z = sin(a); - double s = sqrt((1 - normal.z * normal.z) / (normal.x * normal.x + normal.y * normal.y)); - normal.x = normal.x * s; - normal.y = normal.y * s; - } - } - if (angle_xy_quantization) { - if (normal.x || normal.y) { - double a = atan2(normal.y, normal.x); - a = round(a * angle_xy_quantization / (M_PI * 2)) * (M_PI * 2) / angle_xy_quantization; - double s = sqrt(1 - normal.z * normal.z); - s = std::min(std::max(s, 0.0), 1.0); - normal.x = cos(a) * s; - normal.y = sin(a) * s; - } - } - - std::cerr << "normal = " << normal << std::endl; - - std::vector<double> d_vec; - d_vec.reserve(face->nVertices()); - edge_t *e = face->edge; - do { - d_vec.push_back(-carve::geom::dot(normal, e->vert->v)); - e = e->next; - } while (e != face->edge); - - return carve::geom::plane<3>(normal, mean(d_vec)); - } - - - - double summedError(const carve::geom::vector<3> &vert, const std::list<carve::geom::plane<3> > &planes) { - double d = 0; - for (std::list<carve::geom::plane<3> >::const_iterator i = planes.begin(); i != planes.end(); ++i) { - d += fabs(carve::geom::distance2(*i, vert)); - } - return d; - } - - - - double minimize(carve::geom::vector<3> &vert, const std::list<carve::geom::plane<3> > &planes, int axis) { - double num = 0.0; - double den = 0.0; - int a1 = (axis + 1) % 3; - int a2 = (axis + 2) % 3; - for (std::list<carve::geom::plane<3> >::const_iterator i = planes.begin(); i != planes.end(); ++i) { - const carve::geom::vector<3> &N = (*i).N; - const double d = (*i).d; - den += N.v[axis] * N.v[axis]; - num -= N.v[axis] * (N.v[a1] * vert.v[a1] + N.v[a2] * vert.v[a2] + d); - } - if (fabs(den) < 1e-5) return vert.v[axis]; - return num / den; - } - - - - size_t cleanFaceEdges(mesh_t *mesh) { - size_t n_removed = 0; - for (size_t i = 0; i < mesh->faces.size(); ++i) { - face_t *face = mesh->faces[i]; - edge_t *start = face->edge; - edge_t *edge = start; - do { - if (edge->next == edge->rev || edge->prev == edge->rev) { - edge = edge->removeEdge(); - ++n_removed; - start = edge->prev; - } else { - edge = edge->next; - } - } while (edge != start); - } - return n_removed; - } - - - - size_t cleanFaceEdges(meshset_t *mesh) { - size_t n_removed = 0; - for (size_t i = 0; i < mesh->meshes.size(); ++i) { - n_removed += cleanFaceEdges(mesh->meshes[i]); - } - return n_removed; - } - - - - void removeRemnantFaces(mesh_t *mesh) { - size_t n = 0; - for (size_t i = 0; i < mesh->faces.size(); ++i) { - if (mesh->faces[i]->nEdges() == 0) { - delete mesh->faces[i]; - } else { - mesh->faces[n++] = mesh->faces[i]; - } - } - mesh->faces.resize(n); - } - - - - void removeRemnantFaces(meshset_t *mesh) { - for (size_t i = 0; i < mesh->meshes.size(); ++i) { - removeRemnantFaces(mesh->meshes[i]); - } - } - - - - edge_t *removeFin(edge_t *e) { - // e and e->next are shared with the same reverse triangle. - edge_t *e1 = e->prev; - edge_t *e2 = e->rev->next; - CARVE_ASSERT(e1->v2() == e2->v1()); - CARVE_ASSERT(e2->v2() == e1->v1()); - - CARVE_ASSERT(e1->rev != e2 && e2->rev != e1); - - edge_t *e1r = e1->rev; - edge_t *e2r = e2->rev; - if (e1r) e1r->rev = e2r; - if (e2r) e2r->rev = e1r; - - face_t *f1 = e1->face; - face_t *f2 = e2->face; - f1->clearEdges(); - f2->clearEdges(); - - return e1r; - } - - size_t removeFin(face_t *face) { - if (face->edge == NULL || face->nEdges() != 3) return 0; - edge_t *e = face->edge; - do { - if (e->rev != NULL) { - face_t *revface = e->rev->face; - if (revface->nEdges() == 3) { - if (e->next->rev && e->next->rev->face == revface) { - if (e->next->next->rev && e->next->next->rev->face == revface) { - // isolated tripair - face->clearEdges(); - revface->clearEdges(); - return 1; - } - // fin - edge_t *spliced_edge = removeFin(e); - return 1 + removeFin(spliced_edge->face); - } - } - } - e = e->next; - } while (e != face->edge); - return 0; - } - - - - public: - // Merge adjacent coplanar faces (where coplanar is determined - // by dot-product >= cos(min_normal_angle)). - size_t mergeCoplanarFaces(meshset_t *meshset, double min_normal_angle) { - size_t n_removed = 0; - for (size_t i = 0; i < meshset->meshes.size(); ++i) { - n_removed += mergeCoplanarFaces(meshset->meshes[i], min_normal_angle); - removeRemnantFaces(meshset->meshes[i]); - cleanFaceEdges(meshset->meshes[i]); - meshset->meshes[i]->cacheEdges(); - } - return n_removed; - } - - size_t improveMesh_conservative(meshset_t *meshset) { - initEdgeInfo(meshset); - size_t modifications = flipEdges(meshset, FlippableConservative()); - clearEdgeInfo(); - return modifications; - } - - void dissolveMeshEdges(mesh_t *mesh, std::unordered_set<edge_t *> dissolve_edges) { - while (dissolve_edges.size()) { - MeshSet<3>::edge_t *edge = *dissolve_edges.begin(); - if (edge->face == edge->rev->face) { - dissolve_edges.erase(edge); - continue; - } - - MeshSet<3>::edge_t *removed = edge->mergeFaces(); - if (removed == NULL) { - dissolve_edges.erase(edge); - } else { - MeshSet<3>::edge_t *e = removed; - do { - MeshSet<3>::edge_t *n = e->next; - dissolve_edges.erase(std::min(e, e->rev)); - delete e->rev; - delete e; - e = n; - } while (e != removed); - } - } - - removeRemnantFaces(mesh); - cleanFaceEdges(mesh); - mesh->cacheEdges(); - } - - - size_t improveMesh(meshset_t *meshset, - double min_colinearity, - double min_delta_v, - double min_normal_angle) { - initEdgeInfo(meshset); - size_t modifications = flipEdges(meshset, Flippable(min_colinearity, min_delta_v, min_normal_angle)); - clearEdgeInfo(); - return modifications; - } - - - - size_t eliminateShortEdges(meshset_t *meshset, - double min_length) { - initEdgeInfo(meshset); - size_t modifications = collapseEdges(meshset, EdgeMerger(min_length)); - removeRemnantFaces(meshset); - clearEdgeInfo(); - return modifications; - } - - - - // Snap vertices to grid, aligning almost flat axis-aligned - // faces to the axis, and flattening other faces as much as is - // possible. Passing a number less than DBL_MIN_EXPONENT (-1021) - // turns off snapping to grid (but face alignment is still - // performed). - void snap(meshset_t *meshset, - int log2_grid, - int angle_xy_quantization = 0, - int angle_z_quantization = 0) { - double grid = 0.0; - if (log2_grid >= std::numeric_limits<double>::min_exponent) grid = pow(2.0, (double)log2_grid); - - typedef std::unordered_map<face_t *, uint8_t> axis_influence_map_t; - axis_influence_map_t axis_influence; - - typedef std::unordered_map<face_t *, std::set<face_t *> > interaction_graph_t; - interaction_graph_t interacting_faces; - - for (size_t m = 0; m < meshset->meshes.size(); ++m) { - mesh_t *mesh = meshset->meshes[m]; - for (size_t f = 0; f < mesh->faces.size(); ++f) { - face_t *face = mesh->faces[f]; - axis_influence[face] = affected_axes(face); - } - } - - std::map<vertex_t *, std::list<carve::geom::plane<3> > > non_axis_vertices; - std::unordered_map<vertex_t *, uint8_t> vertex_constraints; - - for (axis_influence_map_t::iterator i = axis_influence.begin(); i != axis_influence.end(); ++i) { - face_t *face = (*i).first; - uint8_t face_axes = (*i).second; - edge_t *edge = face->edge; - if (face_axes != 1 && face_axes != 2 && face_axes != 4) { - do { - non_axis_vertices[edge->vert].push_back(quantizePlane(face, - angle_xy_quantization, - angle_z_quantization)); - edge = edge->next; - } while (edge != face->edge); - } else { - interacting_faces[face].insert(face); - do { - vertex_constraints[edge->vert] |= face_axes; - - if (edge->rev && edge->rev->face) { - face_t *face2 = edge->rev->face; - uint8_t face2_axes = axis_influence[face2]; - if (face2_axes == face_axes) { - interacting_faces[face].insert(face2); - } - } - edge = edge->next; - } while (edge != face->edge); - } - } - - while (interacting_faces.size()) { - std::set<face_t *> face_set; - uint8_t axes = 0; - - std::set<face_t *> open; - open.insert((*interacting_faces.begin()).first); - while (open.size()) { - face_t *curr = *open.begin(); - open.erase(open.begin()); - face_set.insert(curr); - axes |= axis_influence[curr]; - for (interaction_graph_t::data_type::iterator i = interacting_faces[curr].begin(), e = interacting_faces[curr].end(); i != e; ++i) { - face_t *f = *i; - if (face_set.find(f) != face_set.end()) continue; - open.insert(f); - } - } - - switch (axes) { - case 1: snapFaces(face_set.begin(), face_set.end(), grid, 0); break; - case 2: snapFaces(face_set.begin(), face_set.end(), grid, 1); break; - case 4: snapFaces(face_set.begin(), face_set.end(), grid, 2); break; - default: CARVE_FAIL("should not be reached"); - } - - for (std::set<face_t *>::iterator i = face_set.begin(); i != face_set.end(); ++i) { - interacting_faces.erase((*i)); - } - } - - for (std::map<vertex_t *, std::list<carve::geom::plane<3> > >::iterator i = non_axis_vertices.begin(); i != non_axis_vertices.end(); ++i) { - vertex_t *vert = (*i).first; - std::list<carve::geom::plane<3> > &planes = (*i).second; - uint8_t constraint = vertex_constraints[vert]; - - if (constraint == 7) continue; - - double d = summedError(vert->v, planes); - for (size_t N = 0; ; N = (N+1) % 3) { - if (constraint & (1 << N)) continue; - vert->v[N] = minimize(vert->v, planes, N); - double d_next = summedError(vert->v, planes); - if (d - d_next < 1e-20) break; - d = d_next; - } - - if (grid) { - carve::geom::vector<3> v_best = vert->v; - double d_best = 0.0; - - for (int axes = 0; axes < 8; ++axes) { - carve::geom::vector<3> v = vert->v; - for (int N = 0; N < 3; ++N) { - if (constraint & (1 << N)) continue; - if (axes & (1<<N)) { - v.v[N] = ceil(v.v[N] / grid) * grid; - } else { - v.v[N] = floor(v.v[N] / grid) * grid; - } - } - double d = summedError(v, planes); - if (axes == 0 || d < d_best) { - v_best = v; - d_best = d; - } - } - - vert->v = v_best; - } - } - } - - - - size_t simplify(meshset_t *meshset, - double min_colinearity, - double min_delta_v, - double min_normal_angle, - double min_length) { - size_t modifications = 0; - size_t n, n_flip, n_merge; - - initEdgeInfo(meshset); - - std::cerr << "initial merge" << std::endl; - modifications = collapseEdges(meshset, EdgeMerger(0.0)); - removeRemnantFaces(meshset); - - do { - n_flip = n_merge = 0; - // std::cerr << "flip colinear pairs"; - // n = flipEdges(meshset, FlippableColinearPair()); - // std::cerr << " " << n << std::endl; - // n_flip = n; - - std::cerr << "flip conservative"; - n = flipEdges(meshset, FlippableConservative()); - std::cerr << " " << n << std::endl; - n_flip += n; - - std::cerr << "flip"; - n = flipEdges(meshset, Flippable(min_colinearity, min_delta_v, min_normal_angle)); - std::cerr << " " << n << std::endl; - n_flip += n; - - std::cerr << "merge"; - n = collapseEdges(meshset, EdgeMerger(min_length)); - removeRemnantFaces(meshset); - std::cerr << " " << n << std::endl; - n_merge = n; - - modifications += n_flip + n_merge; - std::cerr << "stats:" << n_flip << " " << n_merge << std::endl; - } while (n_flip || n_merge); - - clearEdgeInfo(); - - for (size_t i = 0; i < meshset->meshes.size(); ++i) { - meshset->meshes[i]->cacheEdges(); - } - - return modifications; - } - - - - size_t removeFins(mesh_t *mesh) { - size_t n_removed = 0; - for (size_t i = 0; i < mesh->faces.size(); ++i) { - n_removed += removeFin(mesh->faces[i]); - } - if (n_removed) removeRemnantFaces(mesh); - return n_removed; - } - - - - size_t removeFins(meshset_t *meshset) { - size_t n_removed = 0; - for (size_t i = 0; i < meshset->meshes.size(); ++i) { - n_removed += removeFins(meshset->meshes[i]); - } - return n_removed; - } - - - - size_t removeLowVolumeManifolds(meshset_t *meshset, double min_abs_volume) { - size_t n_removed = 0; - for (size_t i = 0; i < meshset->meshes.size(); ++i) { - if (fabs(meshset->meshes[i]->volume()) < min_abs_volume) { - delete meshset->meshes[i]; - meshset->meshes[i] = NULL; - ++n_removed; - } - } - meshset->meshes.erase(std::remove_if(meshset->meshes.begin(), - meshset->meshes.end(), - std::bind2nd(std::equal_to<mesh_t *>(), (mesh_t *)NULL)), - meshset->meshes.end()); - return n_removed; - } - - struct point_enumerator_t { - struct heapval_t { - double dist; - vector_t pt; - heapval_t(double _dist, vector_t _pt) : dist(_dist), pt(_pt) { - } - heapval_t() {} - bool operator==(const heapval_t &other) const { return dist == other.dist && pt == other.pt; } - bool operator<(const heapval_t &other) const { return dist > other.dist || (dist == other.dist && pt > other.pt); } - }; - - vector_t origin; - double rounding_fac; - heapval_t last; - std::vector<heapval_t> heap; - - point_enumerator_t(vector_t _origin, int _base, int _n_dp) : origin(_origin), rounding_fac(pow((double)_base, _n_dp)), last(-1.0, _origin), heap() { - for (int i = 0; i < (1 << 3); ++i) { - vector_t t = origin; - for (int j = 0; j < 3; ++j) { - if (i & (1U << j)) { - t[j] = ceil(t[j] * rounding_fac) / rounding_fac; - } else { - t[j] = floor(t[j] * rounding_fac) / rounding_fac; - } - } - heap.push_back(heapval_t(carve::geom::distance2(origin, t), t)); - } - std::make_heap(heap.begin(), heap.end()); - } - - vector_t next() { - heapval_t curr; - do { - CARVE_ASSERT(heap.size()); - std::pop_heap(heap.begin(), heap.end()); - curr = heap.back(); - heap.pop_back(); - } while (curr == last); - - vector_t t; - - for (int dx = -1; dx <= +1; ++dx) { - t.x = floor(curr.pt.x * rounding_fac + dx) / rounding_fac; - for (int dy = -1; dy <= +1; ++dy) { - t.y = floor(curr.pt.y * rounding_fac + dy) / rounding_fac; - for (int dz = -1; dz <= +1; ++dz) { - t.z = floor(curr.pt.z * rounding_fac + dz) / rounding_fac; - heapval_t h2(carve::geom::distance2(origin, t), t); - if (h2 < curr) { - heap.push_back(h2); - std::push_heap(heap.begin(), heap.end()); - } - } - } - } - last = curr; - return curr.pt; - } - }; - - struct quantization_info_t { - point_enumerator_t *pt; - std::set<face_t *> faces; - - quantization_info_t() : pt(NULL), faces() { - } - - ~quantization_info_t() { - if (pt) delete pt; - } - - aabb_t getAABB() const { - std::set<face_t *>::const_iterator i = faces.begin(); - aabb_t aabb = (*i)->getAABB(); - while (++i != faces.end()) { - aabb.unionAABB((*i)->getAABB()); - } - return aabb; - } - }; - - void selfIntersectionAwareQuantize(meshset_t *meshset, int base, int n_dp) { - typedef std::unordered_map<vertex_t *, quantization_info_t> vfsmap_t; - - vfsmap_t vertex_qinfo; - - for (size_t m = 0; m < meshset->meshes.size(); ++m) { - mesh_t *mesh = meshset->meshes[m]; - for (size_t f = 0; f < mesh->faces.size(); ++f) { - face_t *face = mesh->faces[f]; - edge_t *e = face->edge; - do { - vertex_qinfo[e->vert].faces.insert(face); - e = e->next; - } while (e != face->edge); - } - } - - face_rtree_t *tree = face_rtree_t::construct_STR(meshset->faceBegin(), meshset->faceEnd(), 4, 4); - - for (vfsmap_t::iterator i = vertex_qinfo.begin(); i != vertex_qinfo.end(); ++i) { - (*i).second.pt = new point_enumerator_t((*i).first->v, base, n_dp); - } - - while (vertex_qinfo.size()) { - std::vector<vertex_t *> quantized; - - std::cerr << "vertex_qinfo.size() == " << vertex_qinfo.size() << std::endl; - - for (vfsmap_t::iterator i = vertex_qinfo.begin(); i != vertex_qinfo.end(); ++i) { - vertex_t *vert = (*i).first; - quantization_info_t &qi = (*i).second; - vector_t q_pt = qi.pt->next(); - aabb_t aabb = qi.getAABB(); - aabb.unionAABB(aabb_t(q_pt)); - - std::vector<face_t *> overlapping; - tree->search(aabb, std::back_inserter(overlapping)); - - - int n_intersections = countIntersectionPairs(qi.faces.begin(), qi.faces.end(), - overlapping.begin(), overlapping.end(), - vert, NULL, q_pt); - - if (n_intersections == 0) { - vert->v = q_pt; - quantized.push_back((*i).first); - tree->updateExtents(aabb); - } - } - for (size_t i = 0; i < quantized.size(); ++i) { - vertex_qinfo.erase(quantized[i]); - } - - if (!quantized.size()) break; - } - } - - - }; - } -} |