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, &param_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: