diff --git a/Embedding.cc b/Embedding.cc index 94ff1d9ba97e861a42f4e508e3ee317b5f134875..7f5e91a9ee5e2327a2a62a5e3715104066c92fe3 100644 --- a/Embedding.cc +++ b/Embedding.cc @@ -3,6 +3,9 @@ #include <QDebug> #include <random> +/*! + * \brief Embedding::Embedding + */ Embedding::Embedding() { qDebug() << "Start of MetaMesh ctor"; base_mesh_ = nullptr; @@ -10,6 +13,12 @@ Embedding::Embedding() { qDebug() << "Initialized MetaMesh"; } +/*! + * \brief Embedding::CopyInitialization initializes the meta mesh as a copy of the + * base mesh + * \param base_mesh + * \param meta_mesh + */ void Embedding::CopyInitialization(TriMesh &base_mesh, PolyMesh &meta_mesh) { qDebug() << "Copying the base mesh into the metamesh."; boundaries_ = false; @@ -92,7 +101,13 @@ void Embedding::CopyInitialization(TriMesh &base_mesh, PolyMesh &meta_mesh) { initial_triangulation_ = false; } -void Embedding::SelectionTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh, TraceType type) { +/*! + * \brief Embedding::SelectionTriangulation triangulate selected meta vertices + * \param base_mesh + * \param meta_mesh + * \param type + */ +void Embedding::SelectionTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh) { qDebug() << "Entering InitialTriangulation function."; boundaries_ = false; initial_triangulation_ = true; @@ -109,13 +124,21 @@ void Embedding::SelectionTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh, CopyInitialization(base_mesh, meta_mesh); return; } - TriangulationPipeline(meta_mesh_points, type); + TriangulationPipeline(meta_mesh_points); initial_triangulation_ = false; } -// 1 / ratio chance of a vertex being randomly selected as a meta vertex +/*! + * \brief Embedding::RandomTriangulation + * 1 / ratio chance of a vertex being randomly selected as a meta vertex + * \param base_mesh + * \param meta_mesh + * \param input + * \param rtype + * \param type + */ void Embedding::RandomTriangulation(TriMesh &base_mesh, PolyMesh &meta_mesh, double input, - RandomType rtype, TraceType type) { + RandomType rtype) { initial_triangulation_ = true; boundaries_ = false; base_mesh_ = &base_mesh; @@ -171,10 +194,10 @@ void Embedding::RandomTriangulation(TriMesh &base_mesh, PolyMesh &meta_mesh, dou } } else if (rtype == TOTAL) { while (meta_mesh_points.size()<input*10000) { - meta_mesh_points.push_back(base_mesh_->vertex_handle(dis1(gen))); + meta_mesh_points.push_back(base_mesh_->vertex_handle(static_cast<uint>(dis1(gen)))); } } - while (!TriangulationPipeline(meta_mesh_points, type)) { + while (!TriangulationPipeline(meta_mesh_points)) { meta_mesh_points.clear(); qDebug() << "Automatically remeshing"; meta_mesh_->clear(); @@ -185,19 +208,25 @@ void Embedding::RandomTriangulation(TriMesh &base_mesh, PolyMesh &meta_mesh, dou } } else if (rtype == TOTAL) { for (unsigned long i=0; i<input*10000; ++i) { - meta_mesh_points.push_back(base_mesh_->vertex_handle(dis1(gen))); + meta_mesh_points.push_back(base_mesh_->vertex_handle(static_cast<uint>(dis1(gen)))); } } } initial_triangulation_ = false; } +/*! + * \brief Embedding::TriangulationPipeline + * \param meta_mesh_points + * \param type + * \return + */ bool Embedding::TriangulationPipeline( - std::vector<OpenMesh::VertexHandle> meta_mesh_points, TraceType type) { + std::vector<OpenMesh::VertexHandle> meta_mesh_points) { debug_hard_stop_ = false; InitializeProperties(); CreateMetaMeshVertices(meta_mesh_points); - if (!TriangulateMetaMesh(type)) + if (!TriangulateMetaMesh()) return false; CleanUpBaseMesh(); TestHalfedgeConsistency(); @@ -205,6 +234,9 @@ bool Embedding::TriangulationPipeline( return true; } +/*! + * \brief Embedding::InitializeProperties + */ void Embedding::InitializeProperties() { base_mesh_->add_property(voronoiID_, "Voronoi area"); base_mesh_->add_property(bsplithandle_, "Vertex to collapse into, undefined if not introduced" @@ -219,6 +251,10 @@ void Embedding::InitializeProperties() { base_mesh_->add_property(halfedge_weight_, "Pointer from base he to meta heh"); } +/*! + * \brief Embedding::CreateMetaMeshVertices + * \param meta_mesh_points + */ void Embedding::CreateMetaMeshVertices(std::vector<OpenMesh::VertexHandle> meta_mesh_points) { qDebug() << "Start appointing BaseMesh properties:"; qDebug() << "is bv_connection_ valid? " << bv_connection_.is_valid(); @@ -246,7 +282,12 @@ void Embedding::CreateMetaMeshVertices(std::vector<OpenMesh::VertexHandle> meta_ qDebug() << "Finish appointing MetaMesh properties:"; } -bool Embedding::TriangulateMetaMesh(TraceType type) { +/*! + * \brief Embedding::TriangulateMetaMesh + * \param type + * \return + */ +bool Embedding::TriangulateMetaMesh() { OpenMesh::VPropHandleT<double> voronoidistance; OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh; OpenMesh::HPropHandleT<int> multiplicity_heh; @@ -254,30 +295,11 @@ bool Embedding::TriangulateMetaMesh(TraceType type) { base_mesh_->add_property(to_heh, "Incoming edge from the shortest path"); base_mesh_->add_property(multiplicity_heh, "Mark duplicate paths for elimination"); qDebug() << "Entering Delaunay:"; - if (!Delaunay(voronoidistance, to_heh, multiplicity_heh, type)) { + if (!Delaunay(voronoidistance, to_heh, multiplicity_heh)) { return false; } - switch (type) { - case IMPLICITDIJKSTRA : - qDebug() << "Entering Implicit Dijkstra Triangulation from Voronoi diagram"; - ImplicitDijkstra(voronoidistance, to_heh, multiplicity_heh); - //PreProcessEdges(); - //EliminateDuplicatePaths(voronoiID, multiplicity_heh); - break; - case A_STAR: - qDebug() << "Entering A* Triangulation:"; - A_StarTriangulation(type); - break; - case A_STAR_MIDPOINTS: - qDebug() << "Entering A* Triangulation with midpoints from Voronoi"; - A_StarTriangulation(type); - break; - } - - - // Finish implementing this later after trying a simpler base method - // EliminateDuplicatePaths(voronoiID, multiplicity_heh); + A_StarTriangulation(); base_mesh_->remove_property(voronoidistance); base_mesh_->remove_property(to_heh); @@ -285,6 +307,9 @@ bool Embedding::TriangulateMetaMesh(TraceType type) { return true; } +/*! + * \brief Embedding::PreProcessEdges global preprocessing + */ void Embedding::PreProcessEdges() { for (auto beh : base_mesh_->edges()) { auto bheh = base_mesh_->halfedge_handle(beh, 0); @@ -293,11 +318,19 @@ void Embedding::PreProcessEdges() { base_mesh_->update_normals(); } +/*! + * \brief Embedding::ProcessEdge local preprocessing + * \param meh + */ void Embedding::ProcessEdge(OpenMesh::EdgeHandle meh) { ProcessHalfedge(meta_mesh_->halfedge_handle(meh, 0)); ProcessHalfedge(meta_mesh_->halfedge_handle(meh, 1)); } +/*! + * \brief Embedding::ProcessVertex local preprocessing + * \param bvh + */ void Embedding::ProcessVertex(OpenMesh::VertexHandle bvh) { std::list<OpenMesh::HalfedgeHandle> splits; for (auto bvoheh : base_mesh_->voh_range(bvh)) { @@ -311,6 +344,10 @@ void Embedding::ProcessVertex(OpenMesh::VertexHandle bvh) { } } +/*! + * \brief Embedding::CleanupVertex perform legal base collapses around vertex bvh + * \param bvh + */ void Embedding::CleanupVertex(OpenMesh::VertexHandle bvh) { std::list<OpenMesh::VertexHandle> collapses; for (auto bvhit : base_mesh_->vv_range(bvh)) { @@ -327,6 +364,10 @@ void Embedding::CleanupVertex(OpenMesh::VertexHandle bvh) { } } +/*! + * \brief Embedding::CleanupFace cleans up the faces around mheh + * \param mheh + */ void Embedding::CleanupFace(OpenMesh::HalfedgeHandle mheh) { auto mhehiter = mheh; do { @@ -337,6 +378,10 @@ void Embedding::CleanupFace(OpenMesh::HalfedgeHandle mheh) { } while (mhehiter != mheh); } +/*! + * \brief Embedding::CleanupHalfedge cleans up mheh + * \param mheh + */ void Embedding::CleanupHalfedge(OpenMesh::HalfedgeHandle mheh) { auto linehalfedges = GetBaseHalfedges(mheh); auto mhehnext = meta_mesh_->next_halfedge_handle(mheh); @@ -365,6 +410,11 @@ void Embedding::CleanupHalfedge(OpenMesh::HalfedgeHandle mheh) { BaseGarbageCollection(); } +/*! + * \brief Embedding::ProcessNeighbors pre process the neighboring edges around mheh + * this is called before tracing + * \param meh + */ void Embedding::ProcessNeighbors(OpenMesh::EdgeHandle meh) { auto mheh0 = meta_mesh_->halfedge_handle(meh, 0); auto mheh1 = meta_mesh_->halfedge_handle(meh, 1); @@ -411,8 +461,12 @@ void Embedding::ProcessNeighbors(OpenMesh::EdgeHandle meh) { } } -// Iterate over the currently traced patch that mheh is part of and call pre-processing -// on all traversed meta halfedges +/*! + * \brief Embedding::ProcessFace + * Iterate over the currently traced patch that mheh is part of and call pre-processing + * on all traversed meta halfedges + * \param mheh + */ void Embedding::ProcessFace(OpenMesh::HalfedgeHandle mheh) { // Edge case: Trying to process the face of an mheh which has an adjacent valence 1 vertex // If mheh points towards that vertex there is no problem in the iteration @@ -425,11 +479,6 @@ void Embedding::ProcessFace(OpenMesh::HalfedgeHandle mheh) { // The previous solution works for edges next to valence 1 being traced but breaks face splits // so instead just find an adjacent traced edge and iterate from there; this works in both // cases. - /* - if (meta_mesh_->next_halfedge_handle(meta_mesh_->opposite_halfedge_handle(mheh)) == mheh) { - mheh = meta_mesh_->opposite_halfedge_handle(mheh); - } - */ auto mhehf = meta_mesh_->next_halfedge_handle(mheh); auto mhehb = meta_mesh_->next_halfedge_handle(meta_mesh_->opposite_halfedge_handle(mheh)); if (base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mhehf))) { @@ -441,7 +490,6 @@ void Embedding::ProcessFace(OpenMesh::HalfedgeHandle mheh) { assert(initial_triangulation_); return; } - auto mhehtemp = mheh; do { if (base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mhehtemp)) @@ -455,6 +503,10 @@ void Embedding::ProcessFace(OpenMesh::HalfedgeHandle mheh) { } while (mhehtemp != mheh); } +/*! + * \brief Embedding::ProcessHalfedge pre-process base halfedges around meta halfedge mheh + * \param mheh + */ void Embedding::ProcessHalfedge(OpenMesh::HalfedgeHandle mheh) { auto linehalfedges = GetBaseHalfedges(mheh); auto mhehnext = meta_mesh_->next_halfedge_handle(mheh); @@ -465,24 +517,22 @@ void Embedding::ProcessHalfedge(OpenMesh::HalfedgeHandle mheh) { for (auto blheh : linehalfedges) { for (auto bheh : LeftHalfCircle(blheh)) { ConditionalSplit(bheh); - /* - qDebug() << "Meta Halfedge: " << mheh.idx() << " -Base Halfedge: " << bheh.idx() - << " -FromVertex: " << base_mesh_->from_vertex_handle(bheh).idx() - << " -C: " - << base_mesh_->property(bv_connection_, base_mesh_->from_vertex_handle(bheh)).idx() - << " -ToVertex: " << base_mesh_->to_vertex_handle(bheh).idx() - << " -C: " - << base_mesh_->property(bv_connection_, base_mesh_->to_vertex_handle(bheh)).idx(); - */ } } } +/*! + * \brief Embedding::ConditionalSplit split bheh if permissible + * \param bheh + * \return + */ bool Embedding::ConditionalSplit(OpenMesh::HalfedgeHandle bheh) { // Don't split boundary halfedges for now since it is leading to crashes. // This could be enabled (I was in the middle of adding boundary split functionality) // But there is not enough time // TODO: remove this check and fix boundary splits in CollapseBaseHe and SplitBaseHe + // After testing quite a bit without splitting boundary halfedges this seems to be working quite + // well. Splitting boundary halfedges may not be necessary at all. if (base_mesh_->is_boundary(bheh) || base_mesh_->is_boundary(base_mesh_->opposite_halfedge_handle(bheh))) { return false; @@ -549,6 +599,12 @@ bool Embedding::ConditionalSplit(OpenMesh::HalfedgeHandle bheh) { return false; } +/*! + * \brief Embedding::LeftHalfCircle + * \param bheh + * \return the halfedges surrounding bheh in a left halfcircle and + * stopping when reaching a meta halfedge (used for preprocessing) + */ std::vector<OpenMesh::HalfedgeHandle> Embedding::LeftHalfCircle(OpenMesh::HalfedgeHandle bheh) { std::vector<OpenMesh::HalfedgeHandle> retval; retval.push_back(bheh); @@ -562,6 +618,11 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::LeftHalfCircle(OpenMesh::Halfed return retval; } +/*! + * \brief Embedding::GetBaseHalfedges + * \param mheh + * \return the base halfedges of meta halfedge mheh + */ std::vector<OpenMesh::HalfedgeHandle> Embedding::GetBaseHalfedges( OpenMesh::HalfedgeHandle mheh) { std::vector<OpenMesh::HalfedgeHandle> retval; @@ -576,15 +637,17 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::GetBaseHalfedges( return retval; } +/*! + * \brief Embedding::CleanUpBaseMesh collapses new bhehs where allowed and collects garbage it + * \param garbagecollection collect garbage if set to true + */ void Embedding::CleanUpBaseMesh(bool garbagecollection) { - //qDebug() << "Calling cleanup."; std::queue<OpenMesh::VertexHandle> hehqueue; for (auto bvh : base_mesh_->vertices()) { if (base_mesh_->is_valid_handle(bvh) && !base_mesh_->status(bvh).deleted() && base_mesh_->is_valid_handle(base_mesh_->property(bsplithandle_, bvh)) && !base_mesh_->status(base_mesh_->property(bsplithandle_, bvh)).deleted()) { - //qDebug() << "Cleanup loop bvh: " << bvh.idx(); auto bvhnew = ConditionalCollapse(bvh); if (base_mesh_->is_valid_handle(bvhnew)) { hehqueue.push(bvhnew); @@ -598,7 +661,6 @@ void Embedding::CleanUpBaseMesh(bool garbagecollection) { // this is tricky because there may be a few that _can't_ be merged no matter what unsigned long ctr = hehqueue.size()*2; while (!hehqueue.empty() && ctr > 0) { - //qDebug() << "hehqueue test " << ctr; auto bvh = hehqueue.front(); hehqueue.pop(); auto bvhnew = ConditionalCollapse(bvh); @@ -613,6 +675,12 @@ void Embedding::CleanUpBaseMesh(bool garbagecollection) { } } +/*! + * \brief Embedding::ConditionalCollapse collapse bvh into its bsplithandle_ halfedge + * if permissible + * \param bvh + * \return + */ OpenMesh::VertexHandle Embedding::ConditionalCollapse(OpenMesh::VertexHandle bvh) { auto bheh = base_mesh_->property(bsplithandle_, bvh); auto bheho = base_mesh_->opposite_halfedge_handle(bheh); @@ -722,9 +790,15 @@ OpenMesh::VertexHandle Embedding::ConditionalCollapse(OpenMesh::VertexHandle bv return OpenMesh::PolyConnectivity::InvalidVertexHandle; } -// Retain properties correctly while splitting halfedges and return the first half of the split -// edge, also marks new vertices introduced by the split with a handle to the vertex to collapse -// them into to undo the split. +/*! + * \brief Embedding::SplitBaseHe + * Retain properties correctly while splitting halfedges and return the first half of the split + * edge, also marks new vertices introduced by the split with a handle to the vertex to collapse + * them into to undo the split. + * \param bheh + * \return the halfedge starting at the from_vertex of bheh and pointing towards the new vertex + * resulting from the split. + */ OpenMesh::HalfedgeHandle Embedding::SplitBaseHe(OpenMesh::HalfedgeHandle bheh) { auto opp = base_mesh_->opposite_halfedge_handle(bheh); auto vertex_colors_pph = base_mesh_->vertex_colors_pph(); @@ -782,21 +856,14 @@ OpenMesh::HalfedgeHandle Embedding::SplitBaseHe(OpenMesh::HalfedgeHandle bheh) TriMesh::Point splitpoint = (base_mesh_->point(base_mesh_->from_vertex_handle(bheh)) + base_mesh_->point(base_mesh_->to_vertex_handle(bheh)) )/2.0; - //auto vh0 = base_mesh_->from_vertex_handle(bheh); - //auto vh1 = base_mesh_->to_vertex_handle(bheh); auto bvh = base_mesh_->split(base_mesh_->edge_handle(bheh), splitpoint); auto back = base_mesh_->next_halfedge_handle(prev); auto left = base_mesh_->next_halfedge_handle(back); auto front = base_mesh_->next_halfedge_handle(base_mesh_->opposite_halfedge_handle(left)); auto right = base_mesh_->next_halfedge_handle(base_mesh_->opposite_halfedge_handle(front)); - /* - qDebug() << vh.idx() << " - " << base_mesh_->to_vertex_handle(back).idx() - << " - " << base_mesh_->from_vertex_handle(bheh).idx() - << "=" << vh0.idx() - << " - " << base_mesh_->to_vertex_handle(bheh).idx() - << "=" << vh1.idx();*/ assert (bvh == base_mesh_->to_vertex_handle(back)); + if (lbound) { front = base_mesh_->next_halfedge_handle(back); right = base_mesh_->next_halfedge_handle(base_mesh_->opposite_halfedge_handle(front)); @@ -941,13 +1008,6 @@ OpenMesh::HalfedgeHandle Embedding::SplitBaseHe(OpenMesh::HalfedgeHandle bheh) if (!meta_mesh_->is_valid_handle(bhe_connection0)) { assert(!meta_mesh_->is_valid_handle(bhe_connection1)); - /* - qDebug() << "bv_connection_ valid: " << base_mesh_->is_valid_handle( - base_mesh_->property(bv_connection_, vh)); - for (auto voh_it : base_mesh_->voh_range(vh)) { - qDebug() << "voh: " << voh_it.idx() << " has a valid bhe_connection_: " << - base_mesh_->is_valid_handle(base_mesh_->property(bhe_connection_, voh_it)); - }*/ assert(!IsSectorBorder(bvh)); assert(ValidA_StarEdge(back, OpenMesh::PolyConnectivity::InvalidHalfedgeHandle)); @@ -980,7 +1040,6 @@ void Embedding::CollapseBaseHe(OpenMesh::HalfedgeHandle bheh) { assert(base_mesh_->is_valid_handle(bheh)); auto bvh0 = base_mesh_->from_vertex_handle(bheh); - auto bvh1 = base_mesh_->to_vertex_handle(bheh); auto bheho = base_mesh_->opposite_halfedge_handle(bheh); bool lbound = base_mesh_->is_boundary(bheh); @@ -1009,61 +1068,15 @@ void Embedding::CollapseBaseHe(OpenMesh::HalfedgeHandle bheh) { base_mesh_->opposite_halfedge_handle(base_mesh_->prev_halfedge_handle(bheho))); } if (debug_hard_stop_) return; - //qDebug() << "Calling base collapse"; - - // collapse - //LowLevelBaseCollapse(bheh); - /* Info dump - qDebug() << "Collapsing halfedge " << bheh.idx() << " from vertex " - << base_mesh_->from_vertex_handle(bheh).idx() << " is a meta vertex: " - << meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - base_mesh_->from_vertex_handle(bheh))) << "; and to vertex " - << base_mesh_->to_vertex_handle(bheh).idx() << " is a meta vertex " - << meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - base_mesh_->to_vertex_handle(bheh))) << "."; - */ base_mesh_->collapse(bheh); - - //BaseGarbageCollection(); - - // Tests, remove comment to test if needed later - /* - for (auto bhehit : base_mesh_->vih_range(bvh1)) { - assert(base_mesh_->is_valid_handle(bhehit)); - assert(!base_mesh_->status(bhehit).deleted()); - auto mheh = base_mesh_->property(bhe_connection_, bhehit); - if (meta_mesh_->is_valid_handle(mheh)) { - auto bhehc = meta_mesh_->property(mhe_connection_, mheh); - assert(base_mesh_->is_valid_handle(bhehc)); - if (base_mesh_->status(bhehc).deleted()) { - qDebug() << "Base halfedge" << bhehc.idx() << " is deleted."; - MarkVertex(base_mesh_->from_vertex_handle(bhehc)); - MarkVertex(base_mesh_->to_vertex_handle(bhehc)); - debug_hard_stop_=true; - return; - } - assert(!base_mesh_->status(bhehc).deleted()); - } - auto bhehn = base_mesh_->property(next_heh_, bhehit); - auto bhehno = base_mesh_->property(next_heh_, - base_mesh_->opposite_halfedge_handle(bhehit)); - if (base_mesh_->is_valid_handle(bhehn)) { - assert(!base_mesh_->status(bhehn).deleted()); - } - if (base_mesh_->is_valid_handle(bhehno)) { - assert(!base_mesh_->status(bhehno).deleted()); - assert(base_mesh_->is_valid_handle(base_mesh_->opposite_halfedge_handle(bhehno))); - assert(base_mesh_->is_valid_handle(base_mesh_->property(next_heh_, - base_mesh_->opposite_halfedge_handle(bhehno)))); - assert(!base_mesh_->status(base_mesh_->property(next_heh_, - base_mesh_->opposite_halfedge_handle(bhehno))).deleted()); - } - } - */ - //qDebug() << "Success"; } +/*! + * \brief Embedding::LowLevelBaseCollapse reimplemented collapse method on the base mesh, not sure + * if this is used at all? TODO: check if this needs deletion. + * \param bheh + */ void Embedding::LowLevelBaseCollapse(OpenMesh::HalfedgeHandle bheh) { // See PolyConnectivity::collapse and PolyConnectivity::collapse_edge OpenMesh::HalfedgeHandle h = bheh; @@ -1118,6 +1131,11 @@ void Embedding::LowLevelBaseCollapse(OpenMesh::HalfedgeHandle bheh) { // How to handle loops then? } +/*! + * \brief Embedding::AdjustPointersForBheCollapse lots of pointer operations to ensure a + * base collapse operation does not disrupt the embedding + * \param bheh + */ void Embedding::AdjustPointersForBheCollapse(OpenMesh::HalfedgeHandle bheh) { auto bheho = base_mesh_->opposite_halfedge_handle(bheh); @@ -1211,8 +1229,13 @@ void Embedding::AdjustPointersForBheCollapse(OpenMesh::HalfedgeHandle bheh) { assert(base_mesh_->property(bsplithandle_, base_mesh_->to_vertex_handle(bheh)) != bheho); } -// Takes two edges and transfers the properties of and pointers -// pointing to the first to the second if they're not empty. +/*! + * \brief Embedding::MergeProperties + * Takes two edges and transfers the properties of and pointers + * pointing to the first to the second if they're not empty. + * \param bheh0 + * \param bheh1 + */ void Embedding::MergeProperties(OpenMesh::HalfedgeHandle bheh0, OpenMesh::HalfedgeHandle bheh1) { auto bheh0o = base_mesh_->opposite_halfedge_handle(bheh0); @@ -1260,34 +1283,9 @@ void Embedding::MergeProperties(OpenMesh::HalfedgeHandle bheh0, base_mesh_->property(bhe_connection_, bheh1) = bhcprop0; base_mesh_->property(bhe_connection_, bheh1o) = bhcprop0o; - // faulty checks - /* - if (mhcprop0 == bheh0 && mhcprop0o == bheh0o) { - qDebug() << "This is not allowed to happen; a meta vertex is being collapsed away."; - assert(false); - } - */ - // check the sides if (!base_mesh_->is_valid_handle(nprop0o)) { assert(mhcprop0 == bheh0); - //assert(base_mesh_->is_valid_handle(nprop0)); - /* - if (!meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - base_mesh_->from_vertex_handle(bheh0)))) { - debug_hard_stop_= true; - base_mesh_->status(bheh0).set_selected(true); - //base_mesh_->status(bheh1).set_selected(true); - qDebug() << "Error while merging properties; selecting edges bheh0 and bheh1. front"; - MarkVertex(base_mesh_->from_vertex_handle(bheh0)); - MarkVertex(base_mesh_->from_vertex_handle(bheh1)); - MarkVertex(base_mesh_->to_vertex_handle(bheh0)); - MarkVertex(base_mesh_->to_vertex_handle(bheh1)); - return; - } - */ - //assert(meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - // base_mesh_->from_vertex_handle(bheh0)))); meta_mesh_->property(mhe_connection_, bhcprop0) = bheh1; // if this is not the end of the edge fix the next_heh pointers } else { @@ -1302,23 +1300,6 @@ void Embedding::MergeProperties(OpenMesh::HalfedgeHandle bheh0, // repeat for the other side if (!base_mesh_->is_valid_handle(nprop0)) { assert(mhcprop0o == bheh0o); - //assert(base_mesh_->is_valid_handle(nprop0o)); - /* - if (!meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - base_mesh_->to_vertex_handle(bheh0)))) { - debug_hard_stop_= true; - base_mesh_->status(bheh0).set_selected(true); - //base_mesh_->status(bheh1).set_selected(true); - qDebug() << "Error while merging properties; selecting edges bheh0 and bheh1. back"; - MarkVertex(base_mesh_->from_vertex_handle(bheh0)); - MarkVertex(base_mesh_->from_vertex_handle(bheh1)); - MarkVertex(base_mesh_->to_vertex_handle(bheh0)); - MarkVertex(base_mesh_->to_vertex_handle(bheh1)); - return; - } - */ - //assert(meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, - // base_mesh_->from_vertex_handle(bheh0o)))); meta_mesh_->property(mhe_connection_, bhcprop0o) = bheh1o; } else { assert(base_mesh_->is_valid_handle(nprop0)); @@ -1338,8 +1319,8 @@ void Embedding::MergeProperties(OpenMesh::HalfedgeHandle bheh0, base_mesh_->property(bsplithandle_, base_mesh_->to_vertex_handle(bheh0)) = bheh1o; } - assert(wprop0 == wprop0o); - assert(wprop1 == wprop1o); + assert(static_cast<int>(wprop0) == static_cast<int>(wprop0o)); + assert(static_cast<int>(wprop1) == static_cast<int>(wprop1o)); base_mesh_->property(halfedge_weight_, bheh1) = std::min(wprop0, wprop1); base_mesh_->property(halfedge_weight_, bheh1o) = std::min(wprop0, wprop1); @@ -1402,10 +1383,17 @@ void Embedding::MergeProperties(OpenMesh::HalfedgeHandle bheh0, assert(!base_mesh_->status(bheh1o).deleted()); } +/*! + * \brief Embedding::Delaunay delaunay triangulation + * \param voronoidistance + * \param to_heh + * \param multiplicity_heh + * \param type + * \return true for success, false for failure + */ bool Embedding::Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - OpenMesh::HPropHandleT<int> multiplicity_heh, - TraceType type) { + OpenMesh::HPropHandleT<int> multiplicity_heh) { for (auto bvh : base_mesh_->vertices()) { base_mesh_->property(voronoiID_, bvh) = OpenMesh::PolyConnectivity::InvalidVertexHandle; @@ -1438,34 +1426,20 @@ bool Embedding::Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, auto metavh0 = base_mesh_->property(voronoiID_, vh0); auto metavh1 = base_mesh_->property(voronoiID_, vh1); auto metavh2 = base_mesh_->property(voronoiID_, vh2); - /* - uint boundaries = static_cast<uint>(base_mesh_->is_boundary( - meta_mesh_->property(mv_connection_, metavh0))); - boundaries += static_cast<uint>(base_mesh_->is_boundary( - meta_mesh_->property(mv_connection_, metavh1))); - boundaries += static_cast<uint>(base_mesh_->is_boundary( - meta_mesh_->property(mv_connection_, metavh2))); - */ if (metavh0 != metavh1 && metavh0 != metavh2 && metavh1 != metavh2) { - //qDebug() << "Adding a face"; auto mheh0 = FindHalfedge(bheh0); auto mheh1 = FindHalfedge(bheh1); auto mheh2 = FindHalfedge(bheh2); auto mf = AddFace({metavh0, metavh1, metavh2}, {mheh0, mheh1, mheh2}); - //qDebug() << "Done adding a face"; - SetFaceProperties(fh, mf, voronoidistance, to_heh, type); + SetFaceProperties(fh, mf); mheh0 = meta_mesh_->halfedge_handle(mf); mheh1 = meta_mesh_->next_halfedge_handle(mheh0); mheh2 = meta_mesh_->next_halfedge_handle(mheh1); - //qDebug() << "Calling Traverseborder"; SetBorderProperties(meta_mesh_->property(mhe_border_, mheh0), mheh0); - //qDebug() << "Calling Traverseborder"; SetBorderProperties(meta_mesh_->property(mhe_border_, mheh1), mheh1); - //qDebug() << "Calling Traverseborder"; SetBorderProperties(meta_mesh_->property(mhe_border_, mheh2), mheh2); } - //qDebug() << "Done setting new meta edge properties for current face."; } qDebug() << "Done adding all basic faces."; @@ -1478,7 +1452,6 @@ bool Embedding::Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, << genus.at(static_cast<unsigned long>(mvh.idx())) << " perhaps you should choose different seed points."; return false; - //MarkVertex(meta_mesh_->property(mv_connection_, mvh)); } } } @@ -1487,7 +1460,6 @@ bool Embedding::Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, qDebug() << "Collecting boundary faces."; for (auto mvh : meta_mesh_->vertices()) { if (base_mesh_->is_boundary(meta_mesh_->property(mv_connection_, mvh))) { - uint neighboringboundaries = 0; auto mheh = meta_mesh_->halfedge_handle(mvh); if (!meta_mesh_->is_valid_handle(mheh)) { TraverseBoundary(mvh); @@ -1538,12 +1510,14 @@ bool Embedding::Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, if (boundaries_) { AddBoundaries(); } - return true; } -// Traverse a patch order and add all faces missed by the Voronoi triangulation to the -// meta mesh. +/*! + * \brief Embedding::TraverseBoundary traverse the boundary that mvh lies on and add faces + * along the boundary that were missed by the voronoi triangulation + * \param mvh + */ void Embedding::TraverseBoundary(OpenMesh::VertexHandle mvh) { assert(base_mesh_->is_boundary(meta_mesh_->property(mv_connection_, mvh))); OpenMesh::HalfedgeHandle bhehstart = OpenMesh::PolyConnectivity::InvalidHalfedgeHandle; @@ -1601,17 +1575,31 @@ void Embedding::TraverseBoundary(OpenMesh::VertexHandle mvh) { } while (bhehcurr != bhehstart); } +/*! + * \brief Embedding::fact + * \param n + * \return n! + */ int Embedding::fact(int n) { return (n == 1 || n == 0) ? 1 : fact(n - 1) * n; } +/*! + * \brief Embedding::nCk + * \param n + * \param k + * \return nCk(n,k) + */ int Embedding::nCk(int n, int k) { return (fact(n)/(fact(k)*fact(n-k))); } -// V - E + F = g -// => g = V-E+F +/*! + * \brief Embedding::VoronoiGenus + * \return the vector with the geni (or euler characteristics? one of those) + * of the voronoi regions + */ std::vector<int> Embedding::VoronoiGenus() { // Initialize faces as 1 to make this work, disk topology std::vector<int> faces(meta_mesh_->n_vertices(), 0); @@ -1645,65 +1633,21 @@ std::vector<int> Embedding::VoronoiGenus() { for (unsigned long i=0; i<meta_mesh_->n_vertices(); ++i) { int g = vertices.at(i) - edges.at(i) + faces.at(i); genus.push_back(g); - /* - qDebug() << "Vertices: " << vertices.at(i) - << " Edges: " << edges.at(i) - << " Faces: " << faces.at(i) - << " Euler Characteristic: " << genus.at(i); - */ } return genus; } -int Embedding::FixMetaMeshConnectivity(OpenMesh::VertexHandle mvh) { - auto currmheh = meta_mesh_->halfedge_handle(mvh); - auto first = meta_mesh_->property(mhe_connection_, currmheh); - auto iter = base_mesh_->opposite_halfedge_handle(base_mesh_->prev_halfedge_handle(first)); - int counter = 0; - std::vector<OpenMesh::HalfedgeHandle> borders; - do { - auto nextmheh = base_mesh_->property(bhe_connection_, iter); - if (meta_mesh_->is_valid_handle(nextmheh)) { - // If the meta connection does not correspond to the base connection, fix it. - if (nextmheh != meta_mesh_->opposite_halfedge_handle( - meta_mesh_->prev_halfedge_handle(currmheh))) { - meta_mesh_->set_next_halfedge_handle(meta_mesh_->opposite_halfedge_handle(nextmheh) - ,currmheh); - ++counter; - qDebug() << "Fixed connectivity of an edge"; - borders.push_back(meta_mesh_->opposite_halfedge_handle(nextmheh)); - } - currmheh = nextmheh; - } - iter = base_mesh_->opposite_halfedge_handle(base_mesh_->prev_halfedge_handle(iter)); - } while (iter != first); - // Symmetry - //assert(counter%2 == 0); - //AddSelfEdges(borders, type); - - return counter/2; -} - -// In cases where a voronoi region has more than one border it needs edges from its meta -// vertex to itself for each pair of borders. Find and add those. -void Embedding::AddSelfEdges(std::vector<OpenMesh::HalfedgeHandle> borders) { - for (unsigned long i = 0; i < borders.size()/2; ++i) { - for (unsigned long j = 0; j<borders.size()-i-1; ++j) { - assert(meta_mesh_->to_vertex_handle(borders.at(j)) - == meta_mesh_->to_vertex_handle(borders.at(j+i+1))); - AddMetaEdge(borders.at(j), borders.at(j+i+1)); - borders.at(j) = base_mesh_->opposite_halfedge_handle( - base_mesh_->next_halfedge_handle(borders.at(j))); - } - } -} - +/*! + * \brief Embedding::SetFaceProperties link a base face with a meta face (connect their + * property handles etc.) + * \param bf + * \param mf + * \param voronoidistance + * \param to_heh + * \param type + */ void Embedding::SetFaceProperties(OpenMesh::FaceHandle bf, - OpenMesh::FaceHandle mf, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - TraceType type) { - //qDebug() << "Setting face properties"; + OpenMesh::FaceHandle mf) { auto bheh0 = base_mesh_->halfedge_handle(bf); auto bheh1 = base_mesh_->next_halfedge_handle(bheh0); auto bheh2 = base_mesh_->next_halfedge_handle(bheh1); @@ -1716,46 +1660,13 @@ void Embedding::SetFaceProperties(OpenMesh::FaceHandle bf, meta_mesh_->property(mhe_border_, mheh0) = bheh0; meta_mesh_->property(mhe_border_, mheh1) = bheh1; meta_mesh_->property(mhe_border_, mheh2) = bheh2; - - if (type == IMPLICITDIJKSTRA || type == A_STAR_MIDPOINTS) { - meta_mesh_->property(mhe_connection_, mheh0) = - FindMiddle(mheh0, voronoidistance, to_heh); - meta_mesh_->property(mhe_connection_, mheh1) = - FindMiddle(mheh1, voronoidistance, to_heh); - meta_mesh_->property(mhe_connection_, mheh2) = - FindMiddle(mheh2, voronoidistance, to_heh); - /* - meta_mesh_->property(mhe_connection_, meta_mesh_->opposite_halfedge_handle(mheh0)) - = base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh0)); - meta_mesh_->property(mhe_connection_, meta_mesh_->opposite_halfedge_handle(mheh1)) - = base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh1)); - meta_mesh_->property(mhe_connection_, meta_mesh_->opposite_halfedge_handle(mheh2)) - = base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh2)); - */ - } - - if (type == IMPLICITDIJKSTRA) { - base_mesh_->property(bhe_connection_, meta_mesh_->property(mhe_connection_, mheh0)) - = mheh0; - base_mesh_->property(bhe_connection_, base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh0))) - = meta_mesh_->opposite_halfedge_handle(mheh0); - base_mesh_->property(bhe_connection_, meta_mesh_->property(mhe_connection_, mheh1)) - = mheh1; - base_mesh_->property(bhe_connection_, base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh1))) - = meta_mesh_->opposite_halfedge_handle(mheh1); - base_mesh_->property(bhe_connection_, meta_mesh_->property(mhe_connection_, mheh2)) - = mheh2; - base_mesh_->property(bhe_connection_, base_mesh_->opposite_halfedge_handle( - meta_mesh_->property(mhe_connection_, mheh2))) - = meta_mesh_->opposite_halfedge_handle(mheh2); - } } +/*! + * \brief Embedding::CopyFaceProperties + * \param mfh + * \param boundaryborders + */ void Embedding::CopyFaceProperties(OpenMesh::FaceHandle mfh, std::vector<OpenMesh::HalfedgeHandle> boundaryborders) { auto mheh = meta_mesh_->halfedge_handle(mfh); @@ -1764,14 +1675,6 @@ void Embedding::CopyFaceProperties(OpenMesh::FaceHandle mfh, uint mfval = meta_mesh_->valence(mfh); for (uint i=0; i<boundaryborders.size(); ++i) { auto bhehb = boundaryborders.at(i); - /* - qDebug() << "mhehiter from: " << meta_mesh_->from_vertex_handle(mhehiter).idx() - << "to: " << meta_mesh_->to_vertex_handle(mhehiter).idx(); - qDebug() << "bb(" << i << ").vID from:" << base_mesh_->property(voronoiID_, - base_mesh_->from_vertex_handle(bhehb)).idx() << " to: " - << base_mesh_->property(voronoiID_, - base_mesh_->to_vertex_handle(bhehb)).idx(); - */ assert(meta_mesh_->from_vertex_handle(mhehiter) == base_mesh_->property(voronoiID_, base_mesh_->from_vertex_handle(bhehb))); assert(meta_mesh_->to_vertex_handle(mhehiter) @@ -1806,6 +1709,14 @@ void Embedding::CopyFaceProperties(OpenMesh::FaceHandle mfh, } while (mheh != mhehiter); } +/*! + * \brief Embedding::AddFace adds a meta face + * \param mvh vertices + * \param mheh halfedges, going mvh(i) -> mheh(i) -> mvh(i+1) + * Use the opposite halfedges of adjacent faces for these, or an invalid handle if they don't exist + * yet and in that case AddFace will make them. + * \return the facehandle + */ OpenMesh::FaceHandle Embedding::AddFace(std::vector<OpenMesh::VertexHandle> mvh, std::vector<OpenMesh::HalfedgeHandle> mheh) { assert(mvh.size() == mheh.size()); @@ -1814,14 +1725,6 @@ OpenMesh::FaceHandle Embedding::AddFace(std::vector<OpenMesh::VertexHandle> mvh, mheh.at(i) = meta_mesh_->new_edge(mvh.at(i), mvh.at((i+1)%mvh.size())); } } - /* - qDebug() << "Expected triangle: " << mvh0.idx() - << ", " << mvh1.idx() - << ", " << mvh2.idx() - << "Actual triangle: " << meta_mesh_->from_vertex_handle(mheh0).idx() - << ", " << meta_mesh_->from_vertex_handle(mheh1).idx() - << ", " << meta_mesh_->from_vertex_handle(mheh2).idx(); - */ for (uint i = 0; i<mheh.size(); ++i) { assert(meta_mesh_->from_vertex_handle(mheh.at(i)) == mvh.at(i)); assert(meta_mesh_->to_vertex_handle(mheh.at(i)) == mvh.at((i+1)%mvh.size())); @@ -1866,6 +1769,9 @@ OpenMesh::FaceHandle Embedding::AddFace(std::vector<OpenMesh::VertexHandle> mvh, return fnew; } +/*! + * \brief Embedding::AddBoundaries set meta properties and pointers for boundaries. + */ void Embedding::AddBoundaries() { for (auto mheh : meta_mesh_->halfedges()) { if (!meta_mesh_->is_valid_handle(meta_mesh_->next_halfedge_handle(mheh)) @@ -1879,6 +1785,12 @@ void Embedding::AddBoundaries() { } } +/*! + * \brief Embedding::FindHalfedge + * \param bheh bheh lying on a mheh + * \return the opposite meta halfedge of the meta halfedge bheh lies on, or nothing + * if this is invalid + */ OpenMesh::HalfedgeHandle Embedding::FindHalfedge(OpenMesh::HalfedgeHandle bheh) { auto oppmheh = base_mesh_->property(bhe_border_, base_mesh_->opposite_halfedge_handle(bheh)); if (!meta_mesh_->is_valid_handle(oppmheh)) { @@ -1888,6 +1800,9 @@ OpenMesh::HalfedgeHandle Embedding::FindHalfedge(OpenMesh::HalfedgeHandle bheh) } } +/*! + * \brief Embedding::VoronoiBorders iteration over all border regions + */ void Embedding::VoronoiBorders() { // Considering the inclusion of boundaries in the meta mesh a local border traversal // becomes more complicated since it would involve iterating around boundaries. @@ -1924,6 +1839,12 @@ void Embedding::VoronoiBorders() { } } +/*! + * \brief Embedding::SetBorderProperties iteration over one specific border region + * TODO: improve this for complex borders, those may break this function at the current state. + * \param bheh + * \param mheh + */ void Embedding::SetBorderProperties(OpenMesh::HalfedgeHandle bheh, OpenMesh::HalfedgeHandle mheh) { assert(base_mesh_->is_valid_handle(bheh)); @@ -1950,26 +1871,17 @@ void Embedding::SetBorderProperties(OpenMesh::HalfedgeHandle bheh, } } -void Embedding::ImplicitDijkstra(OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - OpenMesh::HPropHandleT<int> multiplicity_heh) { - qDebug() << "Starting implicit Dijkstra triangulation from Voronoi diagram"; - for (auto meh : meta_mesh_->edges()) { - auto mheh0 = meta_mesh_->halfedge_handle(meh, 0); - MarkPath(meta_mesh_->property(mhe_connection_, mheh0), mheh0, to_heh, - voronoidistance, multiplicity_heh); - } - base_mesh_->update_normals(); - qDebug() << "Finished implicit Dijkstra triangulation from Voronoi diagram"; -} - -void Embedding::A_StarTriangulation(TraceType type) { +/*! + * \brief Embedding::A_StarTriangulation + * \param type + */ +void Embedding::A_StarTriangulation() { for (auto mheh : meta_mesh_->halfedges()) { if (meta_mesh_->is_boundary(mheh) || meta_mesh_->is_boundary(meta_mesh_->opposite_halfedge_handle(mheh))) { if (debug_hard_stop_) return; - Trace(mheh, true, false, type); + Trace(mheh, true, false); } } for (auto mheh : meta_mesh_->halfedges()) { @@ -1981,7 +1893,7 @@ void Embedding::A_StarTriangulation(TraceType type) { && !meta_mesh_->is_boundary(meta_mesh_->to_vertex_handle(mheh))) { if (debug_hard_stop_) return; - Trace(mheh, true, false, type); + Trace(mheh, true, false); assert(base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mheh))); } } @@ -2000,7 +1912,7 @@ void Embedding::A_StarTriangulation(TraceType type) { || meta_mesh_->is_boundary(meta_mesh_->to_vertex_handle(mheh))) { if (debug_hard_stop_) return; - Trace(mheh, false, false, type); + Trace(mheh, false, false); } } } @@ -2013,7 +1925,7 @@ void Embedding::A_StarTriangulation(TraceType type) { auto mheh1 = meta_mesh_->next_halfedge_handle(mheh0); while (mheh1 != mhehstart) { auto mhehnew = AddMetaEdge(mhehstart, mheh0); - Trace(mhehnew, false, false, type); + Trace(mhehnew, false, false); mheh0 = mheh1; mheh1 = meta_mesh_->next_halfedge_handle(mheh1); } @@ -2025,127 +1937,12 @@ void Embedding::A_StarTriangulation(TraceType type) { base_mesh_->update_normals(); } -OpenMesh::HalfedgeHandle Embedding::FindMiddle(OpenMesh::HalfedgeHandle metaheh, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh) { - //qDebug() << "FindMiddle Start"; - auto baseheh = meta_mesh_->property(mhe_connection_, metaheh); - OpenMesh::HPropHandleT<bool> marked; - base_mesh_->add_property(marked, "Marked for Dijkstra traversal"); - - for (auto heh : base_mesh_->halfedges()) { - base_mesh_->property(marked, heh) = false; - } - - const double inf = std::numeric_limits<double>::infinity(); - double mindist = inf; - auto vid0 = meta_mesh_->from_vertex_handle(metaheh); - auto vid1 = meta_mesh_->to_vertex_handle(metaheh); - OpenMesh::HalfedgeHandle middleheh; - - assert (EligibleHalfedge(baseheh, vid0, vid1)); - while (base_mesh_->is_valid_handle(baseheh)) { - auto bvh0 = base_mesh_->from_vertex_handle(baseheh); - auto bvh1 = base_mesh_->to_vertex_handle(baseheh); - double newdistance = base_mesh_->property(voronoidistance, bvh0) - + base_mesh_->property(voronoidistance, bvh1) + base_mesh_->calc_edge_length(baseheh); - bool okayedge = true; - for (auto voheh : base_mesh_->voh_range(bvh0)) { - if (voheh != baseheh && - meta_mesh_->is_valid_handle(base_mesh_->property(bhe_connection_, voheh))) { - okayedge = false; - } - } - for (auto voheh : base_mesh_->voh_range(bvh1)) { - if (voheh != base_mesh_->opposite_halfedge_handle(baseheh) - && meta_mesh_->is_valid_handle(base_mesh_->property(bhe_connection_, voheh))) { - okayedge = false; - } - } - if (meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, bvh0)) || - meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, bvh1))) { - okayedge = true; - } - - if (okayedge && newdistance < mindist) { - mindist = newdistance; - middleheh = baseheh; - } - baseheh = DijkstraNextHeh(baseheh, vid0, vid1, marked); - } - - base_mesh_->remove_property(marked); - - // Since finding a middle halfedge separated from all other middle halfedges - // can't be easily dont in complex meshes simply create one in cases none exist - if (!base_mesh_->is_valid_handle(middleheh)) { - middleheh = CreateMiddle(meta_mesh_->property(mhe_connection_, metaheh) - ,voronoidistance, to_heh); - } - - assert(base_mesh_->is_valid_handle(middleheh)); - //qDebug() << "FindMiddle End"; - return middleheh; -} - -OpenMesh::HalfedgeHandle Embedding::CreateMiddle(OpenMesh::HalfedgeHandle bheh, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh) { - - auto splitbheh0 = VoronoiSplit(bheh, to_heh, voronoidistance); - auto opp = base_mesh_->opposite_halfedge_handle(base_mesh_->next_halfedge_handle( - base_mesh_->opposite_halfedge_handle(base_mesh_->next_halfedge_handle(splitbheh0)))); - auto splitbheh1 = VoronoiSplit(opp, to_heh, voronoidistance); - auto newbheh = base_mesh_->next_halfedge_handle( - base_mesh_->opposite_halfedge_handle(base_mesh_->next_halfedge_handle(splitbheh1))); - - return newbheh; -} - -bool Embedding::EligibleHalfedge(OpenMesh::HalfedgeHandle baseheh, - OpenMesh::VertexHandle metavh0, - OpenMesh::VertexHandle metavh1) { - auto vid0 = base_mesh_->property(voronoiID_, base_mesh_->from_vertex_handle(baseheh)); - auto vid1 = base_mesh_->property(voronoiID_, base_mesh_->to_vertex_handle(baseheh)); - return (((vid0 == metavh0) && (vid1 == metavh1)) || ((vid0 == metavh1) && (vid1 == metavh0))); -} - -OpenMesh::HalfedgeHandle Embedding::DijkstraNextHeh(OpenMesh::HalfedgeHandle bheh, - OpenMesh::VertexHandle metavh0, - OpenMesh::VertexHandle metavh1, - OpenMesh::HPropHandleT<bool> marked) { - base_mesh_->property(marked, bheh) = true; - auto opp = base_mesh_->opposite_halfedge_handle(bheh); - base_mesh_->property(marked, opp) = true; - auto heh0 = base_mesh_->prev_halfedge_handle(bheh); - auto heh1 = base_mesh_->next_halfedge_handle(bheh); - auto heh2 = base_mesh_->prev_halfedge_handle(opp); - auto heh3 = base_mesh_->next_halfedge_handle(opp); - //qDebug() << EligibleHalfedge(bheh, metavh0, metavh1, voronoiID); - if (EligibleHalfedge(heh0, metavh0, metavh1) && - (base_mesh_->property(marked, heh0) == false)) { - //qDebug() << "1"; - return heh0; - } - if (EligibleHalfedge(heh1, metavh0, metavh1) && - (base_mesh_->property(marked, heh1) == false)) { - //qDebug() << "2"; - return heh1; - } - if (EligibleHalfedge(heh2, metavh0, metavh1) && - (base_mesh_->property(marked, heh2) == false)) { - //qDebug() << "3"; - return heh2; - } - if (EligibleHalfedge(heh3, metavh0, metavh1) && - (base_mesh_->property(marked, heh3) == false)) { - //qDebug() << "4"; - return heh3; - } - - return OpenMesh::PolyConnectivity::InvalidHalfedgeHandle; -} - +/*! + * \brief Embedding::NaiveVoronoi build voronoi regions + * \param queue + * \param voronoidistance + * \param to_heh + */ void Embedding::NaiveVoronoi(std::queue<OpenMesh::VertexHandle> queue, OpenMesh::VPropHandleT<double> voronoidistance, OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh) { @@ -2179,13 +1976,6 @@ void Embedding::NaiveVoronoi(std::queue<OpenMesh::VertexHandle> queue, queue.pop(); } - /* Voronoi Triangulation Visualization with this - for (auto bvh : base_mesh_->vertices()) { - if (base_mesh_->is_valid_handle(base_mesh_->property(to_heh, bvh))) - base_mesh_->status(base_mesh_->property(to_heh, bvh)).set_selected(true); - } - */ - ColorizeVoronoiRegions(); } @@ -2474,7 +2264,6 @@ OpenMesh::HalfedgeHandle Embedding::VoronoiSplit(OpenMesh::HalfedgeHandle bheh, change1 = true; } - auto region = base_mesh_->property(voronoiID_, base_mesh_->from_vertex_handle(bheh)); auto newbheh = SplitBaseHe(bheh); // abuse the to_heh property to point to the split edge regardless of shortest path @@ -2834,7 +2623,7 @@ void Embedding::TestHalfedgeConsistency() { } void Embedding::Trace(OpenMesh::HalfedgeHandle mheh, bool cleanup, bool mark_trace, - TraceType tracetype, TraceFaceAttr facetype) { + TraceFaceAttr facetype) { auto bheh = meta_mesh_->property(mhe_connection_, mheh); if (base_mesh_->is_valid_handle(bheh) && base_mesh_->property(bhe_connection_, bheh) == mheh) { @@ -2850,12 +2639,7 @@ void Embedding::Trace(OpenMesh::HalfedgeHandle mheh, bool cleanup, bool mark_tra AdvancedTrace(mheh); break; case PREPROCESSEDFACE : - //qDebug() << "Entering SimpleTrace"; - if (tracetype == A_STAR) { - SimpleTrace(mheh, cleanup, mark_trace); - } else if (tracetype == A_STAR_MIDPOINTS) { - SimpleMidpointTrace(mheh, mark_trace); - } + SimpleTrace(mheh, cleanup, mark_trace); break; } } @@ -2863,14 +2647,14 @@ void Embedding::Trace(OpenMesh::HalfedgeHandle mheh, bool cleanup, bool mark_tra // Retraces the given meta halfedge void Embedding::Retrace(OpenMesh::HalfedgeHandle mheh, bool cleanup, bool mark_trace, - TraceType tracetype, TraceFaceAttr facetype) { + TraceFaceAttr facetype) { if (!meta_mesh_->is_valid_handle(mheh) || meta_mesh_->status(mheh).deleted()) { qDebug() << "Invalid or deleted halfedge mheh cannot be retraced"; return; } RemoveMetaEdgeFromBaseMesh(mheh); - Trace(mheh, cleanup, mark_trace, tracetype, facetype); + Trace(mheh, cleanup, mark_trace, facetype); } void Embedding::BoundaryTrace(OpenMesh::HalfedgeHandle mheh, bool mark_trace) { @@ -2895,10 +2679,16 @@ void Embedding::BoundaryTrace(OpenMesh::HalfedgeHandle mheh, bool mark_trace) { return; } + if (mark_trace) { + base_mesh_->status(bheh).set_selected(true); + } std::vector<OpenMesh::HalfedgeHandle> path = {bheh}; while (!meta_mesh_->is_valid_handle(base_mesh_->property(bv_connection_, base_mesh_->to_vertex_handle(bheh)))) { bheh = base_mesh_->next_halfedge_handle(bheh); + if (mark_trace) { + base_mesh_->status(bheh).set_selected(true); + } assert(base_mesh_->is_boundary(bheh)); path.push_back(bheh); //base_mesh_->status(bheh).set_selected(true); @@ -3718,7 +3508,7 @@ OpenMesh::HalfedgeHandle Embedding::AddMetaEdge(OpenMesh::HalfedgeHandle mheh0, return mhehnew0; } -void Embedding::Rotate(OpenMesh::EdgeHandle meh, TraceType type) { +void Embedding::Rotate(OpenMesh::EdgeHandle meh) { //qDebug() << "Flip function called"; if (!IsRotationOkay(meh)) { qDebug() << "Meta edge " << meh.idx() << " cannot be rotated"; @@ -3735,7 +3525,7 @@ void Embedding::Rotate(OpenMesh::EdgeHandle meh, TraceType type) { RemoveMetaEdgeFromBaseMesh(mheh); //qDebug() << "RemoveMetaEdgeFromBaseMesh function finished"; //qDebug() << "pre trace"; - Trace(mheh, true, false, type); + Trace(mheh, true, false); //qDebug() << "post trace"; } } @@ -4496,7 +4286,7 @@ void Embedding::Split(OpenMesh::VertexHandle bvh, OpenMesh::HalfedgeHandle mheh, } // Collapses the FROM vertex into the TO vertex -void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType type) { +void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose) { if (debug_hard_stop_) return; //qDebug() << "Calling collapse"; @@ -4552,7 +4342,7 @@ void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType && !meta_mesh_->status(mhehcurr).deleted()) { RemoveMetaEdgeFromBaseMesh(mhehcurr); if (debug_hard_stop_) return; - Trace(mhehcurr, true, false, type); + Trace(mhehcurr, true, false); if (debug_hard_stop_) return; } else { assert(!base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mhehcurr))); @@ -4580,7 +4370,7 @@ void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType && !meta_mesh_->status(mhehcurr).deleted()) { RemoveMetaEdgeFromBaseMesh(mhehcurr); if (debug_hard_stop_) return; - Trace(mhehcurr, true, false, type); + Trace(mhehcurr, true, false); if (debug_hard_stop_) return; } else { assert(!base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mhehcurr))); @@ -4607,7 +4397,7 @@ void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType if (meta_mesh_->next_halfedge_handle(meta_mesh_->next_halfedge_handle(mhehouter)) == mhehouter) { RemoveLoop(mhehouter); - Retrace(mhehouter, true, false, type); + Retrace(mhehouter, true, false); if (debug_hard_stop_) return; } } else if (mhehon == mhehp && mhehn == mheho) { @@ -4621,7 +4411,7 @@ void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType if (meta_mesh_->next_halfedge_handle(meta_mesh_->next_halfedge_handle(mhehouter)) == mhehouter) { RemoveLoop(mhehouter); - Retrace(mhehouter, true, false, type); + Retrace(mhehouter, true, false); if (debug_hard_stop_) return; } } else { @@ -4648,7 +4438,7 @@ void Embedding::Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose, TraceType // Second pass : Retrace to look nicer for (auto mhehit : meta_mesh_->voh_range(mvh)) { if (!meta_mesh_->status(mhehit).deleted()) { - Retrace(mhehit, true, false, type); + Retrace(mhehit, true, false); if (debug_hard_stop_) return; } } diff --git a/Embedding.hh b/Embedding.hh index 1f3c9bd4e8aa0c94fa57ba144ddd0fb8b1b7e33c..f59ba6a729b9cb80136def3264c91999b7450d51 100644 --- a/Embedding.hh +++ b/Embedding.hh @@ -15,26 +15,23 @@ public: ~Embedding() {} enum TraceFaceAttr {UNPROCESSEDFACE, PREPROCESSEDFACE}; - enum TraceType {IMPLICITDIJKSTRA, A_STAR, A_STAR_MIDPOINTS}; enum RandomType {RATIO, TOTAL}; void CopyInitialization(TriMesh& base_mesh, PolyMesh& meta_mesh); - void SelectionTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh, - TraceType type = IMPLICITDIJKSTRA); + void SelectionTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh); void RandomTriangulation(TriMesh& base_mesh, PolyMesh& meta_mesh, double ratio, - RandomType rtype, TraceType type = A_STAR); + RandomType rtype); void ColorizeMetaMesh(); void Trace(OpenMesh::HalfedgeHandle mheh, bool cleanup = true, - bool mark_trace = false, TraceType tracetype = A_STAR, + bool mark_trace = false, TraceFaceAttr facetype = PREPROCESSEDFACE); void Retrace(OpenMesh::HalfedgeHandle mheh, bool cleanup = true, - bool mark_trace = false, TraceType tracetype = A_STAR, + bool mark_trace = false, TraceFaceAttr facetype = PREPROCESSEDFACE); - void Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose = false, - TraceType type = A_STAR); + void Collapse(OpenMesh::HalfedgeHandle mheh, bool verbose = false); bool IsCollapseOkay(OpenMesh::HalfedgeHandle mheh, bool verbose = false); - void Rotate(OpenMesh::EdgeHandle meh, TraceType type = A_STAR); + void Rotate(OpenMesh::EdgeHandle meh); bool IsRotationOkay(OpenMesh::EdgeHandle meh); void Relocate(OpenMesh::VertexHandle mvh, OpenMesh::VertexHandle bvh, bool verbose = false, bool lowlevel = true); @@ -90,9 +87,9 @@ public: private: enum SplitTraversal {LEFT, RIGHT}; bool TriangulationPipeline( - std::vector<OpenMesh::VertexHandle> meta_mesh_points, TraceType type); + std::vector<OpenMesh::VertexHandle> meta_mesh_points); void InitializeProperties(); - bool TriangulateMetaMesh(TraceType type); + bool TriangulateMetaMesh(); void PreProcessEdges(); void ProcessHalfedge(OpenMesh::HalfedgeHandle mheh); void ProcessEdge(OpenMesh::EdgeHandle meh); @@ -114,19 +111,13 @@ private: void CreateMetaMeshVertices(std::vector<OpenMesh::VertexHandle> meta_mesh_points); bool Delaunay(OpenMesh::VPropHandleT<double> voronoidistance, OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - OpenMesh::HPropHandleT<int> multiplicity_heh, - TraceType type); + OpenMesh::HPropHandleT<int> multiplicity_heh); void TraverseBoundary(OpenMesh::VertexHandle mvh); int fact(int n); int nCk(int n, int k); std::vector<int> VoronoiGenus(); - int FixMetaMeshConnectivity(OpenMesh::VertexHandle mvh); - void AddSelfEdges(std::vector<OpenMesh::HalfedgeHandle> borders); void SetFaceProperties(OpenMesh::FaceHandle bf, - OpenMesh::FaceHandle mf, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - TraceType type); + OpenMesh::FaceHandle mf); void CopyFaceProperties(OpenMesh::FaceHandle mfh, std::vector<OpenMesh::HalfedgeHandle> boundaryborders); OpenMesh::FaceHandle AddFace(std::vector<OpenMesh::VertexHandle> mvh, @@ -138,27 +129,12 @@ private: void SetBorderProperties(OpenMesh::HalfedgeHandle bheh, OpenMesh::HalfedgeHandle mheh); - void ImplicitDijkstra(OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, - OpenMesh::HPropHandleT<int> multiplicity_heh); - void A_StarTriangulation(TraceType type); + void A_StarTriangulation(); void NaiveVoronoi(std::queue<OpenMesh::VertexHandle> queue, OpenMesh::VPropHandleT<double> voronoidistance, OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh); - OpenMesh::HalfedgeHandle FindMiddle(OpenMesh::HalfedgeHandle metaheh, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh); - OpenMesh::HalfedgeHandle CreateMiddle(OpenMesh::HalfedgeHandle bheh, - OpenMesh::VPropHandleT<double> voronoidistance, - OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh); - bool EligibleHalfedge(OpenMesh::HalfedgeHandle baseheh, - OpenMesh::VertexHandle metavh0, - OpenMesh::VertexHandle metavh1); - OpenMesh::HalfedgeHandle DijkstraNextHeh(OpenMesh::HalfedgeHandle bheh, - OpenMesh::VertexHandle metavh0, - OpenMesh::VertexHandle metavh1, - OpenMesh::HPropHandleT<bool> marked); + void MarkPath(OpenMesh::HalfedgeHandle heh, OpenMesh::HalfedgeHandle metaheh, OpenMesh::VPropHandleT<OpenMesh::HalfedgeHandle> to_heh, OpenMesh::VPropHandleT<double> voronoidistance, @@ -270,14 +246,7 @@ private: OpenMesh::HalfedgeHandle bheh, OpenMesh::HalfedgeHandle mheh, OpenMesh::HPropHandleT<int> multiplicity_heh); - /* - void MiddleTraversal(OpenMesh::HalfedgeHandle bheh, - OpenMesh::HalfedgeHandle mheh, - OpenMesh::VPropHandleT<OpenMesh::VertexHandle> voronoiID, - OpenMesh::HPropHandleT<int> multiplicity_heh); - void BaseSplit(OpenMesh::HalfedgeHandle leftheh, - OpenMesh::HalfedgeHandle bheh); - */ + bool debug_hard_stop_ = false; bool initial_triangulation_ = false; bool boundaries_ = false; diff --git a/IsotropicRemesher.cc b/IsotropicRemesher.cc index 213e5861bb7bc41bb514f8b73d2275856b8a46c6..b2d481d11c25c37a10682791c814e19d32beb146 100644 --- a/IsotropicRemesher.cc +++ b/IsotropicRemesher.cc @@ -627,7 +627,6 @@ void IsotropicRemesher::SmoothVertexVWD(Embedding *embedding, } ++it; } - //qDebug() << "Relocating vertex " << mvh.idx(); // The new, faster relocate method sadly cannot yet handle complex patches. // Make sure to use the old method if a patch is complex, so check that here. bool simple = true; @@ -646,7 +645,6 @@ void IsotropicRemesher::SmoothVertexVWD(Embedding *embedding, qDebug() << "Relocation failed for vertex " << mih_list.front().idx(); debug_hard_stop_ = true; } - //qDebug() << "Relocation finished."; } /*!