Wed, 16 Oct 2013 15:32:38 +0300
Finally got the ringfinder working! Working on integrating it to ring drawing...
src/file.cpp | file | annotate | diff | comparison | revisions | |
src/file.h | file | annotate | diff | comparison | revisions | |
src/gldraw.cpp | file | annotate | diff | comparison | revisions | |
src/gui.cpp | file | annotate | diff | comparison | revisions | |
src/ldtypes.cpp | file | annotate | diff | comparison | revisions | |
src/misc.cpp | file | annotate | diff | comparison | revisions | |
src/misc.h | file | annotate | diff | comparison | revisions | |
src/primitives.cpp | file | annotate | diff | comparison | revisions | |
src/primitives.h | file | annotate | diff | comparison | revisions | |
src/types.h | file | annotate | diff | comparison | revisions |
--- a/src/file.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/file.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -619,7 +619,7 @@ // File is open, now save the model to it. Note that LDraw requires files to // have DOS line endings, so we terminate the lines with \r\n. -for (LDObject * obj : objects()) + for (LDObject* obj : objects()) f.write (obj->raw() + "\r\n"); // File is saved, now clean up. @@ -1015,9 +1015,12 @@ // ============================================================================= // ----------------------------------------------------------------------------- str LDFile::getShortName() -{ if (name().length() > 0) +{ if (!name().isEmpty()) return basename (name()); + if (!defaultName().isEmpty()) + return defaultName(); + return tr ("<anonymous>"); }
--- a/src/file.h Sun Oct 06 21:37:05 2013 +0300 +++ b/src/file.h Wed Oct 16 15:32:38 2013 +0300 @@ -47,6 +47,9 @@ // // A file is implicit when they are opened automatically for caching purposes // and are hidden from the user. User-opened files are explicit (not implicit). +// +// The default name is a placeholder, initially suggested name for a file. The +// primitive generator uses this to give initial names to primitives. // ============================================================================= class LDFile : public QObject { Q_OBJECT @@ -54,6 +57,7 @@ READ_PROPERTY (History, history, setHistory) READ_PROPERTY (List<LDObject*>, vertices, setVertices) PROPERTY (str, name, setName) + PROPERTY (str, defaultName, setDefaultName) PROPERTY (bool, implicit, setImplicit) PROPERTY (List<LDObject*>, cache, setCache) PROPERTY (long, savePos, setSavePos)
--- a/src/gldraw.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/gldraw.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -36,6 +36,7 @@ #include "dialogs.h" #include "addObjectDialog.h" #include "messagelog.h" +#include "primitives.h" #include "moc_gldraw.cpp" static const LDFixedCameraInfo g_FixedCameras[6] = @@ -655,6 +656,11 @@ if (points.size() >= 33) points.insert (33, points[17]); + // Draw the circle/ring + paint.setPen (linepen); + paint.setBrush ((m_drawedVerts.size() >= 2) ? polybrush : Qt::NoBrush); + paint.drawPolygon (QPolygon (points)); + { // Draw the current radius in the middle of the circle. QPoint origin = coordconv3_2 (m_drawedVerts[0]); str label = str::number (dist0); @@ -666,11 +672,6 @@ paint.drawText (origin.x() - (metrics.width (label) / 2), origin.y() + metrics.height(), label); } } - - // Draw the circle/ring - paint.setPen (linepen); - paint.setBrush ((m_drawedVerts.size() >= 2) ? polybrush : Qt::NoBrush); - paint.drawPolygon (QPolygon (points)); } } } @@ -894,10 +895,12 @@ // ----------------------------------------------------------------------------- void GLRenderer::addDrawnVertex (vertex pos) { // If we picked an already-existing vertex, stop drawing -for (vertex & vert : m_drawedVerts) - { if (vert == pos) - { endDraw (true); - return; + if (editMode() != CircleMode) + { for (vertex& vert : m_drawedVerts) + { if (vert == pos) + { endDraw (true); + return; + } } } @@ -1326,12 +1329,11 @@ // Clean the selection and create the object List<vertex>& verts = m_drawedVerts; - LDObject* obj = null; + List<LDObject*> objs; switch (editMode()) { case Draw: - - if (m_rectdraw) + { if (m_rectdraw) { LDQuad* quad = new LDQuad; // Copy the vertices from m_rectverts @@ -1341,26 +1343,28 @@ quad->setVertex (i, m_rectverts[i]); quad->setColor (maincolor); - obj = quad; + objs << quad; } else { switch (verts.size()) { case 1: - // 1 vertex - add a vertex object - obj = new LDVertex; - static_cast<LDVertex*> (obj)->pos = verts[0]; + { // 1 vertex - add a vertex object + LDVertex* obj = new LDVertex; + obj->pos = verts[0]; obj->setColor (maincolor); - break; + objs << obj; + } break; case 2: - // 2 verts - make a line - obj = new LDLine (verts[0], verts[1]); + { // 2 verts - make a line + LDLine* obj = new LDLine (verts[0], verts[1]); obj->setColor (edgecolor); - break; + objs << obj; + } break; case 3: case 4: - obj = (verts.size() == 3) ? + { LDObject* obj = (verts.size() == 3) ? static_cast<LDObject*> (new LDTriangle) : static_cast<LDObject*> (new LDQuad); @@ -1369,43 +1373,106 @@ for (int i = 0; i < obj->vertices(); ++i) obj->setVertex (i, verts[i]); - break; + objs << obj; + } break; } } - - break; + } break; case CircleMode: - { const double dist = circleDrawDist (0); + { const int segs = lores, divs = lores; // TODO: make customizable + double dist0 = circleDrawDist (0), + dist1 = circleDrawDist (1); + enum {Circle, Ring, Disc, CustomRing} type = Ring; + int num = 0; + double scale; - matrix transform = g_circleDrawTransforms[camera() % 3]; + if (dist1 < dist0) + std::swap<double> (dist0, dist1); - for (int i = 0; i < 9; ++i) - { if (transform[i] == 2) - transform[i] = dist; - elif (transform[i] == 1 && camera() >= 3) - transform[i] = -1; + if (dist0 == dist1) + { scale = dist0; + type = Circle; + } elif (dist0 == 0 || dist1 == 0) + { scale = (dist0 != 0) ? dist0 : dist1; + type = Disc; + } else + { /* scale = |r1 - r0| + number = r0 / scale */ + scale = abs (dist1 - dist0); + assert (scale != 0); + + if (!isInteger (dist0) || !isInteger (scale) || (((int) dist0) % ((int) scale)) != 0) + type = CustomRing; // Non-integer ring number - make a custom ring + else + num = ((int) dist0) / ((int) scale); } - LDSubfile* ref = new LDSubfile; - ref->setFileInfo (findLoadedFile ("4-4edge.dat")); - ref->setTransform (transform); - ref->setPosition (m_drawedVerts[0]); - ref->setColor (maincolor); - obj = ref; - } - break; + if (type == CustomRing) + { // Last resort: draw the ring with quads + List<QLineF> c0, c1; + + makeCircle (segs, divs, dist0, c0); + makeCircle (segs, divs, dist1, c1); + + for (int i = 0; i < 16; ++i) + { + } + } + else + { matrix transform = g_circleDrawTransforms[camera() % 3]; + LDFile* refFile = null; + + for (int i = 0; i < 9; ++i) + { if (transform[i] == 2) + transform[i] = scale; + elif (transform[i] == 1 && camera() >= 3) + transform[i] = -1; + } + + switch (type) + { case Circle: + { refFile = getFile ("4-4edge.dat"); + } break; + + case Disc: + { refFile = getFile ("4-4disc.dat"); + } break; + + case Ring: + { if ((refFile = getFile (radialFileName (::Ring, lores, lores, num))) == null) + { refFile = generatePrimitive (::Ring, lores, lores, num); + refFile->setImplicit (false); + } + } break; + } + + if (refFile) + { LDSubfile* ref = new LDSubfile; + ref->setFileInfo (refFile); + ref->setTransform (transform); + ref->setPosition (m_drawedVerts[0]); + ref->setColor (maincolor); + objs << ref; + } + } + } break; case Select: - assert (false); + { assert (false); return; + } break; } - if (obj) + if (objs.size() > 0) { g_win->beginAction (null); - file()->addObject (obj); - compileObject (obj); - g_win->fullRefresh(); + + for (LDObject* obj : objs) + { file()->addObject (obj); + compileObject (obj); + } + + g_win->refresh(); g_win->endAction(); }
--- a/src/gui.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/gui.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -696,7 +696,7 @@ if (saveAs || path.isEmpty()) { path = QFileDialog::getSaveFileName (g_win, tr ("Save As"), - LDFile::current()->name(), tr ("LDraw files (*.dat *.ldr)")); + (f->name().isEmpty()) ? f->name() : f->defaultName(), tr ("LDraw files (*.dat *.ldr)")); if (path.isEmpty()) { // User didn't give a file name, abort. @@ -755,13 +755,13 @@ bool confirm (str title, str msg) { return QMessageBox::question (g_win, title, msg, - (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes; + (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes; } // ============================================================================= void critical (str msg) { QMessageBox::critical (g_win, ForgeWindow::tr ("Error"), msg, - (QMessageBox::Close), QMessageBox::Close); + (QMessageBox::Close), QMessageBox::Close); } // =============================================================================
--- a/src/ldtypes.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/ldtypes.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -230,12 +230,11 @@ void LDObject::swap (LDObject* other) { int i = 0; -for (LDObject * obj : file()->objects()) + for (LDObject* obj : file()->objects()) { if (obj == this) file()->setObject (i, other); - elif (obj == other) - file()->setObject (i, this); + file()->setObject (i, this); ++i; }
--- a/src/misc.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/misc.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -25,6 +25,8 @@ #include "dialogs.h" #include "ui_rotpoint.h" +RingFinder g_RingFinder; + // Prime number table. const int g_primes[NUM_PRIMES] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, @@ -181,7 +183,7 @@ // ============================================================================= // ----------------------------------------------------------------------------- -void simplify (short& numer, short& denom) +void simplify (int& numer, int& denom) { bool repeat; do @@ -274,7 +276,7 @@ str join (initlist<StringFormatArg> vals, str delim) { QStringList list; -for (const StringFormatArg & arg : vals) + for (const StringFormatArg& arg : vals) list << arg.value(); return list.join (delim); @@ -301,3 +303,46 @@ delete[] buf; return fval; } + +// ============================================================================= +// This is the main algorithm of the ring finder. It tries to use math to find +// the one ring between r0 and r1. If it fails (the ring number is non-integral), +// it finds an intermediate radius (ceil of the ring number times scale) and +// splits the radius at this point, calling this function again to try find the +// rings between r0 - r and r - r1. +// +// This does not always yield into usable results. If at some point r == r0 or +// r == r1, there is no hope of finding the rings, at least with this algorithm, +// as it would fall into an infinite recursion. +// ----------------------------------------------------------------------------- +bool RingFinder::findRings (double r0, double r1) +{ // Find the scale and number of a ring between r1 and r0. + double scale = r1 - r0; + double num = r0 / scale; + + // If the ring number is integral, we have found a fitting ring to r0 -> r1! + if (isInteger (num)) + { SolutionComponent cmp; + cmp.scale = scale; + cmp.num = (int) ceil (num); + m_solution << cmp; + } + else + { // If not, find an intermediate <r> between the radii + double r = ceil (num) * scale; + + // If r is the same as r0 or r1, we simply cannot find any rings between + // r0 and r1. Stop and return failure. + if (isZero (r0 - r) || isZero (r1 - r)) + return false; + + // Split this ring into r0 -> r and r -> r1. Recurse to possibly find + // the rings for these. If either recurse fails, the entire algorithm + // fails as well. + if (!findRings (r0, r) || !findRings (r, r1)) + return false; + } + + // The algorithm did not fail, thus we succeeded! + return true; +} \ No newline at end of file
--- a/src/misc.h Sun Oct 06 21:37:05 2013 +0300 +++ b/src/misc.h Wed Oct 16 15:32:38 2013 +0300 @@ -40,7 +40,7 @@ double atof (str val); // Simplifies the given fraction. -void simplify (short& numer, short& denom); +void simplify (int& numer, int& denom); str join (initlist<StringFormatArg> vals, str delim = " "); @@ -51,7 +51,7 @@ }; extern_cfg (Int, grid); -static const short g_NumGrids = 3; +static const int g_NumGrids = 3; extern const gridinfo g_GridInfo[3]; inline const gridinfo& currentGrid() @@ -87,6 +87,37 @@ } // ============================================================================= +// RingFinder +// +// Provides an algorithm for finding a solution of rings between radii r0 and r1. +// ============================================================================= +class RingFinder +{ public: + struct SolutionComponent + { int num; + double scale; + }; + + typedef List<SolutionComponent> SolutionType; + + RingFinder() {} + bool findRings (double r0, double r1); + + inline const SolutionType& solution() + { return m_solution; + } + + inline bool operator() (double r0, double r1) + { return findRings (r0, r1); + } + +private: + SolutionType m_solution; +}; + +extern RingFinder g_RingFinder; + +// ============================================================================= template<class T> void dataswap (T& a, T& b) { T c = a; a = b; @@ -120,4 +151,12 @@ { return (a >= 0) ? a : -a; } +template<class T> inline bool isZero (T a) +{ return abs<T> (a) < 0.0001; +} + +template<class T> inline bool isInteger (T a) +{ return isZero (a - (int) a); +} + #endif // MISC_H
--- a/src/primitives.cpp Sun Oct 06 21:37:05 2013 +0300 +++ b/src/primitives.cpp Wed Oct 16 15:32:38 2013 +0300 @@ -61,7 +61,7 @@ } else { // Read primitives from prims.cfg - for (str line : conf) + for (str line : conf) { int space = line.indexOf (" "); if (space == -1) @@ -108,7 +108,7 @@ recursiveGetFilenames (dir, fnames); emit starting (fnames.size()); - for (str fname : fnames) +for (str fname : fnames) { File f (fname, File::Read); Primitive info; @@ -133,7 +133,7 @@ // Save to a config file File conf (Config::filepath ("prims.cfg"), File::Write); - for (Primitive & info : m_prims) +for (Primitive & info : m_prims) fprint (conf, "%1 %2\n", info.name, info.title); conf.close(); @@ -166,7 +166,7 @@ // ============================================================================= // ----------------------------------------------------------------------------- static PrimitiveCategory* findCategory (str name) -{ for (PrimitiveCategory& cat : g_PrimitiveCategories) +{ for (PrimitiveCategory & cat : g_PrimitiveCategories) if (cat.name() == name) return &cat; @@ -188,24 +188,24 @@ unmatched = & (g_PrimitiveCategories << cat); } - for (Primitive& prim : g_primitives) +for (Primitive & prim : g_primitives) { bool matched = false; prim.cat = null; // Go over the categories and their regexes, if and when there's a match, // the primitive's category is set to the category the regex beloings to. - for (PrimitiveCategory & cat : g_PrimitiveCategories) - { for (PrimitiveCategory::RegexEntry & entry : cat.regexes) + for (PrimitiveCategory & cat : g_PrimitiveCategories) + { for (PrimitiveCategory::RegexEntry & entry : cat.regexes) { switch (entry.type) { case PrimitiveCategory::Filename: - // f-regex, check against filename - matched = entry.regex.exactMatch (prim.name); - break; + // f-regex, check against filename + matched = entry.regex.exactMatch (prim.name); + break; case PrimitiveCategory::Title: - // t-regex, check against title - matched = entry.regex.exactMatch (prim.title); - break; + // t-regex, check against title + matched = entry.regex.exactMatch (prim.title); + break; } if (matched) @@ -243,7 +243,7 @@ if (f) { PrimitiveCategory cat; - for (str line : f) + for (str line : f) { int colon; if (line.length() == 0 || line[0] == '#') @@ -263,8 +263,9 @@ if (cmd == "f") type = PrimitiveCategory::Filename; + elif (cmd == "t") - type = PrimitiveCategory::Title; + type = PrimitiveCategory::Title; else continue; @@ -293,7 +294,20 @@ // ============================================================================= // ----------------------------------------------------------------------------- static double radialPoint (int i, int divs, double (*func) (double)) -{ return (*func) ((i * 2 * pi) / divs); +{ return (*func) ( (i * 2 * pi) / divs); +} + +// ============================================================================= +// ----------------------------------------------------------------------------- +void makeCircle (int segs, int divs, double radius, List<QLineF>& lines) +{ for (int i = 0; i < segs; ++i) + { double x0 = radius * radialPoint (i, divs, cos), + x1 = radius * radialPoint (i + 1, divs, cos), + z0 = radius * radialPoint (i, divs, sin), + z1 = radius * radialPoint (i + 1, divs, sin); + + lines << QLineF (QPointF (x0, z0), QPointF (x1, z1)); + } } // ============================================================================= @@ -301,12 +315,15 @@ List<LDObject*> makePrimitive (PrimitiveType type, int segs, int divs, int num) { List<LDObject*> objs; List<int> condLineSegs; + List<QLineF> circle; + + makeCircle (segs, divs, 1, circle); for (int i = 0; i < segs; ++i) - { double x0 = radialPoint (i, divs, cos), - x1 = radialPoint (i + 1, divs, cos), - z0 = radialPoint (i, divs, sin), - z1 = radialPoint (i + 1, divs, sin); + { double x0 = circle[i].x1(), + x1 = circle[i].x2(), + z0 = circle[i].y1(), + z1 = circle[i].y2(); switch (type) { case Circle: @@ -318,8 +335,7 @@ line->setVertex (1, v1); line->setColor (edgecolor); objs << line; - } - break; + } break; case Cylinder: case Ring: @@ -374,8 +390,7 @@ if (type == Cylinder || type == Cone) condLineSegs << i; - } - break; + } break; case Disc: case DiscNeg: @@ -400,11 +415,7 @@ seg->setVertex (1, v1); seg->setVertex (type == Disc ? 2 : 0, v2); objs << seg; - } - break; - - default: - break; + } break; } } @@ -413,7 +424,7 @@ if (segs < divs && condLineSegs.size() != 0) condLineSegs << segs; - for (int i : condLineSegs) +for (int i : condLineSegs) { vertex v0 (radialPoint (i, divs, cos), 0.0f, radialPoint (i, divs, sin)), v1, v2 (radialPoint (i + 1, divs, cos), 0.0f, radialPoint (i + 1, divs, sin)), @@ -421,6 +432,7 @@ if (type == Cylinder) v1 = vertex (v0[X], 1.0f, v0[Z]); + elif (type == Cone) { v1 = vertex (v0[X] * (num + 1), 0.0f, v0[Z] * (num + 1)); v0[X] *= num; @@ -454,15 +466,14 @@ // ============================================================================= // ----------------------------------------------------------------------------- str radialFileName (PrimitiveType type, int segs, int divs, int num) -{ short numer = segs, - denom = divs; +{ int numer = segs, + denom = divs; // Simplify the fractional part, but the denominator must be at least 4. simplify (numer, denom); if (denom < 4) - { const short factor = 4 / denom; - + { const int factor = 4 / denom; numer *= factor; denom *= factor; } @@ -476,7 +487,7 @@ // Truncate the root if necessary (7-16rin4.dat for instance). // However, always keep the root at least 2 characters. int extra = (frac.length() + numstr.length() + root.length()) - 8; - root.chop (min<short> (max<short> (extra, 0), 2)); + root.chop (clamp (extra, 0, 2)); // Stick them all together and return the result. return prefix + frac + root + numstr + ".dat"; @@ -486,31 +497,31 @@ // ----------------------------------------------------------------------------- LDFile* generatePrimitive (PrimitiveType type, int segs, int divs, int num) { // Make the description - str frac = ftoa (((float) segs) / divs); + str frac = ftoa ( ( (float) segs) / divs); str name = radialFileName (type, segs, divs, num); str descr; - + // Ensure that there's decimals, even if they're 0. if (frac.indexOf (".") == -1) frac += ".0"; - + if (type == Ring || type == Cone) { str spacing = - (num < 10) ? " " : - (num < 100) ? " " : ""; - + (num < 10) ? " " : + (num < 100) ? " " : ""; + descr = fmt ("%1 %2%3 x %4", primitiveTypeName (type), spacing, num, frac); } else descr = fmt ("%1 %2", primitiveTypeName (type), frac); - + // Prepend "Hi-Res" if 48/ primitive. if (divs == hires) descr.insert (0, "Hi-Res "); - + LDFile* f = new LDFile; - f->setName (QFileDialog::getSaveFileName (null, QObject::tr ("Save Primitive"), name)); - + f->setDefaultName (name); + f->addObjects ( { new LDComment (descr), new LDComment (fmt ("Name: %1", name)), @@ -521,7 +532,7 @@ new LDBFC (LDBFC::CertifyCCW), new LDEmpty, }); - + f->addObjects (makePrimitive (type, segs, divs, num)); return f; } @@ -531,6 +542,7 @@ LDFile* getPrimitive (PrimitiveType type, int segs, int divs, int num) { str name = radialFileName (type, segs, divs, num); LDFile* f = getFile (name); + if (f != null) return f; @@ -540,10 +552,8 @@ // ============================================================================= // ----------------------------------------------------------------------------- PrimitivePrompt::PrimitivePrompt (QWidget* parent, Qt::WindowFlags f) : -QDialog (parent, f) -{ - - ui = new Ui_MakePrimUI; + QDialog (parent, f) +{ ui = new Ui_MakePrimUI; ui->setupUi (this); connect (ui->cb_hires, SIGNAL (toggled (bool)), this, SLOT (hiResToggled (bool))); } @@ -558,7 +568,7 @@ // ----------------------------------------------------------------------------- void PrimitivePrompt::hiResToggled (bool on) { ui->sb_segs->setMaximum (on ? hires : lores); - + // If the current value is 16 and we switch to hi-res, default the // spinbox to 48. if (on && ui->sb_segs->value() == lores) @@ -569,22 +579,22 @@ // ----------------------------------------------------------------------------- DEFINE_ACTION (MakePrimitive, 0) { PrimitivePrompt* dlg = new PrimitivePrompt (g_win); - + if (!dlg->exec()) return; - + int segs = dlg->ui->sb_segs->value(); int divs = dlg->ui->cb_hires->isChecked() ? hires : lores; int num = dlg->ui->sb_ringnum->value(); PrimitiveType type = - dlg->ui->rb_circle->isChecked() ? Circle : - dlg->ui->rb_cylinder->isChecked() ? Cylinder : - dlg->ui->rb_disc->isChecked() ? Disc : - dlg->ui->rb_ndisc->isChecked() ? DiscNeg : - dlg->ui->rb_ring->isChecked() ? Ring : Cone; - + dlg->ui->rb_circle->isChecked() ? Circle : + dlg->ui->rb_cylinder->isChecked() ? Cylinder : + dlg->ui->rb_disc->isChecked() ? Disc : + dlg->ui->rb_ndisc->isChecked() ? DiscNeg : + dlg->ui->rb_ring->isChecked() ? Ring : Cone; + LDFile* f = generatePrimitive (type, segs, divs, num); - + g_win->save (f, false); delete f; -} \ No newline at end of file +}
--- a/src/primitives.h Sun Oct 06 21:37:05 2013 +0300 +++ b/src/primitives.h Wed Oct 16 15:32:38 2013 +0300 @@ -16,8 +16,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PRIMITIVES_H -#define PRIMITIVES_H +#ifndef LDFORGE_PRIMITIVES_H +#define LDFORGE_PRIMITIVES_H #include "common.h" #include "types.h" @@ -104,10 +104,13 @@ void hiResToggled (bool on); }; +void makeCircle (int segs, int divs, double radius, List< QLineF >& lines); LDFile* generatePrimitive (PrimitiveType type, int segs, int divs, int num); // Gets a primitive by the given specs. If the primitive cannot be found, it will // be automatically generated. LDFile* getPrimitive (PrimitiveType type, int segs, int divs, int num); -#endif // PRIMITIVES_H +str radialFileName (PrimitiveType type, int segs, int divs, int num); + +#endif // LDFORGE_PRIMITIVES_H
--- a/src/types.h Sun Oct 06 21:37:05 2013 +0300 +++ b/src/types.h Wed Oct 16 15:32:38 2013 +0300 @@ -165,6 +165,46 @@ }; // ============================================================================= +// ----------------------------------------------------------------------------- +class Line +{ public: + Line() {} + Line (const vertex& v0, const vertex v1) : + m_v0 (v0), + m_v1 (v1) {} + + inline const vertex& getVertex (int i) const + { assert (i == 0 || i == 1); + return (i == 0) ? m_v0 : m_v1; + } + + inline void setVertex (int i, const vertex& a) + { assert (i == 0 || i == 1); + (i == 0) ? m_v0 : m_v1 = a; + } + + inline const vertex& v0() const + { return m_v0; + } + + inline const vertex& v1() const + { return m_v1; + } + + inline void setV0 (const vertex& a) + { m_v0 = a; + } + + inline void setV1 (const vertex& a) + { m_v1 = a; + } + + private: + vertex m_v0, + m_v1; +}; + +// ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= // List