Added a new tool for clamping vertices

Sat, 17 Mar 2018 12:29:52 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 17 Mar 2018 12:29:52 +0200
changeset 1294
adaad0b329e2
parent 1293
52732b1db3f0
child 1295
ac8f0297885b

Added a new tool for clamping vertices

CMakeLists.txt file | annotate | diff | comparison | revisions
src/mainwindow.ui file | annotate | diff | comparison | revisions
src/toolsets/algorithmtoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/algorithmtoolset.h file | annotate | diff | comparison | revisions
src/toolsets/fixroundingerrors.ui file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sat Mar 17 11:35:07 2018 +0200
+++ b/CMakeLists.txt	Sat Mar 17 12:29:52 2018 +0200
@@ -182,6 +182,7 @@
 	src/dialogs/replacecoordinatesdialog.ui
 	src/dialogs/rotationpointdialog.ui
 	src/dialogs/ytruderdialog.ui
+	src/toolsets/fixroundingerrors.ui
 	src/mainwindow.ui
 	src/partdownloader.ui
 	src/widgets/headeredit.ui
--- a/src/mainwindow.ui	Sat Mar 17 11:35:07 2018 +0200
+++ b/src/mainwindow.ui	Sat Mar 17 12:29:52 2018 +0200
@@ -327,6 +327,7 @@
     <addaction name="actionMakeBorders"/>
     <addaction name="actionRoundCoordinates"/>
     <addaction name="actionReplaceCoordinates"/>
+    <addaction name="actionFixRoundingErrors"/>
     <addaction name="actionFlip"/>
     <addaction name="actionDemote"/>
     <addaction name="actionOpenSubfiles"/>
@@ -1734,6 +1735,11 @@
     <string>Polar grid</string>
    </property>
   </action>
+  <action name="actionFixRoundingErrors">
+   <property name="text">
+    <string>Fix rounding errors</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
--- a/src/toolsets/algorithmtoolset.cpp	Sat Mar 17 11:35:07 2018 +0200
+++ b/src/toolsets/algorithmtoolset.cpp	Sat Mar 17 12:29:52 2018 +0200
@@ -20,6 +20,7 @@
 #include <QDir>
 #include <QInputDialog>
 #include <QMessageBox>
+#include <QPushButton>
 #include "../mainwindow.h"
 #include "../main.h"
 #include "../lddocument.h"
@@ -39,6 +40,7 @@
 #include "ui_replacecoordinatesdialog.h"
 #include "ui_editrawdialog.h"
 #include "ui_flipdialog.h"
+#include "ui_fixroundingerrors.h"
 #include "algorithmtoolset.h"
 
 AlgorithmToolset::AlgorithmToolset (MainWindow* parent) :
@@ -196,6 +198,93 @@
 	print (tr ("Rounded %1 values"), num);
 }
 
+void AlgorithmToolset::fixRoundingErrors()
+{
+	QDialog dialog {m_window};
+	Ui::FixRoundingErrors ui;
+	ui.setupUi(&dialog);
+	auto updateDialogButtonBox = [&]()
+	{
+		QPushButton* button = ui.buttonBox->button(QDialogButtonBox::Ok);
+
+		if (button)
+		{
+			button->setEnabled(
+				ui.checkboxX->isChecked()
+				or ui.checkboxY->isChecked()
+				or ui.checkboxZ->isChecked()
+			);
+		}
+	};
+	updateDialogButtonBox();
+	connect(ui.checkboxX, &QCheckBox::clicked, updateDialogButtonBox);
+	connect(ui.checkboxY, &QCheckBox::clicked, updateDialogButtonBox);
+	connect(ui.checkboxZ, &QCheckBox::clicked, updateDialogButtonBox);
+	const int result = dialog.exec();
+
+	if (result == QDialog::Accepted)
+	{
+		const Vertex referencePoint = {
+			ui.valueX->value(),
+			ui.valueY->value(),
+			ui.valueZ->value()
+		};
+
+		// Find out which axes to consider
+		QSet<Axis> axes;
+		if (ui.checkboxX->isChecked())
+			axes << X;
+		if (ui.checkboxY->isChecked())
+			axes << Y;
+		if (ui.checkboxZ->isChecked())
+			axes << Z;
+
+		// Make a reference distance from the threshold value.
+		// If we're only comparing one dimension, this is the square of the threshold.
+		// If we're comparing multiple dimensions, the distance is multiplied to adjust.
+		double thresholdDistanceSquared = countof(axes) * std::pow(ui.threshold->value(), 2);
+		// Add some tiny leeway to fix rounding errors in the rounding error fixer.
+		thresholdDistanceSquared += 1e-10;
+
+		auto fixVertex = [&](Vertex& vertex)
+		{
+			double distanceSquared = 0.0;
+
+			for (Axis axis : axes)
+				distanceSquared += std::pow(vertex[axis] - referencePoint[axis], 2);
+
+			if (distanceSquared < thresholdDistanceSquared)
+			{
+				// It's close enough, so clamp it
+				for (Axis axis : axes)
+					vertex.setCoordinate(axis, referencePoint[axis]);
+			}
+		};
+
+		for (const QModelIndex& index : m_window->selectedIndexes())
+		{
+			LDObject* object = currentDocument()->lookup(index);
+
+			if (object)
+			{
+				for (int i : range(0, 1, object->numVertices() - 1))
+				{
+					Vertex point = object->vertex(i);
+					fixVertex(point);
+					object->setVertex(i, point);
+				}
+				if (object->type() == LDObjectType::SubfileReference)
+				{
+					LDSubfileReference* reference = static_cast<LDSubfileReference*>(object);
+					Vertex point = reference->position();
+					fixVertex(point);
+					reference->setPosition(point);
+				}
+			}
+		}
+	}
+}
+
 void AlgorithmToolset::replaceCoordinates()
 {
 	QDialog dialog {m_window};
--- a/src/toolsets/algorithmtoolset.h	Sat Mar 17 11:35:07 2018 +0200
+++ b/src/toolsets/algorithmtoolset.h	Sat Mar 17 12:29:52 2018 +0200
@@ -28,6 +28,7 @@
 	Q_INVOKABLE void autocolor();
 	Q_INVOKABLE void demote();
 	Q_INVOKABLE void editRaw();
+	Q_INVOKABLE void fixRoundingErrors();
 	Q_INVOKABLE void flip();
 	Q_INVOKABLE void makeBorders();
 	Q_INVOKABLE void replaceCoordinates();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/toolsets/fixroundingerrors.ui	Sat Mar 17 12:29:52 2018 +0200
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FixRoundingErrors</class>
+ <widget class="QDialog" name="FixRoundingErrors">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>235</width>
+    <height>243</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Fix rounding errors</string>
+  </property>
+  <layout class="QFormLayout" name="formLayout">
+   <item row="0" column="0" colspan="2">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Co-ordinates</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QCheckBox" name="checkboxX">
+        <property name="text">
+         <string>X</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QLabel" name="label">
+        <property name="text">
+         <string>=</string>
+        </property>
+        <property name="buddy">
+         <cstring>valueX</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QDoubleSpinBox" name="valueX">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="decimals">
+         <number>5</number>
+        </property>
+        <property name="maximum">
+         <double>10000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QCheckBox" name="checkboxY">
+        <property name="text">
+         <string>Y</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>=</string>
+        </property>
+        <property name="buddy">
+         <cstring>valueY</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QDoubleSpinBox" name="valueY">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="decimals">
+         <number>5</number>
+        </property>
+        <property name="maximum">
+         <double>10000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0">
+       <widget class="QCheckBox" name="checkboxZ">
+        <property name="text">
+         <string>Z</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="1">
+       <widget class="QLabel" name="label_4">
+        <property name="text">
+         <string>=</string>
+        </property>
+        <property name="buddy">
+         <cstring>valueZ</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="2">
+       <widget class="QDoubleSpinBox" name="valueZ">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="decimals">
+         <number>5</number>
+        </property>
+        <property name="maximum">
+         <double>10000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Threshold:</string>
+     </property>
+     <property name="buddy">
+      <cstring>threshold</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QDoubleSpinBox" name="threshold">
+     <property name="decimals">
+      <number>5</number>
+     </property>
+     <property name="minimum">
+      <double>0.000010000000000</double>
+     </property>
+     <property name="maximum">
+      <double>10000.000000000000000</double>
+     </property>
+     <property name="singleStep">
+      <double>0.000100000000000</double>
+     </property>
+     <property name="value">
+      <double>0.001000000000000</double>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+  <zorder>buttonBox</zorder>
+  <zorder>label_2</zorder>
+  <zorder>groupBox</zorder>
+  <zorder>threshold</zorder>
+ </widget>
+ <tabstops>
+  <tabstop>checkboxX</tabstop>
+  <tabstop>valueX</tabstop>
+  <tabstop>checkboxY</tabstop>
+  <tabstop>valueY</tabstop>
+  <tabstop>checkboxZ</tabstop>
+  <tabstop>valueZ</tabstop>
+  <tabstop>threshold</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>FixRoundingErrors</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>225</x>
+     <y>215</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>242</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>FixRoundingErrors</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>225</x>
+     <y>221</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>234</x>
+     <y>242</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkboxX</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>valueX</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>49</x>
+     <y>53</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>93</x>
+     <y>47</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkboxY</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>valueY</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>60</x>
+     <y>94</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>132</x>
+     <y>91</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>checkboxZ</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>valueZ</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>61</x>
+     <y>129</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>107</x>
+     <y>133</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

mercurial