Sat, 24 Mar 2018 11:57:24 +0200
reorganized headers
--- 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);