Thu, 14 Apr 2022 11:08:20 +0300
work on circle tool
--- a/CMakeLists.txt Tue Mar 15 19:48:07 2022 +0200 +++ b/CMakeLists.txt Thu Apr 14 11:08:20 2022 +0300 @@ -54,6 +54,7 @@ src/gl/gridprogram.cpp src/gl/partrenderer.cpp src/gl/vertexprogram.cpp + src/linetypes/circularprimitive.cpp src/linetypes/compoundobject.cpp src/linetypes/conditionaledge.cpp src/linetypes/edge.cpp @@ -77,6 +78,7 @@ src/widgets/matrixeditor.cpp src/widgets/vec3editor.cpp src/tools/basetool.cpp + src/tools/circletool.cpp src/tools/selecttool.cpp src/tools/drawtool.cpp src/tools/pathtool.cpp @@ -113,6 +115,7 @@ src/gl/gridprogram.h src/gl/partrenderer.h src/gl/vertexprogram.h + src/linetypes/circularprimitive.h src/linetypes/compoundobject.h src/linetypes/conditionaledge.h src/linetypes/edge.h @@ -139,6 +142,7 @@ src/widgets/vec3editor.h src/tools/selecttool.h src/tools/basetool.h + src/tools/circletool.h src/tools/drawtool.h src/tools/pathtool.h src/tools/transformtool.h
--- a/ldforge.qrc Tue Mar 15 19:48:07 2022 +0200 +++ b/ldforge.qrc Thu Apr 14 11:08:20 2022 +0300 @@ -31,5 +31,6 @@ <file>icons/axes.png</file> <file>icons/invert.png</file> <file>icons/polyline.png</file> + <file>icons/linetype-circularprimitive.png</file> </qresource> </RCC>
--- a/src/ldrawalgorithm.h Tue Mar 15 19:48:07 2022 +0200 +++ b/src/ldrawalgorithm.h Thu Apr 14 11:08:20 2022 +0300 @@ -19,4 +19,18 @@ void invert(ModelEditor& editor, ldraw::id_t id, GetPolygonsContext *context); void makeUnofficial(ModelEditor &editor); + + template<typename Fn> + void circle(int segments, int divisions, Fn&& fn) + { + float factor = 2.0f * math::pi / divisions; + for (int i = 0; i < segments; i += 1) + { + fn( + glm::vec2{std::sin((i - 1) * factor), std::cos((i - 1) * factor)}, + glm::vec2{std::sin(i * factor), std::cos(i * factor)}, + glm::vec2{std::sin((i + 1) * factor), std::cos((i - 1) * factor)} + ); + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/linetypes/circularprimitive.cpp Thu Apr 14 11:08:20 2022 +0300 @@ -0,0 +1,108 @@ +#include "circularprimitive.h" + +ldraw::CircularPrimitive::CircularPrimitive(CircularPrimitiveType type, int segments, int divisions) : + type{type}, + segments{segments}, + divisions{divisions} +{ +} + +QVariant ldraw::CircularPrimitive::getProperty(Property property) const +{ + switch (property) + { + case Property::Segments: + return this->segments; + case Property::Divisions: + return this->divisions; + case Property::CircularPrimitiveType: + return this->type; + default: + return BaseClass::getProperty(property); + } +} + +QString ldraw::CircularPrimitive::textRepresentation() const +{ + return circularPrimitiveTypeName(this->type) + " " + QString::number(this->fraction()); +} + +QString ldraw::CircularPrimitive::circularPrimitiveTypeName(CircularPrimitiveType type) +{ + switch (type) + { + case Circle: + return QObject::tr("Circle"); + case Disc: + return QObject::tr("Disc"); + } +} + +ldraw::Object::Type ldraw::CircularPrimitive::typeIdentifier() const +{ + return ldraw::Object::Type::CircularPrimitive; +} + +QDataStream &ldraw::CircularPrimitive::serialize(QDataStream &stream) const +{ + return BaseClass::serialize(stream) << this->type << this->segments << this->divisions; +} + +QDataStream &ldraw::CircularPrimitive::deserialize(QDataStream &stream) +{ + return BaseClass::deserialize(stream) >> this->type >> this->segments >> this->divisions; +} + +QString ldraw::CircularPrimitive::toLDrawCode() const +{ + return utility::format( + "0 !LDFORGE CIRCULAR_PRIMITIVE %1 %2 %3 %4", + static_cast<int>(this->type), + this->segments, + this->divisions, + this->transformToBareString()); +} + +QString ldraw::CircularPrimitive::iconName() const +{ + return ":/icons/linetype-circularprimitive.png"; +} + +QString ldraw::CircularPrimitive::typeName() const +{ + return QObject::tr("circular primitive"); +} + +void ldraw::CircularPrimitive::getPolygons(std::vector<gl::Polygon> &polygons, GetPolygonsContext *) const +{ + for (int i = 0; i < this->segments; i += 1) + { + const float ang_1 = (2 * math::pi * i) / this->divisions; + const float ang_2 = (2 * math::pi * (i + 1)) / this->divisions; + const glm::vec3 p_1 = {std::sin(ang_1), 0, std::cos(ang_1)}; + const glm::vec3 p_2 = {std::sin(ang_2), 0, std::cos(ang_2)}; + switch (this->type) + { + case Circle: + polygons.push_back(gl::edgeLine( + p_1, + p_2, + this->colorIndex, + this->id)); + break; + case Disc: + polygons.push_back(gl::triangle( + {0, 0, 0}, + p_1, + p_2, + this->colorIndex, + this->id)); + break; + } + } +} + +float ldraw::CircularPrimitive::fraction() const +{ + return static_cast<float>(this->segments) / static_cast<float>(this->divisions); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/linetypes/circularprimitive.h Thu Apr 14 11:08:20 2022 +0300 @@ -0,0 +1,31 @@ +#pragma once +#include "compoundobject.h" +#include "propertygenerics.h" + +namespace ldraw +{ + class CircularPrimitive; +} + +class ldraw::CircularPrimitive : public CompoundObject +{ +public: + using BaseClass = CompoundObject; + CircularPrimitive() = default; + CircularPrimitive(CircularPrimitiveType type, int segments, int divisions); + QVariant getProperty(Property property) const override; + QString textRepresentation() const override; + static QString circularPrimitiveTypeName(CircularPrimitiveType type); + Type typeIdentifier() const override; + QDataStream& serialize(QDataStream& stream) const override; + QDataStream& deserialize(QDataStream& stream) override; + QString toLDrawCode() const override; + QString iconName() const override; + QString typeName() const override; + void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext*) const override; + float fraction() const; + CircularPrimitiveType type = Circle; + int segments = 16; + int divisions = 16; +}; +
--- a/src/linetypes/compoundobject.cpp Tue Mar 15 19:48:07 2022 +0200 +++ b/src/linetypes/compoundobject.cpp Thu Apr 14 11:08:20 2022 +0300 @@ -113,3 +113,21 @@ return {}; } } + +QString ldraw::CompoundObject::transformToBareString() const +{ + return utility::format( + "%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12", + this->transformation[3][0], + this->transformation[3][1], + this->transformation[3][2], + this->transformation[0][0], + this->transformation[1][0], + this->transformation[2][0], + this->transformation[0][1], + this->transformation[1][1], + this->transformation[2][1], + this->transformation[0][2], + this->transformation[1][2], + this->transformation[2][2]); +}
--- a/src/linetypes/compoundobject.h Tue Mar 15 19:48:07 2022 +0200 +++ b/src/linetypes/compoundobject.h Thu Apr 14 11:08:20 2022 +0300 @@ -27,6 +27,7 @@ QDataStream& deserialize(QDataStream& stream) override; std::optional<Axis> flatDimension(GetPolygonsContext *context) const; glm::mat4 transformation; + QString transformToBareString() const; bool isInverted = false; protected: void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override;
--- a/src/linetypes/object.h Tue Mar 15 19:48:07 2022 +0200 +++ b/src/linetypes/object.h Thu Apr 14 11:08:20 2022 +0300 @@ -48,6 +48,7 @@ ConditionalEdge, Triangle, Quadrilateral, + CircularPrimitive, }; friend bool handled(SetPropertyResult result) {
--- a/src/linetypes/propertygenerics.h Tue Mar 15 19:48:07 2022 +0200 +++ b/src/linetypes/propertygenerics.h Thu Apr 14 11:08:20 2022 +0300 @@ -7,6 +7,11 @@ namespace ldraw { + enum CircularPrimitiveType + { + Circle, + Disc + }; enum class Property; struct PropertyKeyValue; template<Property property> @@ -16,6 +21,8 @@ }; } +Q_DECLARE_METATYPE(ldraw::CircularPrimitiveType) + /** * Different properties */ @@ -30,7 +37,10 @@ Transformation, // 4x4 transformation matrix of a subfile reference ReferenceName, // Subfile reference name IsInverted, // Whether or not the object has been inverted with BFC INVERTNEXT - ErrorMessage // For error lines, why parsing failed + ErrorMessage, // For error lines, why parsing failed + CircularPrimitiveType, // Type of circular primitive (circle, disc, ...) + Segments, // Amount of circular segments this primitive covers (numerator) + Divisions, // Amount of segments in the circle this primitive fits in (8, 16, 48, ...) }; Q_DECLARE_METATYPE(ldraw::Property) @@ -57,6 +67,9 @@ LDFORGE_DEFINE_PROPERTY_TYPE(ReferenceName, QString) LDFORGE_DEFINE_PROPERTY_TYPE(IsInverted, bool) LDFORGE_DEFINE_PROPERTY_TYPE(ErrorMessage, QString) +LDFORGE_DEFINE_PROPERTY_TYPE(CircularPrimitiveType, ldraw::CircularPrimitiveType) +LDFORGE_DEFINE_PROPERTY_TYPE(Segments, int) +LDFORGE_DEFINE_PROPERTY_TYPE(Divisions, int) #define LDRAW_OBJECT_HANDLE_SET_PROPERTY(PROPERTY, HANDLER) \ {this->handle<ldraw::Property::PROPERTY>(result, pair, \
--- a/src/linetypes/subfilereference.cpp Tue Mar 15 19:48:07 2022 +0200 +++ b/src/linetypes/subfilereference.cpp Thu Apr 14 11:08:20 2022 +0300 @@ -107,20 +107,9 @@ result += "0 BFC INVERTNEXT\r\n"; } result += utility::format( - "1 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14", + "1 %1 %2 %3", this->colorIndex.index, - this->transformation[3][0], - this->transformation[3][1], - this->transformation[3][2], - this->transformation[0][0], - this->transformation[1][0], - this->transformation[2][0], - this->transformation[0][1], - this->transformation[1][1], - this->transformation[2][1], - this->transformation[0][2], - this->transformation[1][2], - this->transformation[2][2], + this->transformToBareString(), this->referenceName); return result; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/circletool.cpp Thu Apr 14 11:08:20 2022 +0300 @@ -0,0 +1,34 @@ +#include "circletool.h" + +CircleTool::CircleTool(Document *document) : + AbstractDrawTool{document} +{ +} + +QString CircleTool::name() const +{ + return tr("Circle"); +} + +QString CircleTool::toolTip() const +{ + return tr("Draw circular primitives like circles or discs"); +} + +void CircleTool::overpaint(Canvas *canvas, QPainter *painter) const +{ + if (this->previewPolygon.size() >= 2) + { + canvas->drawWorldPolyline() + } +} + +QString CircleTool::iconName() const +{ + return ":/icons/linetype-circularprimitive.png"; +} + +void CircleTool::closeShape() +{ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tools/circletool.h Thu Apr 14 11:08:20 2022 +0300 @@ -0,0 +1,14 @@ +#pragma once +#include "drawtool.h" + +class CircleTool : public AbstractDrawTool +{ + Q_OBJECT +public: + Q_INVOKABLE CircleTool(Document* document); + QString name() const override; + QString toolTip() const override; + void overpaint(Canvas *canvas, QPainter *painter) const override; + QString iconName() const override; + void closeShape() override; +};