src/ldObject.cpp

changeset 1147
a26568aa3cce
parent 1146
bb728c124d47
child 1148
96cb15a7611f
--- a/src/ldObject.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,825 +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 <assert.h>
-#include "documentmanager.h"
-#include "ldObject.h"
-#include "lddocument.h"
-#include "miscallenous.h"
-#include "mainwindow.h"
-#include "editHistory.h"
-#include "canvas.h"
-#include "colors.h"
-#include "glcompiler.h"
-#include "linetypes/edgeline.h"
-
-// List of all LDObjects
-QMap<qint32, LDObject*> g_allObjects;
-
-enum { MAX_LDOBJECT_IDS = (1 << 24) };
-
-#define LDOBJ_DEFAULT_CTOR(T,BASE) \
-	T :: T (Model* model) : \
-	    BASE {model} {}
-
-// =============================================================================
-// LDObject constructors
-//
-LDObject::LDObject (Model* model) :
-    m_isHidden {false},
-    m_isSelected {false},
-    _model {model},
-    m_coords {Origin}
-{
-	assert(_model != nullptr);
-
-	// Let's hope that nobody goes to create 17 million objects anytime soon...
-	static qint32 nextId = 1; // 0 shalt be null
-	if (nextId < MAX_LDOBJECT_IDS)
-		m_id = nextId++;
-	else
-		m_id = 0;
-
-	if (m_id != 0)
-		g_allObjects[m_id] = this;
-
-	m_randomColor = QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128);
-}
-
-LDSubfileReference::LDSubfileReference (Model* model) :
-    LDMatrixObject (model) {}
-
-LDOBJ_DEFAULT_CTOR (LDError, LDObject)
-LDOBJ_DEFAULT_CTOR (LDTriangle, LDObject)
-LDOBJ_DEFAULT_CTOR (LDQuadrilateral, LDObject)
-LDOBJ_DEFAULT_CTOR (LDBfc, LDObject)
-LDOBJ_DEFAULT_CTOR (LDBezierCurve, LDObject)
-
-LDObject::~LDObject()
-{
-	// Delete the GL lists
-	if (g_win)
-		g_win->renderer()->forgetObject(this);
-
-	// Remove this object from the list of LDObjects
-	g_allObjects.erase(g_allObjects.find(id()));
-}
-
-// =============================================================================
-//
-QString LDSubfileReference::asText() const
-{
-	QString val = format ("1 %1 %2 ", color(), position());
-	val += transformationMatrix().toString();
-	val += ' ';
-	val += fileInfo()->name();
-	return val;
-}
-
-// =============================================================================
-//
-QString LDTriangle::asText() const
-{
-	QString val = format ("3 %1", color());
-
-	for (int i = 0; i < 3; ++i)
-		val += format (" %1", vertex (i));
-
-	return val;
-}
-
-// =============================================================================
-//
-QString LDQuadrilateral::asText() const
-{
-	QString val = format ("4 %1", color());
-
-	for (int i = 0; i < 4; ++i)
-		val += format (" %1", vertex (i));
-
-	return val;
-}
-
-QString LDBezierCurve::asText() const
-{
-	QString result = format ("0 !LDFORGE BEZIER_CURVE %1", color());
-
-	// Add the coordinates
-	for (int i = 0; i < 4; ++i)
-		result += format (" %1", vertex (i));
-
-	return result;
-}
-
-// =============================================================================
-//
-QString LDError::asText() const
-{
-	return contents();
-}
-
-// =============================================================================
-//
-QString LDBfc::asText() const
-{
-	return format ("0 BFC %1", statementToString());
-}
-
-// =============================================================================
-//
-// Swap this object with another.
-//
-void LDObject::swap (LDObject* other)
-{
-	if (model() == other->model())
-		model()->swapObjects (this, other);
-}
-
-int LDObject::triangleCount() const
-{
-	return 0;
-}
-
-int LDSubfileReference::triangleCount() const
-{
-	return fileInfo()->triangleCount();
-}
-
-int LDTriangle::triangleCount() const
-{
-	return 1;
-}
-
-int LDQuadrilateral::triangleCount() const
-{
-	return 2;
-}
-
-int LDObject::numVertices() const
-{
-	return 0;
-}
-
-// =============================================================================
-//
-LDTriangle::LDTriangle (const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v1);
-	setVertex (1, v2);
-	setVertex (2, v3);
-}
-
-// =============================================================================
-//
-LDQuadrilateral::LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v1);
-	setVertex (1, v2);
-	setVertex (2, v3);
-	setVertex (3, v4);
-}
-
-// =============================================================================
-//
-LDBezierCurve::LDBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v0);
-	setVertex (1, v1);
-	setVertex (2, v2);
-	setVertex (3, v3);
-}
-
-// =============================================================================
-//
-void LDObject::setDocument (Model* model)
-{
-	_model = model;
-}
-
-// =============================================================================
-//
-static void TransformObject (LDObject* obj, Matrix transform, Vertex pos, LDColor parentcolor)
-{
-	switch (obj->type())
-	{
-	case LDObjectType::EdgeLine:
-	case LDObjectType::ConditionalEdge:
-	case LDObjectType::Triangle:
-	case LDObjectType::Quadrilateral:
-		for (int i = 0; i < obj->numVertices(); ++i)
-		{
-			Vertex v = obj->vertex (i);
-			v.transform (transform, pos);
-			obj->setVertex (i, v);
-		}
-		break;
-
-	case LDObjectType::SubfileReference:
-		{
-			LDSubfileReference* ref = static_cast<LDSubfileReference*> (obj);
-			Matrix newMatrix = transform * ref->transformationMatrix();
-			Vertex newpos = ref->position();
-			newpos.transform (transform, pos);
-			ref->setPosition (newpos);
-			ref->setTransformationMatrix (newMatrix);
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	if (obj->color() == MainColor)
-		obj->setColor (parentcolor);
-}
-
-// =============================================================================
-// -----------------------------------------------------------------------------
-void LDSubfileReference::inlineContents(Model& model, bool deep, bool render)
-{
-	Model inlined {this->model()->documentManager()};
-	fileInfo()->inlineContents(inlined, deep, render);
-
-	// Transform the objects
-	for (LDObject* object : inlined)
-		TransformObject(object, transformationMatrix(), position(), color());
-
-	model.merge(inlined);
-}
-
-// =============================================================================
-//
-LDPolygon* LDObject::getPolygon()
-{
-	LDObjectType ot = type();
-	int num = (ot == LDObjectType::EdgeLine)		? 2
-			: (ot == LDObjectType::Triangle)	? 3
-			: (ot == LDObjectType::Quadrilateral)		? 4
-			: (ot == LDObjectType::ConditionalEdge)	? 5
-			: 0;
-
-	if (num == 0)
-		return nullptr;
-
-	LDPolygon* data = new LDPolygon;
-	data->id = id();
-	data->num = num;
-	data->color = color().index();
-
-	for (int i = 0; i < data->numVertices(); ++i)
-		data->vertices[i] = vertex (i);
-
-	return data;
-}
-
-LDColor LDObject::defaultColor() const
-{
-	return MainColor;
-}
-
-bool LDObject::isColored() const
-{
-	return true;
-}
-
-bool LDObject::isScemantic() const
-{
-	return true;
-}
-
-bool LDObject::hasMatrix() const
-{
-	return false;
-}
-
-// =============================================================================
-//
-QList<LDPolygon> LDSubfileReference::inlinePolygons()
-{
-	QList<LDPolygon> data = fileInfo()->inlinePolygons();
-
-	for (LDPolygon& entry : data)
-	{
-		for (int i = 0; i < entry.numVertices(); ++i)
-			entry.vertices[i].transform (transformationMatrix(), position());
-	}
-
-	return data;
-}
-
-// =============================================================================
-//
-// Index (i.e. line number) of this object
-//
-int LDObject::lineNumber() const
-{
-	if (model())
-	{
-		for (int i = 0; i < model()->size(); ++i)
-		{
-			if (model()->getObject(i) == this)
-				return i;
-		}
-	}
-
-	return -1;
-}
-
-// =============================================================================
-//
-// Object after this in the current file
-//
-LDObject* LDObject::next() const
-{
-	return model()->getObject(lineNumber() + 1);
-}
-
-// =============================================================================
-//
-// Object prior to this in the current file
-//
-LDObject* LDObject::previous() const
-{
-	return model()->getObject(lineNumber() - 1);
-}
-
-// =============================================================================
-//
-// Is the previous object INVERTNEXT?
-//
-bool LDObject::previousIsInvertnext (LDBfc*& ptr)
-{
-	LDObject* prev = previous();
-
-	if (prev and prev->type() == LDObjectType::Bfc and static_cast<LDBfc*> (prev)->statement() == BfcStatement::InvertNext)
-	{
-		ptr = static_cast<LDBfc*> (prev);
-		return true;
-	}
-
-	return false;
-}
-
-// =============================================================================
-//
-// Moves this object using the given vertex as a movement List
-//
-void LDObject::move (Vertex vect)
-{
-	if (hasMatrix())
-	{
-		LDMatrixObject* mo = static_cast<LDMatrixObject*> (this);
-		mo->setPosition (mo->position() + vect);
-	}
-	else
-	{
-		for (int i = 0; i < numVertices(); ++i)
-			setVertex (i, vertex (i) + vect);
-	}
-}
-
-bool LDObject::isHidden() const
-{
-	return m_isHidden;
-}
-
-void LDObject::setHidden (bool value)
-{
-	m_isHidden = value;
-}
-
-bool LDObject::isSelected() const
-{
-	return m_isSelected;
-}
-
-qint32 LDObject::id() const
-{
-	return m_id;
-}
-
-LDColor LDObject::color() const
-{
-	return m_color;
-}
-
-QColor LDObject::randomColor() const
-{
-	return m_randomColor;
-}
-
-Model* LDObject::model() const
-{
-	return _model;
-}
-
-// =============================================================================
-//
-void LDObject::invert() {}
-void LDBfc::invert() {}
-void LDError::invert() {}
-
-// =============================================================================
-//
-void LDTriangle::invert()
-{
-	// Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1.
-	// Thus, we swap 1 and 2.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (2));
-	setVertex (2, tmp);
-
-	return;
-}
-
-// =============================================================================
-//
-void LDQuadrilateral::invert()
-{
-	// Quad:     0 -> 1 -> 2 -> 3
-	// reversed: 0 -> 3 -> 2 -> 1
-	// Thus, we swap 1 and 3.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (3));
-	setVertex (3, tmp);
-}
-
-// =============================================================================
-//
-void LDSubfileReference::invert()
-{
-	if (model() == nullptr)
-		return;
-
-	// Check whether subfile is flat
-	int axisSet = (1 << X) | (1 << Y) | (1 << Z);
-	Model model {this->model()->documentManager()};
-	fileInfo()->inlineContents(model, true, false);
-
-	for (LDObject* obj : model.objects())
-	{
-		for (int i = 0; i < obj->numVertices(); ++i)
-		{
-			Vertex const& vrt = obj->vertex (i);
-
-			if (axisSet & (1 << X) and vrt.x() != 0.0)
-				axisSet &= ~(1 << X);
-
-			if (axisSet & (1 << Y) and vrt.y() != 0.0)
-				axisSet &= ~(1 << Y);
-
-			if (axisSet & (1 << Z) and vrt.z() != 0.0)
-				axisSet &= ~(1 << Z);
-		}
-
-		if (axisSet == 0)
-			break;
-	}
-
-	if (axisSet != 0)
-	{
-		// Subfile has all vertices zero on one specific plane, so it is flat.
-		// Let's flip it.
-		Matrix matrixModifier = Matrix::identity;
-
-		if (axisSet & (1 << X))
-			matrixModifier(0, 0) = -1;
-
-		if (axisSet & (1 << Y))
-			matrixModifier(1, 1) = -1;
-
-		if (axisSet & (1 << Z))
-			matrixModifier(2, 2) = -1;
-
-		setTransformationMatrix (transformationMatrix() * matrixModifier);
-		return;
-	}
-
-	// Subfile is not flat. Resort to invertnext.
-	int idx = lineNumber();
-
-	if (idx > 0)
-	{
-		LDBfc* bfc = dynamic_cast<LDBfc*> (previous());
-
-		if (bfc and bfc->statement() == BfcStatement::InvertNext)
-		{
-			// This is prefixed with an invertnext, thus remove it.
-			this->model()->remove(bfc);
-			return;
-		}
-	}
-
-	// Not inverted, thus prefix it with a new invertnext.
-	this->model()->emplaceAt<LDBfc>(idx, BfcStatement::InvertNext);
-}
-
-// =============================================================================
-//
-void LDBezierCurve::invert()
-{
-	// A Bézier curve's control points probably need to be, though.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (0));
-	setVertex (0, tmp);
-	tmp = vertex (3);
-	setVertex (3, vertex (2));
-	setVertex (2, tmp);
-}
-
-// =============================================================================
-//
-LDObject* LDObject::fromID(qint32 id)
-{
-	return g_allObjects.value(id);
-}
-
-// =============================================================================
-//
-void LDObject::setColor (LDColor color)
-{
-	changeProperty(&m_color, color);
-}
-
-// =============================================================================
-//
-// Get a vertex by index
-//
-const Vertex& LDObject::vertex (int i) const
-{
-	return m_coords[i];
-}
-
-// =============================================================================
-//
-// Set a vertex to the given value
-//
-void LDObject::setVertex (int i, const Vertex& vert)
-{
-	changeProperty(&m_coords[i], vert);
-}
-
-LDMatrixObject::LDMatrixObject (Model* model) :
-    LDObject (model),
-	m_position (Origin) {}
-
-LDMatrixObject::LDMatrixObject (const Matrix& transform, const Vertex& pos, Model* model) :
-    LDObject (model),
-	m_position (pos),
-	m_transformationMatrix (transform) {}
-
-void LDMatrixObject::setCoordinate (const Axis ax, double value)
-{
-	Vertex v = position();
-
-	switch (ax)
-	{
-		case X: v.setX (value); break;
-		case Y: v.setY (value); break;
-		case Z: v.setZ (value); break;
-	}
-
-	setPosition (v);
-}
-
-const Vertex& LDMatrixObject::position() const
-{
-	return m_position;
-}
-
-// =============================================================================
-//
-void LDMatrixObject::setPosition (const Vertex& a)
-{
-	changeProperty(&m_position, a);
-}
-
-// =============================================================================
-//
-const Matrix& LDMatrixObject::transformationMatrix() const
-{
-	return m_transformationMatrix;
-}
-
-void LDMatrixObject::setTransformationMatrix (const Matrix& val)
-{
-	changeProperty(&m_transformationMatrix, val);
-}
-
-LDError::LDError (QString contents, QString reason, Model* model) :
-    LDObject (model),
-	m_contents (contents),
-	m_reason (reason) {}
-
-QString LDError::reason() const
-{
-	return m_reason;
-}
-
-QString LDError::contents() const
-{
-	return m_contents;
-}
-
-QString LDError::fileReferenced() const
-{
-	return m_fileReferenced;
-}
-
-void LDError::setFileReferenced (QString value)
-{
-	m_fileReferenced = value;
-}
-
-LDBfc::LDBfc (const BfcStatement type, Model* model) :
-    LDObject {model},
-    m_statement {type} {}
-
-BfcStatement LDBfc::statement() const
-{
-	return m_statement;
-}
-
-void LDBfc::setStatement (BfcStatement value)
-{
-	m_statement = value;
-}
-
-QString LDBfc::statementToString() const
-{
-	return LDBfc::statementToString (statement());
-}
-
-QString LDBfc::statementToString (BfcStatement statement)
-{
-	static const char* statementStrings[] =
-	{
-		"CERTIFY CCW",
-		"CCW",
-		"CERTIFY CW",
-		"CW",
-		"NOCERTIFY",
-		"INVERTNEXT",
-		"CLIP",
-		"CLIP CCW",
-		"CLIP CW",
-		"NOCLIP",
-	};
-
-	if ((int) statement >= 0 and (int) statement < countof (statementStrings))
-		return QString::fromLatin1 (statementStrings[(int) statement]);
-	else
-		return "";
-}
-
-Vertex LDBezierCurve::pointAt (qreal t) const
-{
-	if (t >= 0.0 and t <= 1.0)
-	{
-		Vertex result;
-		result += pow (1.0 - t, 3) * vertex (0);
-		result += (3 * pow (1.0 - t, 2) * t) * vertex (2);
-		result += (3 * (1.0 - t) * pow (t, 2)) * vertex (3);
-		result += pow (t, 3) * vertex (1);
-		return result;
-	}
-	else
-		return Vertex();
-}
-
-void LDBezierCurve::rasterize(Model& model, int segments)
-{
-	QVector<LDPolygon> polygons = rasterizePolygons(segments);
-
-	for (LDPolygon& poly : polygons)
-	{
-		LDEdgeLine* line = model.emplace<LDEdgeLine>(poly.vertices[0], poly.vertices[1]);
-		line->setColor (poly.color);
-	}
-}
-
-QVector<LDPolygon> LDBezierCurve::rasterizePolygons(int segments)
-{
-	QVector<LDPolygon> result;
-	QVector<Vertex> parms;
-	parms.append (pointAt (0.0));
-
-	for (int i = 1; i < segments; ++i)
-		parms.append (pointAt (double (i) / segments));
-
-	parms.append (pointAt (1.0));
-	LDPolygon poly;
-	poly.color = color().index();
-	poly.id = id();
-	poly.num = 2;
-
-	for (int i = 0; i < segments; ++i)
-	{
-		poly.vertices[0] = parms[i];
-		poly.vertices[1] = parms[i + 1];
-		result << poly;
-	}
-
-	return result;
-}
-
-LDSubfileReference::LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix,
-                                       const Vertex& position, Model* model) :
-    LDMatrixObject {transformationMatrix, position, model},
-    m_fileInfo {reference} {}
-
-// =============================================================================
-//
-LDDocument* LDSubfileReference::fileInfo() const
-{
-	return m_fileInfo;
-}
-
-void LDSubfileReference::setFileInfo (LDDocument* newReferee)
-{
-	changeProperty(&m_fileInfo, newReferee);
-
-	if (model())
-		model()->recountTriangles();
-
-	// If it's an immediate subfile reference (i.e. this subfile is in an opened document), we need to pre-compile the
-	// GL polygons for the document if they don't exist already.
-	if (newReferee and
-		newReferee->isFrozen() == false and
-		newReferee->polygonData().isEmpty())
-	{
-		newReferee->initializeCachedData();
-	}
-}
-
-void LDObject::getVertices (QSet<Vertex>& verts) const
-{
-	for (int i = 0; i < numVertices(); ++i)
-		verts.insert(vertex(i));
-}
-
-void LDSubfileReference::getVertices (QSet<Vertex>& verts) const
-{
-	verts.unite(fileInfo()->inlineVertices());
-}
-
-QString LDObject::objectListText() const
-{
-	if (numVertices() > 0)
-	{
-		QString result;
-
-		for (int i = 0; i < numVertices(); ++i)
-		{
-			if (i != 0)
-				result += ", ";
-
-			result += vertex(i).toString (true);
-		}
-
-		return result;
-	}
-	else
-	{
-		return typeName();
-	}
-}
-
-QString LDError::objectListText() const
-{
-	return "ERROR: " + asText();
-}
-
-QString LDSubfileReference::objectListText() const
-{
-	QString result = format ("%1 %2, (", fileInfo()->getDisplayName(), position().toString(true));
-
-	for (int i = 0; i < 9; ++i)
-		result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : "");
-
-	result += ')';
-	return result;
-}
-
-QString LDBfc::objectListText() const
-{
-	return statementToString();
-}

mercurial