--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Types.cc Tue Jan 21 02:03:27 2014 +0200 @@ -0,0 +1,416 @@ +/* + * LDForge: LDraw parts authoring CAD + * Copyright (C) 2013, 2014 Santeri 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 <QObject> +#include <QStringList> +#include <QTextStream> +#include <QFile> +#include <assert.h> +#include "Main.h" +#include "Types.h" +#include "Misc.h" +#include "LDObject.h" +#include "Document.h" + +// ============================================================================= +// ----------------------------------------------------------------------------- +QString DoFormat (QList<StringFormatArg> args) +{ + assert (args.size() >= 1); + QString text = args[0].value(); + + for (uchar i = 1; i < args.size(); ++i) + text = text.arg (args[i].value()); + + return text; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex::Vertex (double x, double y, double z) +{ + m_coords[X] = x; + m_coords[Y] = y; + m_coords[Z] = z; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void Vertex::move (const Vertex& other) +{ + for_axes (ax) + m_coords[ax] += other[ax]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +double Vertex::distanceTo (const Vertex& other) const +{ + double dx = abs (x() - other.x()); + double dy = abs (y() - other.y()); + double dz = abs (z() - other.z()); + return sqrt ((dx * dx) + (dy * dy) + (dz * dz)); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex Vertex::midpoint (const Vertex& other) +{ + Vertex mid; + + for_axes (ax) + mid[ax] = (getCoordinate (ax) + other[ax]) / 2; + + return mid; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +QString Vertex::toString (bool mangled) const +{ + QString fmtstr = "%1 %2 %3"; + + if (mangled) + fmtstr = "(%1, %2, %3)"; + + return fmt (fmtstr, x(), y(), z()); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void Vertex::transform (const Matrix& matr, const Vertex& pos) +{ + double x2 = (matr[0] * x()) + (matr[1] * y()) + (matr[2] * z()) + pos[X]; + double y2 = (matr[3] * x()) + (matr[4] * y()) + (matr[5] * z()) + pos[Y]; + double z2 = (matr[6] * x()) + (matr[7] * y()) + (matr[8] * z()) + pos[Z]; + + x() = x2; + y() = y2; + z() = z2; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex Vertex::operator-() const +{ + return Vertex (-m_coords[X], -m_coords[Y], -m_coords[Z]); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +bool Vertex::operator!= (const Vertex& other) const +{ + return !operator== (other); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +bool Vertex::operator== (const Vertex& other) const +{ + return getCoordinate (X) == other[X] && + getCoordinate (Y) == other[Y] && + getCoordinate (Z) == other[Z]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex& Vertex::operator/= (const double d) +{ + for_axes (ax) + m_coords[ax] /= d; + + return *this; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex Vertex::operator/ (const double d) const +{ + Vertex other (*this); + return other /= d; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex& Vertex::operator+= (const Vertex& other) +{ + move (other); + return *this; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex Vertex::operator+ (const Vertex& other) const +{ + Vertex newvert (*this); + newvert.move (other); + return newvert; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +int Vertex::operator< (const Vertex& other) const +{ + if (operator== (other)) + return false; + + if (getCoordinate (X) < other[X]) + return true; + + if (getCoordinate (X) > other[X]) + return false; + + if (getCoordinate (Y) < other[Y]) + return true; + + if (getCoordinate (Y) > other[Y]) + return false; + + return getCoordinate (Z) < other[Z]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Matrix::Matrix (double vals[]) +{ + for (int i = 0; i < 9; ++i) + m_vals[i] = vals[i]; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Matrix::Matrix (double fillval) +{ + for (int i = 0; i < 9; ++i) + m_vals[i] = fillval; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Matrix::Matrix (initlist<double> vals) +{ + assert (vals.size() == 9); + memcpy (&m_vals[0], & (*vals.begin()), sizeof m_vals); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void Matrix::puts() const +{ + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + log ("%1\t", m_vals[ (i * 3) + j]); + + log ("\n"); + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +QString Matrix::toString() const +{ + QString val; + + for (int i = 0; i < 9; ++i) + { + if (i > 0) + val += ' '; + + val += QString::number (m_vals[i]); + } + + return val; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void Matrix::zero() +{ + memset (&m_vals[0], 0, sizeof m_vals); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Matrix Matrix::mult (const Matrix& other) const +{ + Matrix val; + val.zero(); + + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 3; ++k) + val[(i * 3) + j] += m_vals[(i * 3) + k] * other[(k * 3) + j]; + + return val; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Matrix& Matrix::operator= (const Matrix& other) +{ + memcpy (&m_vals[0], &other.m_vals[0], sizeof m_vals); + return *this; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +double Matrix::getDeterminant() const +{ + return (val (0) * val (4) * val (8)) + + (val (1) * val (5) * val (6)) + + (val (2) * val (3) * val (7)) - + (val (2) * val (4) * val (6)) - + (val (1) * val (3) * val (8)) - + (val (0) * val (5) * val (7)); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +bool Matrix::operator== (const Matrix& other) const +{ + for (int i = 0; i < 9; ++i) + if (val (i) != other[i]) + return false; + + return true; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +LDBoundingBox::LDBoundingBox() +{ + reset(); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDBoundingBox::calculate() +{ + reset(); + + if (!getCurrentDocument()) + return; + + for (LDObject* obj : getCurrentDocument()->getObjects()) + calcObject (obj); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDBoundingBox::calcObject (LDObject* obj) +{ + switch (obj->getType()) + { + case LDObject::ELine: + case LDObject::ETriangle: + case LDObject::EQuad: + case LDObject::ECondLine: + { + for (int i = 0; i < obj->vertices(); ++i) + calcVertex (obj->getVertex (i)); + } break; + + case LDObject::ESubfile: + { + LDSubfile* ref = static_cast<LDSubfile*> (obj); + LDObjectList objs = ref->inlineContents (LDSubfile::DeepCacheInline); + + for (LDObject * obj : objs) + { + calcObject (obj); + obj->deleteSelf(); + } + } + break; + + default: + break; + } +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +LDBoundingBox& LDBoundingBox::operator<< (const Vertex& v) +{ + calcVertex (v); + return *this; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +LDBoundingBox& LDBoundingBox::operator<< (LDObject* obj) +{ + calcObject (obj); + return *this; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDBoundingBox::calcVertex (const Vertex& v) +{ + for_axes (ax) + { + m_Vertex0[ax] = min (v[ax], m_Vertex0[ax]); + m_Vertex1[ax] = max (v[ax], m_Vertex1[ax]); + } + + setEmpty (false); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void LDBoundingBox::reset() +{ + m_Vertex0[X] = m_Vertex0[Y] = m_Vertex0[Z] = 10000.0; + m_Vertex1[X] = m_Vertex1[Y] = m_Vertex1[Z] = -10000.0; + setEmpty (true); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +double LDBoundingBox::size() const +{ + double xscale = (m_Vertex0[X] - m_Vertex1[X]); + double yscale = (m_Vertex0[Y] - m_Vertex1[Y]); + double zscale = (m_Vertex0[Z] - m_Vertex1[Z]); + double size = zscale; + + if (xscale > yscale) + { + if (xscale > zscale) + size = xscale; + } + elif (yscale > zscale) + size = yscale; + + if (abs (size) >= 2.0f) + return abs (size / 2); + + return 1.0f; +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +Vertex LDBoundingBox::center() const +{ + return Vertex ( + (m_Vertex0[X] + m_Vertex1[X]) / 2, + (m_Vertex0[Y] + m_Vertex1[Y]) / 2, + (m_Vertex0[Z] + m_Vertex1[Z]) / 2); +}