diff --git a/Embedding.cc b/Embedding.cc index 19292e672ecf561ce8c01d897eb9b784c7301e8a..6ed84f99b98ed2e08dd3e9b1d74124bc8a18423e 100644 --- a/Embedding.cc +++ b/Embedding.cc @@ -2003,7 +2003,7 @@ double Embedding::MetaHalfedgeWeight(OpenMesh::HalfedgeHandle mheh) { double weight = 0.0; std::vector<OpenMesh::HalfedgeHandle> hes = GetBaseHalfedges(mheh); for (auto bheh : hes) { - weight += std::log(base_mesh_->property(halfedge_weight_, bheh)); + weight += base_mesh_->property(halfedge_weight_, bheh); } return weight; } @@ -2017,7 +2017,7 @@ double Embedding::MetaVertexWeight(OpenMesh::VertexHandle mvh) { double weight = 0.0; for (auto moh : meta_mesh_->voh_range(mvh)) { auto bheh = meta_mesh_->property(mhe_connection_, moh); - weight += std::log(base_mesh_->property(halfedge_weight_, bheh)); + weight += base_mesh_->property(halfedge_weight_, bheh); } return weight; } @@ -2511,6 +2511,7 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::A_StarBidirectional( } auto bvh0 = base_mesh_->from_vertex_handle(bheh0); auto bvh1 = base_mesh_->from_vertex_handle(bheh1); + auto mheho = base_mesh_->opposite_halfedge_handle(mheh); const double inf = std::numeric_limits<double>::infinity(); double shortest = inf; @@ -2612,11 +2613,24 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::A_StarBidirectional( } } // Check if a connection with the other side has been made, if so check if it is minimal - if (bvhc != base_mesh_->from_vertex_handle(bheh0) && + if (bvhc != bvh0 && base_mesh_->property(gscore1, bvhc) < inf) { + // Special case: the found "middle" is one of the starting vertices. + // In this case the connection between bvh0 and bvh1 MUST only be one edge long, + // otherwise the trace found a path from the wrong direction. + // This should've been the bug messing up Relocation on complex narrow features of meshes. + bool validvert = true; + if (bvhc == bvh1) { + validvert = false; + for (auto bvhit : base_mesh_->vv_range(bvhc)) { + if (bvhit == bvh0) { + validvert = true; + } + } + } auto newdist = base_mesh_->property(gscore1, bvhc) + base_mesh_->property(gscore0, bvhc); - if (shortest > newdist) { + if (validvert && shortest > newdist) { shortest = newdist; middle = bvhc; //qDebug() << "found new shortest path of length: " << shortest; @@ -2633,7 +2647,7 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::A_StarBidirectional( if (base_mesh_->property(closed_set1, bvhc) == false) { base_mesh_->property(closed_set1, bvhc) = true; // Iterate over the neighboring vertices - auto neighbors1 = A_StarNeighbors(bvhc, mheh, closed_set1, bvh0, bheh1); + auto neighbors1 = A_StarNeighbors(bvhc, mheho, closed_set1, bvh0, bheh1); //if (neighbors1.empty()) // qDebug() << "Empty A* Neighborhood1."; for (auto bvhn : neighbors1) { @@ -2666,11 +2680,25 @@ std::vector<OpenMesh::HalfedgeHandle> Embedding::A_StarBidirectional( } } // Check if a connection with the other side has been made, if so check if it is minimal - if (bvhc != base_mesh_->from_vertex_handle(bheh1) && + if (bvhc != bvh1 && base_mesh_->property(gscore0, bvhc) < inf) { + // Special case: the found "middle" is one of the starting vertices. + // In this case the connection between bvh0 and bvh1 MUST only be one edge long, + // otherwise the trace found a path from the wrong direction. + // This should've been the bug messing up Relocation on complex narrow features of meshes. + bool validvert = true; + if (bvhc == bvh0) { + validvert = false; + for (auto bvhit : base_mesh_->vv_range(bvhc)) { + if (bvhit == bvh1) { + validvert = true; + } + } + } + auto newdist = base_mesh_->property(gscore1, bvhc) + base_mesh_->property(gscore0, bvhc); - if (shortest > newdist) { + if (validvert && shortest > newdist) { shortest = newdist; middle = bvhc; //qDebug() << "found new shortest path of length: " << shortest; @@ -2776,7 +2804,11 @@ std::vector<OpenMesh::VertexHandle> Embedding::A_StarNeighbors(OpenMesh::VertexH if (!meta_mesh_->is_valid_handle(base_mesh_->property(bhe_connection_, bhehiter)) && (!IsSectorBorder(base_mesh_->to_vertex_handle(bhehiter)) || base_mesh_->to_vertex_handle(bhehiter) == towardsbvh)) { - neighbors.push_back(base_mesh_->to_vertex_handle(bhehiter)); + if (!(base_mesh_->to_vertex_handle(bhehiter) == towardsbvh)) { + neighbors.push_back(base_mesh_->to_vertex_handle(bhehiter)); + } else if (SectorEntry(mheh, bhehiter)) { + neighbors.push_back(base_mesh_->to_vertex_handle(bhehiter)); + } } bhehiter = base_mesh_->next_halfedge_handle( base_mesh_->opposite_halfedge_handle(bhehiter)); @@ -2785,8 +2817,8 @@ std::vector<OpenMesh::VertexHandle> Embedding::A_StarNeighbors(OpenMesh::VertexH } else { for (auto voh_it: base_mesh_->voh_range(bvh)) { auto vv_it = base_mesh_->to_vertex_handle(voh_it); - if ((((base_mesh_->property(closed_set, vv_it) == false) - && !IsSectorBorder(vv_it))) + if ((base_mesh_->property(closed_set, vv_it) == false) + && !IsSectorBorder(vv_it) && ValidA_StarEdge(voh_it, mheh)) { neighbors.push_back(vv_it); } @@ -2796,6 +2828,37 @@ std::vector<OpenMesh::VertexHandle> Embedding::A_StarNeighbors(OpenMesh::VertexH return neighbors; } +/*! + * \brief Embedding::SectorEntry check if entry into the to_vertex of mheh + * is allowed via bheh + * \param mheh + * \param bheh + * \return + */ +bool Embedding::SectorEntry(OpenMesh::HalfedgeHandle mheh, OpenMesh::HalfedgeHandle bheh) { + auto mheho = meta_mesh_->opposite_halfedge_handle(mheh); + auto mhehn = meta_mesh_->opposite_halfedge_handle(meta_mesh_->prev_halfedge_handle( + mheho)); + while (!base_mesh_->is_valid_handle(meta_mesh_->property(mhe_connection_, mhehn)) + && mhehn != mheho) { + mhehn = meta_mesh_->opposite_halfedge_handle(meta_mesh_->prev_halfedge_handle(mhehn)); + } + auto bhehc = base_mesh_->opposite_halfedge_handle(bheh); + assert (base_mesh_->property(bv_connection_, base_mesh_->from_vertex_handle(bhehc)) + == meta_mesh_->from_vertex_handle(mheho)); + auto bhehn = base_mesh_->opposite_halfedge_handle(base_mesh_->prev_halfedge_handle(bhehc)); + while (!meta_mesh_->is_valid_handle(base_mesh_->property(bhe_connection_, bhehn)) + && bhehn != bhehc) { + bhehn = base_mesh_->opposite_halfedge_handle(base_mesh_->prev_halfedge_handle(bhehn)); + } + if (((bhehn == meta_mesh_->property(mhe_connection_, mhehn)) + && (base_mesh_->property(bhe_connection_, bhehn) == mhehn)) + || (bhehn == bhehc && mhehn == mheho)) { + return true; + } + return false; +} + /*! * \brief Embedding::ValidA_StarEdge * \param bheh @@ -2932,6 +2995,7 @@ void Embedding::InsertPath(OpenMesh::HalfedgeHandle mheh, * to handle an initial triangulation where edges are traced in an arbitrary order and some edges * may already be traced while others arent. Traces starting in the wrong sectors will fail so * the starting halfedges need to be right. + * Assumes a pre-processed sector to trace in. * \param mheh the halfedge to be traced. * \param verbose * \return Two starting halfedges for use in A* tracing. @@ -2961,6 +3025,7 @@ Embedding::FindA_StarStartingHalfedges(OpenMesh::HalfedgeHandle mheh, bool verbo goto endloop1; } } + /* auto bvhx = meta_mesh_->property(mv_connection_, meta_mesh_->to_vertex_handle(iter)); for (auto bhehiter : base_mesh_->voh_range(meta_mesh_->property(mv_connection_, meta_mesh_->from_vertex_handle(iter)))) { @@ -2972,6 +3037,7 @@ Embedding::FindA_StarStartingHalfedges(OpenMesh::HalfedgeHandle mheh, bool verbo goto endloop1; } } + */ iter = meta_mesh_->opposite_halfedge_handle(meta_mesh_->prev_halfedge_handle(iter)); } endloop1: @@ -3000,6 +3066,7 @@ Embedding::FindA_StarStartingHalfedges(OpenMesh::HalfedgeHandle mheh, bool verbo goto endloop2; } } + /* auto bvhx = meta_mesh_->property(mv_connection_, meta_mesh_->to_vertex_handle(iter)); for (auto bhehiter : base_mesh_->voh_range(meta_mesh_->property(mv_connection_, meta_mesh_->from_vertex_handle(iter)))) { @@ -3009,6 +3076,7 @@ Embedding::FindA_StarStartingHalfedges(OpenMesh::HalfedgeHandle mheh, bool verbo goto endloop2; } } + */ iter = meta_mesh_->opposite_halfedge_handle(meta_mesh_->prev_halfedge_handle(iter)); } endloop2: @@ -3745,14 +3813,15 @@ void Embedding::LowLevelRelocate(OpenMesh::VertexHandle mvh, OpenMesh::VertexHan // Order can be very important when doing this, as otherwise vertices can be blocked off // by edges. Order of retracing: // 1: Boundary edges - // 2: A representative of each connected component in the patch around mvh. + // 2: A non-duplicate representative of each connected component in the patch around mvh. // In most cases there will only be one component - // 3: Self-edges. The representatives of components should wall those off and confine them + // 3: Duplicate representatives of unrepresented connected components + // 4: Self-edges. The representatives of components should wall those off and confine them // to areas so that they cannot vanish - // 4: All other edges that are non-duplicate - // 5: duplicates + // 5: All other edges that are non-duplicate + // 6: All other duplicates OpenMesh::HPropHandleT<bool> he_selected; - OpenMesh::VPropHandleT<bool> v_selected; + OpenMesh::VPropHandleT<uint> v_selected; OpenMesh::VPropHandleT<bool> group_selected; std::queue<OpenMesh::HalfedgeHandle> tracingqueue; meta_mesh_->add_property(he_selected, "select edges for tracing order"); @@ -3760,15 +3829,22 @@ void Embedding::LowLevelRelocate(OpenMesh::VertexHandle mvh, OpenMesh::VertexHan meta_mesh_->add_property(v_selected, "select vertices for tracing order"); // 0: initialize properties meta_mesh_->property(group_selected, mvh) = false; + std::vector<OpenMesh::HalfedgeHandle> moh_range; + for (auto moh : meta_mesh_->voh_range(mvh)) { meta_mesh_->property(he_selected, moh) = false; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = false; meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) = false; - meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = false; + meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = 0; + moh_range.push_back(moh); + } + for (auto moh : meta_mesh_->voh_range(mvh)) { + meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) += 1; } + std::random_shuffle(moh_range.begin(), moh_range.end()); // 1: find boundary edges. - for (auto moh : meta_mesh_->voh_range(mvh)) { + for (auto moh : moh_range) { meta_mesh_->property(he_selected, moh) = false; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = false; if (!meta_mesh_->property(he_selected, moh) @@ -3778,54 +3854,71 @@ void Embedding::LowLevelRelocate(OpenMesh::VertexHandle mvh, OpenMesh::VertexHan meta_mesh_->property(he_selected, moh) = true; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = true; meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) = true; - meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = true; TraverseGroup(mvh, moh, group_selected); } } - // 2: find group representatives - for (auto moh : meta_mesh_->voh_range(mvh)) { + // 2: find non-duplicate group representatives + for (auto moh : moh_range) { // non-self-edges if (meta_mesh_->from_vertex_handle(moh) != meta_mesh_->to_vertex_handle(moh)) { // unselected vertex -> new group found -> take the representative and select it if (!meta_mesh_->property(he_selected, moh) - && !meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh))) { + && !meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) + && meta_mesh_->property(v_selected, + meta_mesh_->to_vertex_handle(moh)) == 1) { tracingqueue.push(moh); meta_mesh_->property(he_selected, moh) = true; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = true; meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) = true; - meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = true; TraverseGroup(mvh, moh, group_selected); } } } - // 3: find self-edges - for (auto moh : meta_mesh_->voh_range(mvh)) { + // 3: find duplicate group representatives + for (auto moh : moh_range) { + // non-self-edges + if (meta_mesh_->from_vertex_handle(moh) + != meta_mesh_->to_vertex_handle(moh)) { + // unselected vertex -> new group found -> take the representative and select it + if (!meta_mesh_->property(he_selected, moh) + && !meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) + && meta_mesh_->property(v_selected, + meta_mesh_->to_vertex_handle(moh)) > 1) { + tracingqueue.push(moh); + meta_mesh_->property(he_selected, moh) = true; + meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = true; + meta_mesh_->property(group_selected, meta_mesh_->to_vertex_handle(moh)) = true; + TraverseGroup(mvh, moh, group_selected); + } + } + } + + // 4: find self-edges + for (auto moh : moh_range) { // Also make sure the self-edge is not selected (can happen if boundary self-edge) if (meta_mesh_->from_vertex_handle(moh) != meta_mesh_->to_vertex_handle(moh) && !meta_mesh_->property(he_selected, moh)) { tracingqueue.push(moh); meta_mesh_->property(he_selected, moh) = true; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = true; - meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = true; } } - // 4: add the remaining non-duplicate edges to the qeuue - for (auto moh : meta_mesh_->voh_range(mvh)) { - if (!meta_mesh_->property(he_selected, moh) && !meta_mesh_->property(v_selected, - meta_mesh_->to_vertex_handle(moh))) { + // 5: add the remaining non-duplicate edges to the qeuue + for (auto moh : moh_range) { + if (!meta_mesh_->property(he_selected, moh) && meta_mesh_->property(v_selected, + meta_mesh_->to_vertex_handle(moh)) == 1) { tracingqueue.push(moh); meta_mesh_->property(he_selected, moh) = true; meta_mesh_->property(he_selected, meta_mesh_->opposite_halfedge_handle(moh)) = true; - meta_mesh_->property(v_selected, meta_mesh_->to_vertex_handle(moh)) = true; } } - // 5: add duplicate edges - for (auto moh : meta_mesh_->voh_range(mvh)) { + // 6: add the remaining duplicate edges + for (auto moh : moh_range) { if (!meta_mesh_->property(he_selected, moh)) { tracingqueue.push(moh); meta_mesh_->property(he_selected, moh) = true; @@ -3834,9 +3927,15 @@ void Embedding::LowLevelRelocate(OpenMesh::VertexHandle mvh, OpenMesh::VertexHan } // Now that the order is set: finally do the tracing + std::vector<int> IDs; while (!tracingqueue.empty()) { auto mhehc = tracingqueue.front(); + if (std::binary_search(IDs.begin(), IDs.end(), mhehc.idx())) { + qDebug() << "Duplicate edge in tracing queue"; + } + IDs.push_back(mhehc.idx()); Trace(mhehc); + tracingqueue.pop(); if (debug_hard_stop_) { qDebug() << "Relocation failed"; diff --git a/Embedding.hh b/Embedding.hh index 6fb035b03c76fb76ac8b1e5b54e81cc3b585923a..7b406d0e34415336907900c1438fdff445491d40 100644 --- a/Embedding.hh +++ b/Embedding.hh @@ -158,6 +158,7 @@ private: OpenMesh::VPropHandleT<bool> closed_set, OpenMesh::VertexHandle towardsbvh, OpenMesh::HalfedgeHandle bheh = OpenMesh::PolyConnectivity::InvalidHalfedgeHandle); + bool SectorEntry(OpenMesh::HalfedgeHandle mheh, OpenMesh::HalfedgeHandle bheh); bool ValidA_StarEdge(OpenMesh::HalfedgeHandle bheh, OpenMesh::HalfedgeHandle mheh); std::vector<OpenMesh::HalfedgeHandle> A_StarReconstructPath(OpenMesh::VertexHandle middle, diff --git a/IsotropicRemesher.cc b/IsotropicRemesher.cc index b2d481d11c25c37a10682791c814e19d32beb146..8532469edb73cfaa54e776c777415ae53e9219c4 100644 --- a/IsotropicRemesher.cc +++ b/IsotropicRemesher.cc @@ -29,11 +29,27 @@ void IsotropicRemesher::Remesh(Embedding* embedding, std::function<void (QString, QString, double, double)> screenshot, bool limitflips, StraighteningType strtype, - CollapsingOrder corder) { + CollapsingOrder corder, + bool dataoutput) { debug_hard_stop_ = false; using namespace PluginFunctions; qDebug() << "Running the Isotropic Remeshing algorithm"; auto base_mesh = embedding->GetBaseMesh(); + if (screenshot || dataoutput) { + QDir dir(QString(SCREENSHOT_PATH) + "/target" + QString::number(target_length) + + "-iterations" + QString::number(iterations)); + if (!dir.exists()) { + dir.mkpath("."); + } + } + QFile param_file(QString(SCREENSHOT_PATH) + "/target" + QString::number(target_length) + + "-iterations" + QString::number(iterations) + "/t" + + QString::number(target_length) + "i" + QString::number(iterations) + + ".param.txt"); + QFile output_file(QString(SCREENSHOT_PATH) + "/target" + QString::number(target_length) + + "-iterations" + QString::number(iterations) + "/t" + + QString::number(target_length) + "i" + QString::number(iterations) + + ".csv"); const double inf = std::numeric_limits<double>::infinity(); ACG::Vec3d minCorner = {+inf, +inf, +inf}; @@ -48,12 +64,15 @@ void IsotropicRemesher::Remesh(Embedding* embedding, double high = target_length * alpha * scale; double low = high * beta / alpha; + if (dataoutput) { + output_file.resize(0); + param_file.resize(0); + DataOutputParam(embedding, ¶m_file, target_length, scale, iterations, alpha, beta, + smtype, limitflips, strtype, corder); + DataOutputHeader(embedding, &output_file); + DataOutput(embedding, &output_file, 0.0, 0); + } if (screenshot) { - QDir dir(QString(SCREENSHOT_PATH) + "/target" + QString::number(target_length) - + "-iterations" + QString::number(iterations)); - if (!dir.exists()) { - dir.mkpath("."); - } screenshot(QString("IsoRemesh0_Start"), QString(SCREENSHOT_PATH) + "/target" + QString::number(target_length) + "-iterations" + QString::number(iterations) , @@ -103,11 +122,7 @@ void IsotropicRemesher::Remesh(Embedding* embedding, qDebug() << "Time elapsed: " << swatchlocal->Delta() << "ms."; swatchlocal->Reset(); qDebug() << "Iteration" << i+1 << "; Smoothing..."; - if (strtype == IMPLICIT) { - Smoothing(embedding, smtype, true); - } else { - Smoothing(embedding, smtype, false); - } + Smoothing(embedding, smtype); if (debug_hard_stop_) return; embedding->CleanUpBaseMesh(); if (screenshot) { @@ -123,8 +138,9 @@ void IsotropicRemesher::Remesh(Embedding* embedding, if (debug_hard_stop_) return; embedding->CleanUpBaseMesh(); qDebug() << "Time elapsed: " << swatchlocal->Delta() << "ms."; + double iteration_time = swatchit->Delta(); qDebug() << "Iteration" << i+1 << " finished, time elapsed: " - << swatchit->Delta() << "ms."; + << iteration_time << "ms."; if (screenshot) { qDebug() << "Iteration" << i+1 << "Screenshot"; screenshot(QString("IsoRemeshIt_") + QString::number(i) + QString(".4Straightening"), @@ -132,6 +148,9 @@ void IsotropicRemesher::Remesh(Embedding* embedding, + "-iterations" + QString::number(iterations) , 0, 0); } + if (dataoutput) { + DataOutput(embedding, &output_file, iteration_time, i+1); + } } qDebug() << "Finished " << iterations << " iterations of Isotropic Remeshing" " with target edge length " << target_length * scale; @@ -234,7 +253,7 @@ void IsotropicRemesher::Collapses(Embedding *embedding, double low, auto mvh0 = meta_mesh->from_vertex_handle(mheh); - int newmvh1edges = static_cast<int>(meta_mesh->valence(mvh0)) - 1; + int newmvh1edges = static_cast<int>(meta_mesh->valence(mvh0)) - 2; if (meta_mesh->from_vertex_handle(mheh0) == meta_mesh->from_vertex_handle(mheh1)) { splitw -= embedding->MetaHalfedgeWeight(mheh0); @@ -419,7 +438,7 @@ int IsotropicRemesher::FlipEval(Embedding *embedding, OpenMesh::EdgeHandle meh) * \param shakeup: smoothes vertices twice, moving them away from center first and then * back to it. Not recommended as it is very expensive and doesn't seem to help much. */ -void IsotropicRemesher::Smoothing(Embedding *embedding, SmoothingType stype, bool shakeup) { +void IsotropicRemesher::Smoothing(Embedding *embedding, SmoothingType stype) { switch(stype) { case FORESTFIRE: { qDebug() << "Forest Fire Smoothing"; @@ -428,12 +447,12 @@ void IsotropicRemesher::Smoothing(Embedding *embedding, SmoothingType stype, boo } case VERTEXWEIGHTS: { qDebug() << "Vertex Weights Smoothing"; - SmoothingVWD(embedding, VERTEXWEIGHTS, shakeup); + SmoothingVWD(embedding, VERTEXWEIGHTS); break; } case VERTEXDISTANCES:{ qDebug() << "Vertex Distances Smoothing"; - SmoothingVWD(embedding, VERTEXDISTANCES, shakeup); + SmoothingVWD(embedding, VERTEXDISTANCES); break; } } @@ -445,8 +464,7 @@ void IsotropicRemesher::Smoothing(Embedding *embedding, SmoothingType stype, boo * \param stype * \param shakeup */ -void IsotropicRemesher::SmoothingVWD(Embedding *embedding, SmoothingType stype - , bool shakeup) { +void IsotropicRemesher::SmoothingVWD(Embedding *embedding, SmoothingType stype) { auto meta_mesh = embedding->GetMetaMesh(); auto base_mesh = embedding->GetBaseMesh(); OpenMesh::VPropHandleT<std::vector<double>> distances; @@ -468,12 +486,12 @@ void IsotropicRemesher::SmoothingVWD(Embedding *embedding, SmoothingType stype for (auto bvh : base_mesh->vertices()) { base_mesh->property(distances, bvh) = {}; } - SmoothVertexVWD(embedding, &distances, mvh, stype, shakeup); + SmoothVertexVWD(embedding, &distances, mvh, stype); if (debug_hard_stop_) return; - embedding->CleanUpBaseMesh(); } ++ctr; } + embedding->CleanUpBaseMesh(); embedding->MetaGarbageCollection();//mvhlist_pointers); base_mesh->remove_property(distances); } @@ -489,18 +507,10 @@ void IsotropicRemesher::SmoothingVWD(Embedding *embedding, SmoothingType stype void IsotropicRemesher::SmoothVertexVWD(Embedding *embedding, const OpenMesh::VPropHandleT<std::vector<double>>* distances, OpenMesh::VertexHandle mvh, - SmoothingType stype, - bool shakeup) { + SmoothingType stype) { const double inf = std::numeric_limits<double>::infinity(); auto meta_mesh = embedding->GetMetaMesh(); auto base_mesh = embedding->GetBaseMesh(); - // Ensure the vertex is moved twice in order to clean up the underlying basemesh - if (shakeup) { - embedding->Relocate(mvh, base_mesh->to_vertex_handle(meta_mesh->property( - embedding->mhe_connection_, meta_mesh->opposite_halfedge_handle( - meta_mesh->halfedge_handle(mvh))))); - embedding->CleanUpBaseMesh(); - } std::list<OpenMesh::HalfedgeHandle> mih_list; for (auto mhehit : meta_mesh->vih_range(mvh)) { if (meta_mesh->is_valid_handle(mhehit) @@ -607,18 +617,19 @@ void IsotropicRemesher::SmoothVertexVWD(Embedding *embedding, // Find neighbors, limited by sector border for (auto boheh : base_mesh->voh_range(bvhcurr)) { if (!embedding->IsSectorBorder(base_mesh->to_vertex_handle(boheh), mih_list)) { + double newlength = base_mesh->property(*distances, bvhcurr).at(it) + + base_mesh->calc_edge_length(boheh); if (base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).size() < it+1) { - base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).push_back( - base_mesh->property(*distances, bvhcurr).at(it) - + base_mesh->calc_edge_length(boheh)); + base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)) + .push_back(newlength); assert(base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).size() == it+1); minheap.push(std::make_pair(base_mesh->to_vertex_handle(boheh), base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)))); - } else if (base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).at(it) > - base_mesh->property(*distances, bvhcurr).at(it) + base_mesh->calc_edge_length(boheh)) { + } else if (base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).at(it) + > newlength) { base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)).at(it) - = base_mesh->property(*distances, bvhcurr).at(it) + base_mesh->calc_edge_length(boheh); + = newlength; minheap.push(std::make_pair(base_mesh->to_vertex_handle(boheh), base_mesh->property(*distances, base_mesh->to_vertex_handle(boheh)))); } @@ -739,9 +750,9 @@ void IsotropicRemesher::SmoothingFF(Embedding *embedding) { SmoothVertexFF(embedding, distance, direction, mih_list); if (debug_hard_stop_) return; embedding->CleanUpBaseMesh(); - embedding->MetaGarbageCollection(); } } + embedding->MetaGarbageCollection(); base_mesh->remove_property(distance); base_mesh->remove_property(direction); } @@ -893,11 +904,7 @@ void IsotropicRemesher::Straightening(Embedding *embedding, StraighteningType st case NONE: { break; } - case IMPLICIT: { - // Straightening handled in smoothing by moving vertices twice. - break; - } - case SIMPLE: { + case EDGEWISE: { // Straighten edgewise std::vector<OpenMesh::EdgeHandle> medges; for (auto meh : meta_mesh->edges()) { @@ -941,6 +948,7 @@ void IsotropicRemesher::Straightening(Embedding *embedding, StraighteningType st embedding->Retrace(moh); } } else { + /* enum facetype{noselfedgesdisc, selfedgesorhighergenus, boundary}; facetype ft = noselfedgesdisc; for (auto moh : meta_mesh->voh_range(mvh)) { @@ -983,12 +991,12 @@ void IsotropicRemesher::Straightening(Embedding *embedding, StraighteningType st break; } case selfedgesorhighergenus: { - for (auto moh : meta_mesh->voh_range(mvh)) { - embedding->Retrace(moh); - } + embedding->Relocate(mvh, meta_mesh->property(embedding->mv_connection_, mvh)); break; } } + */ + embedding->Relocate(mvh, meta_mesh->property(embedding->mv_connection_, mvh)); } } if (ctr%20 == 0) { @@ -1000,3 +1008,160 @@ void IsotropicRemesher::Straightening(Embedding *embedding, StraighteningType st } } } + +void IsotropicRemesher::DataOutputParam(Embedding *embedding, + QFile *file, + double target_length, + double scale, + uint iterations, + double alpha, + double beta, + SmoothingType smtype, + bool limitflips, + StraighteningType strtype, + CollapsingOrder corder) { + if(file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + QString target_length_str = QString::number(target_length); + QString target_length_adjusted_str = QString::number(target_length*scale); + QString iterations_str = QString::number(iterations); + QString alpha_str = QString::number(alpha); + QString beta_str = QString::number(beta); + QString smtype_str; + switch(smtype) { + case FORESTFIRE: { + smtype_str = QString("ForestFire"); + break; + } + case VERTEXWEIGHTS: { + smtype_str = QString("VertexWeights"); + break; + } + case VERTEXDISTANCES: { + smtype_str = QString("VertexDistances"); + break; + } + } + QString limitflips_str; + if (limitflips) { + limitflips_str = QString("true"); + } else { + limitflips_str = QString("false"); + } + QString strtype_str; + switch (strtype) { + case NONE: { + strtype_str = QString("None"); + break; + } + case EDGEWISE: { + strtype_str = QString("Edgewise"); + break; + } + case PATCHWISE: { + strtype_str = QString("Patchwise"); + break; + } + } + QString corder_str; + switch (corder) { + case RANDOM: { + corder_str = QString("Random"); + break; + } + case VALENCE: { + corder_str = QString("Valence"); + break; + } + case SPLITWEIGHT: { + corder_str = QString("Splitweight"); + break; + } + } + + QTextStream tstream(file); + tstream << "Target edge length: " << target_length_str.toStdString().c_str() << endl + << "Adjusted length: " << target_length_adjusted_str.toStdString().c_str() << endl + << "Iterations: " << iterations_str.toStdString().c_str() << endl + << "Alpha: " << alpha_str.toStdString().c_str() << endl + << "Beta: " << beta_str.toStdString().c_str() << endl + << "Smoothing type: " << smtype_str.toStdString().c_str() << endl + << "Limit Flips: " << limitflips_str.toStdString().c_str() << endl + << "Straightening Type: " << strtype_str.toStdString().c_str() << endl + << "Collapsing Order: " << corder_str.toStdString().c_str(); + file->close(); + } +} + +void IsotropicRemesher::DataOutputHeader(Embedding *embedding, QFile *file) { + if(file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + QTextStream tstream(file); + tstream << "iteration," + << "time," + << "basefaces," + << "metafaces," + << "valence.avg," + << "valence.sd," + << "edgelength.avg," + << "edgelength.sd"; + tstream << endl; + file->close(); + } +} + +/*! + * \brief IsotropicRemesher::DataOutput + * write data about the current iteration into the file + * \param embedding + * \param file + * \param time_elapsed + * \param iteration + */ +void IsotropicRemesher::DataOutput(Embedding *embedding, + QFile* file, + double time_elapsed, + uint iteration) { + if(file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { + auto meta_mesh = embedding->GetMetaMesh(); + auto base_mesh = embedding->GetBaseMesh(); + + unsigned long baseeuler = base_mesh->n_vertices() - base_mesh->n_edges() + + base_mesh->n_faces(); + unsigned long metaeuler = meta_mesh->n_vertices() - meta_mesh->n_edges() + + meta_mesh->n_faces(); + double basegenus = (2-baseeuler)/2.0; + double metagenus = (2-metaeuler)/2.0; + double avgmetaedgelength = 0.0; + for (auto meh : meta_mesh->edges()) { + avgmetaedgelength += embedding->CalculateEdgeLength(meh); + } + avgmetaedgelength /= meta_mesh->n_edges(); + double metaedgelengthdeviation = 0.0; + for (auto meh : meta_mesh->edges()) { + metaedgelengthdeviation += (avgmetaedgelength-embedding->CalculateEdgeLength(meh)) + *(avgmetaedgelength-embedding->CalculateEdgeLength(meh)); + } + metaedgelengthdeviation /= meta_mesh->n_edges(); + metaedgelengthdeviation = std::sqrt(metaedgelengthdeviation); + double avgvalence = 0.0; + double valencedeviation = 0.0; + for (auto mvh : meta_mesh->vertices()) { + avgvalence += meta_mesh->valence(mvh); + valencedeviation += (6-meta_mesh->valence(mvh))*(6-meta_mesh->valence(mvh)); + } + avgvalence /= meta_mesh->n_vertices(); + valencedeviation /= meta_mesh->n_vertices(); + valencedeviation = std::sqrt(valencedeviation); + + QTextStream tstream(file); + tstream << iteration << "," + << time_elapsed << "," + << base_mesh->n_faces() << "," + << meta_mesh->n_faces() << "," + << avgvalence << "," + << valencedeviation << "," + << avgmetaedgelength << "," + << metaedgelengthdeviation; + tstream << endl; + file->close(); + } +} diff --git a/IsotropicRemesher.hh b/IsotropicRemesher.hh index 2c531f45bfe6374414132f0a4542ae14e2246d12..7cee0b960427c684f869ebb38d3b671d24ef2bf2 100644 --- a/IsotropicRemesher.hh +++ b/IsotropicRemesher.hh @@ -19,19 +19,20 @@ public: ~IsotropicRemesher() {} enum SmoothingType{FORESTFIRE, VERTEXWEIGHTS, VERTEXDISTANCES}; - enum StraighteningType{NONE, IMPLICIT, SIMPLE, PATCHWISE}; + enum StraighteningType{NONE, EDGEWISE, PATCHWISE}; enum CollapsingOrder{RANDOM, VALENCE, SPLITWEIGHT}; void Remesh(Embedding* embedding, double target_length, uint iterations = 1, - double alpha = 4.0/3.0, - double beta = 4.0/5.0, + double alpha = 2, + double beta = 1.0/2.0, SmoothingType smtype = VERTEXWEIGHTS, std::function<void (QString, QString, double, double)> screenshot = {}, bool limitflips = false, - StraighteningType strtype = PATCHWISE, - CollapsingOrder corder = SPLITWEIGHT); + StraighteningType strtype = NONE, + CollapsingOrder corder = SPLITWEIGHT, + bool dataoutput = true); bool DebugStopStatus() {return debug_hard_stop_;} private: @@ -39,13 +40,12 @@ private: void Collapses(Embedding* embedding, double low, CollapsingOrder corder = SPLITWEIGHT); void Flips(Embedding* embedding, bool limitflips = false); int FlipEval(Embedding* embedding, OpenMesh::EdgeHandle meh); - void Smoothing(Embedding* embedding, SmoothingType stype = FORESTFIRE, bool shakeup = true); - void SmoothingVWD(Embedding* embedding, SmoothingType stype, bool shakeup = true); + void Smoothing(Embedding* embedding, SmoothingType stype = FORESTFIRE); + void SmoothingVWD(Embedding* embedding, SmoothingType stype); void SmoothVertexVWD(Embedding* embedding, const OpenMesh::VPropHandleT<std::vector<double>>* distances, OpenMesh::VertexHandle mvh, - SmoothingType stype, - bool shakeup = true); + SmoothingType stype); double DistanceScoreVW(Embedding* embedding, const OpenMesh::VPropHandleT<std::vector<double>>* distances, OpenMesh::VertexHandle bvh, uint numv); @@ -62,6 +62,19 @@ private: std::list<OpenMesh::HalfedgeHandle> mih_list); void Straightening(Embedding* embedding, StraighteningType strtype = PATCHWISE); + void DataOutputParam(Embedding* embedding, QFile* file, + double target_length, + double scale, + uint iterations, + double alpha, + double beta, + SmoothingType smtype, + bool limitflips, + StraighteningType strtype, + CollapsingOrder corder); + void DataOutputHeader(Embedding* embedding, QFile* file); + void DataOutput(Embedding* embedding, QFile* file, double time_elapsed, + uint iteration); bool debug_hard_stop_ = false; }; diff --git a/MetaMeshPlugin.cc b/MetaMeshPlugin.cc index a854c7a495302a5800084bc573da48e66c877174..d1976488c9f2c849ae5b71d31079fd34d17bb187 100644 --- a/MetaMeshPlugin.cc +++ b/MetaMeshPlugin.cc @@ -318,26 +318,19 @@ void MetaMeshPlugin::remesh() { screenshot(name, dir, width, height); }; - switch(widget_->combo_box_remeshing_->currentIndex()) { - case IsotropicRemesher::FORESTFIRE: { - remesher.Remesh(embedding_, widget_->input_length_->value(), - static_cast<uint>(widget_->input_iterations_->value()), 4.0/3.0, 4.0/5.0, - IsotropicRemesher::FORESTFIRE, take_screenshot); - break; - } - case IsotropicRemesher::VERTEXWEIGHTS:{ - remesher.Remesh(embedding_, widget_->input_length_->value(), - static_cast<uint>(widget_->input_iterations_->value()), 4.0/3.0, 4.0/5.0, - IsotropicRemesher::VERTEXWEIGHTS, take_screenshot); - break; - } - case IsotropicRemesher::VERTEXDISTANCES:{ - remesher.Remesh(embedding_, widget_->input_length_->value(), - static_cast<uint>(widget_->input_iterations_->value()), 4.0/3.0, 4.0/5.0, - IsotropicRemesher::VERTEXDISTANCES, take_screenshot); - break; - } - } + remesher.Remesh(embedding_, widget_->input_length_->value(), + static_cast<uint>(widget_->input_iterations_->value()), + widget_->input_alpha_->value(), + widget_->input_beta_->value(), + IsotropicRemesher::SmoothingType( + widget_->combo_box_remeshing_smtype_->currentIndex()), + take_screenshot, + widget_->checkbox_limit_flips_->isChecked(), + IsotropicRemesher::StraighteningType( + widget_->combo_box_remeshing_strype_->currentIndex()), + IsotropicRemesher::CollapsingOrder( + widget_->combo_box_remeshing_crorder_->currentIndex()), + widget_->checkbox_data_output_->isChecked()); postoperation(UPDATE_TOPOLOGY, UPDATE_TOPOLOGY); } diff --git a/MetaMeshToolbox.cc b/MetaMeshToolbox.cc index 0331249a350f9f0aa01263eb729c559fa11c6bdc..049459eb33a65417bb5960d9b74ca4953fd1e70a 100644 --- a/MetaMeshToolbox.cc +++ b/MetaMeshToolbox.cc @@ -7,18 +7,6 @@ MetaMeshToolbox::MetaMeshToolbox(QWidget* parent) : QWidget(parent) { QGridLayout* layout = new QGridLayout(this); - vbox_ = new QVBoxLayout; - checkbox_implicit_dijkstra_ = new QRadioButton("Implicit Dijkstra from Voronoi"); - checkbox_a_star_triangulation_ = new QRadioButton("Bidirectional A* triangulation"); - checkbox_a_star_midpoint_triangulation_ = new QRadioButton("A* with midpoints from Voronoi"); - mode_selection_ = new QGroupBox("Initial triangulation type"); - checkbox_a_star_triangulation_->setChecked(true); - vbox_->addWidget(checkbox_implicit_dijkstra_); - vbox_->addWidget(checkbox_a_star_triangulation_); - vbox_->addWidget(checkbox_a_star_midpoint_triangulation_); - vbox_->addStretch(1); - mode_selection_->setLayout(vbox_); - combo_box_tests_ = new QComboBox; combo_box_tests_->addItem("Display Mesh Info"); combo_box_tests_->addItem("Mesh Properties"); @@ -27,11 +15,25 @@ MetaMeshToolbox::MetaMeshToolbox(QWidget* parent) : QWidget(parent) combo_box_tests_->addItem("Splits"); combo_box_tests_->addItem("Collapses"); combo_box_tests_->addItem("Relocations"); + combo_box_tests_->setCurrentIndex(1); + + combo_box_remeshing_smtype_ = new QComboBox; + combo_box_remeshing_smtype_->addItem("Forest Fire"); + combo_box_remeshing_smtype_->addItem("Vertex Weights"); + combo_box_remeshing_smtype_->addItem("Vertex Distances"); + combo_box_remeshing_smtype_->setCurrentIndex(2); + + combo_box_remeshing_strype_ = new QComboBox; + combo_box_remeshing_strype_->addItem("None"); + combo_box_remeshing_strype_->addItem("Edgewise"); + combo_box_remeshing_strype_->addItem("Patchwise"); + combo_box_remeshing_strype_->setCurrentIndex(0); - combo_box_remeshing_ = new QComboBox; - combo_box_remeshing_->addItem("Forest Fire"); - combo_box_remeshing_->addItem("Vertex Weights"); - combo_box_remeshing_->addItem("Vertex Distances"); + combo_box_remeshing_crorder_ = new QComboBox; + combo_box_remeshing_crorder_->addItem("Random"); + combo_box_remeshing_crorder_->addItem("Valence"); + combo_box_remeshing_crorder_->addItem("Splitweight"); + combo_box_remeshing_crorder_->setCurrentIndex(2); button_triangulate_ = new QPushButton("Triangulate"); button_randomize_ratio_ = new QPushButton("Randomize a ratio of points"); @@ -43,14 +45,18 @@ MetaMeshToolbox::MetaMeshToolbox(QWidget* parent) : QWidget(parent) button_split_ = new QPushButton("Split"); button_collapse_ = new QPushButton("Collapse"); button_relocate_ = new QPushButton("Relocate"); - button_dummy1_ = new QPushButton("Insert"); - button_dummy2_ = new QPushButton("Delete"); + button_dummy1_ = new QPushButton("Dummy 1"); + button_dummy2_ = new QPushButton("Dummy 2"); button_next_ = new QPushButton("nxt"); button_opp_ = new QPushButton("opp"); button_prev_ = new QPushButton("prv"); button_remesh_ = new QPushButton("Remesh"); + checkbox_limit_flips_ = new QCheckBox("Limit Flips"); + checkbox_data_output_ = new QCheckBox("Output Data"); checkbox_copy_markings_->setCheckState(Qt::Checked); + checkbox_limit_flips_->setCheckState(Qt::Unchecked); + checkbox_data_output_->setCheckState(Qt::Checked); input_ratio_ = new QDoubleSpinBox(); input_ratio_->setRange(0,1); @@ -60,45 +66,74 @@ MetaMeshToolbox::MetaMeshToolbox(QWidget* parent) : QWidget(parent) input_ratio_->setToolTip("Ratio of Base Mesh Vertices to be " "randomly assigned as Meta Mesh vertices"); + input_alpha_ = new QDoubleSpinBox(); + input_alpha_->setRange(1,10); + input_alpha_->setDecimals(3); + input_alpha_->setSingleStep(0.001); + input_alpha_->setValue(4.0/3.0); + input_alpha_->setToolTip("Alpha parameter; splitting slack var"); + + input_beta_ = new QDoubleSpinBox(); + input_beta_->setRange(0.1,1); + input_beta_->setDecimals(3); + input_beta_->setSingleStep(0.001); + input_beta_->setValue(4.0/5.0); + input_beta_->setToolTip("Beta parameter; collapsing slack var"); + input_length_ = new QDoubleSpinBox(); - input_length_->setRange(0,1); + input_length_->setRange(0,2); input_length_->setDecimals(3); input_length_->setSingleStep(0.001); input_length_->setValue(0.2); input_length_->setToolTip("Edge length in % of object diagonal"); input_iterations_ = new QSpinBox(); - input_iterations_->setRange(1,100); + input_iterations_->setRange(1,1000); input_iterations_->setValue(10); input_iterations_->setSingleStep(1); input_iterations_->setToolTip("Number of times the algorithm runs"); + QLabel* label_alpha = new QLabel("Alpha:"); + QLabel* label_beta = new QLabel("Beta:"); QLabel* label_length = new QLabel("Length:"); QLabel* label_iterations = new QLabel("Iterations:"); + QLabel* label_smtype = new QLabel("Smoothing:"); + QLabel* label_strtype = new QLabel("Straightening:"); + QLabel* label_corder = new QLabel("Collapse Order:"); layout->addWidget(button_triangulate_, 0, 0, 1, 6); layout->addWidget(button_randomize_ratio_, 1, 0, 1, 6); layout->addWidget(button_randomize_total_, 2, 0, 1, 6); - layout->addWidget(mode_selection_, 3, 0, 1, 6); - layout->addWidget(input_ratio_, 4, 0, 1, 6); - layout->addWidget(button_run_test_, 5, 0, 1, 3); - layout->addWidget(combo_box_tests_, 5, 3, 1, 3); - layout->addWidget(checkbox_copy_markings_, 6, 0, 1, 3); - layout->addWidget(button_retrace_, 6, 3, 1, 3); - layout->addWidget(button_rotate_, 7, 0, 1, 3); - layout->addWidget(button_split_, 7, 3, 1, 3); - layout->addWidget(button_collapse_, 8, 0, 1, 3); - layout->addWidget(button_relocate_, 8, 3, 1, 3); - layout->addWidget(button_dummy1_, 9, 0, 1, 3); - layout->addWidget(button_dummy2_, 9, 3, 1, 3); - layout->addWidget(button_next_, 10, 0, 1, 2); - layout->addWidget(button_opp_, 10, 2, 1, 2); - layout->addWidget(button_prev_, 10, 4, 1, 2); + layout->addWidget(input_ratio_, 3, 0, 1, 6); + layout->addWidget(button_run_test_, 4, 0, 1, 3); + layout->addWidget(combo_box_tests_, 4, 3, 1, 3); + layout->addWidget(checkbox_copy_markings_, 5, 0, 1, 3); + layout->addWidget(button_retrace_, 5, 3, 1, 3); + layout->addWidget(button_rotate_, 6, 0, 1, 3); + layout->addWidget(button_split_, 6, 3, 1, 3); + layout->addWidget(button_collapse_, 7, 0, 1, 3); + layout->addWidget(button_relocate_, 7, 3, 1, 3); + layout->addWidget(button_dummy1_, 8, 0, 1, 3); + layout->addWidget(button_dummy2_, 8, 3, 1, 3); + layout->addWidget(button_next_, 9, 0, 1, 2); + layout->addWidget(button_opp_, 9, 2, 1, 2); + layout->addWidget(button_prev_, 9, 4, 1, 2); layout->addWidget(button_remesh_, 11, 0, 1, 3); - layout->addWidget(combo_box_remeshing_, 11, 3, 1, 3); - layout->addWidget(label_length, 12, 0, 1, 3); - layout->addWidget(input_length_, 13, 0, 1, 3); - layout->addWidget(label_iterations, 12, 3, 1, 3); - layout->addWidget(input_iterations_, 13, 3, 1, 3); + layout->addWidget(label_smtype, 10, 3, 1, 3); + layout->addWidget(combo_box_remeshing_smtype_, 11, 3, 1, 3); + layout->addWidget(label_strtype, 12, 0, 1, 3); + layout->addWidget(combo_box_remeshing_strype_, 13, 0, 1, 3); + layout->addWidget(label_corder, 12, 3, 1, 3); + layout->addWidget(combo_box_remeshing_crorder_, 13, 3, 1, 3); + layout->addWidget(checkbox_limit_flips_, 15, 0, 1, 2); + layout->addWidget(label_alpha, 14, 2, 1, 2); + layout->addWidget(input_alpha_, 15, 2, 1, 2); + layout->addWidget(label_beta, 14, 4, 1, 2); + layout->addWidget(input_beta_, 15, 4, 1, 2); + layout->addWidget(checkbox_data_output_, 17, 0, 1, 2); + layout->addWidget(label_length, 16, 2, 1, 2); + layout->addWidget(input_length_, 17, 2, 1, 2); + layout->addWidget(label_iterations, 16, 4, 1, 2); + layout->addWidget(input_iterations_, 17, 4, 1, 2); this->setLayout(layout); } diff --git a/MetaMeshToolbox.hh b/MetaMeshToolbox.hh index ebe4ff06a974e5dc93a0e535918bdf871ea4f554..9cb8cce6436d44bb2fb20a483a2dc112e9c020a2 100644 --- a/MetaMeshToolbox.hh +++ b/MetaMeshToolbox.hh @@ -16,13 +16,7 @@ class MetaMeshToolbox : public QWidget public: MetaMeshToolbox(QWidget* parent = nullptr); - QGroupBox* mode_selection_; - QVBoxLayout* vbox_; - QRadioButton* checkbox_implicit_dijkstra_; - QRadioButton* checkbox_a_star_triangulation_; - QRadioButton* checkbox_a_star_midpoint_triangulation_; QComboBox* combo_box_tests_; - QComboBox* combo_box_remeshing_; QPushButton* button_triangulate_; QPushButton* button_randomize_ratio_; @@ -34,14 +28,23 @@ public: QPushButton* button_split_; QPushButton* button_collapse_; QPushButton* button_relocate_; - QPushButton* button_remesh_; QPushButton* button_dummy1_; QPushButton* button_dummy2_; QPushButton* button_next_; QPushButton* button_opp_; QPushButton* button_prev_; - QDoubleSpinBox* input_length_; QDoubleSpinBox* input_ratio_; + + // Remeshing + QPushButton* button_remesh_; + QComboBox* combo_box_remeshing_smtype_; + QComboBox* combo_box_remeshing_strype_; + QComboBox* combo_box_remeshing_crorder_; + QCheckBox* checkbox_limit_flips_; + QDoubleSpinBox* input_alpha_; + QDoubleSpinBox* input_beta_; + QCheckBox* checkbox_data_output_; + QDoubleSpinBox* input_length_; QSpinBox* input_iterations_; }; diff --git a/Testing.cc b/Testing.cc index b43bdb32b318fa034ac9d7fd5f082239f9f84979..f524060bc8640be544f6c4fedbd2f3e5a1ed65cc 100644 --- a/Testing.cc +++ b/Testing.cc @@ -2,6 +2,7 @@ #include <QDebug> #include <math.h> #include <random> +#include <math.h> #define BASE_MESH_ embedding_->base_mesh_ #define META_MESH_ embedding_->meta_mesh_ @@ -123,6 +124,7 @@ void Testing::DisplayMeshInformation() { *(avgmetaedgelength-embedding_->CalculateEdgeLength(meh)); } metaedgelengthdeviation /= META_MESH_->n_edges(); + metaedgelengthdeviation = std::sqrt(metaedgelengthdeviation); double avgvalence = 0.0; double valencedeviation = 0.0; for (auto mvh : META_MESH_->vertices()) { @@ -131,6 +133,7 @@ void Testing::DisplayMeshInformation() { } avgvalence /= META_MESH_->n_vertices(); valencedeviation /= META_MESH_->n_vertices(); + valencedeviation = std::sqrt(valencedeviation); qDebug() << "Base Mesh- V: " << BASE_MESH_->n_vertices() << "E: " << BASE_MESH_->n_edges() << "F: " << BASE_MESH_->n_faces() diff --git a/renamer.py b/renamer.py index 12b309ae0bbc9aa26fb582dbfbf1d53f206eb794..1a2f7bc9c09ee1c4245e20b173c850c5834ccdff 100644 --- a/renamer.py +++ b/renamer.py @@ -6,7 +6,7 @@ from glob import glob import os -files_list = glob("*") +files_list = glob("*.png") for file in files_list: numbers = [file] for s in file: