diff -r 9374fea8f77f -r f1b8cb53d2a2 ldtypes.cpp
--- a/ldtypes.cpp Wed May 08 14:57:48 2013 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,675 +0,0 @@
-/*
- * LDForge: LDraw parts authoring CAD
- * Copyright (C) 2013 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 .
- */
-
-#include "common.h"
-#include "ldtypes.h"
-#include "file.h"
-#include "misc.h"
-#include "gui.h"
-
-char const* g_saObjTypeNames[] = {
- "subfile",
- "radial",
- "quadrilateral",
- "triangle",
- "line",
- "condline",
- "vertex",
- "bfc",
- "comment",
- "unknown",
- "empty",
- "unidentified",
-};
-
-// Should probably get rid of this array sometime
-char const* g_saObjTypeIcons[] = {
- "subfile",
- "radial",
- "quad",
- "triangle",
- "line",
- "condline",
- "vertex",
- "bfc",
- "comment",
- "error",
- "empty",
- "error",
-};
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-// LDObject constructors
-LDObject::LDObject () {
- qObjListEntry = null;
- parent = null;
- m_hidden = false;
-}
-
-LDGibberish::LDGibberish (str _zContent, str _zReason) {
- zContents = _zContent;
- zReason = _zReason;
-}
-
-// =============================================================================
-str LDComment::getContents () {
- return fmt ("0 %s", text.chars ());
-}
-
-str LDSubfile::getContents () {
- str val = fmt ("1 %d %s ", dColor, vPosition.stringRep (false).chars ());
- val += mMatrix.stringRep ();
- val += ' ';
- val += zFileName;
- return val;
-}
-
-str LDLine::getContents () {
- str val = fmt ("2 %d", dColor);
-
- for (ushort i = 0; i < 2; ++i)
- val.appendformat (" %s", vaCoords[i].stringRep (false).chars ());
-
- return val;
-}
-
-str LDTriangle::getContents () {
- str val = fmt ("3 %d", dColor);
-
- for (ushort i = 0; i < 3; ++i)
- val.appendformat (" %s", vaCoords[i].stringRep (false).chars ());
-
- return val;
-}
-
-str LDQuad::getContents () {
- str val = fmt ("4 %d", dColor);
-
- for (ushort i = 0; i < 4; ++i)
- val.appendformat (" %s", vaCoords[i].stringRep (false).chars ());
-
- return val;
-}
-
-str LDCondLine::getContents () {
- str val = fmt ("5 %d", dColor);
-
- // Add the coordinates
- for (ushort i = 0; i < 4; ++i)
- val.appendformat (" %s", vaCoords[i].stringRep (false).chars ());
-
- return val;
-}
-
-str LDGibberish::getContents () {
- return zContents;
-}
-
-str LDVertex::getContents () {
- return fmt ("0 !LDFORGE VERTEX %d %s", dColor, vPosition.stringRep (false).chars());
-}
-
-str LDEmpty::getContents () {
- return str ();
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-const char* LDBFC::statements[] = {
- "CERTIFY CCW",
- "CCW",
- "CERTIFY CW",
- "CW",
- "NOCERTIFY",
- "INVERTNEXT",
-};
-
-str LDBFC::getContents () {
- return fmt ("0 BFC %s", LDBFC::statements[type]);
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-vector LDQuad::splitToTriangles () {
- // Create the two triangles based on this quadrilateral:
- // 0---3 0---3 3
- // | | | / /|
- // | | = | / / |
- // | | |/ / |
- // 1---2 1 1---2
- LDTriangle* tri1 = new LDTriangle;
- tri1->vaCoords[0] = vaCoords[0];
- tri1->vaCoords[1] = vaCoords[1];
- tri1->vaCoords[2] = vaCoords[3];
-
- LDTriangle* tri2 = new LDTriangle;
- tri2->vaCoords[0] = vaCoords[1];
- tri2->vaCoords[1] = vaCoords[2];
- tri2->vaCoords[2] = vaCoords[3];
-
- // The triangles also inherit the quad's color
- tri1->dColor = tri2->dColor = dColor;
-
- vector triangles;
- triangles.push_back (tri1);
- triangles.push_back (tri2);
- return triangles;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void LDObject::replace (LDObject* replacement) {
- // Replace all instances of the old object with the new object
- for (LDObject*& obj : g_curfile->m_objs)
- if (obj == this)
- obj = replacement;
-
- // Remove the old object
- delete this;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void LDObject::swap (LDObject* other) {
- for (LDObject*& obj : g_curfile->m_objs) {
- if (obj == this)
- obj = other;
- else if (obj == other)
- obj = this;
- }
-}
-
-LDLine::LDLine (vertex v1, vertex v2) {
- vaCoords[0] = v1;
- vaCoords[1] = v2;
-}
-
-LDObject::~LDObject () {
- // Remove this object from the selection array if it is there.
- for (ulong i = 0; i < g_win->sel ().size(); ++i)
- if (g_win->sel ()[i] == this)
- g_win->sel ().erase (g_win->sel ().begin() + i);
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-static void transformObject (LDObject* obj, matrix<3> transform, vertex pos, short parentcolor) {
- switch (obj->getType()) {
- case LDObject::Line:
- case LDObject::CondLine:
- case LDObject::Triangle:
- case LDObject::Quad:
- for (short i = 0; i < obj->vertices (); ++i)
- obj->vaCoords[i].transform (transform, pos);
- break;
-
- case LDObject::Subfile:
- {
- LDSubfile* ref = static_cast (obj);
-
- matrix<3> newMatrix = transform * ref->mMatrix;
- ref->vPosition.transform (transform, pos);
- ref->mMatrix = newMatrix;
- }
- break;
-
- default:
- break;
- }
-
- if (obj->dColor == maincolor)
- obj->dColor = parentcolor;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-vector LDSubfile::inlineContents (bool bDeepInline, bool bCache) {
- vector objs, cache;
-
- // If we have this cached, just clone that
- if (bDeepInline && pFile->m_objCache.size ()) {
- for (LDObject* obj : pFile->m_objCache)
- objs.push_back (obj->clone ());
- } else {
- if (!bDeepInline)
- bCache = false;
-
- for (LDObject* obj : pFile->m_objs) {
- // Skip those without schemantic meaning
- switch (obj->getType ()) {
- case LDObject::Comment:
- case LDObject::Empty:
- case LDObject::Gibberish:
- case LDObject::Unidentified:
- case LDObject::Vertex:
- continue;
-
- case LDObject::BFC:
- // Filter non-INVERTNEXT statements
- if (static_cast (obj)->type != LDBFC::InvertNext)
- continue;
- break;
-
- default:
- break;
- }
-
- // Got another sub-file reference, inline it if we're deep-inlining. If not,
- // just add it into the objects normally. Also, we only cache immediate
- // subfiles and this is not one. Yay, recursion!
- if (bDeepInline && obj->getType() == LDObject::Subfile) {
- LDSubfile* ref = static_cast (obj);
-
- vector otherobjs = ref->inlineContents (true, false);
-
- for (LDObject* otherobj : otherobjs) {
- // Cache this object, if desired
- if (bCache)
- cache.push_back (otherobj->clone ());
-
- objs.push_back (otherobj);
- }
- } else {
- if (bCache)
- cache.push_back (obj->clone ());
-
- objs.push_back (obj->clone ());
- }
- }
-
- if (bCache)
- pFile->m_objCache = cache;
- }
-
- // Transform the objects
- for (LDObject* obj : objs) {
- // Set the parent now so we know what inlined this.
- obj->parent = this;
-
- transformObject (obj, mMatrix, vPosition, dColor);
- }
-
- return objs;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-long LDObject::getIndex (OpenFile* pFile) {
- for (ulong i = 0; i < pFile->m_objs.size(); ++i)
- if (pFile->m_objs[i] == this)
- return i;
-
- return -1;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void LDObject::moveObjects (std::vector objs, const bool bUp) {
- // If we move down, we need to iterate the array in reverse order.
- const long start = bUp ? 0 : (objs.size() - 1);
- const long end = bUp ? objs.size() : -1;
- const long incr = bUp ? 1 : -1;
-
- for (long i = start; i != end; i += incr) {
- LDObject* obj = objs[i];
-
- const long lIndex = obj->getIndex (g_curfile),
- lTarget = lIndex + (bUp ? -1 : 1);
-
- if ((bUp == true and lIndex == 0) or
- (bUp == false and lIndex == (long)(g_curfile->m_objs.size() - 1)))
- {
- // One of the objects hit the extrema. If this happens, this should be the first
- // object to be iterated on. Thus, nothing has changed yet and it's safe to just
- // abort the entire operation.
- assert (i == start);
- return;
- }
-
- obj->swap (g_curfile->m_objs[lTarget]);
- }
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-str LDObject::objectListContents (const std::vector& objs) {
- bool firstDetails = true;
- str text = "";
-
- if (objs.size() == 0)
- return "nothing"; // :)
-
- for (long i = 0; i < LDObject::NumTypes; ++i) {
- LDObject::Type objType = (LDObject::Type) i;
- ulong objCount = 0;
-
- for (LDObject* obj : objs)
- if (obj->getType() == objType)
- objCount++;
-
- if (objCount == 0)
- continue;
-
- if (!firstDetails)
- text += ", ";
-
- str noun = fmt ("%s%s", g_saObjTypeNames[objType], PLURAL (objCount));
-
- // Plural of "vertex" is "vertices". Stupid English.
- if (objType == LDObject::Vertex && objCount != 1)
- noun = "vertices";
-
- text.appendformat ("%lu %s", objCount, noun.chars ());
- firstDetails = false;
- }
-
- return text;
-}
-
-// =============================================================================
-LDObject* LDObject::topLevelParent () {
- if (!parent)
- return null;
-
- LDObject* it = this;
-
- while (it->parent)
- it = it->parent;
-
- return it;
-}
-
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-void LDObject::move (vertex vVector) { vVector = vVector; /* to shut up GCC */ }
-void LDEmpty::move (vertex vVector) { vVector = vVector; }
-void LDBFC::move (vertex vVector) { vVector = vVector; }
-void LDComment::move (vertex vVector) { vVector = vVector; }
-void LDGibberish::move (vertex vVector) { vVector = vVector; }
-
-void LDVertex::move (vertex vVector) {
- vPosition += vVector;
-}
-
-void LDSubfile::move (vertex vVector) {
- vPosition += vVector;
-}
-
-void LDRadial::move (vertex vVector) {
- vPosition += vVector;
-}
-
-void LDLine::move (vertex vVector) {
- for (short i = 0; i < 2; ++i)
- vaCoords[i] += vVector;
-}
-
-void LDTriangle::move (vertex vVector) {
- for (short i = 0; i < 3; ++i)
- vaCoords[i] += vVector;
-}
-
-void LDQuad::move (vertex vVector) {
- for (short i = 0; i < 4; ++i)
- vaCoords[i] += vVector;
-}
-
-void LDCondLine::move (vertex vVector) {
- for (short i = 0; i < 4; ++i)
- vaCoords[i] += vVector;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-static char const* g_saRadialTypeNames[] = {
- "Circle",
- "Cylinder",
- "Disc",
- "Disc Negative",
- "Ring",
- "Cone",
- null
-};
-
-char const* LDRadial::radialTypeName () {
- return g_saRadialTypeNames[eRadialType];
-}
-
-char const* LDRadial::radialTypeName (const LDRadial::Type eType) {
- return g_saRadialTypeNames[eType];
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-std::vector LDRadial::decompose (bool bTransform) {
- std::vector paObjects;
-
- for (short i = 0; i < dSegments; ++i) {
- double x0 = cos ((i * 2 * pi) / dDivisions),
- x1 = cos (((i + 1) * 2 * pi) / dDivisions),
- z0 = sin ((i * 2 * pi) / dDivisions),
- z1 = sin (((i + 1) * 2 * pi) / dDivisions);
-
- switch (eRadialType) {
- case LDRadial::Circle:
- {
- vertex v0 (x0, 0.0f, z0),
- v1 (x1, 0.0f, z1);
-
- if (bTransform) {
- v0.transform (mMatrix, vPosition);
- v1.transform (mMatrix, vPosition);
- }
-
- LDLine* pLine = new LDLine;
- pLine->vaCoords[0] = v0;
- pLine->vaCoords[1] = v1;
- pLine->dColor = edgecolor;
- pLine->parent = this;
-
- paObjects.push_back (pLine);
- }
- break;
-
- case LDRadial::Cylinder:
- case LDRadial::Ring:
- case LDRadial::Cone:
- {
- double x2, x3, z2, z3;
- double y0, y1, y2, y3;
-
- if (eRadialType == LDRadial::Cylinder) {
- x2 = x1;
- x3 = x0;
- z2 = z1;
- z3 = z0;
-
- y0 = y1 = 0.0f;
- y2 = y3 = 1.0f;
- } else {
- x2 = x1 * (dRingNum + 1);
- x3 = x0 * (dRingNum + 1);
- z2 = z1 * (dRingNum + 1);
- z3 = z0 * (dRingNum + 1);
-
- x0 *= dRingNum;
- x1 *= dRingNum;
- z0 *= dRingNum;
- z1 *= dRingNum;
-
- if (eRadialType == LDRadial::Ring) {
- y0 = y1 = y2 = y3 = 0.0f;
- } else {
- y0 = y1 = 1.0f;
- y2 = y3 = 0.0f;
- }
- }
-
- vertex v0 (x0, y0, z0),
- v1 (x1, y1, z1),
- v2 (x2, y2, z2),
- v3 (x3, y3, z3);
-
- if (bTransform) {
- v0.transform (mMatrix, vPosition);
- v1.transform (mMatrix, vPosition);
- v2.transform (mMatrix, vPosition);
- v3.transform (mMatrix, vPosition);
- }
-
- LDQuad* pQuad = new LDQuad;
- pQuad->vaCoords[0] = v0;
- pQuad->vaCoords[1] = v1;
- pQuad->vaCoords[2] = v2;
- pQuad->vaCoords[3] = v3;
- pQuad->dColor = dColor;
- pQuad->parent = this;
-
- paObjects.push_back (pQuad);
- }
- break;
-
- case LDRadial::Disc:
- case LDRadial::DiscNeg:
- {
- double x2, z2;
-
- if (eRadialType == LDRadial::Disc) {
- x2 = z2 = 0.0f;
- } else {
- x2 = (x0 >= 0.0f) ? 1.0f : -1.0f;
- z2 = (z0 >= 0.0f) ? 1.0f : -1.0f;
- }
-
- vertex v0 (x0, 0.0f, z0),
- v1 (x1, 0.0f, z1),
- v2 (x2, 0.0f, z2);
-
- if (bTransform) {
- v0.transform (mMatrix, vPosition);
- v1.transform (mMatrix, vPosition);
- v2.transform (mMatrix, vPosition);
- }
-
- LDTriangle* pSeg = new LDTriangle;
- pSeg->vaCoords[0] = v0;
- pSeg->vaCoords[1] = v1;
- pSeg->vaCoords[2] = v2;
- pSeg->dColor = dColor;
- pSeg->parent = this;
-
- paObjects.push_back (pSeg);
- }
- break;
-
- default:
- break;
- }
- }
-
- return paObjects;
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-str LDRadial::getContents () {
- return fmt ("0 !LDFORGE RADIAL %s %d %d %d %d %s %s",
- str (radialTypeName()).toupper ().strip (' ').chars (),
- dColor, dSegments, dDivisions, dRingNum,
- vPosition.stringRep (false).chars(), mMatrix.stringRep().chars());
-}
-
-char const* g_saRadialNameRoots[] = {
- "edge",
- "cyli",
- "disc",
- "ndis",
- "ring",
- "cone",
- null
-};
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-str LDRadial::makeFileName () {
- short numer = dSegments,
- denom = dDivisions;
-
- // Simplify the fractional part, but the denominator must be at least 4.
- simplify (numer, denom);
-
- if (denom < 4) {
- const short factor = (4 / denom);
-
- numer *= factor;
- denom *= factor;
- }
-
- // Compose some general information: prefix, fraction, root, ring number
- str prefix = (dDivisions == 16) ? "" : fmt ("%d/", dDivisions);
- str frac = fmt ("%d-%d", numer, denom);
- str root = g_saRadialNameRoots[eRadialType];
- str ringNum = (eRadialType == Ring || eRadialType == Cone) ? fmt ("%d", dRingNum) : "";
-
- // Truncate the root if necessary (7-16rin4.dat for instance).
- // However, always keep the root at least 2 characters.
- short extra = (~frac + ~ringNum + ~root) - 8;
- root -= min (max (extra, 0), 2);
-
- // Stick them all together and return the result.
- return fmt ("%s%s%s%s", prefix.chars(), frac.chars (), root.chars (), ringNum.chars ());
-}
-
-// =============================================================================
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-// =============================================================================
-#define CHECK_FOR_OBJ(N) \
- if (type == LDObject::N) \
- return new LD##N;
-LDObject* LDObject::getDefault (const LDObject::Type type) {
- CHECK_FOR_OBJ (Comment)
- CHECK_FOR_OBJ (BFC)
- CHECK_FOR_OBJ (Line)
- CHECK_FOR_OBJ (CondLine)
- CHECK_FOR_OBJ (Radial)
- CHECK_FOR_OBJ (Subfile)
- CHECK_FOR_OBJ (Triangle)
- CHECK_FOR_OBJ (Quad)
- CHECK_FOR_OBJ (Empty)
- CHECK_FOR_OBJ (BFC)
- CHECK_FOR_OBJ (Gibberish)
- CHECK_FOR_OBJ (Vertex)
- return null;
-}
\ No newline at end of file