--- 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); -}