reorganized headers

Sat, 24 Mar 2018 11:57:24 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sat, 24 Mar 2018 11:57:24 +0200
changeset 1319
39d7a9642eea
parent 1318
568fcfc6da71
child 1320
bdb4804bc09c

reorganized headers

CMakeLists.txt file | annotate | diff | comparison | revisions
src/algorithms/geometry.cpp file | annotate | diff | comparison | revisions
src/algorithms/geometry.h file | annotate | diff | comparison | revisions
src/basics.cpp file | annotate | diff | comparison | revisions
src/basics.h file | annotate | diff | comparison | revisions
src/canvas.cpp file | annotate | diff | comparison | revisions
src/dialogs/colorselector.cpp file | annotate | diff | comparison | revisions
src/dialogs/configdialog.cpp file | annotate | diff | comparison | revisions
src/editmodes/abstractEditMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/circleMode.cpp file | annotate | diff | comparison | revisions
src/generics/enums.h file | annotate | diff | comparison | revisions
src/generics/functions.h file | annotate | diff | comparison | revisions
src/generics/ring.h file | annotate | diff | comparison | revisions
src/generics/transform.h file | annotate | diff | comparison | revisions
src/glcamera.cpp file | annotate | diff | comparison | revisions
src/glcompiler.cpp file | annotate | diff | comparison | revisions
src/glrenderer.cpp file | annotate | diff | comparison | revisions
src/guiutilities.cpp file | annotate | diff | comparison | revisions
src/linetypes/modelobject.cpp file | annotate | diff | comparison | revisions
src/macros.h file | annotate | diff | comparison | revisions
src/main.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/mathfunctions.cpp file | annotate | diff | comparison | revisions
src/miscallenous.cpp file | annotate | diff | comparison | revisions
src/miscallenous.h file | annotate | diff | comparison | revisions
src/primitives.cpp file | annotate | diff | comparison | revisions
src/ringFinder.cpp file | annotate | diff | comparison | revisions
src/toolsets/algorithmtoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/extprogramtoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/movetoolset.cpp file | annotate | diff | comparison | revisions
src/toolsets/viewtoolset.cpp file | annotate | diff | comparison | revisions
src/transform.h file | annotate | diff | comparison | revisions
src/types/library.h file | annotate | diff | comparison | revisions
src/types/vertex.cpp file | annotate | diff | comparison | revisions
src/types/vertex.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sat Mar 24 11:05:40 2018 +0200
+++ b/CMakeLists.txt	Sat Mar 24 11:57:24 2018 +0200
@@ -52,7 +52,6 @@
 	src/mathfunctions.cpp
 	src/matrixinput.cpp
 	src/messageLog.cpp
-	src/miscallenous.cpp
 	src/model.cpp
 	src/partdownloader.cpp
 	src/partdownloadrequest.cpp
@@ -61,6 +60,7 @@
 	src/serializer.cpp
 	src/ringFinder.cpp
 	src/version.cpp
+	src/algorithms/geometry.cpp
 	src/algorithms/invert.cpp
 	src/dialogs/colorselector.cpp
 	src/dialogs/configdialog.cpp
@@ -118,13 +118,11 @@
 	src/lddocument.h
 	src/ldobjectiterator.h
 	src/librariesmodel.h
-	src/macros.h
 	src/main.h
 	src/mainwindow.h
 	src/mathfunctions.h
 	src/matrixinput.h
 	src/messageLog.h
-	src/miscallenous.h
 	src/model.h
 	src/partdownloader.h
 	src/partdownloadrequest.h
@@ -132,8 +130,8 @@
 	src/primitives.h
 	src/ringFinder.h
 	src/serializer.h
-	src/transform.h
 	src/version.h
+	src/algorithms/geometry.h
 	src/algorithms/invert.h
 	src/dialogs/colorselector.h
 	src/dialogs/configdialog.h
@@ -150,9 +148,12 @@
 	src/editmodes/magicWandMode.h
 	src/editmodes/rectangleMode.h
 	src/editmodes/selectMode.h
+	src/generics/functions.h
 	src/generics/migrate.h
 	src/generics/range.h
 	src/generics/reverse.h
+	src/generics/ring.h
+	src/generics/transform.h
 	src/geometry/linesegment.h
 	src/linetypes/comment.h
 	src/linetypes/conditionaledge.h
@@ -169,6 +170,7 @@
 	src/toolsets/toolset.h
 	src/toolsets/viewtoolset.h
 	src/types/boundingbox.h
+	src/types/library.h
 	src/types/matrix.h
 	src/types/vertex.h
 	src/widgets/headeredit.h
@@ -225,7 +227,6 @@
 
 include_directories ("${PROJECT_BINARY_DIR}")
 include_directories ("${PROJECT_BINARY_DIR}/src")
-include_directories ("${PROJECT_BINARY_DIR}/src/misc")
 include_directories ("${PROJECT_SOURCE_DIR}/src")
 
 if (NOT MSVC)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/algorithms/geometry.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,119 @@
+#include "geometry.h"
+
+/*
+ * getRadialPoint
+ *
+ * Gets an ordinate of a point in circle.
+ * If func == sin, then this gets the Y co-ordinate, if func == cos, then X co-ordinate.
+ */
+QPointF pointOnCircumference(int segment, int divisions)
+{
+	double angle = (segment * 2 * pi) / divisions;
+	return {cos(angle), sin(angle)};
+}
+
+/*
+ * makeCircle
+ *
+ * Creates a possibly partial circle rim.
+ * Divisions is how many segments the circle makes if up if it's full.
+ * Segments is now many segments are added.
+ * Radius is the radius of the circle.
+ *
+ * If divisions == segments, this yields a full circle rim.
+ * The rendered circle is returned as a vector of lines.
+ */
+QVector<QLineF> makeCircle(int segments, int divisions, double radius)
+{
+	QVector<QLineF> lines;
+
+	for (int i = 0; i < segments; i += 1)
+	{
+		QPointF p0 = radius * ::pointOnCircumference(i, divisions);
+		QPointF p1 = radius * ::pointOnCircumference(i + 1, divisions);
+		lines.append({p0, p1});
+	}
+
+	return lines;
+}
+
+/*
+ * Computes the shortest distance from a point to a rectangle.
+ *
+ * The code originates from the Unity3D wiki, and was translated from C# to Qt by me (Teemu Piippo):
+ *
+ * Original code:
+ *     http://wiki.unity3d.com/index.php/Distance_from_a_point_to_a_rectangle
+ *
+ * Copyright 2013 Philip Peterson.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle)
+{
+	//  Calculate a distance between a point and a rectangle.
+	//  The area around/in the rectangle is defined in terms of
+	//  several regions:
+	//
+	//  O--x
+	//  |
+	//  y
+	//
+	//
+	//        I   |    II    |  III
+	//      ======+==========+======   --yMin
+	//       VIII |  IX (in) |  IV
+	//      ======+==========+======   --yMax
+	//       VII  |    VI    |   V
+	//
+	//
+	//  Note that the +y direction is down because of Unity's GUI coordinates.
+	//  - I don't care which way is +y in this function because I want a distance --TP
+
+	if (point.x() < rectangle.left())
+	{
+		// Region I, VIII, or VII
+		if (point.y() < rectangle.top()) // I
+			return QLineF {point, rectangle.topLeft()}.length();
+		else if (point.y() > rectangle.bottom()) // VII
+			return QLineF {point, rectangle.bottomLeft()}.length();
+		else // VIII
+			return rectangle.left() - point.x();
+	}
+	else if (point.x() > rectangle.right())
+	{
+		// Region III, IV, or V
+		if (point.y() < rectangle.top()) // III
+			return QLineF {point, rectangle.topRight()}.length();
+		else if (point.y() > rectangle.bottom()) // V
+			return QLineF {point, rectangle.bottomRight()}.length();
+		else // IV
+			return point.x() - rectangle.right();
+	}
+	else
+	{
+		// Region II, IX, or VI
+		if (point.y() < rectangle.top()) // II
+			return rectangle.top() - point.y();
+		else if (point.y() > rectangle.bottom()) // VI
+			return point.y() - rectangle.bottom();
+		else // IX
+			return 0;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/algorithms/geometry.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,6 @@
+#pragma once
+#include "../main.h"
+
+QPointF pointOnCircumference(int segment, int divisions);
+QVector<QLineF> makeCircle(int segments, int divisions, double radius);
+qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle);
--- a/src/basics.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/basics.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -19,167 +19,70 @@
 #include <QLineF>
 #include "basics.h"
 #include "types/vertex.h"
-
-// http://stackoverflow.com/a/18204188/3629665
-template<typename T>
-inline int rotl10(T x)
-{
-	return (((x) << 10) | (((x) >> 22) & 0x000000ff));
-}
+#include "format.h"
 
-template<typename T>
-inline int rotl20(T x)
+int gcd(int a, int b)
 {
-	return (((x) << 20) | (((x) >> 12) & 0x000000ff));
-}
+	while (b != 0)
+	{
+		int temp = a;
+		a = b;
+		b = temp % b;
+	}
 
-uint qHash(const Vertex& key)
-{
-	return qHash(key.x) ^ rotl10(qHash(key.y)) ^ rotl20(qHash(key.z));
+	return a;
 }
 
-/*
- * getRadialPoint
- *
- * Gets an ordinate of a point in circle.
- * If func == sin, then this gets the Y co-ordinate, if func == cos, then X co-ordinate.
- */
-double getRadialPoint(int segment, int divisions, double(*func)(double))
+
+void simplify(int& numerator, int& denominator)
 {
-	return (*func)((segment * 2 * pi) / divisions);
-}
-
-/*
- * makeCircle
- *
- * Creates a possibly partial circle rim.
- * Divisions is how many segments the circle makes if up if it's full.
- * Segments is now many segments are added.
- * Radius is the radius of the circle.
- *
- * If divisions == segments, this yields a full circle rim.
- * The rendered circle is returned as a vector of lines.
- */
-QVector<QLineF> makeCircle(int segments, int divisions, double radius)
-{
-	QVector<QLineF> lines;
-
-	for (int i = 0; i < segments; ++i)
-	{
-		double x0 = radius * getRadialPoint(i, divisions, cos);
-		double x1 = radius * getRadialPoint(i + 1, divisions, cos);
-		double z0 = radius * getRadialPoint(i, divisions, sin);
-		double z1 = radius * getRadialPoint(i + 1, divisions, sin);
-		lines.append(QLineF {QPointF {x0, z0}, QPointF {x1, z1}});
-	}
-
-	return lines;
+	int factor = gcd(numerator, denominator);
+	numerator /= factor;
+	denominator /= factor;
 }
 
-/*
- * Computes the shortest distance from a point to a rectangle.
- *
- * The code originates from the Unity3D wiki, and was translated from C# to Qt by me (Teemu Piippo):
- *
- * Original code:
- *     http://wiki.unity3d.com/index.php/Distance_from_a_point_to_a_rectangle
- *
- * Copyright 2013 Philip Peterson.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle)
+
+QString joinStrings(const QList<StringFormatArg>& values, QString delimeter)
 {
-	//  Calculate a distance between a point and a rectangle.
-	//  The area around/in the rectangle is defined in terms of
-	//  several regions:
-	//
-	//  O--x
-	//  |
-	//  y
-	//
-	//
-	//        I   |    II    |  III
-	//      ======+==========+======   --yMin
-	//       VIII |  IX (in) |  IV
-	//      ======+==========+======   --yMax
-	//       VII  |    VI    |   V
-	//
-	//
-	//  Note that the +y direction is down because of Unity's GUI coordinates.
+	QStringList list;
+
+	for (const StringFormatArg& arg : values)
+		list << arg.text();
 
-	if (point.x() < rectangle.left())
+	return list.join(delimeter);
+}
+
+
+void roundToDecimals(double& value, int decimals)
+{
+	if (decimals == 0)
 	{
-		// Region I, VIII, or VII
-		if (point.y() < rectangle.top()) // I
-			return QLineF {point, rectangle.topLeft()}.length();
-		else if (point.y() > rectangle.bottom()) // VII
-			return QLineF {point, rectangle.bottomLeft()}.length();
-		else // VIII
-			return rectangle.left() - point.x();
+		value = round(value);
 	}
-	else if (point.x() > rectangle.right())
+	else if (decimals > 0)
 	{
-		// Region III, IV, or V
-		if (point.y() < rectangle.top()) // III
-			return QLineF {point, rectangle.topRight()}.length();
-		else if (point.y() > rectangle.bottom()) // V
-			return QLineF {point, rectangle.bottomRight()}.length();
-		else // IV
-			return point.x() - rectangle.right();
-	}
-	else
-	{
-		// Region II, IX, or VI
-		if (point.y() < rectangle.top()) // II
-			return rectangle.top() - point.y();
-		else if (point.y() > rectangle.bottom()) // VI
-			return point.y() - rectangle.bottom();
-		else // IX
-			return 0;
+		qreal coefficient = pow(10, decimals);
+		value = round(value * coefficient) / coefficient;
 	}
 }
 
-/*
- * Special operator definition that implements the XOR operator for windings.
- * However, if either winding is NoWinding, then this function returns NoWinding.
- */
-Winding operator^(Winding one, Winding other)
+
+void applyToMatrix(Matrix& a, ApplyToMatrixFunction func)
 {
-	if (one == NoWinding or other == NoWinding)
-		return NoWinding;
-	else
-		return static_cast<Winding>(static_cast<int>(one) ^ static_cast<int>(other));
+	for (int i = 0; i < 9; ++i)
+		func(i, a.value(i));
 }
 
-Winding& operator^=(Winding& one, Winding other)
+void applyToMatrix(const Matrix& a, ApplyToMatrixConstFunction func)
 {
-	one = one ^ other;
-	return one;
+	for (int i = 0; i < 9; ++i)
+		func(i, a.value(i));
 }
 
-QDataStream& operator<<(QDataStream& out, const Library& library)
+QString formatFileSize(qint64 size)
 {
-	return out << library.path << library.role;
+	static const QString suffixes[] = {" bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
+	int magnitude = (size > 0) ? floor(log10(size) / 3.0 + 1e-10) : 0;
+	magnitude = qBound(0, magnitude, countof(suffixes) - 1);
+	return QString::number(size / pow(1000, magnitude)) + suffixes[magnitude];
 }
-
-QDataStream& operator>>(QDataStream &in, Library& library)
-{
-	return in >> library.path >> enum_cast<>(library.role);
-}
--- a/src/basics.h	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/basics.h	Sat Mar 24 11:57:24 2018 +0200
@@ -17,68 +17,37 @@
  */
 
 #pragma once
-#include <QString>
-#include <QObject>
-#include <QStringList>
-#include <QMetaType>
-#include <QSet>
-#include <QVector3D>
-#include <QVector>
 #include <QFile>
 #include <QMatrix4x4>
-#include <functional>
-#include <type_traits>
-#include <math.h>
-#include "macros.h"
-#include "transform.h"
+#include <QMetaType>
+#include <QObject>
+#include <QSet>
+#include <QString>
+#include <QStringList>
+#include <QVector>
+#include <QVector3D>
+#include "generics/functions.h"
 
-#if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0))
-template <typename... Args>
-struct QNonConstOverload
-{
-    template <typename R, typename T>
-    Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-    template <typename R, typename T>
-    static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-};
-template <typename... Args>
-struct QConstOverload
-{
-    template <typename R, typename T>
-    Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-    template <typename R, typename T>
-    static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-};
-template <typename... Args>
-struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
-{
-    using QConstOverload<Args...>::of;
-    using QConstOverload<Args...>::operator();
-    using QNonConstOverload<Args...>::of;
-    using QNonConstOverload<Args...>::operator();
-    template <typename R>
-    Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-    template <typename R>
-    static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
-    { return ptr; }
-};
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {};
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {};
-template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> qNonConstOverload = {};
+#ifndef __GNUC__
+# define __attribute__(X)
 #endif
 
-class Matrix;
-struct Vertex;
+#define DEFINE_CLASS(SELF, SUPER) \
+public: \
+	using Self = SELF; \
+	using Super = SUPER;
+
+// TODO: get rid of this
+#ifdef WIN32
+# define DIRSLASH "\\"
+# define DIRSLASH_CHAR '\\'
+#else // WIN32
+# define DIRSLASH "/"
+# define DIRSLASH_CHAR '/'
+#endif // WIN32
+
 using GLRotationMatrix = QMatrix4x4;
 
-template<typename T, typename R>
-using Pair = std::pair<T, R>;
-
 enum Axis
 {
 	X,
@@ -93,346 +62,41 @@
 	Clockwise,
 };
 
-Winding operator^(Winding one, Winding other);
-Winding& operator^=(Winding& one, Winding other);
+/*
+ * Special operator definition that implements the XOR operator for windings.
+ * However, if either winding is NoWinding, then this function returns NoWinding.
+ */
+inline Winding operator^(Winding one, Winding other)
+{
+	if (one == NoWinding or other == NoWinding)
+		return NoWinding;
+	else
+		return static_cast<Winding>(static_cast<int>(one) ^ static_cast<int>(other));
+}
 
+inline Winding& operator^=(Winding& one, Winding other)
+{
+	one = one ^ other;
+	return one;
+}
+
+static const double pi = 3.14159265358979323846;
+
+/*
+ * Returns the norm of a vector.
+ */
 static inline qreal abs(const QVector3D &vector)
 {
 	return vector.length();
 }
 
-static const double pi = 3.14159265358979323846;
-
-
-// =============================================================================
-// Plural expression
-template<typename T>
-static inline const char* plural (T n)
-{
-	return (n != 1) ? "s" : "";
-}
-
-template<typename T>
-bool isZero (T a)
-{
-	return qFuzzyCompare (a + 1.0, 1.0);
-}
-
-template<typename T>
-bool isInteger (T a)
-{
-	return (qAbs (a - floor(a)) < 0.00001) or (qAbs (a - ceil(a)) < 0.00001);
-}
-
-//
-// Returns true if first arg is equal to any of the other args
-//
-template<typename T, typename Arg, typename... Args>
-bool isOneOf (T const& a, Arg const& arg, Args const&... args)
-{
-	if (a == arg)
-		return true;
-
-	return isOneOf (a, args...);
-}
-
-template<typename T>
-bool isOneOf (T const&)
-{
-	return false;
-}
-
-inline void toggle (bool& a)
-{
-	a = not a;
-}
-
-//
-// Iterates an enum
-//
-template<typename Enum>
-struct EnumIterShell
-{
-	struct Iterator
-	{
-		Iterator(typename std::underlying_type<Enum>::type i) :
-			i(i) {}
-
-		Iterator& operator++() { ++i; return *this; }
-		bool operator==(Iterator other) { return i == other.i; }
-		bool operator!=(Iterator other) { return i != other.i; }
-		Enum operator*() const { return Enum(i); }
-
-		typename std::underlying_type<Enum>::type i;
-	};
-
-	Iterator begin()
-	{
-		return Iterator(EnumLimits<Enum>::First);
-	};
-
-	Iterator end()
-	{
-		return Iterator(EnumLimits<Enum>::Last + 1);
-	}
-};
-
-template<typename Enum>
-EnumIterShell<Enum> iterateEnum()
-{
-	return EnumIterShell<Enum>();
-}
-
-// Is a value inside an enum?
-template<typename Enum>
-bool valueInEnum(Enum enumerator)
-{
-	typename std::underlying_type<Enum>::type index = static_cast<typename std::underlying_type<Enum>::type>(enumerator);
-	return index >= EnumLimits<Enum>::First and index <= EnumLimits<Enum>::Last;
-}
-
-double getRadialPoint(int segment, int divisions, double(*func)(double));
-QVector<QLineF> makeCircle(int segments, int divisions, double radius);
-qreal distanceFromPointToRectangle(const QPointF& point, const QRectF& rectangle);
-
-/*
- * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds.
- * The maximum amount can be specified manually.
- *
- * Example:
- *
- *   int A[] = {10,20,30,40};
- *   ring(A)[0]  ==     A[0 % 4]    == A[0]
- *   ring(A)[5]  ==     A[5 % 4]    == A[1]
- *   ring(A)[-1] == ring(A)[-1 + 4] == A[3]
- */
-template<typename T>
-class RingAdapter
-{
-private:
-	// The private section must come first because _collection is used in decltype() below.
-	T& _collection;
-	const int _count;
-
-public:
-	RingAdapter(T& collection, int count) :
-	    _collection {collection},
-	    _count {count} {}
-
-	template<typename IndexType>
-	decltype(_collection[IndexType()]) operator[](IndexType index)
-	{
-		if (_count == 0)
-		{
-			// Argh! ...let the collection deal with this case.
-			return _collection[0];
-		}
-		else
-		{
-			index %= _count;
-
-			// Fix negative modulus...
-			if (index < 0)
-				index += _count;
-
-			return _collection[index];
-		}
-	}
-
-	int size() const
-	{
-		return _count;
-	}
-};
-
-/*
- * Casts a reference to an enum into a reference to its underlying integer type.
- */
-template<typename T>
-typename std::underlying_type<T>::type& enum_cast(T& enu)
-{
-	return *reinterpret_cast<typename std::underlying_type<T>::type*>(&enu);
-}
-
-/*
- * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed
- * to be the amount of elements in the collection.
- */
-template<typename T>
-RingAdapter<T> ring(T& collection)
-{
-	return RingAdapter<T> {collection, countof(collection)};
-}
+using ApplyToMatrixFunction = std::function<void(int, double&)>;
+using ApplyToMatrixConstFunction = std::function<void(int, double)>;
 
-/*
- * Version of ring() that allows manual specification of the count.
- */
-template<typename T>
-RingAdapter<T> ring(T& collection, int count)
-{
-	return RingAdapter<T> {collection, count};
-}
-
-struct Library
-{
-	QString path;
-	enum
-	{
-		ReadOnlyStorage, // for official files, etc
-		UnofficialFiles, // put downloaded files here
-		WorkingDirectory, // for editable documents
-	} role = ReadOnlyStorage;
-
-	bool operator==(const Library& other) const
-	{
-		return (this->path == other.path) and (this->role == other.role);
-	}
-};
-
-Q_DECLARE_METATYPE(Library)
-using Libraries = QVector<Library>;
-
-QDataStream& operator<<(QDataStream& out, const Library& library);
-QDataStream& operator>>(QDataStream& in, Library& library);
-
-//
-// Get the amount of elements in something.
-//
-template<typename T, size_t N>
-int countof(T(&)[N])
-{
-	return N;
-}
-
-static inline int countof(const QString& string)
-{
-	return string.length();
-}
-
-template<typename T>
-int countof(const QVector<T>& vector)
-{
-	return vector.size();
-}
-
-template<typename T>
-int countof(const QList<T>& vector)
-{
-	return vector.size();
-}
-
-template<typename T>
-int countof(const QSet<T>& set)
-{
-	return set.size();
-}
-
-template<typename T>
-int countof(const std::initializer_list<T>& vector)
-{
-	return vector.size();
-}
-
-template<typename T>
-int countof(const RingAdapter<T>& ring)
-{
-	return ring.size();
-}
-
-/*
- * Extracts the sign of x.
- */
-template<typename T>
-T sign(T x)
-{
-	if (isZero(x))
-		return {};
-	else
-		return x / qAbs(x);
-}
-
-template<>
-inline int sign(int x)
-{
-	if (x == 0)
-		return 0;
-	else
-		return x / qAbs(x);
-}
-
-/*
- * Returns the maximum of a single parameter (the parameter itself).
- */
-template <typename T>
-T max(T a)
-{
-	return a;
-}
-
-/*
- * Returns the maximum of two parameters.
- */
-template <typename T>
-T max(T a, T b)
-{
-	return a > b ? a : b;
-}
-
-/*
- * Returns the maximum of n parameters.
- */
-template <typename T, typename... Rest>
-T max(T a, Rest&&... rest)
-{
-	return max(a, max(rest...));
-}
-
-/*
- * Returns the minimum of a single parameter (the parameter itself).
- */
-template <typename T>
-T min(T a)
-{
-	return a;
-}
-
-/*
- * Returns the minimum of two parameters.
- */
-template <typename T>
-T min(T a, T b)
-{
-	return a < b ? a : b;
-}
-
-/*
- * Returns the minimum of n parameters.
- */
-template <typename T, typename... Rest>
-T min(T a, Rest&&... rest)
-{
-	return min(a, min(rest...));
-}
-
-/*
- * Assigns the value of a single flag in a flagset
- */
-template<int Flag, typename T>
-void assignFlag(QFlags<T>& flagset, bool value)
-{
-	if (value)
-		flagset |= static_cast<T>(Flag);
-	else
-		flagset &= ~static_cast<T>(Flag);
-}
-
-/*
- * Returns a singleton of type T, useful for providing a valid but unused
- * pointer.
- */
-template<typename T>
-inline T& sink()
-{
-	static T result;
-	return result;
-}
+void applyToMatrix(class Matrix& a, ApplyToMatrixFunction func);
+void applyToMatrix(const class Matrix& a, ApplyToMatrixConstFunction func);
+QString formatFileSize(qint64 size);
+int gcd(int a, int b);
+QString joinStrings(const QList<class StringFormatArg>& values, QString delimeter = " ");
+void roundToDecimals(double& value, int decimals);
+void simplify(int& numerator, int& denominator);
--- a/src/canvas.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/canvas.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -21,6 +21,8 @@
 #include "grid.h"
 #include "lddocument.h"
 #include "primitives.h"
+#include "algorithms/geometry.h"
+#include "generics/ring.h"
 
 Canvas::Canvas(LDDocument* document, QWidget* parent) :
     GLRenderer {document, parent},
--- a/src/dialogs/colorselector.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/dialogs/colorselector.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -25,7 +25,6 @@
 #include "../guiutilities.h"
 #include "../main.h"
 #include "../mainwindow.h"
-#include "../miscallenous.h"
 #include "colorselector.h"
 #include "ui_colorselector.h"
 
--- a/src/dialogs/configdialog.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/dialogs/configdialog.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -34,7 +34,6 @@
 #include "../main.h"
 #include "../lddocument.h"
 #include "../librariesmodel.h"
-#include "../miscallenous.h"
 #include "../canvas.h"
 #include "../guiutilities.h"
 #include "../documentmanager.h"
--- a/src/editmodes/abstractEditMode.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/editmodes/abstractEditMode.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -29,7 +29,6 @@
 #include "../mainwindow.h"
 #include "../lddocument.h"
 #include "../canvas.h"
-#include "../miscallenous.h"
 #include "../grid.h"
 
 /*
--- a/src/editmodes/circleMode.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/editmodes/circleMode.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -18,18 +18,17 @@
 
 #include <QPainter>
 #include "circleMode.h"
-#include "../miscallenous.h"
 #include "../lddocument.h"
 #include "../ringFinder.h"
 #include "../primitives.h"
 #include "../canvas.h"
 #include "../mainwindow.h"
 #include "../mathfunctions.h"
-#include "../miscallenous.h"
 #include "../documentmanager.h"
 #include "../grid.h"
 #include "../linetypes/modelobject.h"
 #include "../linetypes/quadrilateral.h"
+#include "../algorithms/geometry.h"
 
 CircleMode::CircleMode(Canvas* canvas) :
     Super {canvas} {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/generics/enums.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,71 @@
+#pragma once
+#include <type_traits>
+
+template<typename T>
+struct EnumLimits {};
+
+//
+// Iterates an enum
+//
+template<typename Enum>
+struct EnumIterShell
+{
+	struct Iterator
+	{
+		Iterator(typename std::underlying_type<Enum>::type i) :
+			i(i) {}
+
+		Iterator& operator++() { ++i; return *this; }
+		bool operator==(Iterator other) { return i == other.i; }
+		bool operator!=(Iterator other) { return i != other.i; }
+		Enum operator*() const { return Enum(i); }
+
+		typename std::underlying_type<Enum>::type i;
+	};
+
+	Iterator begin()
+	{
+		return Iterator(EnumLimits<Enum>::First);
+	};
+
+	Iterator end()
+	{
+		return Iterator(EnumLimits<Enum>::Last + 1);
+	}
+};
+
+template<typename Enum>
+EnumIterShell<Enum> iterateEnum()
+{
+	return EnumIterShell<Enum>();
+}
+
+/*
+ * Casts an enum into its underlying type.
+ */
+template<typename T>
+typename std::underlying_type<T>::type& enum_cast(T& enu)
+{
+	return *reinterpret_cast<typename std::underlying_type<T>::type*>(&enu);
+}
+
+/*
+ * Returns whether an enum value is within proper bounds.
+ */
+template<typename Enum>
+bool valueInEnum(Enum enumerator)
+{
+	auto index = enum_cast(enumerator);
+	return index >= EnumLimits<Enum>::First and index <= EnumLimits<Enum>::Last;
+}
+
+#define MAKE_ITERABLE_ENUM(T) \
+	template<> \
+	struct EnumLimits<T> \
+	{\
+		enum { First = 0, Last = static_cast<int>(T::_End) - 1, Count = Last + 1 };\
+	}; \
+	inline T operator++ (T& a) { a = static_cast<T>(enum_cast(a) + 1); return a; } \
+	inline T operator-- (T& a) { a = static_cast<T>(enum_cast(a) - 1); return a; } \
+	inline T operator++ (T& a, int) { T result = a; a = static_cast<T>(enum_cast(a) + 1); return result; } \
+	inline T operator-- (T& a, int) { T result = a; a = static_cast<T>(enum_cast(a) - 1); return result; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/generics/functions.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,244 @@
+#pragma once
+#include <functional>
+#include <cmath>
+#include "../basics.h"
+
+using std::abs;
+using std::ceil;
+using std::cos;
+using std::floor;
+using std::hypot;
+using std::sin;
+using std::sqrt;
+
+/*
+ * Returns whether the argument is reasonably close to zero.
+ */
+template<typename T>
+bool isZero(T a)
+{
+	return qFuzzyCompare(a + 1.0, 1.0);
+}
+
+template<typename T>
+bool isInteger(T a)
+{
+	return (::abs(a - ::floor(a)) < 0.00001) or (::abs(a - ::ceil(a)) < 0.00001);
+}
+
+//
+// Returns true if first arg is equal to any of the other args
+//
+template<typename T, typename Arg, typename... Args>
+bool isOneOf(const T& needle, const Arg& arg, const Args&... args)
+{
+	if (needle == arg)
+		return true;
+	else
+		return isOneOf(needle, args...);
+}
+
+template<typename T>
+bool isOneOf(const T&)
+{
+	return false;
+}
+
+// http://stackoverflow.com/a/18204188/3629665
+template<typename T>
+inline int rotl10(T x)
+{
+	return (((x) << 10) | (((x) >> 22) & 0x000000ff));
+}
+
+template<typename T>
+inline int rotl20(T x)
+{
+	return (((x) << 20) | (((x) >> 12) & 0x000000ff));
+}
+
+//
+// Get the amount of elements in something.
+//
+template<typename T, size_t N>
+int countof(T(&)[N])
+{
+	return N;
+}
+
+static inline int countof(const QString& string)
+{
+	return string.length();
+}
+
+template<typename T>
+int countof(const QVector<T>& vector)
+{
+	return vector.size();
+}
+
+template<typename T>
+int countof(const QList<T>& vector)
+{
+	return vector.size();
+}
+
+template<typename T>
+int countof(const QSet<T>& set)
+{
+	return set.size();
+}
+
+template<typename T>
+int countof(const std::initializer_list<T>& vector)
+{
+	return vector.size();
+}
+
+/*
+ * Extracts the sign of x.
+ */
+template<typename T>
+T sign(T x)
+{
+	if (isZero(x))
+		return {};
+	else
+		return x / qAbs(x);
+}
+
+template<>
+inline int sign(int x)
+{
+	if (x == 0)
+		return 0;
+	else
+		return x / qAbs(x);
+}
+
+/*
+ * Returns the maximum of a single parameter (the parameter itself).
+ */
+template <typename T>
+T max(T a)
+{
+	return a;
+}
+
+/*
+ * Returns the maximum of two parameters.
+ */
+template <typename T>
+T max(T a, T b)
+{
+	return a > b ? a : b;
+}
+
+/*
+ * Returns the maximum of n parameters.
+ */
+template <typename T, typename... Rest>
+T max(T a, Rest&&... rest)
+{
+	return max(a, max(rest...));
+}
+
+/*
+ * Returns the minimum of a single parameter (the parameter itself).
+ */
+template <typename T>
+T min(T a)
+{
+	return a;
+}
+
+/*
+ * Returns the minimum of two parameters.
+ */
+template <typename T>
+T min(T a, T b)
+{
+	return a < b ? a : b;
+}
+
+/*
+ * Returns the minimum of n parameters.
+ */
+template <typename T, typename... Rest>
+T min(T a, Rest&&... rest)
+{
+	return min(a, min(rest...));
+}
+
+/*
+ * Assigns the value of a single flag in a flagset
+ */
+template<int Flag, typename T>
+void assignFlag(QFlags<T>& flagset, bool value)
+{
+	if (value)
+		flagset |= static_cast<T>(Flag);
+	else
+		flagset &= ~static_cast<T>(Flag);
+}
+
+/*
+ * Returns a singleton of type T, useful for providing a valid but unused
+ * pointer.
+ */
+template<typename T>
+inline T& sink()
+{
+	static T result;
+	return result;
+}
+
+/*
+ * Rounds the input value to the nearest multiple of the provided interval.
+ */
+template<typename T>
+T roundToInterval(T value, double interval)
+{
+	return static_cast<T>(round(value / interval) * interval);
+}
+
+// Copy of qOverload so as to drop Qt version requirement from 5.7 to 5.5.
+#if (QT_VERSION < QT_VERSION_CHECK(5, 7, 0))
+template <typename... Args>
+struct QNonConstOverload
+{
+	template <typename R, typename T>
+	Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+	template <typename R, typename T>
+	static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+};
+template <typename... Args>
+struct QConstOverload
+{
+	template <typename R, typename T>
+	Q_DECL_CONSTEXPR auto operator()(R (T::*ptr)(Args...) const) const Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+	template <typename R, typename T>
+	static Q_DECL_CONSTEXPR auto of(R (T::*ptr)(Args...) const) Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+};
+template <typename... Args>
+struct QOverload : QConstOverload<Args...>, QNonConstOverload<Args...>
+{
+	using QConstOverload<Args...>::of;
+	using QConstOverload<Args...>::operator();
+	using QNonConstOverload<Args...>::of;
+	using QNonConstOverload<Args...>::operator();
+	template <typename R>
+	Q_DECL_CONSTEXPR auto operator()(R (*ptr)(Args...)) const Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+	template <typename R>
+	static Q_DECL_CONSTEXPR auto of(R (*ptr)(Args...)) Q_DECL_NOTHROW -> decltype(ptr)
+	{ return ptr; }
+};
+template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QOverload<Args...> qOverload = {};
+template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QConstOverload<Args...> qConstOverload = {};
+template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> qNonConstOverload = {};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/generics/ring.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,95 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include "../basics.h"
+
+/*
+ * Implements a ring adapter over T. This class corrects indices given to the element-operator so that they're within bounds.
+ * The maximum amount can be specified manually.
+ *
+ * Example:
+ *
+ *   int A[] = {10,20,30,40};
+ *   ring(A)[0]  ==     A[0 % 4]    == A[0]
+ *   ring(A)[5]  ==     A[5 % 4]    == A[1]
+ *   ring(A)[-1] == ring(A)[-1 + 4] == A[3]
+ */
+template<typename T>
+class RingAdapter
+{
+private:
+	// The private section must come first because _collection is used in decltype() below.
+	T& _collection;
+	const int _count;
+
+public:
+	RingAdapter(T& collection, int count) :
+		_collection {collection},
+		_count {count} {}
+
+	template<typename IndexType>
+	decltype(_collection[IndexType()]) operator[](IndexType index)
+	{
+		if (_count == 0)
+		{
+			// Argh! ...let the collection deal with this case.
+			return _collection[0];
+		}
+		else
+		{
+			index %= _count;
+
+			// Fix negative modulus...
+			if (index < 0)
+				index += _count;
+
+			return _collection[index];
+		}
+	}
+
+	int size() const
+	{
+		return _count;
+	}
+};
+
+/*
+ * Convenience function for RingAdapter so that the template parameter does not have to be provided. The ring amount is assumed
+ * to be the amount of elements in the collection.
+ */
+template<typename T>
+RingAdapter<T> ring(T& collection)
+{
+	return {collection, countof(collection)};
+}
+
+/*
+ * Version of ring() that allows manual specification of the count.
+ */
+template<typename T>
+RingAdapter<T> ring(T& collection, int count)
+{
+	return {collection, count};
+}
+
+template<typename T>
+int countof(const RingAdapter<T>& ring)
+{
+	return ring.size();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/generics/transform.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,93 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include <functional>
+
+//
+// TransformingIterator
+//
+// Transforming iterator, calls Fn on iterated values before returning them.
+//
+template<typename T, typename Res, typename Arg>
+struct TransformingIterator
+{
+	using Iterator = decltype(T().begin());
+	using Self = TransformingIterator<T, Res, Arg>;
+	Iterator it;
+	std::function<Res(Arg)> fn;
+
+	TransformingIterator(Iterator it, std::function<Res(Arg)> fn) :
+		it(it),
+		fn(fn) {}
+
+	Res operator*()
+	{
+		return fn(*it);
+	}
+
+	bool operator!= (const Self& other) const
+	{
+		return other.it != it;
+	}
+
+	void operator++()
+	{
+		++it;
+	}
+};
+
+//
+// TransformWrapper
+//
+// Transform object, only serves to produce transforming iterators
+//
+template<typename T, typename Res, typename Arg>
+struct TransformWrapper
+{
+	using Iterator = TransformingIterator<T, Res, Arg>;
+
+	TransformWrapper(T& iterable, std::function<Res(Arg)> fn) :
+		iterable(iterable),
+		function(fn) {}
+
+	Iterator begin()
+	{
+		return Iterator(iterable.begin(), function);
+	}
+
+	Iterator end()
+	{
+		return Iterator(iterable.end(), function);
+	}
+
+	T& iterable;
+	std::function<Res(Arg)> function;
+};
+
+template<typename T, typename Res, typename Arg>
+TransformWrapper<T, Res, Arg> transform(T& iterable, Res(*fn)(Arg))
+{
+	return TransformWrapper<T, Res, Arg>(iterable, fn);
+}
+
+template<typename T, typename Res, typename Arg>
+TransformWrapper<T, Res, Arg> transform(T& iterable, std::function<Res(Arg)> fn)
+{
+	return TransformWrapper<T, Res, Arg>(iterable, fn);
+}
--- a/src/glcamera.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/glcamera.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -19,7 +19,6 @@
 #include "glcamera.h"
 #include "glrenderer.h"
 #include "grid.h"
-#include "miscallenous.h"
 
 /*
  * Constructs a fixed camera from parameters.
--- a/src/glcompiler.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/glcompiler.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -20,11 +20,11 @@
 #include <GL/glu.h>
 #include <GL/glext.h>
 #include "glcompiler.h"
-#include "miscallenous.h"
 #include "guiutilities.h"
 #include "documentmanager.h"
 #include "grid.h"
 #include "algorithms/invert.h"
+#include "generics/ring.h"
 
 void checkGLError(HierarchyElement* element, QString file, int line)
 {
--- a/src/glrenderer.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/glrenderer.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -28,7 +28,6 @@
 #include "glrenderer.h"
 #include "colors.h"
 #include "mainwindow.h"
-#include "miscallenous.h"
 #include "editHistory.h"
 #include "glcompiler.h"
 #include "primitives.h"
--- a/src/guiutilities.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/guiutilities.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -101,7 +101,7 @@
 		LDColor color = iterator.key();
 		int frequency = iterator.value();
 		QIcon icon = makeColorIcon(color, 16);
-		box->addItem(icon, format("[%1] %2 (%3 object%4)", color.index(), color.name(), frequency, plural(frequency)));
+		box->addItem(icon, format("[%1] %2 (%3 object(s))", color.index(), color.name(), frequency));
 		box->setItemData(row, color.index());
 		++row;
 	}
--- a/src/linetypes/modelobject.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/linetypes/modelobject.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -16,11 +16,9 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <assert.h>
 #include "../documentmanager.h"
 #include "../linetypes/modelobject.h"
 #include "../lddocument.h"
-#include "../miscallenous.h"
 #include "../mainwindow.h"
 #include "../editHistory.h"
 #include "../canvas.h"
--- a/src/macros.h	Sat Mar 24 11:05:40 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#ifndef __GNUC__
-# define __attribute__(X)
-#endif
-
-#define DEFINE_CLASS(SELF, SUPER) \
-public: \
-	using Self = SELF; \
-	using Super = SUPER;
-
-#ifdef WIN32
-# define DIRSLASH "\\"
-# define DIRSLASH_CHAR '\\'
-#else // WIN32
-# define DIRSLASH "/"
-# define DIRSLASH_CHAR '/'
-#endif // WIN32
-
-#define MAKE_ITERABLE_ENUM(T) \
-	template<> \
-	struct EnumLimits<T> \
-	{\
-	    enum { First = 0, Last = static_cast<int>(T::_End) - 1, Count = Last + 1 };\
-	}; \
-	inline T operator++ (T& a) { a = static_cast<T>(static_cast<int>(a) + 1); return a; } \
-	inline T operator-- (T& a) { a = static_cast<T>(static_cast<int>(a) - 1); return a; } \
-	inline T operator++ (T& a, int) { T result = a; a = static_cast<T>(static_cast<int>(a) + 1); return result; } \
-	inline T operator-- (T& a, int) { T result = a; a = static_cast<T>(static_cast<int>(a) - 1); return result; }
-
-template<typename T>
-struct EnumLimits {};
--- a/src/main.h	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/main.h	Sat Mar 24 11:57:24 2018 +0200
@@ -29,9 +29,10 @@
 #include <QString>
 #include <QTextFormat>
 #include <QVariant>
-#include "macros.h"
+#include "basics.h"
 #include "version.h"
 #include "format.h"
+#include "types/library.h"
 #include "configuration.h"
 #include "generics/range.h"
 #include "types/vertex.h"
--- a/src/mainwindow.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/mainwindow.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -27,7 +27,6 @@
 #include "canvas.h"
 #include "mainwindow.h"
 #include "lddocument.h"
-#include "miscallenous.h"
 #include "messageLog.h"
 #include "ui_mainwindow.h"
 #include "primitives.h"
--- a/src/mathfunctions.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/mathfunctions.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -18,7 +18,6 @@
 
 #include "mathfunctions.h"
 #include "linetypes/modelobject.h"
-#include "miscallenous.h"
 #include "types/boundingbox.h"
 
 MathFunctions::MathFunctions(QObject* parent) :
--- a/src/miscallenous.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <math.h>
-#include <locale.h>
-#include <QColor>
-#include "main.h"
-#include "miscallenous.h"
-#include "mainwindow.h"
-#include "lddocument.h"
-
-
-int gcd (int a, int b)
-{
-	while (b != 0)
-	{
-		int temp = a;
-		a = b;
-		b = temp % b;
-	}
-
-	return a;
-}
-
-
-void simplify (int& numerator, int& denominator)
-{
-	int factor = gcd(numerator, denominator);
-	numerator /= factor;
-	denominator /= factor;
-}
-
-
-QString joinStrings (QList<StringFormatArg> vals, QString delim)
-{
-	QStringList list;
-
-	for (const StringFormatArg& arg : vals)
-		list << arg.text();
-
-	return list.join (delim);
-}
-
-
-void roundToDecimals(double& value, int decimals)
-{
-	if (decimals == 0)
-	{
-		value = round(value);
-	}
-	else if (decimals > 0)
-	{
-		qreal coefficient = pow(10, decimals);
-		value = round(value * coefficient) / coefficient;
-	}
-}
-
-
-void applyToMatrix (Matrix& a, ApplyToMatrixFunction func)
-{
-	for (int i = 0; i < 9; ++i)
-		func(i, a.value(i));
-}
-
-void applyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func)
-{
-	for (int i = 0; i < 9; ++i)
-		func(i, a.value(i));
-}
-
-
-QString formatFileSize (qint64 size)
-{
-	static const QString suffixes[] = {" bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
-	int magnitude = (size > 0) ? floor(log10(size) / 3.0 + 1e-10) : 0;
-	magnitude = qBound(0, magnitude, countof(suffixes) - 1);
-	return QString::number(size / pow(1000, magnitude)) + suffixes[magnitude];
-}
--- a/src/miscallenous.h	Sat Mar 24 11:05:40 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-#include <QVector>
-#include <functional>
-#include "main.h"
-#include "basics.h"
-
-class LDDocument;
-class QColor;
-class QAction;
-
-using ApplyToMatrixFunction = std::function<void (int, double&)>;
-using ApplyToMatrixConstFunction = std::function<void (int, double)>;
-
-void applyToMatrix (Matrix& a, ApplyToMatrixFunction func);
-void applyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func);
-QString formatFileSize (qint64 size);
-int gcd (int a, int b);
-QString joinStrings (QList<StringFormatArg> vals, QString delim = " ");
-void roundToDecimals (double& value, int decimals);
-void simplify (int& numer, int& denom);
-
-/*
- * Rounds the input value to the nearest multiple of the provided interval.
- */
-template<typename T>
-T roundToInterval(T value, double interval)
-{
-	return static_cast<T>(round(value / interval) * interval);
-}
--- a/src/primitives.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/primitives.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -21,10 +21,10 @@
 #include "lddocument.h"
 #include "mainwindow.h"
 #include "primitives.h"
-#include "miscallenous.h"
 #include "colors.h"
 #include "documentmanager.h"
 #include "editHistory.h"
+#include "algorithms/geometry.h"
 #include "linetypes/comment.h"
 #include "linetypes/conditionaledge.h"
 #include "linetypes/edgeline.h"
@@ -372,19 +372,22 @@
 
 	for (int i : conditionalLineSegments)
 	{
-		Vertex v0 = {getRadialPoint(i, divisions, cos), 0.0f, getRadialPoint(i, divisions, sin)};
+		QPointF p0 = ::pointOnCircumference(i, divisions);
+		QPointF p2 = ::pointOnCircumference(i + 1, divisions);
+		QPointF p3 = ::pointOnCircumference(i - 1, divisions);
+		Vertex v0 = {p0.x(), 0.0, p0.y()};
 		Vertex v1;
-		Vertex v2 = {getRadialPoint(i + 1, divisions, cos), 0.0f, getRadialPoint(i + 1, divisions, sin)};
-		Vertex v3 = {getRadialPoint(i - 1, divisions, cos), 0.0f, getRadialPoint(i - 1, divisions, sin)};
+		Vertex v2 = {p2.x(), 0.0, p2.y()};
+		Vertex v3 = {p3.x(), 0.0, p3.y()};
 
 		if (type == Cylinder)
 		{
-			v1 = {v0[X], 1.0f, v0[Z]};
+			v1 = {v0.x, 1.0f, v0.z};
 		}
 		else if (type == Cone)
 		{
-			v1 = {v0[X] * (ringNumber + 1), 0.0, v0[Z] * (ringNumber + 1)};
-			v0 = {v0[X] * ringNumber, 1.0, v0[Z] * ringNumber};
+			v1 = {v0.x * (ringNumber + 1), 0.0, v0.z * (ringNumber + 1)};
+			v0 = {v0.x * ringNumber, 1.0, v0.z * ringNumber};
 		}
 
 		LDConditionalEdge* line = model.emplace<LDConditionalEdge>();
--- a/src/ringFinder.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/ringFinder.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -17,7 +17,6 @@
  */
 
 #include "ringFinder.h"
-#include "miscallenous.h"
 
 RingFinder g_RingFinder;
 
--- a/src/toolsets/algorithmtoolset.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/toolsets/algorithmtoolset.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -24,7 +24,6 @@
 #include "../mainwindow.h"
 #include "../main.h"
 #include "../lddocument.h"
-#include "../miscallenous.h"
 #include "../glrenderer.h"
 #include "../colors.h"
 #include "../mathfunctions.h"
--- a/src/toolsets/extprogramtoolset.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/toolsets/extprogramtoolset.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -29,7 +29,6 @@
 #include <QFileInfo>
 #include "../guiutilities.h"
 #include "../main.h"
-#include "../miscallenous.h"
 #include "../mainwindow.h"
 #include "../lddocument.h"
 #include "../editHistory.h"
--- a/src/toolsets/movetoolset.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/toolsets/movetoolset.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -18,7 +18,6 @@
 
 #include "../lddocument.h"
 #include "../mathfunctions.h"
-#include "../miscallenous.h"
 #include "../mainwindow.h"
 #include "movetoolset.h"
 #include "ui_rotationpointdialog.h"
--- a/src/toolsets/viewtoolset.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/toolsets/viewtoolset.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -21,7 +21,6 @@
 #include <QMessageBox>
 #include "../mainwindow.h"
 #include "../lddocument.h"
-#include "../miscallenous.h"
 #include "../canvas.h"
 #include "../primitives.h"
 #include "../colors.h"
--- a/src/transform.h	Sat Mar 24 11:05:40 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-#include <functional>
-
-//
-// TransformingIterator
-//
-// Transforming iterator, calls Fn on iterated values before returning them.
-//
-template<typename T, typename Res, typename Arg>
-struct TransformingIterator
-{
-	using Iterator = decltype(T().begin());
-	using Self = TransformingIterator<T, Res, Arg>;
-	Iterator it;
-	std::function<Res(Arg)> fn;
-
-	TransformingIterator(Iterator it, std::function<Res(Arg)> fn) :
-		it(it),
-		fn(fn) {}
-
-	Res operator*()
-	{
-		return fn(*it);
-	}
-
-	bool operator!= (const Self& other) const
-	{
-		return other.it != it;
-	}
-
-	void operator++()
-	{
-		++it;
-	}
-};
-
-//
-// TransformWrapper
-//
-// Transform object, only serves to produce transforming iterators
-//
-template<typename T, typename Res, typename Arg>
-struct TransformWrapper
-{
-	using Iterator = TransformingIterator<T, Res, Arg>;
-
-	TransformWrapper(T& iterable, std::function<Res(Arg)> fn) :
-		iterable(iterable),
-		function(fn) {}
-
-	Iterator begin()
-	{
-		return Iterator(iterable.begin(), function);
-	}
-
-	Iterator end()
-	{
-		return Iterator(iterable.end(), function);
-	}
-
-	T& iterable;
-	std::function<Res(Arg)> function;
-};
-
-template<typename T, typename Res, typename Arg>
-TransformWrapper<T, Res, Arg> transform(T& iterable, Res(*fn)(Arg))
-{
-	return TransformWrapper<T, Res, Arg>(iterable, fn);
-}
-
-template<typename T, typename Res, typename Arg>
-TransformWrapper<T, Res, Arg> transform(T& iterable, std::function<Res(Arg)> fn)
-{
-	return TransformWrapper<T, Res, Arg>(iterable, fn);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/types/library.h	Sat Mar 24 11:57:24 2018 +0200
@@ -0,0 +1,50 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include <QDataStream>
+#include "generics/enums.h"
+
+struct Library
+{
+	QString path;
+	enum
+	{
+		ReadOnlyStorage, // for official files, etc
+		UnofficialFiles, // put downloaded files here
+		WorkingDirectory, // for editable documents
+	} role = ReadOnlyStorage;
+
+	bool operator==(const Library& other) const
+	{
+		return (this->path == other.path) and (this->role == other.role);
+	}
+};
+
+Q_DECLARE_METATYPE(Library)
+using Libraries = QVector<Library>;
+
+inline QDataStream& operator<<(QDataStream& out, const Library& library)
+{
+	return out << library.path << library.role;
+}
+
+inline QDataStream& operator>>(QDataStream &in, Library& library)
+{
+	return in >> library.path >> enum_cast(library.role);
+}
--- a/src/types/vertex.cpp	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/types/vertex.cpp	Sat Mar 24 11:57:24 2018 +0200
@@ -200,3 +200,8 @@
 {
 	return in >> vertex.x >> vertex.y >> vertex.z;
 }
+
+unsigned int qHash(const Vertex& key)
+{
+	return qHash(key.x) ^ rotl10(qHash(key.y)) ^ rotl20(qHash(key.z));
+}
--- a/src/types/vertex.h	Sat Mar 24 11:05:40 2018 +0200
+++ b/src/types/vertex.h	Sat Mar 24 11:57:24 2018 +0200
@@ -56,6 +56,6 @@
 }
 
 Q_DECLARE_METATYPE(Vertex)
-uint qHash(const Vertex& key);
+unsigned int qHash(const Vertex& key);
 QDataStream& operator<<(QDataStream& out, const Vertex& vertex);
 QDataStream& operator>>(QDataStream& in, Vertex& vertex);

mercurial