Sun, 10 Jun 2018 16:50:14 +0300
changed LDCylinder to LDCircularPrimitive and moved circles to it
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/linetypes/circularprimitive.cpp | file | annotate | diff | comparison | revisions | |
src/linetypes/circularprimitive.h | file | annotate | diff | comparison | revisions | |
src/linetypes/cylinder.cpp | file | annotate | diff | comparison | revisions | |
src/linetypes/cylinder.h | file | annotate | diff | comparison | revisions | |
src/linetypes/modelobject.cpp | file | annotate | diff | comparison | revisions | |
src/linetypes/modelobject.h | file | annotate | diff | comparison | revisions | |
src/parser.cpp | file | annotate | diff | comparison | revisions | |
src/primitives.cpp | file | annotate | diff | comparison | revisions | |
src/primitives.h | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Sun Jun 10 16:04:38 2018 +0300 +++ b/CMakeLists.txt Sun Jun 10 16:50:14 2018 +0300 @@ -79,9 +79,9 @@ src/editmodes/selectMode.cpp src/geometry/linesegment.cpp src/geometry/plane.cpp + src/linetypes/circularprimitive.cpp src/linetypes/comment.cpp src/linetypes/conditionaledge.cpp - src/linetypes/cylinder.cpp src/linetypes/edgeline.cpp src/linetypes/empty.cpp src/linetypes/modelobject.cpp @@ -161,9 +161,9 @@ src/generics/transform.h src/geometry/linesegment.h src/geometry/plane.h + src/linetypes/circularprimitive.h src/linetypes/comment.h src/linetypes/conditionaledge.h - src/linetypes/cylinder.h src/linetypes/edgeline.h src/linetypes/empty.h src/linetypes/modelobject.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/linetypes/circularprimitive.cpp Sun Jun 10 16:50:14 2018 +0300 @@ -0,0 +1,187 @@ +#include "../algorithms/geometry.h" +#include "../glShared.h" +#include "../model.h" +#include "../algorithms/invert.h" +#include "circularprimitive.h" +#include "quadrilateral.h" +#include "primitives.h" + +QString LDCircularPrimitive::buildFilename() const +{ + int numerator = this->m_segments; + int denominator = this->m_divisions; + QString prefix; + + if (m_divisions != MediumResolution) + prefix = QString::number(m_divisions) + '\\'; + + simplify(numerator, denominator); + + switch (m_type) + { + case PrimitiveModel::Cylinder: + return format("%1%2-%3cyli.dat", prefix, numerator, denominator); + + case PrimitiveModel::Circle: + return format("%1%2-%3edge.dat", prefix, numerator, denominator); + + default: + Q_ASSERT(false); + return ""; + } +} + +LDCircularPrimitive::LDCircularPrimitive( + PrimitiveModel::Type type, + int segments, + int divisions, + const Matrix& transformationMatrix, + const Vertex& position +) : + LDMatrixObject {transformationMatrix, position}, + m_type {type}, + m_segments {segments}, + m_divisions {divisions} {} + +LDObjectType LDCircularPrimitive::type() const +{ + return SubclassType; +} + +QString LDCircularPrimitive::asText() const +{ + return LDSubfileReference(buildFilename(), transformationMatrix(), position()).asText(); +} + +void LDCircularPrimitive::getVertices(DocumentManager* /* context */, QSet<Vertex>& vertices) const +{ + int endSegment = (m_segments == m_divisions) ? m_segments : m_segments + 1; + + for (int i = 0; i < endSegment; i += 1) + { + QPointF point2d = pointOnLDrawCircumference(i, m_divisions); + + for (double y_value : {0.0, 1.0}) + { + Vertex vertex {point2d.x(), y_value, point2d.y()}; + vertex.transform(transformationMatrix(), position()); + vertices.insert(vertex); + } + } +} + +bool LDCircularPrimitive::isRasterizable() const { return true; } + +void LDCircularPrimitive::rasterize( + DocumentManager* context, + Winding /* parentWinding */, + Model& model, + bool /* deep */, + bool /* render */ +) { + Model cylinderBody {context}; + buildPrimitiveBody(cylinderBody); + + for (LDObject* object : cylinderBody.objects()) + { + for (int i = 0; i < object->numVertices(); i += 1) + { + Vertex vertex = object->vertex(i); + vertex.transform(transformationMatrix(), position()); + object->setVertex(i, vertex); + } + } + + model.merge(cylinderBody); +} + +QVector<LDPolygon> LDCircularPrimitive::rasterizePolygons(DocumentManager* context, Winding winding) +{ + Model cylinderBody {context}; + buildPrimitiveBody(cylinderBody); + QVector<LDPolygon> result; + bool cachedShouldInvert = shouldInvert(winding, context); + + for (LDObject* object : cylinderBody.objects()) + { + for (int i = 0; i < object->numVertices(); i += 1) + { + Vertex vertex = object->vertex(i); + vertex.transform(transformationMatrix(), position()); + object->setVertex(i, vertex); + } + + LDPolygon* polygon = object->getPolygon(); + + if (polygon) + { + if (cachedShouldInvert) + invertPolygon(*polygon); + + result.append(*polygon); + } + + delete polygon; + } + + return result; +} + +void LDCircularPrimitive::buildPrimitiveBody(Model& model) const +{ + PrimitiveModel primitive; + primitive.type = m_type; + primitive.segments = m_segments; + primitive.divisions = m_divisions; + primitive.ringNumber = 0; + primitive.generateBody(model); +} + +QString LDCircularPrimitive::objectListText() const +{ + QString result = format( + "%1 %2 %3, (", + PrimitiveModel::typeName(m_type), + m_segments / m_divisions, + position().toString(true) + ); + + for (int i = 0; i < 9; ++i) + result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : ""); + + result += ')'; + return result; +} + +int LDCircularPrimitive::triangleCount(DocumentManager*) const +{ + switch (m_type) + { + case PrimitiveModel::Ring: + case PrimitiveModel::Cone: + throw std::logic_error("Bad primitive type to LDCircularPrimitive"); + + case PrimitiveModel::Cylinder: + return 2 * m_segments; + + case PrimitiveModel::Disc: + case PrimitiveModel::DiscNegative: + return m_segments; + + case PrimitiveModel::Circle: + return 0; + } + + return 0; +} + +QString LDCircularPrimitive::typeName() const +{ + return "circular-primitive"; +} + +void LDCircularPrimitive::serialize(class Serializer& serializer) +{ + LDMatrixObject::serialize(serializer); + serializer << m_segments << m_divisions; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/linetypes/circularprimitive.h Sun Jun 10 16:50:14 2018 +0300 @@ -0,0 +1,43 @@ +#pragma once +#include "../primitives.h" +#include "modelobject.h" + +class LDCircularPrimitive : public LDMatrixObject +{ +public: + static const LDObjectType SubclassType = LDObjectType::CircularPrimitive; + + LDCircularPrimitive() = default; + LDCircularPrimitive( + PrimitiveModel::Type type, + int segments, + int divisions, + const Matrix& transformationMatrix, + const Vertex& position + ); + + LDObjectType type() const override; + QString asText() const override; + void getVertices(DocumentManager *context, QSet<Vertex>& verts) const override; + bool isRasterizable() const override; + void rasterize( + DocumentManager* context, + Winding parentWinding, + Model& model, + bool deep, + bool render + ) override; + QVector<LDPolygon> rasterizePolygons(DocumentManager* context, Winding parentWinding) override; + QString objectListText() const override; + int triangleCount(DocumentManager*) const override; + QString typeName() const override; + void serialize(class Serializer& serializer) override; + +private: + QString buildFilename() const; + void buildPrimitiveBody(Model& model) const; + + PrimitiveModel::Type m_type = PrimitiveModel::Circle; + int m_segments = MediumResolution; + int m_divisions = MediumResolution; +};
--- a/src/linetypes/cylinder.cpp Sun Jun 10 16:04:38 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -#include "../algorithms/geometry.h" -#include "../glShared.h" -#include "../model.h" -#include "../algorithms/invert.h" -#include "cylinder.h" -#include "quadrilateral.h" -#include "primitives.h" - -QString LDCylinder::buildFilename() const -{ - int numerator = this->m_segments; - int denominator = this->m_divisions; - QString prefix; - - if (m_divisions != MediumResolution) - prefix = QString::number(m_divisions) + '\\'; - - simplify(numerator, denominator); - return format("%1%2-%3cyli.dat", prefix, numerator, denominator); -} - -LDCylinder::LDCylinder( - int segments, - int divisions, - const Matrix& transformationMatrix, - const Vertex& position -) : - LDMatrixObject {transformationMatrix, position}, - m_segments {segments}, - m_divisions {divisions} {} - -QString LDCylinder::asText() const -{ - return LDSubfileReference(buildFilename(), transformationMatrix(), position()).asText(); -} - -void LDCylinder::getVertices(DocumentManager* /* context */, QSet<Vertex>& vertices) const -{ - int endSegment = (m_segments == m_divisions) ? m_segments : m_segments + 1; - - for (int i = 0; i < endSegment; i += 1) - { - QPointF point2d = pointOnLDrawCircumference(i, m_divisions); - - for (double y_value : {0.0, 1.0}) - { - Vertex vertex {point2d.x(), y_value, point2d.y()}; - vertex.transform(transformationMatrix(), position()); - vertices.insert(vertex); - } - } -} - -void LDCylinder::rasterize( - DocumentManager* context, - Winding /* parentWinding */, - Model& model, - bool /* deep */, - bool /* render */ -) { - Model cylinderBody {context}; - buildPrimitiveBody(cylinderBody); - - for (LDObject* object : cylinderBody.objects()) - { - for (int i = 0; i < object->numVertices(); i += 1) - { - Vertex vertex = object->vertex(i); - vertex.transform(transformationMatrix(), position()); - object->setVertex(i, vertex); - } - } - - model.merge(cylinderBody); -} - -QVector<LDPolygon> LDCylinder::rasterizePolygons(DocumentManager* context, Winding winding) -{ - Model cylinderBody {context}; - buildPrimitiveBody(cylinderBody); - QVector<LDPolygon> result; - bool cachedShouldInvert = shouldInvert(winding, context); - - for (LDObject* object : cylinderBody.objects()) - { - for (int i = 0; i < object->numVertices(); i += 1) - { - Vertex vertex = object->vertex(i); - vertex.transform(transformationMatrix(), position()); - object->setVertex(i, vertex); - } - - LDPolygon* polygon = object->getPolygon(); - - if (polygon) - { - if (cachedShouldInvert) - invertPolygon(*polygon); - - result.append(*polygon); - } - - delete polygon; - } - - return result; -} - -void LDCylinder::buildPrimitiveBody(Model& model) const -{ - PrimitiveModel primitive; - primitive.type = PrimitiveModel::Cylinder; - primitive.segments = m_segments; - primitive.divisions = m_divisions; - primitive.ringNumber = 0; - primitive.generateCylinder(model); -} - -QString LDCylinder::objectListText() const -{ - QString result = format("Cylinder %1 %2, (", m_segments / m_divisions, position().toString(true)); - - for (int i = 0; i < 9; ++i) - result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : ""); - - result += ')'; - return result; -} - -void LDCylinder::serialize(class Serializer& serializer) -{ - LDMatrixObject::serialize(serializer); - serializer << m_segments << m_divisions; -}
--- a/src/linetypes/cylinder.h Sun Jun 10 16:04:38 2018 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -#pragma once -#include "modelobject.h" - -class LDCylinder : public LDMatrixObject -{ -public: - static const LDObjectType SubclassType = LDObjectType::Cylinder; - - LDCylinder() = default; - LDCylinder(int segments, int divisions, const Matrix& transformationMatrix, const Vertex& position); - - virtual LDObjectType type() const override - { - return SubclassType; - } - - virtual QString asText() const override; - virtual void getVertices(DocumentManager *context, QSet<Vertex>& verts) const override; - bool isRasterizable() const override { return true; } - void rasterize( - DocumentManager* context, - Winding parentWinding, - Model& model, - bool deep, - bool render - ) override; - QVector<LDPolygon> rasterizePolygons(DocumentManager* context, Winding parentWinding) override; - QString objectListText() const override; - int triangleCount(DocumentManager*) const override { return 2 * m_segments; } - QString typeName() const override { return "cylinder"; } - void serialize(class Serializer& serializer) override; - -private: - QString buildFilename() const; - void buildPrimitiveBody(Model& model) const; - - int m_segments; - int m_divisions; -};
--- a/src/linetypes/modelobject.cpp Sun Jun 10 16:04:38 2018 +0300 +++ b/src/linetypes/modelobject.cpp Sun Jun 10 16:50:14 2018 +0300 @@ -31,7 +31,7 @@ #include "conditionaledge.h" #include "comment.h" #include "empty.h" -#include "cylinder.h" +#include "circularprimitive.h" // List of all LDObjects QMap<qint32, LDObject*> g_allObjects; @@ -356,8 +356,8 @@ case LDObjectType::BezierCurve: return new LDBezierCurve {}; - case LDObjectType::Cylinder: - return new LDCylinder {}; + case LDObjectType::CircularPrimitive: + return new LDCircularPrimitive {}; case LDObjectType::_End: break;
--- a/src/linetypes/modelobject.h Sun Jun 10 16:04:38 2018 +0300 +++ b/src/linetypes/modelobject.h Sun Jun 10 16:50:14 2018 +0300 @@ -40,7 +40,7 @@ Error, // Object is the result of failed parsing Empty, // Object represents an empty line BezierCurve, // Object represents a Bézier curve - Cylinder, + CircularPrimitive, _End };
--- a/src/parser.cpp Sun Jun 10 16:04:38 2018 +0300 +++ b/src/parser.cpp Sun Jun 10 16:50:14 2018 +0300 @@ -24,7 +24,7 @@ #include "linetypes/empty.h" #include "linetypes/quadrilateral.h" #include "linetypes/triangle.h" -#include "linetypes/cylinder.h" +#include "linetypes/circularprimitive.h" /* * Constructs an LDraw parser @@ -389,20 +389,32 @@ for (int i = 0; i < 9; ++i) transform.value(i) = tokens[i + 5].toDouble(); // 5 - 13 - static const QRegExp cylinderRegexp {R"((?:(\d+)\\)?(\d+)-(\d+)cyli\.dat)"}; + static const QRegExp circularPrimitiveRegexp {R"((?:(\d+)\\)?(\d+)-(\d+)(cyli|edge)\.dat)"}; LDObject* obj; - if (cylinderRegexp.exactMatch(referenceName)) + if (circularPrimitiveRegexp.exactMatch(referenceName)) { int resolution = MediumResolution; - if (not cylinderRegexp.capturedTexts()[1].isEmpty()) - resolution = cylinderRegexp.capturedTexts()[1].toInt(); + if (not circularPrimitiveRegexp.capturedTexts()[1].isEmpty()) + resolution = circularPrimitiveRegexp.capturedTexts()[1].toInt(); + + int numerator = circularPrimitiveRegexp.capturedTexts()[2].toInt(); + int denominator = circularPrimitiveRegexp.capturedTexts()[3].toInt(); + int segments = (numerator * resolution) / denominator; + PrimitiveModel::Type type = PrimitiveModel::Cylinder; - int numerator = cylinderRegexp.capturedTexts()[2].toInt(); - int denominator = cylinderRegexp.capturedTexts()[3].toInt(); - int segments = (numerator * resolution) / denominator; - obj = model.emplaceAt<LDCylinder>(position, segments, resolution, transform, displacement); + if (circularPrimitiveRegexp.capturedTexts()[4] == "edge") + type = PrimitiveModel::Circle; + + obj = model.emplaceAt<LDCircularPrimitive>( + position, + type, + segments, + resolution, + transform, + displacement + ); } else {
--- a/src/primitives.cpp Sun Jun 10 16:04:38 2018 +0300 +++ b/src/primitives.cpp Sun Jun 10 16:50:14 2018 +0300 @@ -325,12 +325,41 @@ } } +/* + * Builds a circle primitive. + */ +void PrimitiveModel::generateCircle(Model& model) const +{ + QVector<QLineF> circle = makeCircle(segments, divisions, 1); + + for (int i = 0; i < segments; ++i) + { + double x0 = circle[i].x1(); + double x1 = circle[i].x2(); + double z0 = circle[i].y1(); + double z1 = circle[i].y2(); + + LDEdgeLine* line = model.emplace<LDEdgeLine>(); + line->setVertex(0, Vertex {x0, 0.0f, z0}); + line->setVertex(1, Vertex {x1, 0.0f, z1}); + line->setColor(EdgeColor); + } +} + void PrimitiveModel::generateBody(Model& model) const { - if (this->type == Cylinder) + switch (type) { - this->generateCylinder(model); + case Cylinder: + generateCylinder(model); return; + + case Circle: + generateCircle(model); + return; + + default: + break; } QVector<int> conditionalLineSegments; @@ -345,15 +374,6 @@ switch (type) { - case Circle: - { - LDEdgeLine* line = model.emplace<LDEdgeLine>(); - line->setVertex(0, Vertex {x0, 0.0f, z0}); - line->setVertex(1, Vertex {x1, 0.0f, z1}); - line->setColor(EdgeColor); - } - break; - case Ring: case Cone: { @@ -421,6 +441,7 @@ } break; + case Circle: case Cylinder: break; }
--- a/src/primitives.h Sun Jun 10 16:04:38 2018 +0300 +++ b/src/primitives.h Sun Jun 10 16:50:14 2018 +0300 @@ -58,6 +58,7 @@ QString typeName() const; void generateBody(Model& model) const; void generateCylinder(Model& model, Winding winding = CounterClockwise) const; + void generateCircle(Model& model) const; static QString typeName(Type type); QString makeFileName(FilenameStyle style) const; };