diff --git a/plugins/circuits/src/visuals/CircuitElementNode.h b/plugins/circuits/src/visuals/CircuitElementNode.h index a7392f9..2f9fb30 100644 --- a/plugins/circuits/src/visuals/CircuitElementNode.h +++ b/plugins/circuits/src/visuals/CircuitElementNode.h @@ -11,5 +11,5 @@ public: virtual ~CircuitElementNode(); - virtual Point getConnectionLocation(Wire* wire) const = 0; + virtual Point2 getConnectionLocation(Wire* wire) const = 0; }; \ No newline at end of file diff --git a/plugins/circuits/src/visuals/LogicGateNode.cpp b/plugins/circuits/src/visuals/LogicGateNode.cpp index b234484..31bc9fb 100644 --- a/plugins/circuits/src/visuals/LogicGateNode.cpp +++ b/plugins/circuits/src/visuals/LogicGateNode.cpp @@ -18,7 +18,7 @@ LogicGateNode::~LogicGateNode() } -Point LogicGateNode::getConnectionLocation(Wire* wire) const +Point2 LogicGateNode::getConnectionLocation(Wire* wire) const { bool is_input{ false }; std::size_t connection_id{ 0 }; @@ -42,7 +42,7 @@ Point LogicGateNode::getConnectionLocation(Wire* wire) const } } - Point loc; + Point2 loc; if (mContent->getGateType() == LogicGate::GateType::AND) { loc = LogicGatePrimitiveShapes::getAndGateConnectionLocation(is_input, connection_id); @@ -52,7 +52,7 @@ Point LogicGateNode::getConnectionLocation(Wire* wire) const loc = LogicGatePrimitiveShapes::getOrGateConnectionLocation(is_input, connection_id); } - loc.move(mTransform.getLocation().getX(), mTransform.getLocation().getY()); + loc.moveBy(mTransform.getLocation().getX(), mTransform.getLocation().getY()); return loc; } diff --git a/plugins/circuits/src/visuals/LogicGateNode.h b/plugins/circuits/src/visuals/LogicGateNode.h index 2cf172f..47d10ad 100644 --- a/plugins/circuits/src/visuals/LogicGateNode.h +++ b/plugins/circuits/src/visuals/LogicGateNode.h @@ -14,7 +14,7 @@ public: virtual ~LogicGateNode(); - Point getConnectionLocation(Wire* wire) const override; + Point2 getConnectionLocation(Wire* wire) const override; void setContent(LogicGate* content); diff --git a/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.cpp b/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.cpp index 06b6a30..a4d0522 100644 --- a/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.cpp +++ b/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.cpp @@ -5,7 +5,7 @@ std::string LogicGatePrimitiveShapes::getAndGateShape() return "M4 8 h24 a16 16 0 0 1 0 32 h-24Z"; } -Point LogicGatePrimitiveShapes::getAndGateConnectionLocation(bool isInput, std::size_t idx) +Point2 LogicGatePrimitiveShapes::getAndGateConnectionLocation(bool isInput, std::size_t idx) { if (isInput) { @@ -29,7 +29,7 @@ std::string LogicGatePrimitiveShapes::getOrGateShape() return "M4 8 h16 q16 2 24 16 q-12 16 -24 16 h-16 q12 -16 0 -32Z"; } -Point LogicGatePrimitiveShapes::getOrGateConnectionLocation(bool isInput, std::size_t idx) +Point2 LogicGatePrimitiveShapes::getOrGateConnectionLocation(bool isInput, std::size_t idx) { if (isInput) { diff --git a/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.h b/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.h index 64ac11a..2350087 100644 --- a/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.h +++ b/plugins/circuits/src/visuals/LogicGatePrimitiveShapes.h @@ -7,11 +7,11 @@ class LogicGatePrimitiveShapes { public: - static Point getAndGateConnectionLocation(bool isInput, std::size_t idx); + static Point2 getAndGateConnectionLocation(bool isInput, std::size_t idx); static std::string getAndGateShape(); - static Point getOrGateConnectionLocation(bool isInput, std::size_t idx); + static Point2 getOrGateConnectionLocation(bool isInput, std::size_t idx); static std::string getOrGateShape(); }; \ No newline at end of file diff --git a/plugins/circuits/src/visuals/TerminalNode.cpp b/plugins/circuits/src/visuals/TerminalNode.cpp index 95cb1ac..9e8877e 100644 --- a/plugins/circuits/src/visuals/TerminalNode.cpp +++ b/plugins/circuits/src/visuals/TerminalNode.cpp @@ -34,7 +34,7 @@ void TerminalNode::update(SceneInfo* sceneInfo) } } -Point TerminalNode::getConnectionLocation(Wire*) const +Point2 TerminalNode::getConnectionLocation(Wire*) const { - return mTransform.getLocation(); + return { mTransform.getLocation().getX(), mTransform.getLocation().getY() }; } diff --git a/plugins/circuits/src/visuals/TerminalNode.h b/plugins/circuits/src/visuals/TerminalNode.h index c505119..14c79d0 100644 --- a/plugins/circuits/src/visuals/TerminalNode.h +++ b/plugins/circuits/src/visuals/TerminalNode.h @@ -11,7 +11,7 @@ class TerminalNode : public CircuitElementNode public: TerminalNode(const Transform& transform); - Point getConnectionLocation(Wire* wire) const override; + Point2 getConnectionLocation(Wire* wire) const override; void setContent(Terminal* terminal); diff --git a/plugins/circuits/src/visuals/WireNode.cpp b/plugins/circuits/src/visuals/WireNode.cpp index b245215..12d9ed2 100644 --- a/plugins/circuits/src/visuals/WireNode.cpp +++ b/plugins/circuits/src/visuals/WireNode.cpp @@ -14,7 +14,7 @@ void WireNode::setContent(Wire* wire) mContentDirty = true; } -void WireNode::setInputLocation(const Point& point) +void WireNode::setInputLocation(const Point2& point) { if (mInputLocation != point) { @@ -23,7 +23,7 @@ void WireNode::setInputLocation(const Point& point) } } -void WireNode::setOutputLocation(const Point& point) +void WireNode::setOutputLocation(const Point2& point) { if (mOutputLocation != point) { @@ -46,9 +46,9 @@ void WireNode::createOrUpdateGeometry(SceneInfo*) if (!mLine) { auto loc = mOutputLocation; - loc.move(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ()); + loc.moveBy(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ()); - std::vector points; + std::vector points; if (loc.getY() == 0.0) { @@ -56,8 +56,8 @@ void WireNode::createOrUpdateGeometry(SceneInfo*) } else { - auto join0 = Point(loc.getX() * 3.0 / 4.0, 0.0); - auto join1 = Point(loc.getX() * 3.0 / 4.0, loc.getY()); + auto join0 = Point2(loc.getX() * 3.0 / 4.0, 0.0); + auto join1 = Point2(loc.getX() * 3.0 / 4.0, loc.getY()); points = { join0, join1 , loc}; } diff --git a/plugins/circuits/src/visuals/WireNode.h b/plugins/circuits/src/visuals/WireNode.h index c042aa3..ee52d1a 100644 --- a/plugins/circuits/src/visuals/WireNode.h +++ b/plugins/circuits/src/visuals/WireNode.h @@ -13,9 +13,9 @@ public: void setContent(Wire* wire); - void setInputLocation(const Point& point); + void setInputLocation(const Point2& point); - void setOutputLocation(const Point& point); + void setOutputLocation(const Point2& point); void update(SceneInfo* sceneInfo); private: @@ -23,8 +23,8 @@ private: Wire* mContent{ nullptr }; bool mContentDirty{ true }; - Point mInputLocation; - Point mOutputLocation; + Point2 mInputLocation; + Point2 mOutputLocation; std::unique_ptr mLine; }; \ No newline at end of file diff --git a/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp b/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp index 3883f88..31059b8 100644 --- a/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp +++ b/plugins/quantum_computing/src/visuals/BlochSphereNode.cpp @@ -3,8 +3,8 @@ #include "CircleNode.h" #include "LineNode.h" -BlochSphereNode::BlochSphereNode(const Point& location) - : AbstractVisualNode(location, "BlochSphereNode") +BlochSphereNode::BlochSphereNode(const Point2& location) + : AbstractVisualNode(Transform(location)) { } @@ -40,8 +40,8 @@ void BlochSphereNode::update(SceneInfo*) mOuterCircle = std::make_unique(loc, mSize/2.0); - const auto end_point_x = Point(loc.getX() + 1.2 * mSize / 2.0, loc.getY()); - const std::vector points{end_point_x }; + const auto end_point_x = Point2(loc.getX() + 1.2 * mSize / 2.0, loc.getY()); + const std::vector points{end_point_x }; mXAxis = std::make_unique(loc, points); mCentreCircle = std::make_unique(loc, mSize / 50.0); diff --git a/plugins/quantum_computing/src/visuals/BlochSphereNode.h b/plugins/quantum_computing/src/visuals/BlochSphereNode.h index c5280fe..6109610 100644 --- a/plugins/quantum_computing/src/visuals/BlochSphereNode.h +++ b/plugins/quantum_computing/src/visuals/BlochSphereNode.h @@ -11,7 +11,7 @@ class LineNode; class BlochSphereNode : public AbstractVisualNode { public: - BlochSphereNode(const Point& location); + BlochSphereNode(const Point2& location); void setContent(BlochSphere* content); diff --git a/plugins/quantum_computing/src/visuals/QuantumCircuitElementNode.h b/plugins/quantum_computing/src/visuals/QuantumCircuitElementNode.h index 29c489a..0d52dcd 100644 --- a/plugins/quantum_computing/src/visuals/QuantumCircuitElementNode.h +++ b/plugins/quantum_computing/src/visuals/QuantumCircuitElementNode.h @@ -11,5 +11,5 @@ public: virtual ~QuantumCircuitElementNode(); - virtual Point getConnectionLocation(AbstractQuantumWire* wire) const = 0; + virtual Point2 getConnectionLocation(AbstractQuantumWire* wire) const = 0; }; \ No newline at end of file diff --git a/plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp b/plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp index e7044bb..9d6fcc1 100644 --- a/plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp +++ b/plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp @@ -123,7 +123,7 @@ void QuantumCircuitNode::createOrUpdateGeometry(SceneInfo*) wire_node->setInputLocation(start_loc); auto end_loc = end_node->getConnectionLocation(wire); - auto straight_end_loc = Point(end_loc.getX(), start_loc.getY()); + auto straight_end_loc = Point2(end_loc.getX(), start_loc.getY()); wire_node->setOutputLocation(straight_end_loc); addChild(wire_node.get()); diff --git a/plugins/quantum_computing/src/visuals/QuantumGateNode.cpp b/plugins/quantum_computing/src/visuals/QuantumGateNode.cpp index 1e18d72..eb9716a 100644 --- a/plugins/quantum_computing/src/visuals/QuantumGateNode.cpp +++ b/plugins/quantum_computing/src/visuals/QuantumGateNode.cpp @@ -72,7 +72,7 @@ void QuantumGateNode::createOrUpdateGeometry(SceneInfo*) } } -Point QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const +Point2 QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const { bool is_input{ false }; //std::size_t connection_id{ 0 }; @@ -96,16 +96,16 @@ Point QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const } } - Point loc; + Point2 loc; if (is_input) { - loc = Point(0.0, mBodyHeight/2.0); + loc = Point2(0.0, mBodyHeight/2.0); } else { - loc = Point(mBodyWidth, mBodyHeight / 2.0); + loc = Point2(mBodyWidth, mBodyHeight / 2.0); } - loc.move(mTransform.getLocation().getX(), mTransform.getLocation().getY()); + loc.moveBy(mTransform.getLocation().getX(), mTransform.getLocation().getY()); return loc; } diff --git a/plugins/quantum_computing/src/visuals/QuantumGateNode.h b/plugins/quantum_computing/src/visuals/QuantumGateNode.h index 178f8a2..289153d 100644 --- a/plugins/quantum_computing/src/visuals/QuantumGateNode.h +++ b/plugins/quantum_computing/src/visuals/QuantumGateNode.h @@ -14,7 +14,7 @@ public: virtual ~QuantumGateNode(); - Point getConnectionLocation(AbstractQuantumWire* wire) const override; + Point2 getConnectionLocation(AbstractQuantumWire* wire) const override; void setContent(QuantumGate* gate); diff --git a/plugins/quantum_computing/src/visuals/QuantumTerminalNode.cpp b/plugins/quantum_computing/src/visuals/QuantumTerminalNode.cpp index 9a2f165..d581c4e 100644 --- a/plugins/quantum_computing/src/visuals/QuantumTerminalNode.cpp +++ b/plugins/quantum_computing/src/visuals/QuantumTerminalNode.cpp @@ -52,9 +52,9 @@ void QuantumTerminalNode::createOrUpdateGeometry(SceneInfo*) } } -Point QuantumTerminalNode::getConnectionLocation(AbstractQuantumWire*) const +Point2 QuantumTerminalNode::getConnectionLocation(AbstractQuantumWire*) const { auto left = mTransform.getLocation(); - left.move(mWidth, mHeight/2.0); - return left; + left.moveBy(mWidth, mHeight/2.0); + return { left.getX(), left.getY() }; } diff --git a/plugins/quantum_computing/src/visuals/QuantumTerminalNode.h b/plugins/quantum_computing/src/visuals/QuantumTerminalNode.h index 565cfb7..0744649 100644 --- a/plugins/quantum_computing/src/visuals/QuantumTerminalNode.h +++ b/plugins/quantum_computing/src/visuals/QuantumTerminalNode.h @@ -11,7 +11,7 @@ class QuantumTerminalNode : public QuantumCircuitElementNode public: QuantumTerminalNode(const Transform& transform); - Point getConnectionLocation(AbstractQuantumWire* wire) const override; + Point2 getConnectionLocation(AbstractQuantumWire* wire) const override; void setContent(QuantumTerminal* terminal); diff --git a/plugins/quantum_computing/src/visuals/QuantumWireNode.cpp b/plugins/quantum_computing/src/visuals/QuantumWireNode.cpp index 182b0fd..34b96c7 100644 --- a/plugins/quantum_computing/src/visuals/QuantumWireNode.cpp +++ b/plugins/quantum_computing/src/visuals/QuantumWireNode.cpp @@ -20,7 +20,7 @@ void QuantumWireNode::setContent(QuantumWire* content) mContentDirty = true; } -void QuantumWireNode::setInputLocation(const Point& point) +void QuantumWireNode::setInputLocation(const Point2& point) { if (mInputLocation != point) { @@ -29,7 +29,7 @@ void QuantumWireNode::setInputLocation(const Point& point) } } -void QuantumWireNode::setOutputLocation(const Point& point) +void QuantumWireNode::setOutputLocation(const Point2& point) { if (mOutputLocation != point) { @@ -52,9 +52,9 @@ void QuantumWireNode::createOrUpdateGeometry(SceneInfo*) if (!mLine) { auto loc = mOutputLocation; - loc.move(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ()); + loc.moveBy(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ()); - std::vector points; + std::vector points; if (loc.getY() == 0.0) { @@ -62,8 +62,8 @@ void QuantumWireNode::createOrUpdateGeometry(SceneInfo*) } else { - auto join0 = Point(loc.getX() * 3.0 / 4.0, 0.0); - auto join1 = Point(loc.getX() * 3.0 / 4.0, loc.getY()); + auto join0 = Point2(loc.getX() * 3.0 / 4.0, 0.0); + auto join1 = Point2(loc.getX() * 3.0 / 4.0, loc.getY()); points = { join0, join1 , loc }; } diff --git a/plugins/quantum_computing/src/visuals/QuantumWireNode.h b/plugins/quantum_computing/src/visuals/QuantumWireNode.h index 72b0fce..c703ea7 100644 --- a/plugins/quantum_computing/src/visuals/QuantumWireNode.h +++ b/plugins/quantum_computing/src/visuals/QuantumWireNode.h @@ -12,9 +12,9 @@ public: virtual ~QuantumWireNode(); - void setInputLocation(const Point& point); + void setInputLocation(const Point2& point); - void setOutputLocation(const Point& point); + void setOutputLocation(const Point2& point); void setContent(QuantumWire* content); @@ -26,8 +26,8 @@ private: QuantumWire* mContent{ nullptr }; bool mContentDirty{ true }; - Point mInputLocation; - Point mOutputLocation; + Point2 mInputLocation; + Point2 mOutputLocation; std::unique_ptr mLine; }; \ No newline at end of file diff --git a/plugins/quantum_computing/test/TestBlochSphereNode.cpp b/plugins/quantum_computing/test/TestBlochSphereNode.cpp index e955870..10ad271 100644 --- a/plugins/quantum_computing/test/TestBlochSphereNode.cpp +++ b/plugins/quantum_computing/test/TestBlochSphereNode.cpp @@ -11,7 +11,7 @@ TEST_CASE(TestBlochSphereNode, "quantum_computing") { TestRenderer renderer(100, 100); - auto node = std::make_unique(Point(0.5, 0.5)); + auto node = std::make_unique(Point2(0.5, 0.5)); Qubit state({ 1.0, 0.0 }, { 0.0, 0.0 }); diff --git a/src/base/geometry/AbstractGeometricItem.h b/src/base/geometry/AbstractGeometricItem.h index 49f693e..c52b5c9 100644 --- a/src/base/geometry/AbstractGeometricItem.h +++ b/src/base/geometry/AbstractGeometricItem.h @@ -1,10 +1,6 @@ #pragma once #include "Bounds.h" -#include "Point.h" - -template -class SparseGrid; class AbstractGeometricItem { @@ -28,9 +24,5 @@ public: virtual Bounds getBounds() const = 0; - virtual const Point& getLocation() const = 0; - - virtual void sample(SparseGrid* grid) const = 0; - virtual Type getType() const { return Type::UNKNOWN; }; }; diff --git a/src/base/geometry/CMakeLists.txt b/src/base/geometry/CMakeLists.txt index 840a36b..a438ab1 100644 --- a/src/base/geometry/CMakeLists.txt +++ b/src/base/geometry/CMakeLists.txt @@ -16,7 +16,6 @@ list(APPEND HEADERS path/Line.h path/LineSegment.h path/Path.h - path/PathPostScriptConverter.h path/PathElement.h path/Arc.h path/QuadraticBezierCurve.h @@ -43,7 +42,6 @@ list(APPEND SOURCES path/Line.cpp path/LineSegment.cpp path/Path.cpp - path/PathPostScriptConverter.cpp path/PathElement.cpp path/Arc.cpp path/QuadraticBezierCurve.cpp diff --git a/src/base/geometry/Rotation.cpp b/src/base/geometry/Rotation.cpp index 2dfd754..49c4f6b 100644 --- a/src/base/geometry/Rotation.cpp +++ b/src/base/geometry/Rotation.cpp @@ -1,16 +1,16 @@ #include "Rotation.h" -Rotation::Rotation(double angle, Axis axis, const Point& loc, const Vector& customAxis) +Rotation::Rotation(double angle, Axis axis, const Point3& loc, const Vector3& customAxis) : mAngle(angle), mAxis(axis), mPoint(loc), mCustomAxis(customAxis), - mMatrix(3, 3) + mMatrix() { updateMatrix(); } -const Matrix& Rotation::getMatrix() const +const SquareMatrix3& Rotation::getMatrix() const { return mMatrix; } diff --git a/src/base/geometry/Rotation.h b/src/base/geometry/Rotation.h index bef1948..da7580f 100644 --- a/src/base/geometry/Rotation.h +++ b/src/base/geometry/Rotation.h @@ -15,9 +15,9 @@ public: USER }; - Rotation(double angle = 0.0, Axis axis = Axis::Z, const Point& loc = {}, const Vector& customAxis = {}); + Rotation(double angle = 0.0, Axis axis = Axis::Z, const Point3& loc = {}, const Vector3& customAxis = {}); - const Matrix& getMatrix() const; + const SquareMatrix3& getMatrix() const; bool isIdentity() const; @@ -38,8 +38,8 @@ private: double mAngle{ 0 }; Axis mAxis{ Axis::Z }; - Point mPoint; - Vector mCustomAxis; + Point3 mPoint; + Vector3 mCustomAxis; - Matrix mMatrix; + SquareMatrix3 mMatrix; }; diff --git a/src/base/geometry/Transform.cpp b/src/base/geometry/Transform.cpp index 9b200bb..60090bd 100644 --- a/src/base/geometry/Transform.cpp +++ b/src/base/geometry/Transform.cpp @@ -18,22 +18,22 @@ bool Scale::isEqual(const Scale& scale) const return mX == scale.mX && mY == scale.mY && mZ == scale.mZ; } -Transform::Transform(const Point& location, const Scale& scale, const Rotation& rotation) +Transform::Transform(const Point3& location, const Scale& scale, const Rotation& rotation) : mLocation(location), mScale(scale), mRotation(rotation), - mMatrix(4, 4) + mMatrix() { - + } void Transform::applyPre(const Transform& transform) { - mLocation.move(transform.getLocation().getX(), transform.getLocation().getY(), transform.getLocation().getZ()); + mLocation.moveBy(transform.getLocation().getX(), transform.getLocation().getY(), transform.getLocation().getZ()); mScale *= transform.getScale(); } -const Point& Transform::getLocation() const +const Point3& Transform::getLocation() const { return mLocation; } @@ -58,7 +58,7 @@ bool Transform::isIdentityTransform() const return mLocation.isAtOrigin() && mScale.isIdentity(); } -void Transform::setLocation(const Point& loc) +void Transform::setLocation(const Point3& loc) { if (mLocation != loc) { diff --git a/src/base/geometry/Transform.h b/src/base/geometry/Transform.h index 9940342..bebbe06 100644 --- a/src/base/geometry/Transform.h +++ b/src/base/geometry/Transform.h @@ -35,23 +35,23 @@ struct Scale class Transform { public: - Transform(const Point& location = {}, const Scale& scale = {}, const Rotation& rotation = {}); + Transform(const Point3& location = {}, const Scale& scale = {}, const Rotation& rotation = {}); void applyPre(const Transform& transform); - const Point& getLocation() const; + const Point3& getLocation() const; const Scale& getScale() const; const Rotation& getRotation() const; - const Matrix& getMatrix() const; + const SquareMatrix4& getMatrix() const; bool isEqual(const Transform& transform) const; bool isIdentityTransform() const; - void setLocation(const Point& loc); + void setLocation(const Point3& loc); void setScale(const Scale& scale); @@ -70,8 +70,8 @@ public: private: void updateMatrix(); - Point mLocation; + Point3 mLocation; Scale mScale; Rotation mRotation; - Matrix mMatrix; + SquareMatrix4 mMatrix; }; diff --git a/src/base/geometry/math/Linalg.cpp b/src/base/geometry/math/Linalg.cpp index 932fb1f..c0710d9 100644 --- a/src/base/geometry/math/Linalg.cpp +++ b/src/base/geometry/math/Linalg.cpp @@ -1,11 +1,8 @@ #include "Linalg.h" -double Linalg::dotProduct(const Vector& v0, const Vector& v1) -{ - return v0.dotProduct(v1); -} -Vector Linalg::crossProduct(const Vector& v0, const Vector& v1) +template +Vector Linalg::crossProduct(const Vector& v0, const Vector& v1) { return v0.crossProduct(v1); } \ No newline at end of file diff --git a/src/base/geometry/math/Linalg.h b/src/base/geometry/math/Linalg.h index 82f7622..9544f7f 100644 --- a/src/base/geometry/math/Linalg.h +++ b/src/base/geometry/math/Linalg.h @@ -4,7 +4,6 @@ class Linalg { - static double dotProduct(const Vector& v0, const Vector& v1); - - static Vector crossProduct(const Vector& v0, const Vector& v1); + template + static Vector crossProduct(const Vector& v0, const Vector& v1); }; \ No newline at end of file diff --git a/src/base/geometry/math/Matrix.cpp b/src/base/geometry/math/Matrix.cpp index 642a013..9e0d4a6 100644 --- a/src/base/geometry/math/Matrix.cpp +++ b/src/base/geometry/math/Matrix.cpp @@ -3,23 +3,86 @@ #include #include -Matrix::Matrix(std::size_t numRows, std::size_t numColumns) - : mNumRows(numRows), - mNumColumns(numColumns) +template +Matrix::Matrix(T value) { - mData = std::vector(numRows * numColumns, 0.0); + mData = std::vector(M * N, value); } -bool Matrix::isIdentity() const +template +Matrix::Matrix(T value, InputType inputType) +{ + if (inputType == InputType::DIAGONAL) + { + mData = std::vector(M * N, 0.0); + setDiagonals(value); + } + else + { + mData = std::vector(M * N, value); + } +} + +template +void Matrix::applyTo(Vector& v) const +{ + +} + +template +void Matrix::setDiagonals(T value) +{ + if (!isSquare()) + { + throw std::logic_error("Requested setting diagonals on non-square Matrix."); + } + + for (std::size_t idx = 0; idx < M; idx++) + { + mData[getFlatIndex(idx, idx)] = value; + } +} + +template +void Matrix::setDiagonals(const std::vector& values) +{ + if (!isSquare()) + { + throw std::logic_error("Requested setting diagonals on non-square Matrix."); + } + + for (std::size_t idx = 0; idx < values.size(); idx++) + { + if (idx >= M) + { + break; + } + mData[getFlatIndex(idx, idx)] = values[idx]; + } +} + +template +void Matrix::setItem(std::size_t rowId, std::size_t columnId, T value) +{ + const auto index = getFlatIndex(rowId, columnId); + if (index >= mData.size()) + { + throw std::range_error("Out of bounds array access: " + std::to_string(index) + " for size " + std::to_string(mData.size())); + } + mData[index] = value; +} + +template +bool Matrix::isIdentity() const { if (!isSquare()) { return false; } - for(std::size_t idx=0; idx +T Matrix::getItem(std::size_t rowId, std::size_t columnId) const { const auto index = getFlatIndex(rowId, columnId); if (index >= mData.size()) @@ -50,17 +114,27 @@ double Matrix::getItem(std::size_t rowId, std::size_t columnId) const return mData[getFlatIndex(rowId, columnId)]; } -bool Matrix::isSquare() const +template +bool Matrix::isSquare() const { - return mNumRows == mNumColumns; + return M == N; } -bool Matrix::isEqual(const Matrix& matrix) const +template +bool Matrix::isEqual(const Matrix& matrix) const { return mData == matrix.mData; } -std::size_t Matrix::getFlatIndex(std::size_t rowId, std::size_t columnId) const +template +std::size_t Matrix::getFlatIndex(std::size_t rowId, std::size_t columnId) const { - return columnId + rowId*mNumColumns; + return columnId + rowId*N; } + +template class Matrix; +template class Matrix; +template class Matrix; + +template class Matrix, 2, 2>; +template class Matrix, 3, 3>; diff --git a/src/base/geometry/math/Matrix.h b/src/base/geometry/math/Matrix.h index 4fd6b70..c04980d 100644 --- a/src/base/geometry/math/Matrix.h +++ b/src/base/geometry/math/Matrix.h @@ -1,35 +1,63 @@ #pragma once #include "Vector.h" -#include +#include +#include + +template class Matrix { public: - Matrix(std::size_t numRows, std::size_t numColumns); + enum class InputType + { + UNIFORM, + DIAGONAL + }; + + Matrix(T value = 0.0); + + Matrix(T value, InputType inputType); + + void applyTo(Vector& v) const; std::size_t getFlatIndex(std::size_t rowId, std::size_t columnId) const; - double getItem(std::size_t rowId, std::size_t columnId) const; + T getItem(std::size_t rowId, std::size_t columnId) const; bool isIdentity() const; bool isSquare() const; - bool isEqual(const Matrix& matrix) const; + bool isEqual(const Matrix& matrix) const; - bool operator==(const Matrix& rhs) const + void setDiagonals(T value); + + void setDiagonals(const std::vector& values); + + void setItem(std::size_t rowId, std::size_t columnId, T value); + + bool operator==(const Matrix& rhs) const { return isEqual(rhs); } - bool operator!=(const Matrix& rhs) const + bool operator!=(const Matrix& rhs) const { return !operator==(rhs); } private: - std::size_t mNumRows{0}; - std::size_t mNumColumns{0}; - std::vector mData; + std::vector mData; }; + +using Matrix3x3 = Matrix; +using SquareMatrix3 = Matrix; + +using Matrix2x2 = Matrix; +using SquareMatrix2 = Matrix; + +using SquareMatrix4 = Matrix; + +using ComplexMatrix3x3 = Matrix, 3, 3>; +using ComplexMatrix2x2 = Matrix, 3, 3>; \ No newline at end of file diff --git a/src/base/geometry/math/Vector.cpp b/src/base/geometry/math/Vector.cpp index ce6a50a..841fb59 100644 --- a/src/base/geometry/math/Vector.cpp +++ b/src/base/geometry/math/Vector.cpp @@ -1,92 +1,156 @@ #include "Vector.h" #include +#include +#include #include +#include -Vector::Vector(Primitive p) +template +Vector::Vector(Primitive p) { + mData = std::vector(DIM, 0.0); switch(p) { case Primitive::UNIT_X: - mX = 1.0; + mData[0] = 1.0; break; case Primitive::UNIT_Y: - mY = 1.0; + mData[1] = 1.0; break; case Primitive::UNIT_Z: - mZ = 1.0; + mData[2] = 1.0; break; case Primitive::NEGATIVE_X: - mX = -1.0; + mData[0] = -1.0; break; case Primitive::NEGATIVE_Y: - mY = -1.0; + mData[1] = -1.0; break; case Primitive::NEGATIVE_Z: - mZ = -1.0; + mData[2] = -1.0; break; } } -Vector::Vector(double x, double y, double z) - : mX(x), - mY(y), - mZ(z) +template +Vector::Vector(const std::vector& values) { + mData = std::vector(DIM, 0.0); + + if (values.empty()) + { + return; + } + + for (std::size_t idx = 0; idx < std::min(values.size(), DIM); idx++) + { + mData[idx] = values[idx]; + } } -Vector::~Vector() +template +Vector::~Vector() { }; -void Vector::reverseDirection() +template +Vector Vector::add(const Vector& v) const { - (*this) *= -1.0; + Vector result = *this; + result.inPlaceAdd(v); + return result; } -double Vector::getX() const +template +void Vector::inPlaceAdd(const Vector& v) { - return mX; + std::transform(mData.begin(), mData.end(), v.mData.begin(), mData.begin(), std::plus()); } -double Vector::getY() const +template +bool Vector::equals(const Vector& v) const { - return mY; + return mData == v.mData; } -double Vector::getZ() const +template +void Vector::inPlaceMultiply(double v) { - return mZ; + //std::transform(mData.begin(), mData.end(), mData.begin(), std::bind(std::multiplies(), std::placeholders::_1, v)); } -double Vector::getLength() const +template +Vector Vector::multiply(double v) const { - return std::sqrt(mX * mX + mY * mY + mZ * mZ); + Vector result = *this; + result.inPlaceMultiply(v); + return result; } -double Vector::dotProduct(const Vector& v) const +template +void Vector::reverseDirection() { - return mX * v.mX + mY * v.mY + mZ * v.mZ; + inPlaceMultiply(-1.0); } -Vector Vector::crossProduct(const Vector& v) const +template +T Vector::getEntry(std::size_t idx) const { - return Vector(v.mY * mZ - v.mZ * mY, v.mZ * mX - v.mX * mZ, v.mX * mY - v.mY * mX); + if (idx >= DIM) + { + throw std::range_error("Out of bounds access for Vector"); + } + return mData[idx]; } -Vector Vector::getNormalized() const +template +double Vector::getLength() const +{ + return std::sqrt(getSelfInnerProduct()); +} + +template +double Vector::getSelfInnerProduct() const +{ + return 0.0; + //return std::inner_product(mData.begin(), mData.end(), mData.begin(), 0.0); +} + +template +double Vector::innerPoduct(const Vector& v) const +{ + return 0.0; + //return std::inner_product(mData.begin(), mData.end(), v.mData.begin(), 0.0); +} + +template +Vector Vector::crossProduct(const Vector& v) const +{ + return Vector(); + //return Vector(v.mY * mZ - v.mZ * mY, v.mZ * mX - v.mX * mZ, v.mX * mY - v.mY * mX); +} + +template +Vector Vector::getNormalized() const { const auto length = getLength(); if (length == 0.0) { throw std::logic_error("Divide by zero getting normalizing vector"); } - return Vector(mX / length, mY / length, mZ / length); + return (*this).multiply(1.0 / length); } -void Vector::scale(double x, double y, double z) +template +void Vector::scale(const std::vector& factors) { - mX = x * mX; - mY = y * mY; - mZ = z * mZ; + //std::transform(mData.begin(), mData.end(), factors.begin(), mData.begin(), std::multiplies()); } + +template class Vector; +template class Vector; +template class Vector; + +template class Vector, 2>; +template class Vector, 3>; diff --git a/src/base/geometry/math/Vector.h b/src/base/geometry/math/Vector.h index 46dfe44..333916f 100644 --- a/src/base/geometry/math/Vector.h +++ b/src/base/geometry/math/Vector.h @@ -1,5 +1,9 @@ #pragma once +#include +#include + +template class Vector { public: @@ -15,56 +19,79 @@ public: Vector(Primitive p); - Vector(double x = 0, double y = 0, double z = 0); + Vector(const std::vector& values = {}); ~Vector(); - double dotProduct(const Vector& v) const; + Vector add(const Vector& v) const; - Vector crossProduct(const Vector& v) const; + void inPlaceAdd(const Vector& v); + + double innerPoduct(const Vector& v) const; + + Vector crossProduct(const Vector& v) const; + + bool equals(const Vector& v) const; void reverseDirection(); - double getX() const; - - double getY() const; - - double getZ() const; + T getEntry(std::size_t idx) const; double getLength() const; - Vector getNormalized() const; + Vector getNormalized() const; - void scale(double x, double y = 1.0, double z = 1.0); + double getSelfInnerProduct() const; - void operator*=(double d) + Vector multiply(double s) const; + + void inPlaceMultiply(double s); + + void scale(const std::vector& factors); + + Vector operator+(const Vector& v) const { - mX *= d; - mY *= d; - mZ *= d; + return add(v); } - void operator+=(const Vector& vector) + Vector operator*(double s) const { - mX += vector.mX; - mY += vector.mY; - mZ += vector.mZ; + return multiply(s); } - bool operator==(const Vector& rhs) const + void operator*=(double s) { - return (mX == rhs.mX) - && (mY == rhs.mY) - && (mZ == rhs.mZ); + inPlaceMultiply(s); } - bool operator!=(const Vector& rhs) const + void operator+=(const Vector& v) + { + add(v); + } + + bool operator==(const Vector& rhs) const + { + return equals(rhs); + } + + bool operator!=(const Vector& rhs) const { return !operator==(rhs); } + T operator[](std::size_t idx) const + { + return getEntry(idx); + } + private: - double mX{ 0 }; - double mY{ 0 }; - double mZ{ 0 }; + std::vector mData; }; + +using Vector4 = Vector; +using Vector3 = Vector; +using Vector2 = Vector; + +using ComplexVector3 = Vector, 3>; +using ComplexVector2 = Vector, 2>; + diff --git a/src/base/geometry/path/Arc.cpp b/src/base/geometry/path/Arc.cpp index bc96db9..7fdf781 100644 --- a/src/base/geometry/path/Arc.cpp +++ b/src/base/geometry/path/Arc.cpp @@ -4,9 +4,8 @@ #include namespace ntk { - Arc::Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation, bool largeArc, bool sweep) - : mStartPoint(startPoint), - mEndPoint(endPoint), + Arc::Arc(const Vector2& endoffset, double rX, double rY, double rotation, bool largeArc, bool sweep) + : mEndOffset(endoffset), mRx(rX), mRy(rY), mRotation(rotation), @@ -16,43 +15,9 @@ namespace ntk { } - Point Arc::getFirstPoint() const + Vector2 Arc::getEndOffset() const { - return mStartPoint; - } - - Point Arc::getEndPoint() const - { - return mEndPoint; - } - - std::string Arc::toPostScriptString(std::size_t precision) const - { - const auto large = mLargeArc ? "1" : "0"; - const auto sweep = mSweep ? "1" : "0"; - std::stringstream sstr; - if (precision > 0) - { - sstr.precision(precision); - } - if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO) - { - sstr << "a"; - } - else - { - sstr << "A"; - } - sstr << mRx << " " << mRy << " " << mRotation << " " << large << " " << sweep << " "; - if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO) - { - sstr << PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision); - } - else - { - sstr << PointParser::toString(mEndPoint, 2, " ", precision); - } - return sstr.str(); + return mEndOffset; } Bounds Arc::getBounds() const @@ -60,22 +25,7 @@ namespace ntk { return {}; } - const Point& Arc::getLocation() const - { - return mStartPoint; - } - - void Arc::sample(SparseGrid*) const - { - - } - - Arc::Type Arc::getType() const - { - return Type::CURVE; - } - - Arc::CurveType Arc::getCurveType() const + CurveType Arc::getCurveType() const { return CurveType::ARC; } diff --git a/src/base/geometry/path/Arc.h b/src/base/geometry/path/Arc.h index eeb0831..0d65233 100644 --- a/src/base/geometry/path/Arc.h +++ b/src/base/geometry/path/Arc.h @@ -1,24 +1,18 @@ #pragma once #include "Curve.h" -#include "Point.h" +#include "Vector.h" namespace ntk{ -class Arc : public Curve +class Arc : public Curve<2> { public: - Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation = 0, bool largeArc = false, bool sweep = false); + Arc(const Vector2& endoffset, double rX, double rY, double rotation = 0, bool largeArc = false, bool sweep = false); - Point getFirstPoint() const override; - - Point getEndPoint() const override; + Vector2 getEndOffset() const override; Bounds getBounds() const override; - const Point& getLocation() const override; - - Type getType() const override; - CurveType getCurveType() const override; double getRx() const; @@ -31,13 +25,8 @@ public: bool getSweepParam() const; - void sample(SparseGrid*) const override; - - std::string toPostScriptString(std::size_t precision = 0) const override; - private: - Point mStartPoint; - Point mEndPoint; + Vector2 mEndOffset; double mRx{ 0.0 }; double mRy{ 0.0 }; double mRotation{ 0 }; diff --git a/src/base/geometry/path/CubicBezierCurve.cpp b/src/base/geometry/path/CubicBezierCurve.cpp index dce9db0..914af4d 100644 --- a/src/base/geometry/path/CubicBezierCurve.cpp +++ b/src/base/geometry/path/CubicBezierCurve.cpp @@ -1,75 +1,43 @@ #include "CubicBezierCurve.h" -#include "PointParser.h" - -CubicBezierCurve::CubicBezierCurve(const Point& startPoint, const Point& endPoint, const Point& startControlPoint, const Point& endControlPoint) - : mStartPoint(startPoint), - mEndPoint(endPoint), - mStartControlPoint(startControlPoint), - mEndControlPoint(endControlPoint) +template +CubicBezierCurve::CubicBezierCurve(const Vector& endOffset, const Vector& startControlOffset, const Vector& endControlOffset) + : mEndOffset(endOffset), + mStartControlOffset(startControlOffset), + mEndControlOffset(endControlOffset) { } -Point CubicBezierCurve::getFirstPoint() const +template +Vector CubicBezierCurve::getEndOffset() const { - return mStartPoint; + return mEndOffset; } -Point CubicBezierCurve::getEndPoint() const +template +const Vector& CubicBezierCurve::getStartControlOffset() const { - return mEndPoint; + return mStartControlOffset; } -const Point& CubicBezierCurve::getStartControlPoint() const +template +const Vector& CubicBezierCurve::getEndControlOffset() const { - return mStartControlPoint; + return mEndControlOffset; } -const Point& CubicBezierCurve::getEndControlPoint() const -{ - return mEndControlPoint; -} - -std::string CubicBezierCurve::toPostScriptString(std::size_t precision) const -{ - if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO) - { - const auto start_control = PointParser::toStringRelative(mStartControlPoint, mStartPoint, 2, " ", precision); - const auto end_control = PointParser::toStringRelative(mEndControlPoint, mStartPoint, 2, " ", precision); - const auto end = PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision); - return "c" + start_control + " " + end_control + " " + end; - } - else - { - const auto start_control = PointParser::toString(mStartControlPoint, 2, " ", precision); - const auto end_control = PointParser::toString(mEndControlPoint, 2, " ", precision); - const auto end = PointParser::toString(mEndPoint, 2, " ", precision); - return "C" + start_control + " " + end_control + " " + end; - } -} - -Bounds CubicBezierCurve::getBounds() const +template +Bounds CubicBezierCurve::getBounds() const { return {}; } -const Point& CubicBezierCurve::getLocation() const -{ - return mStartPoint; -} - -void CubicBezierCurve::sample(SparseGrid*) const -{ - -} - -CubicBezierCurve::Type CubicBezierCurve::getType() const -{ - return Type::CURVE; -} - -CubicBezierCurve::CurveType CubicBezierCurve::getCurveType() const +template +CurveType CubicBezierCurve::getCurveType() const { return CurveType::CUBIC_BEZIER; } + +template class CubicBezierCurve<2>; +template class CubicBezierCurve<3>; diff --git a/src/base/geometry/path/CubicBezierCurve.h b/src/base/geometry/path/CubicBezierCurve.h index 76cc3e3..e7fc905 100644 --- a/src/base/geometry/path/CubicBezierCurve.h +++ b/src/base/geometry/path/CubicBezierCurve.h @@ -1,36 +1,26 @@ #pragma once #include "Curve.h" -#include "Point.h" +#include "Vector.h" -class CubicBezierCurve : public Curve +template +class CubicBezierCurve : public Curve { public: - CubicBezierCurve(const Point& startPoint, const Point& endPoint, const Point& startControlPoint, const Point& endControlPoint); + CubicBezierCurve(const Vector& endOffset, const Vector& startControlOffset, const Vector& endControlOffset); - Point getFirstPoint() const override; + Vector getEndOffset() const override; - Point getEndPoint() const override; + const Vector& getStartControlOffset() const; - const Point& getStartControlPoint() const; - - const Point& getEndControlPoint() const; + const Vector& getEndControlOffset() const; Bounds getBounds() const override; - const Point& getLocation() const override; - - Type getType() const override; - CurveType getCurveType() const override; - void sample(SparseGrid*) const override; - - std::string toPostScriptString(std::size_t precision = 0) const override; - private: - Point mStartPoint; - Point mEndPoint; - Point mStartControlPoint; - Point mEndControlPoint; + Vector mEndOffset; + Vector mStartControlOffset; + Vector mEndControlOffset; }; diff --git a/src/base/geometry/path/Curve.h b/src/base/geometry/path/Curve.h index 804fcae..cc25c39 100644 --- a/src/base/geometry/path/Curve.h +++ b/src/base/geometry/path/Curve.h @@ -2,16 +2,22 @@ #include "PathElement.h" -class Curve : public PathElement +enum class CurveType +{ + ARC, + QUADRATIC_BEZIER, + CUBIC_BEZIER, + UNKNOWN +}; + +template +class Curve : public PathElement { public: - enum class CurveType + Curve::Type getType() const override { - ARC, - QUADRATIC_BEZIER, - CUBIC_BEZIER, - UNKNOWN - }; + return Curve::Type::CURVE; + } virtual CurveType getCurveType() const = 0; }; diff --git a/src/base/geometry/path/Line.cpp b/src/base/geometry/path/Line.cpp index 2fc5c88..e8ec117 100644 --- a/src/base/geometry/path/Line.cpp +++ b/src/base/geometry/path/Line.cpp @@ -1,119 +1,66 @@ #include "Line.h" -#include "PointParser.h" - -Line::Line(const Point& start, const PointCollection& points) - : mStartPoint(start), - mPoints(points) +template +Line::Line(const PointCollection& points) + : mPoints(points) { } -Line::Line(const Point& start, InputBufferType bufferType, const std::vector& buffer) - : mStartPoint(start) +template +Line::Line(InputBufferType bufferType, const std::vector& buffer) { - if (bufferType == InputBufferType::XY_REL) + if (bufferType == InputBufferType::XY) { for (std::size_t idx = 0; idx < buffer.size(); idx += 2) { const auto x = buffer[idx]; const auto y = buffer[idx + 1]; - mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY() + y)); + mPoints.addPoint(Point(x, y)); } } - else if (bufferType == InputBufferType::XY_ABS) - { - for (std::size_t idx = 0; idx < buffer.size(); idx += 2) - { - const auto x = buffer[idx]; - const auto y = buffer[idx + 1]; - mPoints.addPoint(Point(x, y)); - } - } - else if (bufferType == InputBufferType::HORIZONTAL_REL) + else if (bufferType == InputBufferType::HORIZONTAL) { for (std::size_t idx = 0; idx < buffer.size(); idx ++) { - const auto x = buffer[idx]; - mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY())); + mPoints.addPoint(Point(buffer[idx], 0.0)); } } - else if (bufferType == InputBufferType::HORIZONTAL_ABS) + else if (bufferType == InputBufferType::VERTICAL) { for (std::size_t idx = 0; idx < buffer.size(); idx++) { - const auto x = buffer[idx]; - mPoints.addPoint(Point(x, mStartPoint.getY())); - } - } - else if (bufferType == InputBufferType::VERTICAL_REL) - { - for (std::size_t idx = 0; idx < buffer.size(); idx++) - { - const auto y = buffer[idx]; - mPoints.addPoint(Point(mStartPoint.getX(), mStartPoint.getY() + y)); - } - } - else if (bufferType == InputBufferType::VERTICAL_ABS) - { - for (std::size_t idx = 0; idx < buffer.size(); idx++) - { - const auto y = buffer[idx]; - mPoints.addPoint(Point(mStartPoint.getX(), y)); + mPoints.addPoint(Point(0.0, buffer[idx])); } } } -std::string Line::toPostScriptString(std::size_t precision) const +template +Vector Line::getEndOffset() const { - if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO) - { - std::string path = "L"; - for (const auto& point : mPoints.getPoints()) - { - path += PointParser::toString(point, 2, " ", precision) + " "; - } - return path; - } - else - { - std::string path = "l"; - for (const auto& point : mPoints.getPoints()) - { - path += PointParser::toStringRelative(point, mStartPoint, 2, " ", precision) + " "; - } - return path; - } + return mPoints.getEndPoint().getOriginOffset(); } -Point Line::getFirstPoint() const -{ - return getLocation(); -} - -Point Line::getEndPoint() const -{ - return mPoints.getEndPoint(); -} - -const PointCollection& Line::getPoints() const +template +const PointCollection& Line::getPoints() const { return mPoints; } -Line::Type Line::getType() const +template +AbstractGeometricItem::Type Line::getType() const { - return Line::Type::LINE; + return AbstractGeometricItem::Type::LINE; } -const Point& Line::getLocation() const -{ - return mStartPoint; -} - -Bounds Line::getBounds() const +template +Bounds Line::getBounds() const { auto bounds = mPoints.getBounds(); - bounds.includePoint(mStartPoint.getX(), mStartPoint.getY(), mStartPoint.getZ()); + bounds.includePoint(0.0, 0.0, 0.0); return bounds; -} \ No newline at end of file +} + +template class Line<2>; +template class Line<3>; + diff --git a/src/base/geometry/path/Line.h b/src/base/geometry/path/Line.h index e4c4143..85a0466 100644 --- a/src/base/geometry/path/Line.h +++ b/src/base/geometry/path/Line.h @@ -6,40 +6,31 @@ #include #include -class Line : public PathElement +template +class Line : public PathElement { public: enum class InputBufferType { - HORIZONTAL_REL, - HORIZONTAL_ABS, - VERTICAL_REL, - VERTICAL_ABS, - XY_REL, - XY_ABS + HORIZONTAL, + VERTICAL, + XY }; - Line(const Point& start, const PointCollection& points); + Line(const PointCollection& points); - Line(const Point& start, InputBufferType bufferType, const std::vector& buffer); + Line(InputBufferType bufferType, const std::vector& buffer); - const PointCollection& getPoints() const; + const PointCollection& getPoints() const; - Line::Type getType() const override; - - const Point& getLocation() const override; + AbstractGeometricItem::Type getType() const override; Bounds getBounds() const override; - Point getFirstPoint() const override; - - Point getEndPoint() const override; - - void sample(SparseGrid*) const override {}; - - std::string toPostScriptString(std::size_t precision = 0) const override; + Vector getEndOffset() const override; private: - Point mStartPoint; - PointCollection mPoints; + PointCollection mPoints; }; + +using Line2 = Line<2>; diff --git a/src/base/geometry/path/LineSegment.cpp b/src/base/geometry/path/LineSegment.cpp index 73c294b..cae0bf0 100644 --- a/src/base/geometry/path/LineSegment.cpp +++ b/src/base/geometry/path/LineSegment.cpp @@ -1,87 +1,51 @@ #include "LineSegment.h" -#include "PointParser.h" - -LineSegment::LineSegment(const Point& p0, const Point& p1) +template +LineSegment::LineSegment(const Point& p0, const Point& p1) : mP0(p0), mP1(p1) { } -std::unique_ptr LineSegment::Create(const Point& p0, const Point& p1) +template +std::unique_ptr > LineSegment ::Create(const Point& p0, const Point& p1) { - return std::make_unique(p0, p1); + return std::make_unique >(p0, p1); } -double LineSegment::getLength() const +template +double LineSegment ::getLength() const { return mP0.getDistance(mP1); } -const Point& LineSegment::getPoint0() const +template +const Point& LineSegment ::getPoint0() const { return mP0; } -const Point& LineSegment::getPoint1() const +template +const Point& LineSegment ::getPoint1() const { return mP1; } -void LineSegment::sample(SparseGrid*) const -{ - -} - -std::string LineSegment::toPostScriptString(std::size_t precision) const -{ - if (isHorizontal()) - { - if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO) - { - return "H" + PointParser::toString(mP1.getX(), precision); - } - else - { - return "h" + PointParser::toString(mP0.getDeltaX(mP1), precision); - } - } - else if (isVertical()) - { - if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO) - { - return "V" + PointParser::toString(mP1.getY(), precision); - } - else - { - return "v" + PointParser::toString(mP0.getDeltaY(mP1), precision); - } - } - else - { - if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO) - { - return "L" + PointParser::toString(mP1, 2, " ", precision); - } - else - { - return "l" + PointParser::toStringRelative(mP1, mP0, 2, " ", precision); - } - } -} - -bool LineSegment::isHorizontal() const +template +bool LineSegment::isHorizontal() const { return mP0.getDeltaY(mP1) == 0.0; } -bool LineSegment::isVertical() const +template +bool LineSegment::isVertical() const { return mP0.getDeltaX(mP1) == 0.0; } -Bounds LineSegment::getBounds() const +template +Bounds LineSegment::getBounds() const { const auto minX = std::min(mP0.getX(), mP1.getX()); const auto maxX = std::max(mP0.getX(), mP1.getX()); @@ -92,22 +56,23 @@ Bounds LineSegment::getBounds() const return {minX, maxX, minY, maxY}; } -const Point& LineSegment::getLocation() const +template +Vector LineSegment::getEndOffset() const { - return mP0; + return getPoint1().getOriginOffset(); } -Point LineSegment::getFirstPoint() const -{ - return getPoint0(); -} - -Point LineSegment::getEndPoint() const -{ - return getPoint1(); -} - -LineSegment::Type LineSegment::getType() const +template +AbstractGeometricItem::Type LineSegment::getType() const { return AbstractGeometricItem::Type::LINE_SEGMENT; } + +template +Vector LineSegment::asVector() const +{ + return mP1.getDelta(mP0); +} + +template class LineSegment<2>; +template class LineSegment<3>; \ No newline at end of file diff --git a/src/base/geometry/path/LineSegment.h b/src/base/geometry/path/LineSegment.h index 6c9a9e2..5ad7e72 100644 --- a/src/base/geometry/path/LineSegment.h +++ b/src/base/geometry/path/LineSegment.h @@ -1,41 +1,37 @@ #pragma once #include "PathElement.h" +#include "Point.h" -#include - -class LineSegment : public PathElement +template +class LineSegment : public PathElement { public: - LineSegment(const Point& p0, const Point& p1); + LineSegment(const Point& p0, const Point& p1); - static std::unique_ptr Create(const Point& p0, const Point& p1); + static std::unique_ptr > Create(const Point& p0, const Point& p1); double getLength() const; - const Point& getPoint0() const; + const Point& getPoint0() const; - const Point& getPoint1() const; + const Point& getPoint1() const; Bounds getBounds() const override; - const Point& getLocation() const override; + Vector asVector() const; - Point getFirstPoint() const override; + Vector getEndOffset() const override; - Point getEndPoint() const override; - - Type getType() const override; + AbstractGeometricItem::Type getType() const override; bool isHorizontal() const; bool isVertical() const; - void sample(SparseGrid*) const override; - - std::string toPostScriptString(std::size_t precision = 0) const override; - private: - Point mP0; - Point mP1; + Point mP0; + Point mP1; }; + +using LineSegment2 = LineSegment<2>; diff --git a/src/base/geometry/path/Path.cpp b/src/base/geometry/path/Path.cpp index 67455d0..7681a18 100644 --- a/src/base/geometry/path/Path.cpp +++ b/src/base/geometry/path/Path.cpp @@ -1,12 +1,5 @@ #include "Path.h" -#include "StringUtils.h" -#include "FileLogger.h" - -#include "Line.h" -#include "LineSegment.h" -#include "PathPostScriptConverter.h" - GeometryPath::~GeometryPath() { @@ -17,22 +10,12 @@ const std::vector& GeometryPath::getFeatures() const return mFeatures; } -void GeometryPath::buildFromPostscript(const std::string& psString) -{ - PathPostScriptConverter converter; - converter.fromPostScript(this, psString); -} void GeometryPath::addFeature(GeometryPathFeaturePtr feature) { mFeatures.push_back(std::move(feature)); } -const Point& GeometryPath::getLocation() const -{ - return mLocation; -} - Bounds GeometryPath::getBounds() const { return {}; @@ -41,15 +24,4 @@ Bounds GeometryPath::getBounds() const GeometryPath::Type GeometryPath::getType() const { return GeometryPath::Type::PATH; -} - -void GeometryPath::sample(SparseGrid*) const -{ - -} - -std::string GeometryPath::getAsPostScript() const -{ - PathPostScriptConverter converter; - return converter.toPostScript(this); -} +} \ No newline at end of file diff --git a/src/base/geometry/path/Path.h b/src/base/geometry/path/Path.h index e81a6a3..308f729 100644 --- a/src/base/geometry/path/Path.h +++ b/src/base/geometry/path/Path.h @@ -6,23 +6,24 @@ #include #include -using PathElementPtr = std::unique_ptr; +using PathElementPtr = std::unique_ptr >; class GeometryPathFeature { public: + void setLocation(Vector2 offset) + { + mOffset = offset; + } + void addElement(PathElementPtr element) { - if (mElements.empty()) - { - mLocation = element->getFirstPoint(); - } mElements.push_back(std::move(element)); } - const Point& getLocation() const + const Vector2& getOffset() const { - return mLocation; + return mOffset; } const std::vector& getElements() const @@ -30,8 +31,19 @@ public: return mElements; } + PathOffsetType getPathOffsetType() const + { + return mOffsetType; + } + + void setPathOffsetType(PathOffsetType offsetType) + { + mOffsetType = offsetType; + } + private: - Point mLocation; + Vector2 mOffset; + PathOffsetType mOffsetType{PathOffsetType::RELATIVE_TO}; std::vector mElements; }; using GeometryPathFeaturePtr = std::unique_ptr; @@ -43,21 +55,12 @@ public: void addFeature(GeometryPathFeaturePtr feature); - void buildFromPostscript(const std::string& psString); - - std::string getAsPostScript() const; - - const Point& getLocation() const override; - Bounds getBounds() const override; Type getType() const override; const std::vector& getFeatures() const; - void sample(SparseGrid*) const override; - private: - Point mLocation; std::vector mFeatures; }; diff --git a/src/base/geometry/path/PathElement.cpp b/src/base/geometry/path/PathElement.cpp index 568527c..e923f44 100644 --- a/src/base/geometry/path/PathElement.cpp +++ b/src/base/geometry/path/PathElement.cpp @@ -1,6 +1,10 @@ #include "PathElement.h" -PathElement::~PathElement() +template +PathElement::~PathElement() { -} \ No newline at end of file +} + +template class PathElement<2>; +template class PathElement<3>; \ No newline at end of file diff --git a/src/base/geometry/path/PathElement.h b/src/base/geometry/path/PathElement.h index 215aeb3..486abf0 100644 --- a/src/base/geometry/path/PathElement.h +++ b/src/base/geometry/path/PathElement.h @@ -1,31 +1,39 @@ #pragma once #include "AbstractGeometricItem.h" +#include "Vector.h" -#include +enum class PathOffsetType +{ + RELATIVE_TO, + ABSOLUTE_TO +}; +template class PathElement : public AbstractGeometricItem { public: - enum class PostscriptPositioning - { - RELATIVE_TO, - ABSOLUTE_TO - }; - ~PathElement(); - virtual Point getFirstPoint() const = 0; + virtual Vector getEndOffset() const = 0; - virtual Point getEndPoint() const = 0; - - void setPostscriptPositioning(PostscriptPositioning positioning) + PathOffsetType getPathOffsetType() const { - mPostscriptPositioning = positioning; + return mOffsetType; } - virtual std::string toPostScriptString(std::size_t precision = 0) const = 0; + bool isRelativeOffset() const + { + return mOffsetType == PathOffsetType::RELATIVE_TO; + } -protected: - PostscriptPositioning mPostscriptPositioning{ PostscriptPositioning::RELATIVE_TO}; + void setPathOffsetType(PathOffsetType offsetType) + { + mOffsetType = offsetType; + } + +private: + PathOffsetType mOffsetType; }; + +using PathElement2 = PathElement<2>; diff --git a/src/base/geometry/path/PathPostScriptConverter.cpp b/src/base/geometry/path/PathPostScriptConverter.cpp deleted file mode 100644 index 82b77b9..0000000 --- a/src/base/geometry/path/PathPostScriptConverter.cpp +++ /dev/null @@ -1,333 +0,0 @@ -#include "PathPostScriptConverter.h" - -#include "Path.h" - -#include "StringUtils.h" -#include "FileLogger.h" - -#include "Line.h" -#include "LineSegment.h" -#include "Arc.h" -#include "QuadraticBezierCurve.h" -#include "CubicBezierCurve.h" - -#include "PointParser.h" - -void PathPostScriptConverter::fromPostScript(GeometryPath* targetPath, const std::string& postScriptPath) -{ - mCurrentPoint = Point(); - - for (auto c : postScriptPath) - { - if (c == 'M' || c == 'm') - { - mLineState = LineState::IN_FIRST_POINT; - mPositionState = getPositionState(c); - - mWorkingFeature = std::make_unique(); - } - else if (c == 'H' || c == 'h') - { - onNewElement(c); - mLineState = LineState::IN_HORIZONTAL; - } - else if (c == 'V' || c == 'v') - { - onNewElement(c); - mLineState = LineState::IN_VERTICAL; - } - else if (c == 'L' || c == 'l') - { - onNewElement(c); - mLineState = LineState::IN_LINE; - } - else if (c == 'C' || c == 'c') - { - onNewElement(c); - mLineState = LineState::IN_CUBIC_BEZIER; - } - else if (c == 'Q' || c == 'q') - { - onNewElement(c); - mLineState = LineState::IN_QUADRATIC_BEZIER; - } - else if (c == 'A' || c == 'a') - { - onNewElement(c); - mLineState = LineState::IN_ARC; - } - else if (c == 'Z' || c == 'z') - { - onNewElement(c); - - mLineState = LineState::START; - targetPath->addFeature(std::move(mWorkingFeature)); - mWorkingFeature = nullptr; - } - else if (std::isblank(c)) - { - onNonNumeric(); - } - else if (std::isalpha(c)) - { - onNewElement(c); - mLineState = LineState::IN_UNSUPPORTED; - } - else - { - mBuffer.push_back(c); - } - } -} - -void PathPostScriptConverter::onNewElement(char c) -{ - onNonNumeric(); - - onElementEnd(); - - mPositionState = getPositionState(c); -} - -void PathPostScriptConverter::onNonNumeric() -{ - if (!mBuffer.empty()) - { - mPointBuffer.push_back(std::stod(mBuffer)); - mBuffer.clear(); - } -} - -PathPostScriptConverter::PositionState PathPostScriptConverter::getPositionState(char c) const -{ - return std::isupper(c) ? PositionState::ABSOLUTE : PositionState::RELATIVE; -} - -void PathPostScriptConverter::onElementEnd() -{ - if (mPointBuffer.empty()) - { - return; - } - - PathElementPtr element; - if (mLineState == LineState::IN_HORIZONTAL) - { - element = onHorizontalLineTo(); - } - else if (mLineState == LineState::IN_VERTICAL) - { - element = onVerticalLineTo(); - } - else if (mLineState == LineState::IN_LINE) - { - element = onLineTo(); - } - else if (mLineState == LineState::IN_ARC) - { - element = onArc(); - } - else if (mLineState == LineState::IN_QUADRATIC_BEZIER) - { - element = onQuadraticBezier(); - } - else if (mLineState == LineState::IN_CUBIC_BEZIER) - { - element = onCubicBezier(); - } - else if (mLineState == LineState::IN_FIRST_POINT) - { - onMoveTo(); - } - - if (element) - { - const auto positioning = (mPositionState == PositionState::RELATIVE) ? PathElement::PostscriptPositioning::RELATIVE_TO : PathElement::PostscriptPositioning::ABSOLUTE_TO; - element->setPostscriptPositioning(positioning); - mCurrentPoint = element->getEndPoint(); - mWorkingFeature->addElement(std::move(element)); - } - - mPointBuffer.clear(); -} - -void PathPostScriptConverter::onMoveTo() -{ - if (mPointBuffer.size() != 2) - { - return; - } - if (mPositionState == PositionState::RELATIVE) - { - mCurrentPoint = Point(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY() + mPointBuffer[1]); - } - else - { - mCurrentPoint = Point(mPointBuffer[0], mPointBuffer[1]); - } -} - -PathElementPtr PathPostScriptConverter::onHorizontalLineTo() -{ - PathElementPtr element; - if (mPointBuffer.size() == 1) - { - if (mPositionState == PositionState::RELATIVE) - { - element = std::make_unique(mCurrentPoint, Point(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY())); - } - else - { - element = std::make_unique(mCurrentPoint, Point(mPointBuffer[0], mCurrentPoint.getY())); - } - } - else - { - Line::InputBufferType buffer_type = mPositionState == PositionState::RELATIVE ? Line::InputBufferType::HORIZONTAL_REL : Line::InputBufferType::HORIZONTAL_ABS; - element = std::make_unique(mCurrentPoint, buffer_type, mPointBuffer); - } - return element; -} - -PathElementPtr PathPostScriptConverter::onVerticalLineTo() -{ - PathElementPtr element; - if (mPointBuffer.size() == 1) - { - if (mPositionState == PositionState::RELATIVE) - { - element = std::make_unique(mCurrentPoint, Point(mCurrentPoint.getX(), mCurrentPoint.getY() + mPointBuffer[0])); - } - else - { - element = std::make_unique(mCurrentPoint, Point(mCurrentPoint.getX(), mPointBuffer[0])); - } - } - else - { - Line::InputBufferType buffer_type = mPositionState == PositionState::RELATIVE ? Line::InputBufferType::VERTICAL_REL : Line::InputBufferType::VERTICAL_ABS; - element = std::make_unique(mCurrentPoint, buffer_type, mPointBuffer); - } - return element; -} - -PathElementPtr PathPostScriptConverter::onLineTo() -{ - PathElementPtr element; - if (mPointBuffer.size() == 2) - { - if (mPositionState == PositionState::RELATIVE) - { - const auto next_point = Point(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY() + mPointBuffer[1]); - element = std::make_unique(mCurrentPoint, next_point); - } - else - { - const auto next_point = Point(mPointBuffer[0], mPointBuffer[1]); - element = std::make_unique(mCurrentPoint, next_point); - } - } - else - { - Line::InputBufferType buffer_type = mPositionState == PositionState::RELATIVE ? Line::InputBufferType::XY_REL : Line::InputBufferType::XY_ABS; - element = std::make_unique(mCurrentPoint, buffer_type, mPointBuffer); - } - return element; -} - -PathElementPtr PathPostScriptConverter::onArc() -{ - PathElementPtr element; - if (mPointBuffer.size() == 7) - { - double rx = mPointBuffer[0]; - double ry = mPointBuffer[1]; - double rotation = mPointBuffer[2]; - bool large_arc = bool(mPointBuffer[3]); - bool sweep = bool(mPointBuffer[4]); - - if (mPositionState == PositionState::RELATIVE) - { - const auto end_point = Point(mCurrentPoint.getX() + mPointBuffer[5], mCurrentPoint.getY() + mPointBuffer[6]); - element = std::make_unique(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep); - } - else - { - const auto end_point = Point(mPointBuffer[5], mPointBuffer[6]); - element = std::make_unique(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep); - } - } - return element; -} - -PathElementPtr PathPostScriptConverter::onQuadraticBezier() -{ - PathElementPtr element; - if (mPointBuffer.size() == 4) - { - double control_x = mPointBuffer[0]; - double control_y = mPointBuffer[1]; - double end_x = mPointBuffer[2]; - double end_y = mPointBuffer[3]; - if (mPositionState == PositionState::RELATIVE) - { - const auto control_point = Point(mCurrentPoint.getX() + control_x, mCurrentPoint.getY() + control_y); - const auto end_point = Point(mCurrentPoint.getX() + end_x, mCurrentPoint.getY() + end_y); - element = std::make_unique(mCurrentPoint, end_point, control_point); - } - else - { - const auto control_point = Point(control_x, control_y); - const auto end_point = Point(end_x, end_y); - element = std::make_unique(mCurrentPoint, end_point, control_point); - } - } - return element; -} - -PathElementPtr PathPostScriptConverter::onCubicBezier() -{ - PathElementPtr element; - if (mPointBuffer.size() == 6) - { - double control0_x = mPointBuffer[0]; - double control0_y = mPointBuffer[1]; - double control1_x = mPointBuffer[2]; - double control1_y = mPointBuffer[3]; - double end_x = mPointBuffer[4]; - double end_y = mPointBuffer[5]; - if (mPositionState == PositionState::RELATIVE) - { - const auto control_point0 = Point(mCurrentPoint.getX() + control0_x, mCurrentPoint.getY() + control0_y); - const auto control_point1 = Point(mCurrentPoint.getX() + control1_x, mCurrentPoint.getY() + control1_y); - const auto end_point = Point(mCurrentPoint.getX() + end_x, mCurrentPoint.getY() + end_y); - element = std::make_unique(mCurrentPoint, end_point, control_point0, control_point1); - } - else - { - const auto control_point0 = Point(control0_x, control0_y); - const auto control_point1 = Point(control1_x, control1_y); - const auto end_point = Point(end_x, end_y); - element = std::make_unique(mCurrentPoint, end_point, control_point0, control_point1); - } - } - return element; -} - -std::string PathPostScriptConverter::toPostScript(const GeometryPath* targetPath) -{ - std::string path; - for (const auto& feature : targetPath->getFeatures()) - { - auto start_loc = feature->getLocation(); - path += "M" + PointParser::toString(start_loc, 2, " ", mPrecision); - - for (const auto& path_element : feature->getElements()) - { - path += path_element->toPostScriptString(mPrecision); - } - path += "Z "; - } - return path; -} - diff --git a/src/base/geometry/path/QuadraticBezierCurve.cpp b/src/base/geometry/path/QuadraticBezierCurve.cpp index fff1072..d96a0fd 100644 --- a/src/base/geometry/path/QuadraticBezierCurve.cpp +++ b/src/base/geometry/path/QuadraticBezierCurve.cpp @@ -1,63 +1,36 @@ #include "QuadraticBezierCurve.h" -#include "PointParser.h" - -QuadraticBezierCurve::QuadraticBezierCurve(const Point& startPoint, const Point& endPoint, const Point& controlPoint) - : mStartPoint(startPoint), - mEndPoint(endPoint), - mControlPoint(controlPoint) +template +QuadraticBezierCurve::QuadraticBezierCurve(const Vector& endOffset, const Vector& controlOffset) + : mEndOffset(endOffset), + mControlOffset(controlOffset) { } -Point QuadraticBezierCurve::getFirstPoint() const +template +Vector QuadraticBezierCurve::getEndOffset() const { - return mStartPoint; + return mEndOffset; } -Point QuadraticBezierCurve::getEndPoint() const +template +const Vector& QuadraticBezierCurve::getControlOffset() const { - return mEndPoint; + return mControlOffset; } -Point QuadraticBezierCurve::getControlPoint() const -{ - return mControlPoint; -} - -std::string QuadraticBezierCurve::toPostScriptString(std::size_t precision) const -{ - if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO) - { - return "q" + PointParser::toStringRelative(mControlPoint, mStartPoint, 2, " ", precision) + " " + PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision); - } - else - { - return "Q" + PointParser::toString(mControlPoint, 2, " ", precision) + " " + PointParser::toString(mEndPoint, 2, " ", precision); - } -} - -Bounds QuadraticBezierCurve::getBounds() const +template +Bounds QuadraticBezierCurve::getBounds() const { return {}; } -const Point& QuadraticBezierCurve::getLocation() const -{ - return mStartPoint; -} - -void QuadraticBezierCurve::sample(SparseGrid*) const -{ - -} - -QuadraticBezierCurve::Type QuadraticBezierCurve::getType() const -{ - return Type::CURVE; -} - -QuadraticBezierCurve::CurveType QuadraticBezierCurve::getCurveType() const +template +CurveType QuadraticBezierCurve::getCurveType() const { return CurveType::QUADRATIC_BEZIER; } + +template class QuadraticBezierCurve<2>; +template class QuadraticBezierCurve<3>; \ No newline at end of file diff --git a/src/base/geometry/path/QuadraticBezierCurve.h b/src/base/geometry/path/QuadraticBezierCurve.h index ce85d93..28125c2 100644 --- a/src/base/geometry/path/QuadraticBezierCurve.h +++ b/src/base/geometry/path/QuadraticBezierCurve.h @@ -3,31 +3,21 @@ #include "Curve.h" #include "Point.h" -class QuadraticBezierCurve : public Curve +template +class QuadraticBezierCurve : public Curve { public: - QuadraticBezierCurve(const Point& startPoint, const Point& endPoint, const Point& controlPoint); + QuadraticBezierCurve(const Vector& endOffset, const Vector& controlOffset); - Point getFirstPoint() const override; + const Vector& getControlOffset() const; - Point getControlPoint() const; - - Point getEndPoint() const override; + Vector getEndOffset() const override; Bounds getBounds() const override; - const Point& getLocation() const override; - - Type getType() const override; - CurveType getCurveType() const override; - void sample(SparseGrid*) const override; - - std::string toPostScriptString(std::size_t precision = 0) const override; - private: - Point mStartPoint; - Point mEndPoint; - Point mControlPoint; + Vector mEndOffset; + Vector mControlOffset; }; diff --git a/src/base/geometry/points/Point.cpp b/src/base/geometry/points/Point.cpp index 65a1d1d..a1e6484 100644 --- a/src/base/geometry/points/Point.cpp +++ b/src/base/geometry/points/Point.cpp @@ -2,51 +2,116 @@ #include "Transform.h" +#include #include +#include -Point::Point(double x, double y, double z) - : mX(x), - mY(y), - mZ(z) -{ -} - -Point::Point(const DiscretePoint& point) - : mX(static_cast(point.getX())), - mY(static_cast(point.getY())), - mZ(0) +template +Point::Point(const Point<2>& p) + : Point(p.getX(), p.getY()) { } -Point::Point(const Point& reference, double offSetX, double offSetY, double offSetZ) -: mX(reference.getX() + offSetX), - mY(reference.getY() + offSetY), - mZ(reference.getZ() + offSetZ) +template +Point::Point(double x, double y, double z) { - + mCoords = std::vector(DIM); + if (DIM > 0) + { + mCoords[0] = x; + } + if (DIM > 1) + { + mCoords[1] = y; + } + if (DIM > 2) + { + mCoords[2] = z; + } } -Point::~Point() +template +Point::Point(const Vector& v) +{ + mCoords = std::vector(DIM); + for (std::size_t idx = 0; idx < DIM; idx++) + { + mCoords[idx] = v.getEntry(idx); + } +} + +template +Point::Point(const DiscretePoint& point) + : Point(static_cast(point.getX()), static_cast(point.getY()), 0.0) +{ + +} + +template +Point::Point(const Point& reference, double offSetX, double offSetY, double offSetZ) +{ + mCoords = std::vector(DIM); + if (DIM > 0) + { + mCoords[0] = reference.getX() + offSetX; + } + if (DIM > 1) + { + mCoords[1] = reference.getY() + offSetY; + } + if (DIM > 2) + { + mCoords[2] = reference.getZ() + offSetZ; + } +} + +template +Point::~Point() { }; -double Point::getX() const +template +double Point::getX() const { - return mX; + if (DIM > 0) + { + return mCoords[0]; + } + else + { + return 0.0; + } } -double Point::getY() const +template +double Point::getY() const { - return mY; + if (DIM > 1) + { + return mCoords[1]; + } + else + { + return 0.0; + } } -double Point::getZ() const +template +double Point::getZ() const { - return mZ; + if (DIM > 2) + { + return mCoords[2]; + } + else + { + return 0.0; + } } -double Point::getDistance(const Point& point) const +template +double Point::getDistance(const Point& point) const { const auto deltaX = getDeltaX(point); const auto deltaY = getDeltaY(point); @@ -54,50 +119,97 @@ double Point::getDistance(const Point& point) const return std::sqrt(deltaX* deltaX + deltaY* deltaY + deltaZ* deltaZ); } -Vector Point::getDelta(const Point& point) const +template +Vector Point::getDelta(const Point& point) const { - return Vector(point.mX - mX, point.mY - mY, point.mZ - mZ); + return Vector({ point.getX() - getX(), point.getY() - getY(), point.getZ() - getZ() }); } -double Point::getDeltaX(const Point& point) const +template +double Point::getDeltaX(const Point& point) const { - return point.getX() - mX; + return point.getX() - getX(); } -double Point::getDeltaY(const Point& point) const +template +double Point::getDeltaY(const Point& point) const { - return point.getY() - mY; + return point.getY() - getY(); } -double Point::getDeltaZ(const Point& point) const +template +double Point::getDeltaZ(const Point& point) const { - return point.getZ() - mZ; + return point.getZ() - getZ(); } -bool Point::isAtOrigin() const +template +bool Point::isAtOrigin() const { - return mX == 0.0 && mY == 0.0 && mZ == 0.0; + return std::accumulate(mCoords.begin(), mCoords.end(), 0.0) == 0.0; } -void Point::apply(const Transform& transform) +template +Vector Point::getOriginOffset() const { - mX -= transform.getLocation().getX(); - mY -= transform.getLocation().getY(); - mZ -= transform.getLocation().getZ(); - - mX *= transform.getScale().mX; - mY *= transform.getScale().mY; - mZ *= transform.getScale().mZ; + return Vector(mCoords); } -void Point::move(double x, double y, double z) +template +void Point::apply(const Transform& transform) { - mX += x; - mY += y; - mZ += z; + moveBy(-transform.getLocation().getX(), -transform.getLocation().getY(), -transform.getLocation().getZ()); + scale(transform.getScale().mX, transform.getScale().mY, transform.getScale().mZ); } -void Point::move(const Vector& vector) +template +void Point::scale(double x, double y, double z) { - move(vector.getX(), vector.getY(), vector.getZ()); + if (DIM > 0) + { + mCoords[0] *= x; + } + if (DIM > 1) + { + mCoords[1] *= y; + } + if (DIM > 2) + { + mCoords[2] *= z; + } } + +template +void Point::moveBy(double x, double y, double z) +{ + if (DIM > 0) + { + mCoords[0] += x; + } + if (DIM > 1) + { + mCoords[1] += y; + } + if (DIM > 2) + { + mCoords[2] += z; + } +} + +template +void Point::moveBy(const Vector& vector) +{ + for (std::size_t idx = 0; idx < DIM; idx++) + { + mCoords[idx] += vector.getEntry(idx); + } +} + +template +bool Point::isEqual(const Point& rhs) const +{ + return mCoords == rhs.mCoords; +} + +template class Point<2>; +template class Point<3>; diff --git a/src/base/geometry/points/Point.h b/src/base/geometry/points/Point.h index 8efa5f2..c490c9c 100644 --- a/src/base/geometry/points/Point.h +++ b/src/base/geometry/points/Point.h @@ -7,14 +7,19 @@ class Transform; +template class Point { public: - Point(double x = 0, double y = 0, double z = 0); + Point(double x = 0, double y = 0, double z = 0.0); + + Point(const Vector& v); + + Point(const Point<2>& p); Point(const DiscretePoint& point); - Point(const Point& reference, double offSetX, double offSetY, double offSetZ = 0); + Point(const Point& reference, double offSetX, double offSetY, double offSetZ = 0); ~Point(); @@ -26,43 +31,56 @@ public: double getZ() const; - double getDistance(const Point& point) const; + double getDistance(const Point& point) const; - double getDeltaX(const Point& point) const; + double getDeltaX(const Point& point) const; - double getDeltaY(const Point& point) const; + double getDeltaY(const Point& point) const; - double getDeltaZ(const Point& point) const; + double getDeltaZ(const Point& point) const; - Vector getDelta(const Point& point) const; + Vector getOriginOffset() const; + + Vector getDelta(const Point& point) const; bool isAtOrigin() const; - void move(const Vector& vector); + bool isEqual(const Point& rhs) const; - void move(double x, double y = 0.0, double z = 0.0); + void moveBy(const Vector& vector); - void operator+=(const Vector& vector) + void scale(double x, double y = 0.0, double z = 0.0); + + void moveBy(double x, double y = 0.0, double z = 0.0); + + Point operator+(const Vector& vector) { - move(vector); + Point p(*this); + p += vector; + return p; } - bool operator==(const Point& rhs) const + void operator+=(const Vector& vector) { - return (mX == rhs.mX) - && (mY == rhs.mY) - && (mZ == rhs.mZ); + moveBy(vector); } - bool operator!=(const Point& rhs) const + bool operator==(const Point& rhs) const + { + return isEqual(rhs); + } + + bool operator!=(const Point& rhs) const { return !operator==(rhs); } private: - double mX{0}; - double mY{0}; - double mZ{0}; + std::vector mCoords; }; -using PointPtr = std::unique_ptr; +using Point3 = Point<3>; +using Point2 = Point<2>; + +using PointPtr3 = std::unique_ptr >; +using PointPtr2 = std::unique_ptr >; \ No newline at end of file diff --git a/src/base/geometry/points/PointCollection.cpp b/src/base/geometry/points/PointCollection.cpp index 3c87cfa..9322094 100644 --- a/src/base/geometry/points/PointCollection.cpp +++ b/src/base/geometry/points/PointCollection.cpp @@ -1,12 +1,14 @@ #include "PointCollection.h" -PointCollection::PointCollection(const std::vector points) +template +PointCollection::PointCollection(const std::vector > points) : mPoints(points) { } -void PointCollection::apply(const Transform& transform) +template +void PointCollection::apply(const Transform& transform) { for (auto& point : mPoints) { @@ -14,12 +16,14 @@ void PointCollection::apply(const Transform& transform) } } -void PointCollection::addPoint(const Point& point) +template +void PointCollection::addPoint(const Point& point) { mPoints.push_back(point); } -Bounds PointCollection::getBounds() const +template +Bounds PointCollection::getBounds() const { Bounds bounds{0.0, 0.0, 0.0, 0.0}; @@ -36,7 +40,8 @@ Bounds PointCollection::getBounds() const return bounds; } -Point PointCollection::getEndPoint() const +template +Point PointCollection::getEndPoint() const { if (mPoints.empty()) { @@ -48,7 +53,11 @@ Point PointCollection::getEndPoint() const } } -const std::vector& PointCollection::getPoints() const +template +const std::vector >& PointCollection::getPoints() const { return mPoints; -} \ No newline at end of file +} + +template class PointCollection<2>; +template class PointCollection<3>; \ No newline at end of file diff --git a/src/base/geometry/points/PointCollection.h b/src/base/geometry/points/PointCollection.h index 99f917b..777ba20 100644 --- a/src/base/geometry/points/PointCollection.h +++ b/src/base/geometry/points/PointCollection.h @@ -6,21 +6,22 @@ #include +template class PointCollection { public: - PointCollection(const std::vector points = {}); + PointCollection(const std::vector > points = {}); - void addPoint(const Point& point); + void addPoint(const Point& point); void apply(const Transform& transform); Bounds getBounds() const; - Point getEndPoint() const; + Point getEndPoint() const; - const std::vector& getPoints() const; + const std::vector >& getPoints() const; private: - std::vector mPoints; + std::vector > mPoints; }; diff --git a/src/base/geometry/points/PointParser.cpp b/src/base/geometry/points/PointParser.cpp index 7fa3608..82213f0 100644 --- a/src/base/geometry/points/PointParser.cpp +++ b/src/base/geometry/points/PointParser.cpp @@ -2,49 +2,27 @@ #include -std::string PointParser::toString(const Point& p, std::size_t dimensions, const std::string& delimiter, std::size_t precision) +std::string PointParser::toString(const Point2& p, const std::string& delimiter, std::size_t precision) { - return toString(p.getX(), p.getY(), p.getZ(), dimensions, delimiter, precision); + return toString(p.getX(), p.getY(), delimiter, precision); } -std::string PointParser::toStringRelative(const Point& p, const Point& relativeTo, std::size_t dimensions, const std::string& delimiter, std::size_t precision) +std::string PointParser::toString(const Vector2& v, const std::string& delimiter, std::size_t precision) { - return toString(relativeTo.getDeltaX(p), relativeTo.getDeltaY(p), relativeTo.getDeltaZ(p), dimensions, delimiter, precision); + return toString(v.getEntry(0), v.getEntry(1), delimiter, precision); } -std::string PointParser::toString(double x, double y, double z, std::size_t dimensions, const std::string& delimiter, std::size_t precision) +std::string PointParser::toString(double x, double y, const std::string& delimiter, std::size_t precision) { if (precision == 0) { - if (dimensions == 1) - { - return std::to_string(x); - } - else if (dimensions == 2) - { - return std::to_string(x) + delimiter + std::to_string(y); - } - else - { - return std::to_string(x) + delimiter + std::to_string(y) + delimiter + std::to_string(z); - } + return std::to_string(x) + delimiter + std::to_string(y); } else { std::stringstream sstr; sstr.precision(precision); - if (dimensions == 1) - { - sstr << x; - } - else if (dimensions == 2) - { - sstr << x << delimiter << y; - } - else - { - sstr << x << delimiter << y << delimiter << z; - } + sstr << x << delimiter << y; return sstr.str(); } } diff --git a/src/base/geometry/points/PointParser.h b/src/base/geometry/points/PointParser.h index 3ab83ce..6f64329 100644 --- a/src/base/geometry/points/PointParser.h +++ b/src/base/geometry/points/PointParser.h @@ -7,12 +7,11 @@ class PointParser { public: + static std::string toString(const Point2& p, const std::string& delimiter = " ", std::size_t precision = 0); - static std::string toString(const Point& p, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0); + static std::string toString(const Vector2& v, const std::string& delimiter = " ", std::size_t precision = 0); - static std::string toStringRelative(const Point& p, const Point& relativeTo, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0); - - static std::string toString(double x, double y, double z, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0); + static std::string toString(double x, double y, const std::string& delimiter = " ", std::size_t precision = 0); static std::string toString(double x, std::size_t precision = 0); }; diff --git a/src/base/geometry/primitives/Circle.cpp b/src/base/geometry/primitives/Circle.cpp index 5261e63..168119d 100644 --- a/src/base/geometry/primitives/Circle.cpp +++ b/src/base/geometry/primitives/Circle.cpp @@ -1,18 +1,11 @@ #include "Circle.h" -Circle::Circle(const Point& centre, double radius) - : mRadius(radius), - mCentre(centre) - +Circle::Circle(double radius) + : mRadius(radius) { mMinorRadius = mRadius; } -const Point& Circle::getLocation() const -{ - return mCentre; -} - double Circle::getRadius() const { return mRadius; @@ -28,11 +21,6 @@ void Circle::setMinorRadius(double radius) mMinorRadius = radius; } -void Circle::sample(SparseGrid*) const -{ - -} - bool Circle::isEllipse() const { return mRadius != mMinorRadius; @@ -40,10 +28,10 @@ bool Circle::isEllipse() const Bounds Circle::getBounds() const { - double minX = mCentre.getX() - mRadius; - double maxX = mCentre.getX() + mRadius; - double minY = mCentre.getY() - mMinorRadius; - double maxY = mCentre.getY() + mMinorRadius; + double minX = -mRadius; + double maxX = mRadius; + double minY = -mMinorRadius; + double maxY = mMinorRadius; return { minX, maxX, minY, maxY }; } diff --git a/src/base/geometry/primitives/Circle.h b/src/base/geometry/primitives/Circle.h index 3b69bb0..f7b623b 100644 --- a/src/base/geometry/primitives/Circle.h +++ b/src/base/geometry/primitives/Circle.h @@ -1,14 +1,11 @@ #pragma once #include "AbstractGeometricItem.h" -#include "Point.h" class Circle : public AbstractGeometricItem { public: - Circle(const Point& centre, double radius = 0.5); - - const Point& getLocation() const override; + Circle(double radius = 0.5); double getRadius() const; @@ -22,10 +19,7 @@ public: void setMinorRadius(double radius); - void sample(SparseGrid*) const override; - private: double mMinorRadius{ 0.5 }; double mRadius{ 0.5 }; - Point mCentre; }; diff --git a/src/base/geometry/primitives/Polygon.cpp b/src/base/geometry/primitives/Polygon.cpp index 839cf22..abdbdf1 100644 --- a/src/base/geometry/primitives/Polygon.cpp +++ b/src/base/geometry/primitives/Polygon.cpp @@ -1,38 +1,31 @@ #include "Polygon.h" namespace ntk { - Polygon::Polygon(const std::vector& points) + template + Polygon::Polygon(const std::vector >& points) : AbstractGeometricItem() { - if (points.size() > 0) - { - mStartPoint = points[0]; - } - mPoints = PointCollection(points); + mPoints = PointCollection(points); } - const PointCollection& Polygon::getPoints() const + template + const PointCollection& Polygon::getPoints() const { return mPoints; } - Bounds Polygon::getBounds() const + template + Bounds Polygon::getBounds() const { return mPoints.getBounds(); } - const Point& Polygon::getLocation() const - { - return mStartPoint; - } - - void Polygon::sample(SparseGrid*) const - { - - } - - Polygon::Type Polygon::getType() const + template + AbstractGeometricItem::Type Polygon::getType() const { return Polygon::Type::POLYGON; } + + template class Polygon<2>; + template class Polygon<3>; } \ No newline at end of file diff --git a/src/base/geometry/primitives/Polygon.h b/src/base/geometry/primitives/Polygon.h index b270dbd..07a005d 100644 --- a/src/base/geometry/primitives/Polygon.h +++ b/src/base/geometry/primitives/Polygon.h @@ -5,23 +5,21 @@ #include "PointCollection.h" namespace ntk{ +template class Polygon : public AbstractGeometricItem { public: - Polygon(const std::vector& points); + Polygon(const std::vector >& points); - const PointCollection& getPoints() const; + const PointCollection& getPoints() const; Bounds getBounds() const override; - const Point& getLocation() const override; - - void sample(SparseGrid*) const override; - - Type getType() const override; + AbstractGeometricItem::Type getType() const override; private: - Point mStartPoint; - PointCollection mPoints; + PointCollection mPoints; }; -} \ No newline at end of file +} + +using Polygon2 = ntk::Polygon<2>; \ No newline at end of file diff --git a/src/base/geometry/primitives/Rectangle.cpp b/src/base/geometry/primitives/Rectangle.cpp index 0c38e44..63a4646 100644 --- a/src/base/geometry/primitives/Rectangle.cpp +++ b/src/base/geometry/primitives/Rectangle.cpp @@ -1,18 +1,9 @@ #include "Rectangle.h" namespace ntk { - Rectangle::Rectangle(const Point& bottomLeft, const Point& topRight) - : mBottomLeft(bottomLeft) - { - mHeight = mBottomLeft.getDeltaY(topRight); - mWidth = mBottomLeft.getDeltaX(topRight); - } - - Rectangle::Rectangle(const Point& bottomLeft, double width, double height) - : mBottomLeft(bottomLeft), - mWidth(width), - mHeight(height) - + Rectangle::Rectangle(double width, double height) + : mWidth(width), + mHeight(height) { } @@ -24,19 +15,14 @@ namespace ntk { Bounds Rectangle::getBounds() const { - const auto minX = mBottomLeft.getX(); - const auto maxX = mBottomLeft.getX() + mWidth; + const auto minX = 0.0; + const auto maxX = mWidth; - const auto minY = mBottomLeft.getY(); - const auto maxY = mBottomLeft.getY() + mHeight; + const auto minY = 0.0; + const auto maxY = mHeight; return { minX , maxX , minY , maxY }; } - void Rectangle::sample(SparseGrid*) const - { - - } - double Rectangle::getHeight() const { return mHeight; @@ -47,11 +33,6 @@ namespace ntk { return mWidth; } - const Point& Rectangle::getLocation() const - { - return mBottomLeft; - } - double Rectangle::getRadius() const { return mRadius; diff --git a/src/base/geometry/primitives/Rectangle.h b/src/base/geometry/primitives/Rectangle.h index 2961db4..bbff2ff 100644 --- a/src/base/geometry/primitives/Rectangle.h +++ b/src/base/geometry/primitives/Rectangle.h @@ -6,15 +6,12 @@ namespace ntk{ class Rectangle : public AbstractGeometricItem { public: - Rectangle(const Point& bottomLeft, const Point& topRight); - Rectangle(const Point& bottomLeft, double width, double height); + Rectangle(double width, double height); double getHeight() const; double getWidth() const; - const Point& getLocation() const override; - Bounds getBounds() const override; Type getType() const override; @@ -23,10 +20,7 @@ public: void setRadius(double radius); - void sample(SparseGrid*) const override; - private: - Point mBottomLeft; double mWidth{0}; double mHeight{0}; double mRadius{ 0.0 }; diff --git a/src/publishing/plotting/EquationNode.cpp b/src/publishing/plotting/EquationNode.cpp index 155089f..7bfaa47 100644 --- a/src/publishing/plotting/EquationNode.cpp +++ b/src/publishing/plotting/EquationNode.cpp @@ -60,7 +60,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression node->setFont(mDefaultFont); addChild(node.get()); - mTextCursor.move(node->getContentWidth(sceneInfo), 0.0); + mTextCursor.moveBy(node->getContentWidth(sceneInfo), 0.0); mText.push_back(std::move(node)); } @@ -70,19 +70,19 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression if (expression->getExpressions().size() == 2) { auto x_cache = mTextCursor.getX(); - mTextCursor.move(0.0, -9.0); + mTextCursor.moveBy(0.0, -9.0); addExpression(sceneInfo, expression->getExpressions()[0].get()); - mTextCursor.move(x_cache - mTextCursor.getX(), 16.0); - std::vector end_loc{ { 25.0, 0.0 } }; + mTextCursor.moveBy(x_cache - mTextCursor.getX(), 16.0); + std::vector end_loc{ { 25.0, 0.0 } }; auto dividing_line = std::make_unique(Transform(mTextCursor), end_loc); addChild(dividing_line.get()); mLines.push_back(std::move(dividing_line)); - mTextCursor.move(0.0, 2.0); + mTextCursor.moveBy(0.0, 2.0); addExpression(sceneInfo, expression->getExpressions()[1].get()); - mTextCursor.move(0.0, -9.0); + mTextCursor.moveBy(0.0, -9.0); } } else if (expression->getType() == LatexMathExpression::Type::ENCLOSING) @@ -96,7 +96,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression left_node->setFont(mDefaultFont); addChild(left_node.get()); - mTextCursor.move(left_node->getContentWidth(sceneInfo), 0.0); + mTextCursor.moveBy(left_node->getContentWidth(sceneInfo), 0.0); mText.push_back(std::move(left_node)); addExpression(sceneInfo, expression->getExpressions()[0].get()); @@ -107,7 +107,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression right_node->setFont(mDefaultFont); addChild(right_node.get()); - mTextCursor.move(right_node->getContentWidth(sceneInfo), 0.0); + mTextCursor.moveBy(right_node->getContentWidth(sceneInfo), 0.0); mText.push_back(std::move(right_node)); } diff --git a/src/publishing/plotting/EquationNode.h b/src/publishing/plotting/EquationNode.h index da4ee51..0e9018b 100644 --- a/src/publishing/plotting/EquationNode.h +++ b/src/publishing/plotting/EquationNode.h @@ -30,7 +30,7 @@ protected: FontItem mDefaultFont{ "Cambria Math", 14 }; //FontItem mDefaultFont{ "Latin Modern Math", 14 }; - Point mTextCursor; + Point2 mTextCursor; LatexMathExpression* mContent{ nullptr }; bool mContentDirty{ true }; diff --git a/src/publishing/plotting/Plot.h b/src/publishing/plotting/Plot.h index 5cb1553..b1fc438 100644 --- a/src/publishing/plotting/Plot.h +++ b/src/publishing/plotting/Plot.h @@ -54,14 +54,14 @@ public: } - void setData(const std::vector& data) + void setData(const std::vector& data) { mData = data; } private: std::string mLabel; - std::vector mData; + std::vector mData; }; class Plot diff --git a/src/publishing/plotting/PlotNode.cpp b/src/publishing/plotting/PlotNode.cpp index 2ce9da4..95ad9ea 100644 --- a/src/publishing/plotting/PlotNode.cpp +++ b/src/publishing/plotting/PlotNode.cpp @@ -44,14 +44,14 @@ void PlotNode::createOrUpdateGeometry(SceneInfo*) const double width = 100.0; Point x_axis_start{ 0.0, height }; - std::vector x_axis_points = { Point(width, 0.0) }; + std::vector x_axis_points = { Point2(width, 0.0) }; mXAxis = std::make_unique(Transform(x_axis_start), x_axis_points); mXAxis->setEndEndStyle(mAxisEndStyle); addChild(mXAxis.get()); Point y_axis_start{ 0.0, height }; - std::vector y_axis_points = { Point(0.0, -height) }; + std::vector y_axis_points = { Point2(0.0, -height) }; mYAxis = std::make_unique(Transform(y_axis_start), y_axis_points); mYAxis->setEndEndStyle(mAxisEndStyle); diff --git a/src/rendering/fonts/FontGlyph.cpp b/src/rendering/fonts/FontGlyph.cpp index f1cd14f..8230323 100644 --- a/src/rendering/fonts/FontGlyph.cpp +++ b/src/rendering/fonts/FontGlyph.cpp @@ -5,7 +5,7 @@ void GlyphRunOutlines::addSegment(const GlyphRunSegment& segment) mFeatures[mFeatures.size() - 1].mSegments.push_back(segment); } -void GlyphRunOutlines::startFeature(const Point& point, bool isFilled) +void GlyphRunOutlines::startFeature(const Point2& point, bool isFilled) { GlyphRunFeature feature; feature.mFilled = isFilled; diff --git a/src/rendering/fonts/FontGlyph.h b/src/rendering/fonts/FontGlyph.h index 1b2ddf9..4fab17c 100644 --- a/src/rendering/fonts/FontGlyph.h +++ b/src/rendering/fonts/FontGlyph.h @@ -15,7 +15,7 @@ struct GlyphRunSegment LINE, BEZIER }; - std::vector mPoints; + std::vector mPoints; Type mType{ Type::LINE }; }; @@ -29,7 +29,7 @@ class GlyphRunOutlines { public: void addSegment(const GlyphRunSegment& point); - void startFeature(const Point& point, bool isFilled); + void startFeature(const Point2& point, bool isFilled); std::string toPostScriptPath(); private: diff --git a/src/rendering/fonts/directx/DirectWriteHelpers.cpp b/src/rendering/fonts/directx/DirectWriteHelpers.cpp index 2bdd7b6..6d1dacf 100644 --- a/src/rendering/fonts/directx/DirectWriteHelpers.cpp +++ b/src/rendering/fonts/directx/DirectWriteHelpers.cpp @@ -80,7 +80,7 @@ void __stdcall GlyphOutlineGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT verte void __stdcall GlyphOutlineGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin) { - mGlyphRunOutline->startFeature(Point(startPoint.x, startPoint.y), figureBegin == D2D1_FIGURE_BEGIN_FILLED); + mGlyphRunOutline->startFeature(Point2(startPoint.x, startPoint.y), figureBegin == D2D1_FIGURE_BEGIN_FILLED); } void __stdcall GlyphOutlineGeometrySink::AddLines(_In_reads_(pointsCount) CONST D2D1_POINT_2F* points, UINT32 pointsCount) @@ -90,7 +90,7 @@ void __stdcall GlyphOutlineGeometrySink::AddLines(_In_reads_(pointsCount) CONST for (UINT32 idx = 0; idx < pointsCount; idx++) { auto point = points[idx]; - segment.mPoints.push_back(Point(point.x, point.y)); + segment.mPoints.push_back(Point2(point.x, point.y)); } mGlyphRunOutline->addSegment(segment); } @@ -103,9 +103,9 @@ void __stdcall GlyphOutlineGeometrySink::AddBeziers(_In_reads_(beziersCount) CON segment.mType = GlyphRunSegment::Type::BEZIER; auto bezier = beziers[idx]; - segment.mPoints.push_back(Point(bezier.point1.x, bezier.point1.y)); - segment.mPoints.push_back(Point(bezier.point2.x, bezier.point2.y)); - segment.mPoints.push_back(Point(bezier.point3.x, bezier.point3.y)); + segment.mPoints.push_back(Point2(bezier.point1.x, bezier.point1.y)); + segment.mPoints.push_back(Point2(bezier.point2.x, bezier.point2.y)); + segment.mPoints.push_back(Point2(bezier.point3.x, bezier.point3.y)); mGlyphRunOutline->addSegment(segment); } diff --git a/src/rendering/graphics/directx/DirectX2dPainter.cpp b/src/rendering/graphics/directx/DirectX2dPainter.cpp index 981cd27..8dc1268 100644 --- a/src/rendering/graphics/directx/DirectX2dPainter.cpp +++ b/src/rendering/graphics/directx/DirectX2dPainter.cpp @@ -73,8 +73,8 @@ void DirectX2dPainter::paintRect(SceneModel* model) auto rect = dynamic_cast(model->getGeometry()); const auto loc = model->getTransform().getLocation(); - const auto scale_x = model->getTransform().getScaleX(); - const auto scale_y = model->getTransform().getScaleY(); + const auto scale_x = model->getTransform().getScale().mX; + const auto scale_y = model->getTransform().getScale().mY; const auto min_x = static_cast(loc.getX()); const auto max_x = static_cast(loc.getX() + rect->getWidth() * scale_x); @@ -117,8 +117,8 @@ void DirectX2dPainter::paintRect(SceneModel* model) void DirectX2dPainter::paintCircle(SceneModel* model) { const auto loc = model->getTransform().getLocation(); - const auto scale_x = model->getTransform().getScaleX(); - const auto scale_y = model->getTransform().getScaleY(); + const auto scale_x = model->getTransform().getScale().mX; + const auto scale_y = model->getTransform().getScale().mY; auto circle = dynamic_cast(model->getGeometry()); const auto radius = circle->getRadius() * scale_x; @@ -141,7 +141,7 @@ void DirectX2dPainter::paintCircle(SceneModel* model) } } -D2D_POINT_2F DirectX2dPainter::toD2dPoint(const Point& point) +D2D_POINT_2F DirectX2dPainter::toD2dPoint(const Point<2>& point) { return D2D1::Point2F(static_cast(point.getX()), static_cast(point.getY())); } @@ -155,9 +155,9 @@ void DirectX2dPainter::paintLine(SceneModel* model) path_geom->Open(&path_sink); - auto line = dynamic_cast(model->getGeometry()); + auto line = dynamic_cast*>(model->getGeometry()); - path_sink->BeginFigure(toD2dPoint(line->getFirstPoint()), D2D1_FIGURE_BEGIN_FILLED); + path_sink->BeginFigure(toD2dPoint(line->getPoints().getPoints()[0]), D2D1_FIGURE_BEGIN_FILLED); onLine(line, path_sink.Get()); @@ -194,9 +194,9 @@ void DirectX2dPainter::paintPolygon(SceneModel* model) path_geom->Open(&path_sink); - auto polygon = dynamic_cast(model->getGeometry()); + auto polygon = dynamic_cast*>(model->getGeometry()); - path_sink->BeginFigure(toD2dPoint(polygon->getLocation()), D2D1_FIGURE_BEGIN_FILLED); + path_sink->BeginFigure(toD2dPoint(Point2(0.0, 0.0)), D2D1_FIGURE_BEGIN_FILLED); bool first{ true }; for (const auto& point : polygon->getPoints().getPoints()) @@ -245,7 +245,7 @@ void DirectX2dPainter::paintPath(SceneModel* model) auto path_item = dynamic_cast(model->getGeometry()); for (const auto& feature : path_item->getFeatures()) { - const auto loc = feature->getLocation(); + const auto loc = feature->getOffset(); path_sink->BeginFigure(toD2dPoint(loc), D2D1_FIGURE_BEGIN_FILLED); for (const auto& element : feature->getElements()) @@ -260,16 +260,16 @@ void DirectX2dPainter::paintPath(SceneModel* model) } else if (element->getType() == AbstractGeometricItem::Type::CURVE) { - auto curve = dynamic_cast(element.get()); - if (curve->getCurveType() == Curve::CurveType::ARC) + auto curve = dynamic_cast*>(element.get()); + if (curve->getCurveType() == CurveType::ARC) { onArc(curve, path_sink.Get()); } - else if (curve->getCurveType() == Curve::CurveType::CUBIC_BEZIER) + else if (curve->getCurveType() == CurveType::CUBIC_BEZIER) { onCubicBezier(curve, path_sink.Get()); } - else if (curve->getCurveType() == Curve::CurveType::QUADRATIC_BEZIER) + else if (curve->getCurveType() == CurveType::QUADRATIC_BEZIER) { onQuadraticBezier(curve, path_sink.Get()); } @@ -299,11 +299,11 @@ void DirectX2dPainter::paintPath(SceneModel* model) rt->SetTransform(D2D1::Matrix3x2F::Identity()); } -void DirectX2dPainter::onArc(Curve* element, ID2D1GeometrySink* sink) +void DirectX2dPainter::onArc(Curve<2>* element, ID2D1GeometrySink* sink) { auto arc = dynamic_cast(element); - const auto end = toD2dPoint(arc->getEndPoint()); + const auto end = toD2dPoint(arc->getEndOffset()); D2D1_SIZE_F size{static_cast(arc->getRx()), static_cast(arc->getRx()) }; const auto angle = static_cast(arc->getRotation()); D2D1_SWEEP_DIRECTION direction = arc->getSweepParam() ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE; @@ -313,31 +313,31 @@ void DirectX2dPainter::onArc(Curve* element, ID2D1GeometrySink* sink) sink->AddArc(segment); } -void DirectX2dPainter::onQuadraticBezier(Curve* element, ID2D1GeometrySink* sink) +void DirectX2dPainter::onQuadraticBezier(Curve<2>* element, ID2D1GeometrySink* sink) { - auto bezier = dynamic_cast(element); - D2D1_QUADRATIC_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getControlPoint()) , toD2dPoint(bezier->getEndPoint()) }; + auto bezier = dynamic_cast*>(element); + D2D1_QUADRATIC_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getControlOffset()) , toD2dPoint(bezier->getEndOffset()) }; sink->AddQuadraticBezier(segment); } -void DirectX2dPainter::onCubicBezier(Curve* element, ID2D1GeometrySink* sink) +void DirectX2dPainter::onCubicBezier(Curve<2>* element, ID2D1GeometrySink* sink) { - auto bezier = dynamic_cast(element); - D2D1_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getStartControlPoint()), toD2dPoint(bezier->getEndControlPoint()), toD2dPoint(bezier->getEndPoint()) }; + auto bezier = dynamic_cast*>(element); + D2D1_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getStartControlOffset()), toD2dPoint(bezier->getEndControlOffset()), toD2dPoint(bezier->getEndOffset()) }; sink->AddBezier(segment); } -void DirectX2dPainter::onLine(PathElement* element, ID2D1GeometrySink* sink) +void DirectX2dPainter::onLine(PathElement<2>* element, ID2D1GeometrySink* sink) { - for (const auto& point : dynamic_cast(element)->getPoints().getPoints()) + for (const auto& point : dynamic_cast*>(element)->getPoints().getPoints()) { sink->AddLine(toD2dPoint(point)); } } -void DirectX2dPainter::onLineSegment(PathElement* element, ID2D1GeometrySink* sink) +void DirectX2dPainter::onLineSegment(PathElement<2>* element, ID2D1GeometrySink* sink) { - const auto loc = element->getEndPoint(); + const auto loc = element->getEndOffset(); sink->AddLine(toD2dPoint(loc)); } diff --git a/src/rendering/graphics/directx/DirectX2dPainter.h b/src/rendering/graphics/directx/DirectX2dPainter.h index f4306ff..422f241 100644 --- a/src/rendering/graphics/directx/DirectX2dPainter.h +++ b/src/rendering/graphics/directx/DirectX2dPainter.h @@ -1,14 +1,18 @@ #pragma once #include "Color.h" +#include "PathElement.h" #include class SceneModel; + +template class Point; + class DirectX2dInterface; -class PathElement; +template class Curve; struct ID2D1SolidColorBrush; @@ -34,15 +38,15 @@ public: void setD2dInterface(DirectX2dInterface* d2dIterface); private: - void onLine(PathElement* element, ID2D1GeometrySink* sink); + void onLine(PathElement<2>* element, ID2D1GeometrySink* sink); - void onLineSegment(PathElement* element, ID2D1GeometrySink* sink); + void onLineSegment(PathElement<2>* element, ID2D1GeometrySink* sink); - void onArc(Curve* element, ID2D1GeometrySink* sink); + void onArc(Curve<2>* element, ID2D1GeometrySink* sink); - void onQuadraticBezier(Curve* element, ID2D1GeometrySink* sink); + void onQuadraticBezier(Curve<2>* element, ID2D1GeometrySink* sink); - void onCubicBezier(Curve* element, ID2D1GeometrySink* sink); + void onCubicBezier(Curve<2>* element, ID2D1GeometrySink* sink); void paintRect(SceneModel* model); @@ -56,7 +60,7 @@ private: static D2D1::ColorF toD2dColor(const Color& color); - static D2D_POINT_2F toD2dPoint(const Point& point); + static D2D_POINT_2F toD2dPoint(const Point<2>& point); Microsoft::WRL::ComPtr mSolidBrush; diff --git a/src/rendering/graphics/directx/DirectXMesh.cpp b/src/rendering/graphics/directx/DirectXMesh.cpp index 5257d29..57416b7 100644 --- a/src/rendering/graphics/directx/DirectXMesh.cpp +++ b/src/rendering/graphics/directx/DirectXMesh.cpp @@ -33,8 +33,8 @@ void DirectXMesh::update(DrawingContext* context, ID3D12Device* device) { for (const auto& loc : face->getNodeLocations(AbstractFace::Orientation::CW)) { - auto x = loc.getX() * transform.getScaleX() + transform.getLocation().getX(); - auto y = loc.getY() * transform.getScaleY() + transform.getLocation().getY(); + auto x = loc.getX() * transform.getScale().mX + transform.getLocation().getX(); + auto y = loc.getY() * transform.getScale().mY + transform.getLocation().getY(); x = 2 * x - 1; y = 2 * y - 1; diff --git a/src/rendering/mesh/AbstractFace.h b/src/rendering/mesh/AbstractFace.h index e4b3f8f..d2b6256 100644 --- a/src/rendering/mesh/AbstractFace.h +++ b/src/rendering/mesh/AbstractFace.h @@ -35,7 +35,7 @@ public: virtual std::vector getEdgeIds() const = 0; - virtual std::vector getNodeLocations(Orientation orientation = Orientation::CCW) const = 0; + virtual std::vector getNodeLocations(Orientation orientation = Orientation::CCW) const = 0; virtual void replaceEdge(Edge* original, Edge* replacement) = 0; diff --git a/src/rendering/mesh/AbstractMesh.cpp b/src/rendering/mesh/AbstractMesh.cpp index 91b4db7..e522427 100644 --- a/src/rendering/mesh/AbstractMesh.cpp +++ b/src/rendering/mesh/AbstractMesh.cpp @@ -74,7 +74,7 @@ void AbstractMesh::translate(double offsetX, double offsetY, double offsetZ) } } -void AbstractMesh::translate(const Point& offset) +void AbstractMesh::translate(const Point3& offset) { translate(offset.getX(), offset.getY(), offset.getZ()); } diff --git a/src/rendering/mesh/AbstractMesh.h b/src/rendering/mesh/AbstractMesh.h index cac717f..0af926e 100644 --- a/src/rendering/mesh/AbstractMesh.h +++ b/src/rendering/mesh/AbstractMesh.h @@ -52,7 +52,7 @@ public: void scale(double scaleX, double scaleY); - void translate(const Point& offset); + void translate(const Point3& offset); void translate(double offsetX, double offsetY, double offsetZ = 0.0); diff --git a/src/rendering/mesh/MeshBuilder.h b/src/rendering/mesh/MeshBuilder.h index 2bbf539..50e15ab 100644 --- a/src/rendering/mesh/MeshBuilder.h +++ b/src/rendering/mesh/MeshBuilder.h @@ -8,7 +8,7 @@ using EdgeIds = std::vector >; using FaceIds = std::vector >; -using VecPoints = std::vector; +using VecPoints = std::vector; class MeshBuilder { diff --git a/src/rendering/mesh/Node.cpp b/src/rendering/mesh/Node.cpp index 435f82f..476b19a 100644 --- a/src/rendering/mesh/Node.cpp +++ b/src/rendering/mesh/Node.cpp @@ -1,6 +1,6 @@ #include "Node.h" -std::unique_ptr Node::Create(const Point& p, std::size_t index) +std::unique_ptr Node::Create(const Point3& p, std::size_t index) { return std::make_unique(p, index); } @@ -10,7 +10,7 @@ Node::~Node() } -Node::Node(const Point& p, std::size_t index) +Node::Node(const Point3& p, std::size_t index) : mIndex(index), mPoint(p) { @@ -42,7 +42,7 @@ std::vector Node::getVectorAttribute(const std::string& tag) const return {}; } -const Point& Node::getPoint() const +const Point3& Node::getPoint() const { return mPoint; } diff --git a/src/rendering/mesh/Node.h b/src/rendering/mesh/Node.h index bf53841..7e2fd5e 100644 --- a/src/rendering/mesh/Node.h +++ b/src/rendering/mesh/Node.h @@ -17,9 +17,9 @@ public: DIRTY }; - Node(const Point& p, std::size_t index = 0); + Node(const Point3& p, std::size_t index = 0); - static std::unique_ptr Create(const Point& p, std::size_t index = 0); + static std::unique_ptr Create(const Point3& p, std::size_t index = 0); ~Node(); @@ -45,7 +45,7 @@ public: State getState() const; - const Point& getPoint() const; + const Point3& getPoint() const; std::vector getVectorAttribute(const std::string& tag) const; @@ -60,7 +60,7 @@ public: private: std::unordered_map > mVectorAttributes; std::size_t mIndex{0}; - Point mPoint; + Point3 mPoint; std::vector mAssociatedEdgeIds; std::vector mAssociatedFaceIds; diff --git a/src/rendering/mesh/TriFace.cpp b/src/rendering/mesh/TriFace.cpp index 68aef8f..257d706 100644 --- a/src/rendering/mesh/TriFace.cpp +++ b/src/rendering/mesh/TriFace.cpp @@ -75,7 +75,7 @@ void TriFace::associateWidthEdges() mEdge2->associateFace(mId); } -std::vector TriFace::getNodeLocations(Orientation orientation) const +std::vector TriFace::getNodeLocations(Orientation orientation) const { if (orientation != getOrientation()) { @@ -87,7 +87,7 @@ std::vector TriFace::getNodeLocations(Orientation orientation) const } } -Vector TriFace::getNormal() const +Vector3 TriFace::getNormal() const { auto v0 = mEdge0->getNode0()->getPoint().getDelta(mEdge0->getNode1()->getPoint()); auto v1 = mEdge0->getNode0()->getPoint().getDelta(mEdge1->getNode1()->getPoint()); @@ -96,8 +96,10 @@ Vector TriFace::getNormal() const AbstractFace::Orientation TriFace::getOrientation() const { - Vector z_norm(0, 0, 1); - if (z_norm.dotProduct(getNormal()) < 0.0) + return Orientation::CW; + /* + Vector3 z_norm(0, 0, 1); + if (z_norm.innerProduct(getNormal()) < 0.0) { return Orientation::CW; } @@ -105,4 +107,5 @@ AbstractFace::Orientation TriFace::getOrientation() const { return Orientation::CCW; } + */ } diff --git a/src/rendering/mesh/TriFace.h b/src/rendering/mesh/TriFace.h index 1ffc536..11cfc5a 100644 --- a/src/rendering/mesh/TriFace.h +++ b/src/rendering/mesh/TriFace.h @@ -27,9 +27,9 @@ public: std::size_t getEdge2Id () const; std::vector getEdgeIds() const override; - std::vector getNodeLocations(Orientation orientation = Orientation::CCW) const override; + std::vector getNodeLocations(Orientation orientation = Orientation::CCW) const override; - Vector getNormal() const; + Vector3 getNormal() const; AbstractFace::Orientation getOrientation() const; diff --git a/src/rendering/visual_elements/CMakeLists.txt b/src/rendering/visual_elements/CMakeLists.txt index 3c595a1..cd5264f 100644 --- a/src/rendering/visual_elements/CMakeLists.txt +++ b/src/rendering/visual_elements/CMakeLists.txt @@ -54,6 +54,10 @@ list(APPEND visual_elements_LIB_INCLUDES nodes/GeometryNode.cpp nodes/AbstractVisualNode.h nodes/AbstractVisualNode.cpp + postscript/PostscriptReader.h + postscript/PostscriptReader.cpp + postscript/PostscriptWriter.h + postscript/PostscriptWriter.cpp Material.h BasicMaterial.h BasicMaterial.cpp @@ -67,6 +71,7 @@ target_include_directories(${MODULE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/basic_shapes ${CMAKE_CURRENT_SOURCE_DIR}/scene ${CMAKE_CURRENT_SOURCE_DIR}/nodes + ${CMAKE_CURRENT_SOURCE_DIR}/postscript ${CMAKE_CURRENT_SOURCE_DIR}/svg ${CMAKE_CURRENT_SOURCE_DIR}/svg/elements ) diff --git a/src/rendering/visual_elements/basic_shapes/CircleNode.cpp b/src/rendering/visual_elements/basic_shapes/CircleNode.cpp index 1433075..72d6f3d 100644 --- a/src/rendering/visual_elements/basic_shapes/CircleNode.cpp +++ b/src/rendering/visual_elements/basic_shapes/CircleNode.cpp @@ -1,8 +1,6 @@ #include "CircleNode.h" #include "SceneModel.h" -#include "AbstractMesh.h" -#include "MeshPrimitives.h" #include "SceneInfo.h" #include "Circle.h" @@ -47,43 +45,18 @@ void CircleNode::setMinorRadius(double radius) } } -std::unique_ptr CircleNode::createGeometryPrimitive() const +void CircleNode::createOrUpdateGeometry(SceneInfo*) { - auto circle = std::make_unique(Point{ 0, 0 }, mRadius); + auto circle = std::make_unique(mRadius); circle->setMinorRadius(mMinorRadius); - return circle; -} -std::unique_ptr CircleNode::createMeshPrimitive() const -{ - return MeshPrimitives::buildCircleAsTriMesh(); -} - -void CircleNode::createOrUpdateGeometry(SceneInfo* sceneInfo) -{ if (!mBackgroundItem) { - if (sceneInfo->mSupportsGeometryPrimitives) - { - mBackgroundItem = std::make_unique(createGeometryPrimitive()); - } - else - { - mBackgroundItem = std::make_unique(createMeshPrimitive()); - mBackgroundItem->setMeshTransform(Transform({}, mRadius, mRadius)); - } + mBackgroundItem = std::make_unique(std::move(circle)); mBackgroundItem->setName(mName + "_Model"); } else { - if (sceneInfo->mSupportsGeometryPrimitives) - { - mBackgroundItem->updateGeometry(createGeometryPrimitive()); - } - else - { - mBackgroundItem->updateMesh(createMeshPrimitive()); - mBackgroundItem->setMeshTransform(Transform({}, mRadius, mRadius)); - } + mBackgroundItem->updateGeometry(std::move(circle)); } } diff --git a/src/rendering/visual_elements/basic_shapes/CircleNode.h b/src/rendering/visual_elements/basic_shapes/CircleNode.h index 1d1362f..b03988c 100644 --- a/src/rendering/visual_elements/basic_shapes/CircleNode.h +++ b/src/rendering/visual_elements/basic_shapes/CircleNode.h @@ -20,9 +20,6 @@ public: private: void createOrUpdateGeometry(SceneInfo* sceneInfo) override; - std::unique_ptr createGeometryPrimitive() const; - std::unique_ptr createMeshPrimitive() const; - double mRadius{1.0}; double mMinorRadius{ 1.0 }; }; diff --git a/src/rendering/visual_elements/basic_shapes/LineNode.cpp b/src/rendering/visual_elements/basic_shapes/LineNode.cpp index 4df5ac8..bc2935d 100644 --- a/src/rendering/visual_elements/basic_shapes/LineNode.cpp +++ b/src/rendering/visual_elements/basic_shapes/LineNode.cpp @@ -2,7 +2,7 @@ #include "SceneModel.h" -LineNode::LineNode(const Transform& transform, const std::vector& points) +LineNode::LineNode(const Transform& transform, const std::vector& points) : GeometryNode(transform), mPoints(points) { @@ -16,35 +16,32 @@ LineNode::Type LineNode::getType() void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo) { - if (sceneInfo->mSupportsGeometryPrimitives) + auto line = std::make_unique(mPoints); + mBackgroundItem = std::make_unique(std::move(line)); + + if (mStartEndStyle != LineEndNode::Style::NONE) { - auto line = std::make_unique(Point{ 0, 0 }, mPoints); - mBackgroundItem = std::make_unique(std::move(line)); - - if (mStartEndStyle != LineEndNode::Style::NONE) + if (!mStartNode) { - if (!mStartNode) - { - mStartNode = std::make_unique(Point{ 0, 0 }); - addChild(mStartNode.get()); - } - mStartNode->setStyle(mStartEndStyle); - mStartNode->setSize(mStartEndSize); - } - - if (mEndEndStyle != LineEndNode::Style::NONE) - { - if (!mEndNode) - { - auto end_loc = mPoints[mPoints.size() - 1]; - - mEndNode = std::make_unique(end_loc); - addChild(mEndNode.get()); - } - mEndNode->setStyle(mEndEndStyle); - mEndNode->setSize(mEndEndSize); + mStartNode = std::make_unique(); + addChild(mStartNode.get()); } + mStartNode->setStyle(mStartEndStyle); + mStartNode->setSize(mStartEndSize); } + + if (mEndEndStyle != LineEndNode::Style::NONE) + { + if (!mEndNode) + { + auto end_loc = mPoints[mPoints.size() - 1]; + mEndNode = std::make_unique(Transform(end_loc)); + addChild(mEndNode.get()); + } + mEndNode->setStyle(mEndEndStyle); + mEndNode->setSize(mEndEndSize); + } + mBackgroundItem->setName(mName + "_Model"); } diff --git a/src/rendering/visual_elements/basic_shapes/LineNode.h b/src/rendering/visual_elements/basic_shapes/LineNode.h index 90d9a9f..dd9489b 100644 --- a/src/rendering/visual_elements/basic_shapes/LineNode.h +++ b/src/rendering/visual_elements/basic_shapes/LineNode.h @@ -11,7 +11,7 @@ class LineNode : public GeometryNode { public: - LineNode(const Transform& transform, const std::vector& points); + LineNode(const Transform& transform, const std::vector& points); Type getType() override; @@ -28,7 +28,7 @@ private: LineEndNode::Style mStartEndStyle{ LineEndNode::Style::NONE }; LineEndNode::Style mEndEndStyle{ LineEndNode::Style::NONE }; - std::vector mPoints; + std::vector mPoints; std::unique_ptr mStartNode; std::unique_ptr mEndNode; diff --git a/src/rendering/visual_elements/basic_shapes/PolygonNode.cpp b/src/rendering/visual_elements/basic_shapes/PolygonNode.cpp index 8c3f5f7..c7e01f0 100644 --- a/src/rendering/visual_elements/basic_shapes/PolygonNode.cpp +++ b/src/rendering/visual_elements/basic_shapes/PolygonNode.cpp @@ -20,7 +20,7 @@ PolygonNode::Type PolygonNode::getType() return Type::Polygon; } -void PolygonNode::setPoints(const std::vector& points) +void PolygonNode::setPoints(const std::vector& points) { mPoints = points; mGeometryIsDirty = true; @@ -28,26 +28,15 @@ void PolygonNode::setPoints(const std::vector& points) void PolygonNode::createOrUpdateGeometry(SceneInfo* sceneInfo) { + auto polygon = std::make_unique(mPoints); + if (!mBackgroundItem) { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto polygon = std::make_unique(mPoints); - mBackgroundItem = std::make_unique(std::move(polygon)); - } - else - { - //auto mesh = MeshPrimitives::buildRectangleAsTriMesh(); - //mBackgroundItem = std::make_unique(std::move(mesh)); - } + mBackgroundItem = std::make_unique(std::move(polygon)); mBackgroundItem->setName(mName + "_Model"); } else { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto polygon = std::make_unique(mPoints); - mBackgroundItem->updateGeometry(std::move(polygon)); - } + mBackgroundItem->updateGeometry(std::move(polygon)); } } \ No newline at end of file diff --git a/src/rendering/visual_elements/basic_shapes/PolygonNode.h b/src/rendering/visual_elements/basic_shapes/PolygonNode.h index 282c6c3..32aa8b8 100644 --- a/src/rendering/visual_elements/basic_shapes/PolygonNode.h +++ b/src/rendering/visual_elements/basic_shapes/PolygonNode.h @@ -11,9 +11,9 @@ public: Type getType() override; - void setPoints(const std::vector& points); + void setPoints(const std::vector& points); private: void createOrUpdateGeometry(SceneInfo* sceneInfo) override; - std::vector mPoints; + std::vector mPoints; }; \ No newline at end of file diff --git a/src/rendering/visual_elements/basic_shapes/RectangleNode.cpp b/src/rendering/visual_elements/basic_shapes/RectangleNode.cpp index abc8f25..4e214fc 100644 --- a/src/rendering/visual_elements/basic_shapes/RectangleNode.cpp +++ b/src/rendering/visual_elements/basic_shapes/RectangleNode.cpp @@ -2,8 +2,6 @@ #include "Rectangle.h" -#include "MeshPrimitives.h" - #include "SceneInfo.h" #include "SceneModel.h" @@ -67,31 +65,18 @@ void RectangleNode::setRadius(double radius) } } -void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo) +void RectangleNode::createOrUpdateGeometry(SceneInfo*) { + auto rect = std::make_unique(mWidth, mHeight); + rect->setRadius(mRadius); + if (!mBackgroundItem) { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto rect = std::make_unique(Point{ 0, 0 }, mWidth, mHeight); - rect->setRadius(mRadius); - mBackgroundItem = std::make_unique(std::move(rect)); - } - else - { - auto mesh = MeshPrimitives::buildRectangleAsTriMesh(); - mBackgroundItem = std::make_unique(std::move(mesh)); - - } + mBackgroundItem = std::make_unique(std::move(rect)); mBackgroundItem->setName(mName + "_Model"); } else { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto rect = std::make_unique(Point{ 0, 0 }, mWidth, mHeight); - rect->setRadius(mRadius); - mBackgroundItem->updateGeometry(std::move(rect)); - } + mBackgroundItem->updateGeometry(std::move(rect)); } } \ No newline at end of file diff --git a/src/rendering/visual_elements/nodes/LineEndNode.cpp b/src/rendering/visual_elements/nodes/LineEndNode.cpp index ec16888..5ba42f0 100644 --- a/src/rendering/visual_elements/nodes/LineEndNode.cpp +++ b/src/rendering/visual_elements/nodes/LineEndNode.cpp @@ -34,9 +34,9 @@ void LineEndNode::createOrUpdateGeometry(SceneInfo*) if (mStyle == Style::CLOSED_ARROW) { auto polygon = std::make_unique(); - auto p0 = Point(0.0, -mSize / 2.0); - auto p1 = Point(mSize, 0.0); - auto p2 = Point(0.0, mSize / 2.0); + auto p0 = Point2(0.0, -mSize / 2.0); + auto p1 = Point2(mSize, 0.0); + auto p2 = Point2(0.0, mSize / 2.0); polygon->setPoints({ p0, p1, p2 }); polygon->setFillColor({ 0, 0, 0 }); diff --git a/src/rendering/visual_elements/nodes/LineEndNode.h b/src/rendering/visual_elements/nodes/LineEndNode.h index 9973f69..9cc1885 100644 --- a/src/rendering/visual_elements/nodes/LineEndNode.h +++ b/src/rendering/visual_elements/nodes/LineEndNode.h @@ -30,7 +30,7 @@ private: std::unique_ptr mContentNode; - Vector mDirection; + Vector3 mDirection; bool mContentDirty{ true }; double mSize{ 5.0 }; diff --git a/src/rendering/visual_elements/nodes/PathNode.cpp b/src/rendering/visual_elements/nodes/PathNode.cpp index 3e84d52..bcbc2f8 100644 --- a/src/rendering/visual_elements/nodes/PathNode.cpp +++ b/src/rendering/visual_elements/nodes/PathNode.cpp @@ -4,6 +4,7 @@ #include "SceneInfo.h" #include "SceneModel.h" +#include "PostscriptReader.h" PathNode::PathNode(const Transform& transform, const std::string& psPath) : GeometryNode(transform), @@ -34,23 +35,17 @@ void PathNode::setPathString(const std::string& psPath) void PathNode::createOrUpdateGeometry(SceneInfo* sceneInfo) { + auto path = std::make_unique(); + PostscriptReader reader; + reader.read(path.get(), mPathString); + if (!mBackgroundItem) { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto path = std::make_unique(); - path->buildFromPostscript(mPathString); - mBackgroundItem = std::make_unique(std::move(path)); - mBackgroundItem->setName(mName + "_Model"); - } + mBackgroundItem = std::make_unique(std::move(path)); + mBackgroundItem->setName(mName + "_Model"); } else { - if (sceneInfo->mSupportsGeometryPrimitives) - { - auto path = std::make_unique(); - path->buildFromPostscript(mPathString); - mBackgroundItem->updateGeometry(std::move(path)); - } + mBackgroundItem->updateGeometry(std::move(path)); } } \ No newline at end of file diff --git a/src/rendering/visual_elements/nodes/TextNode.cpp b/src/rendering/visual_elements/nodes/TextNode.cpp index 86f30ec..0b2d53f 100644 --- a/src/rendering/visual_elements/nodes/TextNode.cpp +++ b/src/rendering/visual_elements/nodes/TextNode.cpp @@ -224,7 +224,7 @@ void TextNode::update(SceneInfo* sceneInfo) if (mRenderNodeBounds) { - auto rect = std::make_unique(Point(0.0, 0.0), mWidth, mHeight); + auto rect = std::make_unique(mWidth, mHeight); mNodeBounds = std::make_unique(); mNodeBounds->updateGeometry(std::move(rect)); @@ -235,7 +235,7 @@ void TextNode::update(SceneInfo* sceneInfo) if (mRenderTextBounds) { - auto rect = std::make_unique(Point(0.0, 0.0), mContentWidth, mContentHeight); + auto rect = std::make_unique(mContentWidth, mContentHeight); mTextBounds = std::make_unique(); mTextBounds->updateGeometry(std::move(rect)); diff --git a/src/rendering/visual_elements/postscript/PostscriptReader.cpp b/src/rendering/visual_elements/postscript/PostscriptReader.cpp new file mode 100644 index 0000000..4797cbd --- /dev/null +++ b/src/rendering/visual_elements/postscript/PostscriptReader.cpp @@ -0,0 +1,313 @@ +#include "PostscriptReader.h" + +#include "Path.h" + +#include "StringUtils.h" +#include "FileLogger.h" + +#include "Line.h" +#include "LineSegment.h" +#include "Arc.h" +#include "QuadraticBezierCurve.h" +#include "CubicBezierCurve.h" + +#include "PointParser.h" + +void PostscriptReader::read(GeometryPath* targetPath, const std::string& postScriptPath) +{ + mCurrentPoint = Point2(); + + for (auto c : postScriptPath) + { + if (c == 'M' || c == 'm') + { + mLineState = LineState::IN_FIRST_POINT; + mPositionState = getPositionState(c); + + mWorkingFeature = std::make_unique(); + } + else if (c == 'H' || c == 'h') + { + onNewElement(c); + mLineState = LineState::IN_HORIZONTAL; + } + else if (c == 'V' || c == 'v') + { + onNewElement(c); + mLineState = LineState::IN_VERTICAL; + } + else if (c == 'L' || c == 'l') + { + onNewElement(c); + mLineState = LineState::IN_LINE; + } + else if (c == 'C' || c == 'c') + { + onNewElement(c); + mLineState = LineState::IN_CUBIC_BEZIER; + } + else if (c == 'Q' || c == 'q') + { + onNewElement(c); + mLineState = LineState::IN_QUADRATIC_BEZIER; + } + else if (c == 'A' || c == 'a') + { + onNewElement(c); + mLineState = LineState::IN_ARC; + } + else if (c == 'Z' || c == 'z') + { + onNewElement(c); + + mLineState = LineState::START; + targetPath->addFeature(std::move(mWorkingFeature)); + mWorkingFeature = nullptr; + } + else if (std::isblank(c)) + { + onNonNumeric(); + } + else if (std::isalpha(c)) + { + onNewElement(c); + mLineState = LineState::IN_UNSUPPORTED; + } + else + { + mBuffer.push_back(c); + } + } +} + +void PostscriptReader::onNewElement(char c) +{ + onNonNumeric(); + + onElementEnd(); + + mPositionState = getPositionState(c); +} + +void PostscriptReader::onNonNumeric() +{ + if (!mBuffer.empty()) + { + mPointBuffer.push_back(std::stod(mBuffer)); + mBuffer.clear(); + } +} + +PostscriptReader::PositionState PostscriptReader::getPositionState(char c) const +{ + return std::isupper(c) ? PositionState::ABSOLUTE : PositionState::RELATIVE; +} + +void PostscriptReader::onElementEnd() +{ + if (mPointBuffer.empty()) + { + return; + } + + PathElementPtr element; + if (mLineState == LineState::IN_HORIZONTAL) + { + element = onHorizontalLineTo(); + } + else if (mLineState == LineState::IN_VERTICAL) + { + element = onVerticalLineTo(); + } + else if (mLineState == LineState::IN_LINE) + { + element = onLineTo(); + } + else if (mLineState == LineState::IN_ARC) + { + element = onArc(); + } + else if (mLineState == LineState::IN_QUADRATIC_BEZIER) + { + element = onQuadraticBezier(); + } + else if (mLineState == LineState::IN_CUBIC_BEZIER) + { + element = onCubicBezier(); + } + else if (mLineState == LineState::IN_FIRST_POINT) + { + onMoveTo(); + } + + if (element) + { + const auto positioning = (mPositionState == PositionState::RELATIVE) ? PathOffsetType::RELATIVE_TO : PathOffsetType::ABSOLUTE_TO; + element->setPathOffsetType(positioning); + + mCurrentPoint += element->getEndOffset(); + mWorkingFeature->addElement(std::move(element)); + } + + mPointBuffer.clear(); +} + +void PostscriptReader::onMoveTo() +{ + if (mPointBuffer.size() != 2) + { + return; + } + if (mPositionState == PositionState::RELATIVE) + { + mCurrentPoint = Point2(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY() + mPointBuffer[1]); + } + else + { + mCurrentPoint = Point2(mPointBuffer[0], mPointBuffer[1]); + } +} + +PathElementPtr PostscriptReader::onHorizontalLineTo() +{ + PathElementPtr element; + if (mPointBuffer.size() == 1) + { + if (mPositionState == PositionState::RELATIVE) + { + element = std::make_unique(mCurrentPoint, Point2(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY())); + } + else + { + element = std::make_unique(mCurrentPoint, Point2(mPointBuffer[0], mCurrentPoint.getY())); + } + } + else + { + element = std::make_unique(Line<2>::InputBufferType::HORIZONTAL, mPointBuffer); + } + return element; +} + +PathElementPtr PostscriptReader::onVerticalLineTo() +{ + PathElementPtr element; + if (mPointBuffer.size() == 1) + { + if (mPositionState == PositionState::RELATIVE) + { + //element = std::make_unique(Point2(mCurrentPoint.getX(), mCurrentPoint.getY() + mPointBuffer[0])); + } + else + { + //element = std::make_unique(Point2(mCurrentPoint.getX(), mPointBuffer[0])); + } + } + else + { + element = std::make_unique(Line<2>::InputBufferType::VERTICAL, mPointBuffer); + } + return element; +} + +PathElementPtr PostscriptReader::onLineTo() +{ + PathElementPtr element; + if (mPointBuffer.size() == 2) + { + if (mPositionState == PositionState::RELATIVE) + { + const auto next_point = Point2(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY() + mPointBuffer[1]); + element = std::make_unique(mCurrentPoint, next_point); + } + else + { + const auto next_point = Point2(mPointBuffer[0], mPointBuffer[1]); + element = std::make_unique(mCurrentPoint, next_point); + } + } + else + { + element = std::make_unique(Line2::InputBufferType::XY, mPointBuffer); + } + return element; +} + +PathElementPtr PostscriptReader::onArc() +{ + PathElementPtr element; + if (mPointBuffer.size() == 7) + { + double rx = mPointBuffer[0]; + double ry = mPointBuffer[1]; + double rotation = mPointBuffer[2]; + bool large_arc = bool(mPointBuffer[3]); + bool sweep = bool(mPointBuffer[4]); + + if (mPositionState == PositionState::RELATIVE) + { + const auto end_point = Vector2({ mCurrentPoint.getX() + mPointBuffer[5], mCurrentPoint.getY() + mPointBuffer[6] }); + element = std::make_unique(end_point, rx, ry, rotation, large_arc, sweep); + } + else + { + const auto end_point = Vector2({ mPointBuffer[5], mPointBuffer[6] }); + element = std::make_unique(end_point, rx, ry, rotation, large_arc, sweep); + } + } + return element; +} + +PathElementPtr PostscriptReader::onQuadraticBezier() +{ + PathElementPtr element; + if (mPointBuffer.size() == 4) + { + double control_x = mPointBuffer[0]; + double control_y = mPointBuffer[1]; + double end_x = mPointBuffer[2]; + double end_y = mPointBuffer[3]; + if (mPositionState == PositionState::RELATIVE) + { + const auto control_point = Vector2({ mCurrentPoint.getX() + control_x, mCurrentPoint.getY() + control_y }); + const auto end_point = Vector2({ mCurrentPoint.getX() + end_x, mCurrentPoint.getY() + end_y }); + element = std::make_unique >(end_point, control_point); + } + else + { + const auto control_point = Vector2({ control_x, control_y }); + const auto end_point = Vector2({ end_x, end_y }); + element = std::make_unique >(end_point, control_point); + } + } + return element; +} + +PathElementPtr PostscriptReader::onCubicBezier() +{ + PathElementPtr element; + if (mPointBuffer.size() == 6) + { + double control0_x = mPointBuffer[0]; + double control0_y = mPointBuffer[1]; + double control1_x = mPointBuffer[2]; + double control1_y = mPointBuffer[3]; + double end_x = mPointBuffer[4]; + double end_y = mPointBuffer[5]; + if (mPositionState == PositionState::RELATIVE) + { + const auto control_point0 = Vector2({ mCurrentPoint.getX() + control0_x, mCurrentPoint.getY() + control0_y }); + const auto control_point1 = Vector2({ mCurrentPoint.getX() + control1_x, mCurrentPoint.getY() + control1_y }); + const auto end_point = Vector2({ mCurrentPoint.getX() + end_x, mCurrentPoint.getY() + end_y }); + element = std::make_unique >(end_point, control_point0, control_point1); + } + else + { + const auto control_point0 = Vector2({ control0_x, control0_y }); + const auto control_point1 = Vector2({ control1_x, control1_y }); + const auto end_point = Vector2({ end_x, end_y }); + element = std::make_unique >(end_point, control_point0, control_point1); + } + } + return element; +} diff --git a/src/base/geometry/path/PathPostScriptConverter.h b/src/rendering/visual_elements/postscript/PostscriptReader.h similarity index 80% rename from src/base/geometry/path/PathPostScriptConverter.h rename to src/rendering/visual_elements/postscript/PostscriptReader.h index a40265a..5fcc5e3 100644 --- a/src/base/geometry/path/PathPostScriptConverter.h +++ b/src/rendering/visual_elements/postscript/PostscriptReader.h @@ -8,17 +8,15 @@ #include class GeometryPath; -using PathElementPtr = std::unique_ptr; +using PathElementPtr = std::unique_ptr >; class GeometryPathFeature; using GeometryPathFeaturePtr = std::unique_ptr; -class PathPostScriptConverter +class PostscriptReader { public: - void fromPostScript(GeometryPath* targetPath, const std::string& postScriptPath); - - std::string toPostScript(const GeometryPath* targetPath); + void read(GeometryPath* targetPath, const std::string& postScriptPath); private: enum class LineState @@ -61,7 +59,7 @@ private: std::vector mPointBuffer; GeometryPathFeaturePtr mWorkingFeature; - Point mCurrentPoint; + Point2 mCurrentPoint; std::size_t mPrecision{ 3 }; }; diff --git a/src/rendering/visual_elements/postscript/PostscriptWriter.cpp b/src/rendering/visual_elements/postscript/PostscriptWriter.cpp new file mode 100644 index 0000000..bf1557a --- /dev/null +++ b/src/rendering/visual_elements/postscript/PostscriptWriter.cpp @@ -0,0 +1,217 @@ +#include "PostscriptWriter.h" + +#include "Arc.h" +#include "QuadraticBezierCurve.h" +#include "CubicBezierCurve.h" +#include "Line.h" +#include "LineSegment.h" + +#include "PointParser.h" +#include "PathElement.h" +#include "Path.h" + +void PostscriptWriter::setPrecision(std::size_t precision) +{ + mPrecision = precision; +} + +std::string PostscriptWriter::toString(GeometryPath* path) +{ + std::string path_str; + mCursor = { 0.0, 0.0 }; + for (const auto& feature : path->getFeatures()) + { + auto start_offset = feature->getOffset(); + if (feature->getPathOffsetType() == PathOffsetType::RELATIVE_TO) + { + mCursor += start_offset; + path_str += "m" + PointParser::toString(start_offset, " ", mPrecision); + } + else + { + mCursor = start_offset; + path_str += "M" + PointParser::toString(start_offset, " ", mPrecision); + } + + for (const auto& path_element : feature->getElements()) + { + path_str += toString(path_element.get()); + } + path_str += "Z "; + } + return path_str; +} + +std::string PostscriptWriter::toString(PathElement<2>* pathElement) +{ + if (pathElement->getType() == AbstractGeometricItem::Type::CURVE) + { + if (auto curve = dynamic_cast*>(pathElement); curve) + { + if (curve->getCurveType() == CurveType::ARC) + { + return toString(dynamic_cast(pathElement)); + } + else if (curve->getCurveType() == CurveType::CUBIC_BEZIER) + { + return toString(dynamic_cast *>(pathElement)); + } + else if (curve->getCurveType() == CurveType::QUADRATIC_BEZIER) + { + return toString(dynamic_cast *>(pathElement)); + } + } + } + else if (pathElement->getType() == AbstractGeometricItem::Type::LINE) + { + if (auto line = dynamic_cast*>(pathElement); line) + { + return toString(line); + } + } + else if (pathElement->getType() == AbstractGeometricItem::Type::LINE_SEGMENT) + { + if (auto line = dynamic_cast*>(pathElement); line) + { + return toString(line); + } + } + return {}; +} + +std::string PostscriptWriter::toString(QuadraticBezierCurve<2>* curve) +{ + Vector2 end_offset = curve->getEndOffset(); + std::string prefix = curve->isRelativeOffset() ? "q" : "Q"; + + std::string result = prefix + PointParser::toString(curve->getControlOffset(), " ", mPrecision) + " " + PointParser::toString(end_offset, " ", mPrecision); + if (curve->isRelativeOffset()) + { + mCursor += end_offset; + } + else + { + mCursor = end_offset; + } + return result; +} + +std::string PostscriptWriter::toString(ntk::Arc* arc) +{ + const auto large = arc->getUseLargeArc() ? "1" : "0"; + const auto sweep = arc->getSweepParam() ? "1" : "0"; + std::stringstream sstr; + if (mPrecision > 0) + { + sstr.precision(mPrecision); + } + + if (arc->isRelativeOffset()) + { + sstr << "a"; + } + else + { + sstr << "A"; + } + sstr << arc->getRx() << " " << arc->getRy() << " " << arc->getRotation() << " " << large << " " << sweep << " "; + + auto end_offset = arc->getEndOffset(); + sstr << PointParser::toString(end_offset, " ", mPrecision); + if (arc->isRelativeOffset()) + { + mCursor += end_offset; + } + else + { + mCursor = end_offset; + } + return sstr.str(); +} + +std::string PostscriptWriter::toString(CubicBezierCurve<2>* curve) +{ + Vector2 end_offset = curve->getEndOffset(); + std::string prefix = curve->isRelativeOffset() ? "c" : "C"; + + const auto start_control = curve->getStartControlOffset(); + const auto end_control = curve->getStartControlOffset(); + const auto start_control_str = PointParser::toString(start_control, " ", mPrecision); + const auto end_control_str = PointParser::toString(end_control, " ", mPrecision); + const auto end_str = PointParser::toString(end_offset, " ", mPrecision); + + if (curve->isRelativeOffset()) + { + mCursor += end_offset; + } + else + { + mCursor = end_offset; + } + return prefix + start_control_str + " " + end_control_str + " " + end_str; +} + +std::string PostscriptWriter::toString(Line<2>* line) +{ + std::string prefix = line->isRelativeOffset() ? "l" : "L"; + std::string path = prefix; + for (const auto& point : line->getPoints().getPoints()) + { + path += PointParser::toString(point, " ", mPrecision) + " "; + } + + if (line->isRelativeOffset()) + { + mCursor += line->getEndOffset(); + } + else + { + mCursor = line->getEndOffset(); + } + return path; +} + +std::string PostscriptWriter::toString(LineSegment<2>* line) +{ + if (line->isHorizontal()) + { + double delta_x = line->isRelativeOffset() ? line->getPoint0().getDeltaX(line->getPoint1()) : line->getPoint1().getX(); + if (line->isRelativeOffset()) + { + mCursor.moveBy(delta_x, 0.0); + return "h" + PointParser::toString(delta_x, mPrecision); + } + else + { + mCursor = Vector2({ delta_x, 0.0 }); + return "H" + PointParser::toString(delta_x, mPrecision); + } + } + else if (line->isVertical()) + { + double delta_y = line->isRelativeOffset() ? line->getPoint0().getDeltaY(line->getPoint1()) : line->getPoint1().getY(); + if (line->isRelativeOffset()) + { + mCursor.moveBy(delta_y, 0.0); + return "v" + PointParser::toString(delta_y, mPrecision); + } + else + { + mCursor = Vector2({ 0.0, delta_y }); + return "V" + PointParser::toString(delta_y, mPrecision); + } + } + else + { + if (line->isRelativeOffset()) + { + mCursor += line->getEndOffset(); + return "l" + PointParser::toString(line->asVector(), " ", mPrecision); + } + else + { + mCursor = line->getPoint1(); + return "L" + PointParser::toString(line->getPoint1(), " ", mPrecision); + } + } +} \ No newline at end of file diff --git a/src/rendering/visual_elements/postscript/PostscriptWriter.h b/src/rendering/visual_elements/postscript/PostscriptWriter.h new file mode 100644 index 0000000..2f5bbe5 --- /dev/null +++ b/src/rendering/visual_elements/postscript/PostscriptWriter.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +namespace ntk +{ + class Arc; +} + +template +class QuadraticBezierCurve; + +template +class CubicBezierCurve; + +template +class Line; + +template +class LineSegment; + +template +class PathElement; + +class GeometryPath; + +class PostscriptWriter +{ +public: + void setPrecision(std::size_t precision); + + std::string toString(GeometryPath* path); + +private: + std::string toString(PathElement<2>* pathElement); + + std::string toString(Line<2>* line); + + std::string toString(LineSegment<2>* line); + + std::string toString(ntk::Arc* arc); + + std::string toString(QuadraticBezierCurve<2>* curve); + + std::string toString(CubicBezierCurve<2>* curve); + + std::size_t mPrecision{ 3 }; + Point2 mCursor; +}; \ No newline at end of file diff --git a/src/rendering/visual_elements/svg/SvgNode.cpp b/src/rendering/visual_elements/svg/SvgNode.cpp index 64dc86c..0085f4e 100644 --- a/src/rendering/visual_elements/svg/SvgNode.cpp +++ b/src/rendering/visual_elements/svg/SvgNode.cpp @@ -125,12 +125,12 @@ void SvgNode::onCircle(XmlElement* element, std::unique_ptr& node) if (element->hasAttribute("transform")) { const auto transform = svg_circle->getTransform(); - loc.move(transform.getLocation().getX(), transform.getLocation().getY()); + loc.moveBy(transform.getLocation().getX(), transform.getLocation().getY()); radius *= transform.getScale().mX; minor_radius *= transform.getScale().mY; } - auto circle_node = std::make_unique(loc, radius); + auto circle_node = std::make_unique(Transform(loc), radius); circle_node->setMinorRadius(minor_radius); node = std::move(circle_node); } diff --git a/src/rendering/visual_elements/svg/SvgPainter.cpp b/src/rendering/visual_elements/svg/SvgPainter.cpp index 9f8a730..7a4a70b 100644 --- a/src/rendering/visual_elements/svg/SvgPainter.cpp +++ b/src/rendering/visual_elements/svg/SvgPainter.cpp @@ -23,6 +23,8 @@ #include "SvgTextElement.h" #include "XmlAttribute.h" +#include "PostscriptWriter.h" + std::unique_ptr SvgPainter::paint(Scene* scene, double width, double height) const { auto doc = std::make_unique(); @@ -65,7 +67,7 @@ void SvgPainter::paintMesh(SvgDocument* document, SceneModel* model, bool showOu { auto svg_tri = std::make_unique(); - std::vector points(3); + std::vector points(3); unsigned count = 0; auto face_locs = face->getNodeLocations(); @@ -158,7 +160,7 @@ void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const void SvgPainter::paintPolygon(SvgDocument* document, SceneModel* model) const { - auto model_polygon = dynamic_cast(model->getGeometry()); + auto model_polygon = dynamic_cast(model->getGeometry()); auto svg_polygon = std::make_unique(); svg_polygon->setPoints(model_polygon->getPoints().getPoints()); @@ -201,9 +203,9 @@ void SvgPainter::paintCircle(SvgDocument* document, SceneModel* model) const void SvgPainter::paintLine(SvgDocument* document, SceneModel* model) const { - auto model_line = dynamic_cast(model->getGeometry()); + auto model_line = dynamic_cast(model->getGeometry()); auto svg_line = std::make_unique(); - svg_line->setPoints(model_line->getFirstPoint(), model_line->getPoints().getPoints()); + svg_line->setPoints(model_line->getPoints().getPoints()); setStyle(model, svg_line.get()); document->getRoot()->addChild(std::move(svg_line)); @@ -211,8 +213,8 @@ void SvgPainter::paintLine(SvgDocument* document, SceneModel* model) const void SvgPainter::paintLineSegment(SvgDocument* document, SceneModel* model) const { - auto model_line = dynamic_cast(model->getGeometry()); - auto svg_line = std::make_unique(model_line->getFirstPoint(), model_line->getEndPoint()); + auto model_line = dynamic_cast(model->getGeometry()); + auto svg_line = std::make_unique(model_line->getPoint0(), model_line->getPoint1()); setStyle(model, svg_line.get()); document->getRoot()->addChild(std::move(svg_line)); @@ -222,7 +224,8 @@ void SvgPainter::paintPath(SvgDocument* document, SceneModel* model) const { auto model_path = dynamic_cast(model->getGeometry()); - auto path_string = model_path->getAsPostScript(); + PostscriptWriter writer; + const auto path_string = writer.toString(model_path); auto svg_path = std::make_unique(); svg_path->setPath(path_string); @@ -236,7 +239,7 @@ void SvgPainter::paintText(SvgDocument* document, SceneText* text) const auto svg_text = std::make_unique(); svg_text->setContent(text->getTextData().mContent); - Point centre(text->getTextWidth() / 2.0, text->getTextHeight() / 2.0); + Point2 centre(text->getTextWidth() / 2.0, text->getTextHeight() / 2.0); svg_text->setLocation(centre); svg_text->setFontFamily(text->getTextData().mFont.getFaceName()); diff --git a/src/rendering/visual_elements/svg/SvgShapeElement.cpp b/src/rendering/visual_elements/svg/SvgShapeElement.cpp index f648253..0068a03 100644 --- a/src/rendering/visual_elements/svg/SvgShapeElement.cpp +++ b/src/rendering/visual_elements/svg/SvgShapeElement.cpp @@ -73,11 +73,10 @@ std::string SvgShapeElement::getLabelledContent(const std::string& key, const st return content.substr(key.size(), content.size() - key.size() - 2); } -Point SvgShapeElement::parsePoint(const std::string& pointString, double defaultVal) const +Point2 SvgShapeElement::parsePoint(const std::string& pointString, double defaultVal) const { double x = defaultVal; double y = defaultVal; - double z = defaultVal; const auto split = StringUtils::split(pointString); for (std::size_t idx = 0; idx < split.size(); idx++) @@ -90,12 +89,8 @@ Point SvgShapeElement::parsePoint(const std::string& pointString, double default { y = std::stod(split[idx]); } - else if (idx == 2) - { - z = std::stod(split[idx]); - } } - return { x, y, z }; + return { x, y }; } bool SvgShapeElement::hasTransform() const diff --git a/src/rendering/visual_elements/svg/SvgShapeElement.h b/src/rendering/visual_elements/svg/SvgShapeElement.h index 36e345c..91ae775 100644 --- a/src/rendering/visual_elements/svg/SvgShapeElement.h +++ b/src/rendering/visual_elements/svg/SvgShapeElement.h @@ -30,5 +30,5 @@ protected: private: std::string getLabelledContent(const std::string& key, const std::string& content) const; - Point parsePoint(const std::string& pointString, double defaultVal = 0.0) const; + Point2 parsePoint(const std::string& pointString, double defaultVal = 0.0) const; }; diff --git a/src/rendering/visual_elements/svg/SvgTextElement.cpp b/src/rendering/visual_elements/svg/SvgTextElement.cpp index 3d219d9..57f75e7 100644 --- a/src/rendering/visual_elements/svg/SvgTextElement.cpp +++ b/src/rendering/visual_elements/svg/SvgTextElement.cpp @@ -23,7 +23,7 @@ void SvgTextElement::setFillOpacity(float opacity) addAttribute(std::move(attr)); } -void SvgTextElement::setLocation(const Point& loc) +void SvgTextElement::setLocation(const Point2& loc) { auto x = std::make_unique("x"); auto y = std::make_unique("y"); diff --git a/src/rendering/visual_elements/svg/SvgTextElement.h b/src/rendering/visual_elements/svg/SvgTextElement.h index bf41967..e90fcc7 100644 --- a/src/rendering/visual_elements/svg/SvgTextElement.h +++ b/src/rendering/visual_elements/svg/SvgTextElement.h @@ -9,7 +9,7 @@ class SvgTextElement : public SvgElement public: SvgTextElement(); - void setLocation(const Point& loc); + void setLocation(const Point2& loc); void setContent(const std::string& content); diff --git a/src/rendering/visual_elements/svg/elements/SvgShapeElements.cpp b/src/rendering/visual_elements/svg/elements/SvgShapeElements.cpp index 97ec24c..170acb5 100644 --- a/src/rendering/visual_elements/svg/elements/SvgShapeElements.cpp +++ b/src/rendering/visual_elements/svg/elements/SvgShapeElements.cpp @@ -10,7 +10,7 @@ SvgCircle::SvgCircle(Type type) } -Point SvgCircle::getLocation() const +Point2 SvgCircle::getLocation() const { double cx = 0.0; double cy = 0.0; @@ -54,7 +54,7 @@ double SvgCircle::getMinorRadius() const return radius; } -void SvgCircle::setLocation(const Point& loc) +void SvgCircle::setLocation(const Point2& loc) { auto cx = std::make_unique("cx"); auto cy = std::make_unique("cy"); @@ -95,7 +95,7 @@ SvgRectangle::SvgRectangle() } -void SvgRectangle::setLocation(const Point& loc) +void SvgRectangle::setLocation(const Point2& loc) { auto x = std::make_unique("x"); auto y = std::make_unique("y"); @@ -141,7 +141,7 @@ SvgPolygon::SvgPolygon() } -void SvgPolygon::setPoints(const std::vector& locs) +void SvgPolygon::setPoints(const std::vector& locs) { auto points = std::make_unique("points"); @@ -162,7 +162,7 @@ SvgPolyline::SvgPolyline() addAttribute(std::move(fill)); } -void SvgPolyline::setPoints(const std::vector& locs) +void SvgPolyline::setPoints(const std::vector& locs) { auto points = std::make_unique("points"); @@ -175,7 +175,7 @@ void SvgPolyline::setPoints(const std::vector& locs) addAttribute(std::move(points)); } -void SvgPolyline::setPoints(const Point& startPoint, const std::vector& locs) +void SvgPolyline::setPoints(const Point2& startPoint, const std::vector& locs) { auto points = std::make_unique("points"); @@ -190,7 +190,7 @@ void SvgPolyline::setPoints(const Point& startPoint, const std::vector& l addAttribute(std::move(points)); } -SvgLine::SvgLine(const Point& startPoint, const Point& endPoint, std::size_t precision) +SvgLine::SvgLine(const Point2& startPoint, const Point2& endPoint, std::size_t precision) : SvgShapeElement("line", precision) { auto fill = std::make_unique("fill"); diff --git a/src/rendering/visual_elements/svg/elements/SvgShapeElements.h b/src/rendering/visual_elements/svg/elements/SvgShapeElements.h index 458c52d..3814baf 100644 --- a/src/rendering/visual_elements/svg/elements/SvgShapeElements.h +++ b/src/rendering/visual_elements/svg/elements/SvgShapeElements.h @@ -16,7 +16,7 @@ public: SvgCircle(Type type = Type::REGULAR); - Point getLocation() const; + Point2 getLocation() const; double getRadius() const; @@ -24,7 +24,7 @@ public: double getMinorRadius() const; - void setLocation(const Point& loc); + void setLocation(const Point2& loc); void setRadius(double rad); @@ -38,7 +38,7 @@ class SvgRectangle : public SvgShapeElement public: SvgRectangle(); - void setLocation(const Point& loc); + void setLocation(const Point2& loc); void setWidth(double width); @@ -52,7 +52,7 @@ class SvgPolygon : public SvgShapeElement public: SvgPolygon(); - void setPoints(const std::vector& loc); + void setPoints(const std::vector& loc); }; class SvgPolyline : public SvgShapeElement @@ -60,15 +60,15 @@ class SvgPolyline : public SvgShapeElement public: SvgPolyline(); - void setPoints(const Point& startPoint, const std::vector& loc); + void setPoints(const Point2& startPoint, const std::vector& loc); - void setPoints(const std::vector& loc); + void setPoints(const std::vector& loc); }; class SvgLine : public SvgShapeElement { public: - SvgLine(const Point& startPoint, const Point& endPoint, std::size_t precision = 0); + SvgLine(const Point2& startPoint, const Point2& endPoint, std::size_t precision = 0); }; class SvgPath : public SvgShapeElement diff --git a/test/geometry/TestPath.cpp b/test/geometry/TestPath.cpp index 6381ddd..2205f47 100644 --- a/test/geometry/TestPath.cpp +++ b/test/geometry/TestPath.cpp @@ -2,9 +2,12 @@ #include "TestUtils.h" #include "Path.h" +#include "PostscriptReader.h" + TEST_CASE(TestPath, "geometry") { GeometryPath path; - path.buildFromPostscript("M11 39h7.5V26.5h11V39H37V19.5L24 9.75 11 19.5Zm-3 3V18L24 6l16 12v24H26.5V29.5h-5V42Zm16-17.65Z"); + PostscriptReader reader; + reader.read(&path, "M11 39h7.5V26.5h11V39H37V19.5L24 9.75 11 19.5Zm-3 3V18L24 6l16 12v24H26.5V29.5h-5V42Zm16-17.65Z"); }; \ No newline at end of file diff --git a/test/graphics/TestD2dOffScreenRendering.cpp b/test/graphics/TestD2dOffScreenRendering.cpp index f6309cc..539d232 100644 --- a/test/graphics/TestD2dOffScreenRendering.cpp +++ b/test/graphics/TestD2dOffScreenRendering.cpp @@ -8,20 +8,20 @@ #include "PathNode.h" #include "PolygonNode.h" -void addRect(const Point& loc, std::vector >& nodes, double radius = 0.0) +void addRect(const Point2& loc, std::vector >& nodes, double radius = 0.0) { - auto node = std::make_unique(loc, 150.0, 100.0); + auto node = std::make_unique(Transform(loc), 150.0, 100.0); node->setRadius(radius); nodes.push_back(std::move(node)); } -void addCircle(const Point& loc, std::vector >& nodes, double minorRadius = 0.0) +void addCircle(const Point2& loc, std::vector >& nodes, double minorRadius = 0.0) { const auto radius = 50.0; auto centre_loc = loc; - centre_loc.move(0.0, radius); + centre_loc.moveBy(0.0, radius); - auto node = std::make_unique(centre_loc, radius); + auto node = std::make_unique(Transform(centre_loc), radius); if (minorRadius != 0.0) { @@ -31,31 +31,31 @@ void addCircle(const Point& loc, std::vector >& no nodes.push_back(std::move(node)); } -void addLine(const Point& loc, std::vector >& nodes) +void addLine(const Point2& loc, std::vector >& nodes) { - std::vector points = { Point(150.0, 100.0) }; - auto node = std::make_unique(loc, points); + std::vector points = { Point2(150.0, 100.0) }; + auto node = std::make_unique(Transform(loc), points); nodes.push_back(std::move(node)); } -void addPath(const Point& loc, const std::string& path, std::vector >& nodes) +void addPath(const Point2& loc, const std::string& path, std::vector >& nodes) { - auto node = std::make_unique(loc, path); + auto node = std::make_unique(Transform(loc), path); nodes.push_back(std::move(node)); } -void addPolygon(const Point& loc, std::vector >& nodes) +void addPolygon(const Point2& loc, std::vector >& nodes) { - auto p0 = Point{ 0.0, 0.0 }; - auto p1 = Point{ 150.0, 0.0 }; - auto p2 = Point{ 75.0, 75.0 }; + auto p0 = Point2{ 0.0, 0.0 }; + auto p1 = Point2{ 150.0, 0.0 }; + auto p2 = Point2{ 75.0, 75.0 }; - auto node = std::make_unique(loc); + auto node = std::make_unique(Transform(loc)); node->setPoints({ p0, p1, p2 }); nodes.push_back(std::move(node)); } -void addShapes(const Point& start_loc, std::vector >& nodes, bool use_fill = false) +void addShapes(const Point2& start_loc, std::vector >& nodes, bool use_fill = false) { auto loc = start_loc; @@ -63,31 +63,31 @@ void addShapes(const Point& start_loc, std::vector addRect(loc, nodes); - loc.move(250, 0); + loc.moveBy(250, 0); addCircle(loc, nodes); - loc.move(100, 0); + loc.moveBy(100, 0); addLine(loc, nodes); - loc.move(200, 0); + loc.moveBy(200, 0); addPolygon(loc, nodes); - loc = Point(10, 150); + loc = Point2(10, 150); addRect(loc, nodes, 10.0); - loc.move(250, 0); + loc.moveBy(250, 0); addCircle(loc, nodes, 75.0); - loc.move(100, 0); + loc.moveBy(100, 0); addPath(loc, "M0 0 h150 v100 h-150Z", nodes); - loc = Point(10, 300); + loc = Point2(10, 300); addPath(loc, "M0 0 h150 q50 50 0 100 h-150Z", nodes); - loc.move(250, 0); + loc.moveBy(250, 0); addPath(loc, "M0 0 h150 c25 25 25 75 0 100 h-150Z", nodes); - loc.move(250, 0); + loc.moveBy(250, 0); addPath(loc, "M0 0 h150 a50 50 0 0 1 0 100 h-150Z", nodes); if (use_fill) @@ -105,7 +105,7 @@ TEST_CASE(TestD2dOffScreenRendering_Outlines, "graphics") std::vector > nodes; - auto loc = Point(10, 10); + auto loc = Point2(10, 10); addShapes(loc, nodes, false); @@ -125,7 +125,7 @@ TEST_CASE(TestD2dOffScreenRendering_Fill, "graphics") std::vector > nodes; - auto loc = Point(10, 10); + auto loc = Point2(10, 10); addShapes(loc, nodes, true); diff --git a/test/publishing/TestPlotting.cpp b/test/publishing/TestPlotting.cpp index ccaba17..f8b6201 100644 --- a/test/publishing/TestPlotting.cpp +++ b/test/publishing/TestPlotting.cpp @@ -18,7 +18,7 @@ TEST_CASE(TestPlotting, "[publishing]") PlotSeries series("Series-1"); - std::vector data{ {0.0, 0.0}, {10.0, 40.0}, {20.0, 80.0} }; + std::vector data{ {0.0, 0.0}, {10.0, 40.0}, {20.0, 80.0} }; series.setData(data); plot->addSeries(series);