// +------------------------------------------------------------------------- // | mesh.tpp // | // | Author: Gilbert Bernstein // +------------------------------------------------------------------------- // | COPYRIGHT: // | Copyright Gilbert Bernstein 2013 // | See the included COPYRIGHT file for further details. // | // | This file is part of the Cork library. // | // | Cork is free software: you can redistribute it and/or modify // | it under the terms of the GNU Lesser General Public License as // | published by the Free Software Foundation, either version 3 of // | the License, or (at your option) any later version. // | // | Cork is distributed in the hope that it will be useful, // | but WITHOUT ANY WARRANTY; without even the implied warranty of // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // | GNU Lesser General Public License for more details. // | // | You should have received a copy // | of the GNU Lesser General Public License // | along with Cork. If not, see . // +------------------------------------------------------------------------- #pragma once #include #include "../isct/unsafeRayTriIsct.h" #include #include #include #include "../util/unionFind.h" // constructors template Mesh::Mesh() {} template Mesh::Mesh(Mesh &&cp) : tris(cp.tris), verts(cp.verts) {} template Mesh::Mesh(const RawMesh &raw) : tris(raw.triangles.size()), verts(raw.vertices) { // fill out the triangles for(uint i=0; i Mesh::~Mesh() {} template void Mesh::operator=(Mesh &&src) { tris = src.tris; verts = src.verts; } template bool Mesh::valid() const { for(uint i=0; i= verts.size() || tris[i].b >= verts.size() || tris[i].c >= verts.size()) { std::ostringstream message; message << "triangle #" << i << " should have indices in " << "the range 0 to " << (verts.size()-1) << ", but it has invalid indices: " << tris[i].a << ", " << tris[i].b << ", " << tris[i].c; CORK_ERROR(message.str()); return false; } } return true; } template RawMesh Mesh::raw() const { RawMesh result; result.vertices = verts; result.triangles.resize(tris.size()); for(uint i=0; i void Mesh::disjointUnion(const Mesh &cp) { uint oldVsize = verts.size(); uint oldTsize = tris.size(); uint cpVsize = cp.verts.size(); uint cpTsize = cp.tris.size(); uint newVsize = oldVsize + cpVsize; uint newTsize = oldTsize + cpTsize; std::vector v_remap(cpVsize); // oh this is obvious... verts.resize(newVsize); tris.resize(newTsize); for(uint i=0; i typename Mesh::Isct Mesh::pick(Ray3d ray) { Isct result; result.ray = ray; result.exists = false; double mint = DBL_MAX; // pass all triangles over ray for(uint i=0; i b) { std::swap(a, b); std::swap(va, vb); } if(b > c) { std::swap(b, c); std::swap(vb, vc); } if(a > b) { std::swap(a, b); std::swap(va, vb); } double t; Vec3d bary; if(isct_ray_triangle(ray, va, vb, vc, &t, &bary)) { if(t > 0 && t < mint) { result.exists = true; mint = t; result.tri_id = i; result.isct = ray.p + t * ray.r; result.bary = bary; } } } return result; } template bool Mesh::isClosed() { EGraphCache chains = createEGraphCache(); chains.for_each([&](uint i, uint j, EGraphEntry &entry) { entry.data = 0; }); // count up how many times each edge is encountered in one // orientation vs. the other for(Tri &tri : tris) { chains(tri.a, tri.b).data ++; chains(tri.b, tri.a).data --; chains(tri.b, tri.c).data ++; chains(tri.c, tri.b).data --; chains(tri.c, tri.a).data ++; chains(tri.a, tri.c).data --; } // now go through and see if any of these are non-zero bool closed = true; chains.for_each([&](uint i, uint j, EGraphEntry &entry) { if(entry.data != 0) closed = false; }); return closed; } static inline bool contains(const ShortVec &list, uint item) { for(uint k : list) if(k == item) return true; return false; } template typename Mesh::NeighborCache Mesh::createNeighborCache() { NeighborCache result; result.skeleton.resize(verts.size()); for(uint tid = 0; tid < tris.size(); tid++) { const Tri &tri = tris[tid]; result(tri.a, tri.b).tids.push_back(tid); result(tri.b, tri.a).tids.push_back(tid); result(tri.a, tri.c).tids.push_back(tid); result(tri.c, tri.a).tids.push_back(tid); result(tri.b, tri.c).tids.push_back(tid); result(tri.c, tri.b).tids.push_back(tid); } return result; } // This function signature is an amazing disaster... #ifdef _WIN32 template template typename Mesh::EGraphCache #else template template typename Mesh::template EGraphCache #endif Mesh::createEGraphCache() { EGraphCache result; result.skeleton.resize(verts.size()); for(uint tid = 0; tid < tris.size(); tid++) { const Tri &tri = tris[tid]; result(tri.a, tri.b).tids.push_back(tid); result(tri.b, tri.a).tids.push_back(tid); result(tri.a, tri.c).tids.push_back(tid); result(tri.c, tri.a).tids.push_back(tid); result(tri.b, tri.c).tids.push_back(tid); result(tri.c, tri.b).tids.push_back(tid); } return result; } template std::vector Mesh::getComponentIds() { UnionFind uf(verts.size()); for(const Tri &tri : tris) { uf.unionIds(tri.a, tri.b); uf.unionIds(tri.a, tri.c); } return uf.dump(); }