// Begin License: // Copyright (C) 2006-2008 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 the GNU General Public // License version 2.0 as published by the Free Software Foundation // and appearing in the file LICENSE.GPL2 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 #include #include namespace carve { namespace poly { template struct VPtrSort { order_t ℴ VPtrSort(order_t &_order) : order(_order) {} bool operator()(carve::poly::Polyhedron::vertex_t const *a, carve::poly::Polyhedron::vertex_t const *b) const { return order(a->v, b->v); } }; template bool Geometry<3>::orderVertices(order_t order) { static carve::TimingName FUNC_NAME("Geometry<3>::orderVertices()"); carve::TimingBlock block(FUNC_NAME); std::vector vptr; std::vector vmap; std::vector vout; const size_t N = vertices.size(); vptr.reserve(N); vout.reserve(N); vmap.resize(N); for (size_t i = 0; i != N; ++i) { vptr.push_back(&vertices[i]); } std::sort(vptr.begin(), vptr.end(), VPtrSort(order)); for (size_t i = 0; i != N; ++i) { vout.push_back(*vptr[i]); vmap[vertexToIndex_fast(vptr[i])] = &vout[i]; } for (size_t i = 0; i < faces.size(); ++i) { face_t &f = faces[i]; for (size_t j = 0; j < f.nVertices(); ++j) { f.vertex(j) = vmap[vertexToIndex_fast(f.vertex(j))]; } } for (size_t i = 0; i < edges.size(); ++i) { edges[i].v1 = vmap[vertexToIndex_fast(edges[i].v1)]; edges[i].v2 = vmap[vertexToIndex_fast(edges[i].v2)]; } vout.swap(vertices); return true; } template int Geometry<3>::_faceNeighbourhood(const face_t *f, int depth, T *result) const { if (depth < 0 || f->is_tagged()) return 0; f->tag(); *(*result)++ = f; int r = 1; for (size_t i = 0; i < f->edges.size(); ++i) { const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(f->edges[i])]; const face_t *f2 = connectedFace(f, f->edges[i]); if (f2) { r += _faceNeighbourhood(f2, depth - 1, (*result)); } } return r; } template int Geometry<3>::faceNeighbourhood(const face_t *f, int depth, T result) const { tagable::tag_begin(); return _faceNeighbourhood(f, depth, &result); } template int Geometry<3>::faceNeighbourhood(const edge_t *e, int m_id, int depth, T result) const { tagable::tag_begin(); int r = 0; const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)]; for (size_t i = 0; i < edge_faces.size(); ++i) { const face_t *f = edge_faces[i]; if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); } } return r; } template int Geometry<3>::faceNeighbourhood(const vertex_t *v, int m_id, int depth, T result) const { tagable::tag_begin(); int r = 0; const std::vector &vertex_faces = connectivity.vertex_to_face[vertexToIndex_fast(v)]; for (size_t i = 0; i < vertex_faces.size(); ++i) { const face_t *f = vertex_faces[i]; if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); } } return r; } // accessing connectivity information. template int Geometry<3>::vertexToEdges(const vertex_t *v, T result) const { const std::vector &e = connectivity.vertex_to_edge[vertexToIndex_fast(v)]; std::copy(e.begin(), e.end(), result); return e.size(); } template int Geometry<3>::vertexToFaces(const vertex_t *v, T result) const { const std::vector &vertex_faces = connectivity.vertex_to_face[vertexToIndex_fast(v)]; int c = 0; for (size_t i = 0; i < vertex_faces.size(); ++i) { *result++ = vertex_faces[i]; ++c; } return c; } template int Geometry<3>::edgeToFaces(const edge_t *e, T result) const { const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)]; int c = 0; for (size_t i = 0; i < edge_faces.size(); ++i) { if (edge_faces[i] != NULL) { *result++ = edge_faces[i]; ++c; } } return c; } inline const Geometry<3>::face_t *Geometry<3>::connectedFace(const face_t *f, const edge_t *e) const { const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)]; for (size_t i = 0; i < (edge_faces.size() & ~1U); i++) { if (edge_faces[i] == f) return edge_faces[i^1]; } return NULL; } inline void Polyhedron::invert(int m_id) { std::vector selected_manifolds(manifold_is_closed.size(), false); if (m_id >=0 && (unsigned)m_id < selected_manifolds.size()) selected_manifolds[m_id] = true; invert(selected_manifolds); } inline void Polyhedron::invert() { invertAll(); } inline bool Polyhedron::edgeOnManifold(const edge_t *e, int m_id) const { const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)]; for (size_t i = 0; i < edge_faces.size(); ++i) { if (edge_faces[i] && edge_faces[i]->manifold_id == m_id) return true; } return false; } inline bool Polyhedron::vertexOnManifold(const vertex_t *v, int m_id) const { const std::vector &f = connectivity.vertex_to_face[vertexToIndex_fast(v)]; for (size_t i = 0; i < f.size(); ++i) { if (f[i]->manifold_id == m_id) return true; } return false; } template int Polyhedron::edgeManifolds(const edge_t *e, T result) const { const std::vector &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)]; for (size_t i = 0; i < (edge_faces.size() & ~1U); i += 2) { const face_t *f1 = edge_faces[i]; const face_t *f2 = edge_faces[i+1]; assert (f1 || f2); if (f1) *result++ = f1->manifold_id; else if (f2) *result++ = f2->manifold_id; } return edge_faces.size() >> 1; } template int Polyhedron::vertexManifolds(const vertex_t *v, T result) const { const std::vector &f = connectivity.vertex_to_face[vertexToIndex_fast(v)]; std::set em; for (size_t i = 0; i < f.size(); ++i) { em.insert(f[i]->manifold_id); } std::copy(em.begin(), em.end(), result); return em.size(); } template void Polyhedron::transform(const T &xform) { for (size_t i = 0; i < vertices.size(); i++) { vertices[i].v = xform(vertices[i].v); } faceRecalc(); init(); } inline size_t Polyhedron::manifoldCount() const { return manifold_is_closed.size(); } inline bool Polyhedron::hasOpenManifolds() const { for (size_t i = 0; i < manifold_is_closed.size(); ++i) { if (!manifold_is_closed[i]) return true; } return false; } inline std::ostream &operator<<(std::ostream &o, const Polyhedron &p) { p.print(o); return o; } } }