Switch to template types for vectors
This commit is contained in:
parent
9f036d6438
commit
8192ef78e8
105 changed files with 1614 additions and 1424 deletions
|
@ -11,5 +11,5 @@ public:
|
||||||
|
|
||||||
virtual ~CircuitElementNode();
|
virtual ~CircuitElementNode();
|
||||||
|
|
||||||
virtual Point getConnectionLocation(Wire* wire) const = 0;
|
virtual Point2 getConnectionLocation(Wire* wire) const = 0;
|
||||||
};
|
};
|
|
@ -18,7 +18,7 @@ LogicGateNode::~LogicGateNode()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point LogicGateNode::getConnectionLocation(Wire* wire) const
|
Point2 LogicGateNode::getConnectionLocation(Wire* wire) const
|
||||||
{
|
{
|
||||||
bool is_input{ false };
|
bool is_input{ false };
|
||||||
std::size_t connection_id{ 0 };
|
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)
|
if (mContent->getGateType() == LogicGate::GateType::AND)
|
||||||
{
|
{
|
||||||
loc = LogicGatePrimitiveShapes::getAndGateConnectionLocation(is_input, connection_id);
|
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 = LogicGatePrimitiveShapes::getOrGateConnectionLocation(is_input, connection_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
loc.move(mTransform.getLocation().getX(), mTransform.getLocation().getY());
|
loc.moveBy(mTransform.getLocation().getX(), mTransform.getLocation().getY());
|
||||||
return loc;
|
return loc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
|
|
||||||
virtual ~LogicGateNode();
|
virtual ~LogicGateNode();
|
||||||
|
|
||||||
Point getConnectionLocation(Wire* wire) const override;
|
Point2 getConnectionLocation(Wire* wire) const override;
|
||||||
|
|
||||||
void setContent(LogicGate* content);
|
void setContent(LogicGate* content);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ std::string LogicGatePrimitiveShapes::getAndGateShape()
|
||||||
return "M4 8 h24 a16 16 0 0 1 0 32 h-24Z";
|
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)
|
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";
|
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)
|
if (isInput)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
class LogicGatePrimitiveShapes
|
class LogicGatePrimitiveShapes
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Point getAndGateConnectionLocation(bool isInput, std::size_t idx);
|
static Point2 getAndGateConnectionLocation(bool isInput, std::size_t idx);
|
||||||
|
|
||||||
static std::string getAndGateShape();
|
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();
|
static std::string getOrGateShape();
|
||||||
};
|
};
|
|
@ -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() };
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TerminalNode : public CircuitElementNode
|
||||||
public:
|
public:
|
||||||
TerminalNode(const Transform& transform);
|
TerminalNode(const Transform& transform);
|
||||||
|
|
||||||
Point getConnectionLocation(Wire* wire) const override;
|
Point2 getConnectionLocation(Wire* wire) const override;
|
||||||
|
|
||||||
void setContent(Terminal* terminal);
|
void setContent(Terminal* terminal);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ void WireNode::setContent(Wire* wire)
|
||||||
mContentDirty = true;
|
mContentDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireNode::setInputLocation(const Point& point)
|
void WireNode::setInputLocation(const Point2& point)
|
||||||
{
|
{
|
||||||
if (mInputLocation != 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)
|
if (mOutputLocation != point)
|
||||||
{
|
{
|
||||||
|
@ -46,9 +46,9 @@ void WireNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
if (!mLine)
|
if (!mLine)
|
||||||
{
|
{
|
||||||
auto loc = mOutputLocation;
|
auto loc = mOutputLocation;
|
||||||
loc.move(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ());
|
loc.moveBy(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ());
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point2> points;
|
||||||
|
|
||||||
if (loc.getY() == 0.0)
|
if (loc.getY() == 0.0)
|
||||||
{
|
{
|
||||||
|
@ -56,8 +56,8 @@ void WireNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto join0 = Point(loc.getX() * 3.0 / 4.0, 0.0);
|
auto join0 = Point2(loc.getX() * 3.0 / 4.0, 0.0);
|
||||||
auto join1 = Point(loc.getX() * 3.0 / 4.0, loc.getY());
|
auto join1 = Point2(loc.getX() * 3.0 / 4.0, loc.getY());
|
||||||
points = { join0, join1 , loc};
|
points = { join0, join1 , loc};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ public:
|
||||||
|
|
||||||
void setContent(Wire* wire);
|
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);
|
void update(SceneInfo* sceneInfo);
|
||||||
private:
|
private:
|
||||||
|
@ -23,8 +23,8 @@ private:
|
||||||
Wire* mContent{ nullptr };
|
Wire* mContent{ nullptr };
|
||||||
bool mContentDirty{ true };
|
bool mContentDirty{ true };
|
||||||
|
|
||||||
Point mInputLocation;
|
Point2 mInputLocation;
|
||||||
Point mOutputLocation;
|
Point2 mOutputLocation;
|
||||||
|
|
||||||
std::unique_ptr<LineNode> mLine;
|
std::unique_ptr<LineNode> mLine;
|
||||||
};
|
};
|
|
@ -3,8 +3,8 @@
|
||||||
#include "CircleNode.h"
|
#include "CircleNode.h"
|
||||||
#include "LineNode.h"
|
#include "LineNode.h"
|
||||||
|
|
||||||
BlochSphereNode::BlochSphereNode(const Point& location)
|
BlochSphereNode::BlochSphereNode(const Point2& location)
|
||||||
: AbstractVisualNode(location, "BlochSphereNode")
|
: AbstractVisualNode(Transform(location))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ void BlochSphereNode::update(SceneInfo*)
|
||||||
|
|
||||||
mOuterCircle = std::make_unique<CircleNode>(loc, mSize/2.0);
|
mOuterCircle = std::make_unique<CircleNode>(loc, mSize/2.0);
|
||||||
|
|
||||||
const auto end_point_x = Point(loc.getX() + 1.2 * mSize / 2.0, loc.getY());
|
const auto end_point_x = Point2(loc.getX() + 1.2 * mSize / 2.0, loc.getY());
|
||||||
const std::vector<Point> points{end_point_x };
|
const std::vector<Point2> points{end_point_x };
|
||||||
mXAxis = std::make_unique<LineNode>(loc, points);
|
mXAxis = std::make_unique<LineNode>(loc, points);
|
||||||
|
|
||||||
mCentreCircle = std::make_unique<CircleNode>(loc, mSize / 50.0);
|
mCentreCircle = std::make_unique<CircleNode>(loc, mSize / 50.0);
|
||||||
|
|
|
@ -11,7 +11,7 @@ class LineNode;
|
||||||
class BlochSphereNode : public AbstractVisualNode
|
class BlochSphereNode : public AbstractVisualNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlochSphereNode(const Point& location);
|
BlochSphereNode(const Point2& location);
|
||||||
|
|
||||||
void setContent(BlochSphere* content);
|
void setContent(BlochSphere* content);
|
||||||
|
|
||||||
|
|
|
@ -11,5 +11,5 @@ public:
|
||||||
|
|
||||||
virtual ~QuantumCircuitElementNode();
|
virtual ~QuantumCircuitElementNode();
|
||||||
|
|
||||||
virtual Point getConnectionLocation(AbstractQuantumWire* wire) const = 0;
|
virtual Point2 getConnectionLocation(AbstractQuantumWire* wire) const = 0;
|
||||||
};
|
};
|
|
@ -123,7 +123,7 @@ void QuantumCircuitNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
wire_node->setInputLocation(start_loc);
|
wire_node->setInputLocation(start_loc);
|
||||||
|
|
||||||
auto end_loc = end_node->getConnectionLocation(wire);
|
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);
|
wire_node->setOutputLocation(straight_end_loc);
|
||||||
|
|
||||||
addChild(wire_node.get());
|
addChild(wire_node.get());
|
||||||
|
|
|
@ -72,7 +72,7 @@ void QuantumGateNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const
|
Point2 QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const
|
||||||
{
|
{
|
||||||
bool is_input{ false };
|
bool is_input{ false };
|
||||||
//std::size_t connection_id{ 0 };
|
//std::size_t connection_id{ 0 };
|
||||||
|
@ -96,16 +96,16 @@ Point QuantumGateNode::getConnectionLocation(AbstractQuantumWire* wire) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point loc;
|
Point2 loc;
|
||||||
if (is_input)
|
if (is_input)
|
||||||
{
|
{
|
||||||
loc = Point(0.0, mBodyHeight/2.0);
|
loc = Point2(0.0, mBodyHeight/2.0);
|
||||||
}
|
}
|
||||||
else
|
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;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public:
|
||||||
|
|
||||||
virtual ~QuantumGateNode();
|
virtual ~QuantumGateNode();
|
||||||
|
|
||||||
Point getConnectionLocation(AbstractQuantumWire* wire) const override;
|
Point2 getConnectionLocation(AbstractQuantumWire* wire) const override;
|
||||||
|
|
||||||
void setContent(QuantumGate* gate);
|
void setContent(QuantumGate* gate);
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,9 @@ void QuantumTerminalNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point QuantumTerminalNode::getConnectionLocation(AbstractQuantumWire*) const
|
Point2 QuantumTerminalNode::getConnectionLocation(AbstractQuantumWire*) const
|
||||||
{
|
{
|
||||||
auto left = mTransform.getLocation();
|
auto left = mTransform.getLocation();
|
||||||
left.move(mWidth, mHeight/2.0);
|
left.moveBy(mWidth, mHeight/2.0);
|
||||||
return left;
|
return { left.getX(), left.getY() };
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class QuantumTerminalNode : public QuantumCircuitElementNode
|
||||||
public:
|
public:
|
||||||
QuantumTerminalNode(const Transform& transform);
|
QuantumTerminalNode(const Transform& transform);
|
||||||
|
|
||||||
Point getConnectionLocation(AbstractQuantumWire* wire) const override;
|
Point2 getConnectionLocation(AbstractQuantumWire* wire) const override;
|
||||||
|
|
||||||
void setContent(QuantumTerminal* terminal);
|
void setContent(QuantumTerminal* terminal);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ void QuantumWireNode::setContent(QuantumWire* content)
|
||||||
mContentDirty = true;
|
mContentDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuantumWireNode::setInputLocation(const Point& point)
|
void QuantumWireNode::setInputLocation(const Point2& point)
|
||||||
{
|
{
|
||||||
if (mInputLocation != 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)
|
if (mOutputLocation != point)
|
||||||
{
|
{
|
||||||
|
@ -52,9 +52,9 @@ void QuantumWireNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
if (!mLine)
|
if (!mLine)
|
||||||
{
|
{
|
||||||
auto loc = mOutputLocation;
|
auto loc = mOutputLocation;
|
||||||
loc.move(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ());
|
loc.moveBy(-mInputLocation.getX(), -mInputLocation.getY(), -mInputLocation.getZ());
|
||||||
|
|
||||||
std::vector<Point> points;
|
std::vector<Point2> points;
|
||||||
|
|
||||||
if (loc.getY() == 0.0)
|
if (loc.getY() == 0.0)
|
||||||
{
|
{
|
||||||
|
@ -62,8 +62,8 @@ void QuantumWireNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto join0 = Point(loc.getX() * 3.0 / 4.0, 0.0);
|
auto join0 = Point2(loc.getX() * 3.0 / 4.0, 0.0);
|
||||||
auto join1 = Point(loc.getX() * 3.0 / 4.0, loc.getY());
|
auto join1 = Point2(loc.getX() * 3.0 / 4.0, loc.getY());
|
||||||
points = { join0, join1 , loc };
|
points = { join0, join1 , loc };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ public:
|
||||||
|
|
||||||
virtual ~QuantumWireNode();
|
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);
|
void setContent(QuantumWire* content);
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ private:
|
||||||
QuantumWire* mContent{ nullptr };
|
QuantumWire* mContent{ nullptr };
|
||||||
bool mContentDirty{ true };
|
bool mContentDirty{ true };
|
||||||
|
|
||||||
Point mInputLocation;
|
Point2 mInputLocation;
|
||||||
Point mOutputLocation;
|
Point2 mOutputLocation;
|
||||||
|
|
||||||
std::unique_ptr<LineNode> mLine;
|
std::unique_ptr<LineNode> mLine;
|
||||||
};
|
};
|
|
@ -11,7 +11,7 @@ TEST_CASE(TestBlochSphereNode, "quantum_computing")
|
||||||
{
|
{
|
||||||
TestRenderer renderer(100, 100);
|
TestRenderer renderer(100, 100);
|
||||||
|
|
||||||
auto node = std::make_unique<BlochSphereNode>(Point(0.5, 0.5));
|
auto node = std::make_unique<BlochSphereNode>(Point2(0.5, 0.5));
|
||||||
|
|
||||||
Qubit state({ 1.0, 0.0 }, { 0.0, 0.0 });
|
Qubit state({ 1.0, 0.0 }, { 0.0, 0.0 });
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Bounds.h"
|
#include "Bounds.h"
|
||||||
#include "Point.h"
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class SparseGrid;
|
|
||||||
|
|
||||||
class AbstractGeometricItem
|
class AbstractGeometricItem
|
||||||
{
|
{
|
||||||
|
@ -28,9 +24,5 @@ public:
|
||||||
|
|
||||||
virtual Bounds getBounds() const = 0;
|
virtual Bounds getBounds() const = 0;
|
||||||
|
|
||||||
virtual const Point& getLocation() const = 0;
|
|
||||||
|
|
||||||
virtual void sample(SparseGrid<bool>* grid) const = 0;
|
|
||||||
|
|
||||||
virtual Type getType() const { return Type::UNKNOWN; };
|
virtual Type getType() const { return Type::UNKNOWN; };
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,6 @@ list(APPEND HEADERS
|
||||||
path/Line.h
|
path/Line.h
|
||||||
path/LineSegment.h
|
path/LineSegment.h
|
||||||
path/Path.h
|
path/Path.h
|
||||||
path/PathPostScriptConverter.h
|
|
||||||
path/PathElement.h
|
path/PathElement.h
|
||||||
path/Arc.h
|
path/Arc.h
|
||||||
path/QuadraticBezierCurve.h
|
path/QuadraticBezierCurve.h
|
||||||
|
@ -43,7 +42,6 @@ list(APPEND SOURCES
|
||||||
path/Line.cpp
|
path/Line.cpp
|
||||||
path/LineSegment.cpp
|
path/LineSegment.cpp
|
||||||
path/Path.cpp
|
path/Path.cpp
|
||||||
path/PathPostScriptConverter.cpp
|
|
||||||
path/PathElement.cpp
|
path/PathElement.cpp
|
||||||
path/Arc.cpp
|
path/Arc.cpp
|
||||||
path/QuadraticBezierCurve.cpp
|
path/QuadraticBezierCurve.cpp
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#include "Rotation.h"
|
#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),
|
: mAngle(angle),
|
||||||
mAxis(axis),
|
mAxis(axis),
|
||||||
mPoint(loc),
|
mPoint(loc),
|
||||||
mCustomAxis(customAxis),
|
mCustomAxis(customAxis),
|
||||||
mMatrix(3, 3)
|
mMatrix()
|
||||||
{
|
{
|
||||||
updateMatrix();
|
updateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Matrix& Rotation::getMatrix() const
|
const SquareMatrix3& Rotation::getMatrix() const
|
||||||
{
|
{
|
||||||
return mMatrix;
|
return mMatrix;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ public:
|
||||||
USER
|
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;
|
bool isIdentity() const;
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ private:
|
||||||
|
|
||||||
double mAngle{ 0 };
|
double mAngle{ 0 };
|
||||||
Axis mAxis{ Axis::Z };
|
Axis mAxis{ Axis::Z };
|
||||||
Point mPoint;
|
Point3 mPoint;
|
||||||
Vector mCustomAxis;
|
Vector3 mCustomAxis;
|
||||||
|
|
||||||
Matrix mMatrix;
|
SquareMatrix3 mMatrix;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,22 +18,22 @@ bool Scale::isEqual(const Scale& scale) const
|
||||||
return mX == scale.mX && mY == scale.mY && mZ == scale.mZ;
|
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),
|
: mLocation(location),
|
||||||
mScale(scale),
|
mScale(scale),
|
||||||
mRotation(rotation),
|
mRotation(rotation),
|
||||||
mMatrix(4, 4)
|
mMatrix()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transform::applyPre(const Transform& transform)
|
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();
|
mScale *= transform.getScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Transform::getLocation() const
|
const Point3& Transform::getLocation() const
|
||||||
{
|
{
|
||||||
return mLocation;
|
return mLocation;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ bool Transform::isIdentityTransform() const
|
||||||
return mLocation.isAtOrigin() && mScale.isIdentity();
|
return mLocation.isAtOrigin() && mScale.isIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transform::setLocation(const Point& loc)
|
void Transform::setLocation(const Point3& loc)
|
||||||
{
|
{
|
||||||
if (mLocation != loc)
|
if (mLocation != loc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,23 +35,23 @@ struct Scale
|
||||||
class Transform
|
class Transform
|
||||||
{
|
{
|
||||||
public:
|
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);
|
void applyPre(const Transform& transform);
|
||||||
|
|
||||||
const Point& getLocation() const;
|
const Point3& getLocation() const;
|
||||||
|
|
||||||
const Scale& getScale() const;
|
const Scale& getScale() const;
|
||||||
|
|
||||||
const Rotation& getRotation() const;
|
const Rotation& getRotation() const;
|
||||||
|
|
||||||
const Matrix& getMatrix() const;
|
const SquareMatrix4& getMatrix() const;
|
||||||
|
|
||||||
bool isEqual(const Transform& transform) const;
|
bool isEqual(const Transform& transform) const;
|
||||||
|
|
||||||
bool isIdentityTransform() const;
|
bool isIdentityTransform() const;
|
||||||
|
|
||||||
void setLocation(const Point& loc);
|
void setLocation(const Point3& loc);
|
||||||
|
|
||||||
void setScale(const Scale& scale);
|
void setScale(const Scale& scale);
|
||||||
|
|
||||||
|
@ -70,8 +70,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void updateMatrix();
|
void updateMatrix();
|
||||||
|
|
||||||
Point mLocation;
|
Point3 mLocation;
|
||||||
Scale mScale;
|
Scale mScale;
|
||||||
Rotation mRotation;
|
Rotation mRotation;
|
||||||
Matrix mMatrix;
|
SquareMatrix4 mMatrix;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
#include "Linalg.h"
|
#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<std::size_t DIM>
|
||||||
|
Vector<double, DIM> Linalg::crossProduct(const Vector<double, DIM>& v0, const Vector<double, DIM>& v1)
|
||||||
{
|
{
|
||||||
return v0.crossProduct(v1);
|
return v0.crossProduct(v1);
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
class Linalg
|
class Linalg
|
||||||
{
|
{
|
||||||
static double dotProduct(const Vector& v0, const Vector& v1);
|
template<std::size_t DIM>
|
||||||
|
static Vector<double, DIM> crossProduct(const Vector<double, DIM>& v0, const Vector<double, DIM>& v1);
|
||||||
static Vector crossProduct(const Vector& v0, const Vector& v1);
|
|
||||||
};
|
};
|
|
@ -3,23 +3,86 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
Matrix::Matrix(std::size_t numRows, std::size_t numColumns)
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
: mNumRows(numRows),
|
Matrix<T, M, N>::Matrix(T value)
|
||||||
mNumColumns(numColumns)
|
|
||||||
{
|
{
|
||||||
mData = std::vector<double>(numRows * numColumns, 0.0);
|
mData = std::vector<T>(M * N, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Matrix::isIdentity() const
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
Matrix<T, M, N>::Matrix(T value, InputType inputType)
|
||||||
|
{
|
||||||
|
if (inputType == InputType::DIAGONAL)
|
||||||
|
{
|
||||||
|
mData = std::vector<T>(M * N, 0.0);
|
||||||
|
setDiagonals(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mData = std::vector<T>(M * N, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
void Matrix<T, M, N>::applyTo(Vector<T, N>& v) const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
void Matrix<T, M, N>::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<typename T, std::size_t M, std::size_t N>
|
||||||
|
void Matrix<T, M, N>::setDiagonals(const std::vector<T>& 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<typename T, std::size_t M, std::size_t N>
|
||||||
|
void Matrix<T, M, N>::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<typename T, std::size_t M, std::size_t N>
|
||||||
|
bool Matrix<T, M, N>::isIdentity() const
|
||||||
{
|
{
|
||||||
if (!isSquare())
|
if (!isSquare())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::size_t idx=0; idx<mNumRows; idx++)
|
for(std::size_t idx=0; idx<M; idx++)
|
||||||
{
|
{
|
||||||
for(std::size_t jdx=0; jdx<mNumColumns; jdx++)
|
for(std::size_t jdx=0; jdx<N; jdx++)
|
||||||
{
|
{
|
||||||
if (idx == jdx)
|
if (idx == jdx)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +103,8 @@ bool Matrix::isIdentity() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Matrix::getItem(std::size_t rowId, std::size_t columnId) const
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
T Matrix<T, M, N>::getItem(std::size_t rowId, std::size_t columnId) const
|
||||||
{
|
{
|
||||||
const auto index = getFlatIndex(rowId, columnId);
|
const auto index = getFlatIndex(rowId, columnId);
|
||||||
if (index >= mData.size())
|
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)];
|
return mData[getFlatIndex(rowId, columnId)];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Matrix::isSquare() const
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
bool Matrix<T, M, N>::isSquare() const
|
||||||
{
|
{
|
||||||
return mNumRows == mNumColumns;
|
return M == N;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Matrix::isEqual(const Matrix& matrix) const
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
bool Matrix<T, M, N>::isEqual(const Matrix<T, M, N>& matrix) const
|
||||||
{
|
{
|
||||||
return mData == matrix.mData;
|
return mData == matrix.mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Matrix::getFlatIndex(std::size_t rowId, std::size_t columnId) const
|
template<typename T, std::size_t M, std::size_t N>
|
||||||
|
std::size_t Matrix<T, M, N>::getFlatIndex(std::size_t rowId, std::size_t columnId) const
|
||||||
{
|
{
|
||||||
return columnId + rowId*mNumColumns;
|
return columnId + rowId*N;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class Matrix<double, 2, 2>;
|
||||||
|
template class Matrix<double, 3, 3>;
|
||||||
|
template class Matrix<double, 4, 4>;
|
||||||
|
|
||||||
|
template class Matrix<std::complex<double>, 2, 2>;
|
||||||
|
template class Matrix<std::complex<double>, 3, 3>;
|
||||||
|
|
|
@ -1,35 +1,63 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <complex>
|
||||||
|
|
||||||
|
template<typename T, std::size_t M = 3, std::size_t N = 3>
|
||||||
class Matrix
|
class Matrix
|
||||||
{
|
{
|
||||||
public:
|
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<T, N>& v) const;
|
||||||
|
|
||||||
std::size_t getFlatIndex(std::size_t rowId, std::size_t columnId) 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 isIdentity() const;
|
||||||
|
|
||||||
bool isSquare() const;
|
bool isSquare() const;
|
||||||
|
|
||||||
bool isEqual(const Matrix& matrix) const;
|
bool isEqual(const Matrix<T, M, N>& matrix) const;
|
||||||
|
|
||||||
bool operator==(const Matrix& rhs) const
|
void setDiagonals(T value);
|
||||||
|
|
||||||
|
void setDiagonals(const std::vector<T>& values);
|
||||||
|
|
||||||
|
void setItem(std::size_t rowId, std::size_t columnId, T value);
|
||||||
|
|
||||||
|
bool operator==(const Matrix<T, M, N>& rhs) const
|
||||||
{
|
{
|
||||||
return isEqual(rhs);
|
return isEqual(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Matrix& rhs) const
|
bool operator!=(const Matrix<T, M, N>& rhs) const
|
||||||
{
|
{
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t mNumRows{0};
|
std::vector<T> mData;
|
||||||
std::size_t mNumColumns{0};
|
|
||||||
std::vector<double> mData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Matrix3x3 = Matrix<double, 3, 3>;
|
||||||
|
using SquareMatrix3 = Matrix<double, 3, 3>;
|
||||||
|
|
||||||
|
using Matrix2x2 = Matrix<double, 2, 2>;
|
||||||
|
using SquareMatrix2 = Matrix<double, 2, 2>;
|
||||||
|
|
||||||
|
using SquareMatrix4 = Matrix<double, 4, 4>;
|
||||||
|
|
||||||
|
using ComplexMatrix3x3 = Matrix<std::complex<double>, 3, 3>;
|
||||||
|
using ComplexMatrix2x2 = Matrix<std::complex<double>, 3, 3>;
|
|
@ -1,92 +1,156 @@
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
Vector::Vector(Primitive p)
|
template<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM>::Vector(Primitive p)
|
||||||
{
|
{
|
||||||
|
mData = std::vector<T>(DIM, 0.0);
|
||||||
switch(p)
|
switch(p)
|
||||||
{
|
{
|
||||||
case Primitive::UNIT_X:
|
case Primitive::UNIT_X:
|
||||||
mX = 1.0;
|
mData[0] = 1.0;
|
||||||
break;
|
break;
|
||||||
case Primitive::UNIT_Y:
|
case Primitive::UNIT_Y:
|
||||||
mY = 1.0;
|
mData[1] = 1.0;
|
||||||
break;
|
break;
|
||||||
case Primitive::UNIT_Z:
|
case Primitive::UNIT_Z:
|
||||||
mZ = 1.0;
|
mData[2] = 1.0;
|
||||||
break;
|
break;
|
||||||
case Primitive::NEGATIVE_X:
|
case Primitive::NEGATIVE_X:
|
||||||
mX = -1.0;
|
mData[0] = -1.0;
|
||||||
break;
|
break;
|
||||||
case Primitive::NEGATIVE_Y:
|
case Primitive::NEGATIVE_Y:
|
||||||
mY = -1.0;
|
mData[1] = -1.0;
|
||||||
break;
|
break;
|
||||||
case Primitive::NEGATIVE_Z:
|
case Primitive::NEGATIVE_Z:
|
||||||
mZ = -1.0;
|
mData[2] = -1.0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector::Vector(double x, double y, double z)
|
template<typename T, std::size_t DIM>
|
||||||
: mX(x),
|
Vector<T, DIM>::Vector(const std::vector<T>& values)
|
||||||
mY(y),
|
|
||||||
mZ(z)
|
|
||||||
{
|
{
|
||||||
|
mData = std::vector<T>(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<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM>::~Vector()
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
void Vector::reverseDirection()
|
template<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM> Vector<T, DIM>::add(const Vector<T, DIM>& v) const
|
||||||
{
|
{
|
||||||
(*this) *= -1.0;
|
Vector<T, DIM> result = *this;
|
||||||
|
result.inPlaceAdd(v);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector::getX() const
|
template<typename T, std::size_t DIM>
|
||||||
|
void Vector<T, DIM>::inPlaceAdd(const Vector<T, DIM>& v)
|
||||||
{
|
{
|
||||||
return mX;
|
std::transform(mData.begin(), mData.end(), v.mData.begin(), mData.begin(), std::plus<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector::getY() const
|
template<typename T, std::size_t DIM>
|
||||||
|
bool Vector<T, DIM>::equals(const Vector<T, DIM>& v) const
|
||||||
{
|
{
|
||||||
return mY;
|
return mData == v.mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector::getZ() const
|
template<typename T, std::size_t DIM>
|
||||||
|
void Vector<T, DIM>::inPlaceMultiply(double v)
|
||||||
{
|
{
|
||||||
return mZ;
|
//std::transform(mData.begin(), mData.end(), mData.begin(), std::bind(std::multiplies<double>(), std::placeholders::_1, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector::getLength() const
|
template<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM> Vector<T, DIM>::multiply(double v) const
|
||||||
{
|
{
|
||||||
return std::sqrt(mX * mX + mY * mY + mZ * mZ);
|
Vector<T, DIM> result = *this;
|
||||||
|
result.inPlaceMultiply(v);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector::dotProduct(const Vector& v) const
|
template<typename T, std::size_t DIM>
|
||||||
|
void Vector<T, DIM>::reverseDirection()
|
||||||
{
|
{
|
||||||
return mX * v.mX + mY * v.mY + mZ * v.mZ;
|
inPlaceMultiply(-1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector Vector::crossProduct(const Vector& v) const
|
template<typename T, std::size_t DIM>
|
||||||
|
T Vector<T, DIM>::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<typename T, std::size_t DIM>
|
||||||
|
double Vector<T, DIM>::getLength() const
|
||||||
|
{
|
||||||
|
return std::sqrt(getSelfInnerProduct());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIM>
|
||||||
|
double Vector<T, DIM>::getSelfInnerProduct() const
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
//return std::inner_product(mData.begin(), mData.end(), mData.begin(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIM>
|
||||||
|
double Vector<T, DIM>::innerPoduct(const Vector<T, DIM>& v) const
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
//return std::inner_product(mData.begin(), mData.end(), v.mData.begin(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM> Vector<T, DIM>::crossProduct(const Vector<T, DIM>& v) const
|
||||||
|
{
|
||||||
|
return Vector<T, DIM>();
|
||||||
|
//return Vector(v.mY * mZ - v.mZ * mY, v.mZ * mX - v.mX * mZ, v.mX * mY - v.mY * mX);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIM>
|
||||||
|
Vector<T, DIM> Vector<T, DIM>::getNormalized() const
|
||||||
{
|
{
|
||||||
const auto length = getLength();
|
const auto length = getLength();
|
||||||
if (length == 0.0)
|
if (length == 0.0)
|
||||||
{
|
{
|
||||||
throw std::logic_error("Divide by zero getting normalizing vector");
|
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<typename T, std::size_t DIM>
|
||||||
|
void Vector<T, DIM>::scale(const std::vector<double>& factors)
|
||||||
{
|
{
|
||||||
mX = x * mX;
|
//std::transform(mData.begin(), mData.end(), factors.begin(), mData.begin(), std::multiplies<double>());
|
||||||
mY = y * mY;
|
|
||||||
mZ = z * mZ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class Vector<double, 2>;
|
||||||
|
template class Vector<double, 3>;
|
||||||
|
template class Vector<double, 4>;
|
||||||
|
|
||||||
|
template class Vector<std::complex<double>, 2>;
|
||||||
|
template class Vector<std::complex<double>, 3>;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <complex>
|
||||||
|
|
||||||
|
template<typename T, std::size_t DIM = 3>
|
||||||
class Vector
|
class Vector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -15,56 +19,79 @@ public:
|
||||||
|
|
||||||
Vector(Primitive p);
|
Vector(Primitive p);
|
||||||
|
|
||||||
Vector(double x = 0, double y = 0, double z = 0);
|
Vector(const std::vector<T>& values = {});
|
||||||
|
|
||||||
~Vector();
|
~Vector();
|
||||||
|
|
||||||
double dotProduct(const Vector& v) const;
|
Vector<T, DIM> add(const Vector<T, DIM>& v) const;
|
||||||
|
|
||||||
Vector crossProduct(const Vector& v) const;
|
void inPlaceAdd(const Vector<T, DIM>& v);
|
||||||
|
|
||||||
|
double innerPoduct(const Vector<T, DIM>& v) const;
|
||||||
|
|
||||||
|
Vector<T, DIM> crossProduct(const Vector<T, DIM>& v) const;
|
||||||
|
|
||||||
|
bool equals(const Vector<T, DIM>& v) const;
|
||||||
|
|
||||||
void reverseDirection();
|
void reverseDirection();
|
||||||
|
|
||||||
double getX() const;
|
T getEntry(std::size_t idx) const;
|
||||||
|
|
||||||
double getY() const;
|
|
||||||
|
|
||||||
double getZ() const;
|
|
||||||
|
|
||||||
double getLength() const;
|
double getLength() const;
|
||||||
|
|
||||||
Vector getNormalized() const;
|
Vector<T, DIM> getNormalized() const;
|
||||||
|
|
||||||
void scale(double x, double y = 1.0, double z = 1.0);
|
double getSelfInnerProduct() const;
|
||||||
|
|
||||||
void operator*=(double d)
|
Vector<T, DIM> multiply(double s) const;
|
||||||
|
|
||||||
|
void inPlaceMultiply(double s);
|
||||||
|
|
||||||
|
void scale(const std::vector<double>& factors);
|
||||||
|
|
||||||
|
Vector<T, DIM> operator+(const Vector<T, DIM>& v) const
|
||||||
{
|
{
|
||||||
mX *= d;
|
return add(v);
|
||||||
mY *= d;
|
|
||||||
mZ *= d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator+=(const Vector& vector)
|
Vector<T, DIM> operator*(double s) const
|
||||||
{
|
{
|
||||||
mX += vector.mX;
|
return multiply(s);
|
||||||
mY += vector.mY;
|
|
||||||
mZ += vector.mZ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Vector& rhs) const
|
void operator*=(double s)
|
||||||
{
|
{
|
||||||
return (mX == rhs.mX)
|
inPlaceMultiply(s);
|
||||||
&& (mY == rhs.mY)
|
|
||||||
&& (mZ == rhs.mZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Vector& rhs) const
|
void operator+=(const Vector<T, DIM>& v)
|
||||||
|
{
|
||||||
|
add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Vector<T, DIM>& rhs) const
|
||||||
|
{
|
||||||
|
return equals(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Vector<T, DIM>& rhs) const
|
||||||
{
|
{
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T operator[](std::size_t idx) const
|
||||||
|
{
|
||||||
|
return getEntry(idx);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double mX{ 0 };
|
std::vector<T> mData;
|
||||||
double mY{ 0 };
|
|
||||||
double mZ{ 0 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Vector4 = Vector<double, 4>;
|
||||||
|
using Vector3 = Vector<double, 3>;
|
||||||
|
using Vector2 = Vector<double, 2>;
|
||||||
|
|
||||||
|
using ComplexVector3 = Vector<std::complex<double>, 3>;
|
||||||
|
using ComplexVector2 = Vector<std::complex<double>, 2>;
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace ntk {
|
namespace ntk {
|
||||||
Arc::Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation, bool largeArc, bool sweep)
|
Arc::Arc(const Vector2& endoffset, double rX, double rY, double rotation, bool largeArc, bool sweep)
|
||||||
: mStartPoint(startPoint),
|
: mEndOffset(endoffset),
|
||||||
mEndPoint(endPoint),
|
|
||||||
mRx(rX),
|
mRx(rX),
|
||||||
mRy(rY),
|
mRy(rY),
|
||||||
mRotation(rotation),
|
mRotation(rotation),
|
||||||
|
@ -16,43 +15,9 @@ namespace ntk {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point Arc::getFirstPoint() const
|
Vector2 Arc::getEndOffset() const
|
||||||
{
|
{
|
||||||
return mStartPoint;
|
return mEndOffset;
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bounds Arc::getBounds() const
|
Bounds Arc::getBounds() const
|
||||||
|
@ -60,22 +25,7 @@ namespace ntk {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Arc::getLocation() const
|
CurveType Arc::getCurveType() const
|
||||||
{
|
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Arc::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Arc::Type Arc::getType() const
|
|
||||||
{
|
|
||||||
return Type::CURVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Arc::CurveType Arc::getCurveType() const
|
|
||||||
{
|
{
|
||||||
return CurveType::ARC;
|
return CurveType::ARC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "Point.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
namespace ntk{
|
namespace ntk{
|
||||||
class Arc : public Curve
|
class Arc : public Curve<2>
|
||||||
{
|
{
|
||||||
public:
|
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;
|
Vector2 getEndOffset() const override;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
|
|
||||||
CurveType getCurveType() const override;
|
CurveType getCurveType() const override;
|
||||||
|
|
||||||
double getRx() const;
|
double getRx() const;
|
||||||
|
@ -31,13 +25,8 @@ public:
|
||||||
|
|
||||||
bool getSweepParam() const;
|
bool getSweepParam() const;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mStartPoint;
|
Vector2 mEndOffset;
|
||||||
Point mEndPoint;
|
|
||||||
double mRx{ 0.0 };
|
double mRx{ 0.0 };
|
||||||
double mRy{ 0.0 };
|
double mRy{ 0.0 };
|
||||||
double mRotation{ 0 };
|
double mRotation{ 0 };
|
||||||
|
|
|
@ -1,75 +1,43 @@
|
||||||
#include "CubicBezierCurve.h"
|
#include "CubicBezierCurve.h"
|
||||||
|
|
||||||
#include "PointParser.h"
|
template<std::size_t DIM>
|
||||||
|
CubicBezierCurve<DIM>::CubicBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& startControlOffset, const Vector<double, DIM>& endControlOffset)
|
||||||
CubicBezierCurve::CubicBezierCurve(const Point& startPoint, const Point& endPoint, const Point& startControlPoint, const Point& endControlPoint)
|
: mEndOffset(endOffset),
|
||||||
: mStartPoint(startPoint),
|
mStartControlOffset(startControlOffset),
|
||||||
mEndPoint(endPoint),
|
mEndControlOffset(endControlOffset)
|
||||||
mStartControlPoint(startControlPoint),
|
|
||||||
mEndControlPoint(endControlPoint)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point CubicBezierCurve::getFirstPoint() const
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> CubicBezierCurve<DIM>::getEndOffset() const
|
||||||
{
|
{
|
||||||
return mStartPoint;
|
return mEndOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point CubicBezierCurve::getEndPoint() const
|
template<std::size_t DIM>
|
||||||
|
const Vector<double, DIM>& CubicBezierCurve<DIM>::getStartControlOffset() const
|
||||||
{
|
{
|
||||||
return mEndPoint;
|
return mStartControlOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& CubicBezierCurve::getStartControlPoint() const
|
template<std::size_t DIM>
|
||||||
|
const Vector<double, DIM>& CubicBezierCurve<DIM>::getEndControlOffset() const
|
||||||
{
|
{
|
||||||
return mStartControlPoint;
|
return mEndControlOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& CubicBezierCurve::getEndControlPoint() const
|
template<std::size_t DIM>
|
||||||
{
|
Bounds CubicBezierCurve<DIM>::getBounds() 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
|
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& CubicBezierCurve::getLocation() const
|
template<std::size_t DIM>
|
||||||
{
|
CurveType CubicBezierCurve<DIM>::getCurveType() const
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CubicBezierCurve::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CubicBezierCurve::Type CubicBezierCurve::getType() const
|
|
||||||
{
|
|
||||||
return Type::CURVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CubicBezierCurve::CurveType CubicBezierCurve::getCurveType() const
|
|
||||||
{
|
{
|
||||||
return CurveType::CUBIC_BEZIER;
|
return CurveType::CUBIC_BEZIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class CubicBezierCurve<2>;
|
||||||
|
template class CubicBezierCurve<3>;
|
||||||
|
|
|
@ -1,36 +1,26 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "Point.h"
|
#include "Vector.h"
|
||||||
|
|
||||||
class CubicBezierCurve : public Curve
|
template<std::size_t DIM>
|
||||||
|
class CubicBezierCurve : public Curve<DIM>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CubicBezierCurve(const Point& startPoint, const Point& endPoint, const Point& startControlPoint, const Point& endControlPoint);
|
CubicBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& startControlOffset, const Vector<double, DIM>& endControlOffset);
|
||||||
|
|
||||||
Point getFirstPoint() const override;
|
Vector<double, DIM> getEndOffset() const override;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
const Vector<double, DIM>& getStartControlOffset() const;
|
||||||
|
|
||||||
const Point& getStartControlPoint() const;
|
const Vector<double, DIM>& getEndControlOffset() const;
|
||||||
|
|
||||||
const Point& getEndControlPoint() const;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
|
|
||||||
CurveType getCurveType() const override;
|
CurveType getCurveType() const override;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mStartPoint;
|
Vector<double, DIM> mEndOffset;
|
||||||
Point mEndPoint;
|
Vector<double, DIM> mStartControlOffset;
|
||||||
Point mStartControlPoint;
|
Vector<double, DIM> mEndControlOffset;
|
||||||
Point mEndControlPoint;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,16 +2,22 @@
|
||||||
|
|
||||||
#include "PathElement.h"
|
#include "PathElement.h"
|
||||||
|
|
||||||
class Curve : public PathElement
|
enum class CurveType
|
||||||
|
{
|
||||||
|
ARC,
|
||||||
|
QUADRATIC_BEZIER,
|
||||||
|
CUBIC_BEZIER,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
class Curve : public PathElement<DIM>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class CurveType
|
Curve::Type getType() const override
|
||||||
{
|
{
|
||||||
ARC,
|
return Curve::Type::CURVE;
|
||||||
QUADRATIC_BEZIER,
|
}
|
||||||
CUBIC_BEZIER,
|
|
||||||
UNKNOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual CurveType getCurveType() const = 0;
|
virtual CurveType getCurveType() const = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,119 +1,66 @@
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
|
|
||||||
#include "PointParser.h"
|
template<std::size_t DIM>
|
||||||
|
Line<DIM>::Line(const PointCollection<DIM>& points)
|
||||||
Line::Line(const Point& start, const PointCollection& points)
|
: mPoints(points)
|
||||||
: mStartPoint(start),
|
|
||||||
mPoints(points)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Line::Line(const Point& start, InputBufferType bufferType, const std::vector<double>& buffer)
|
template<std::size_t DIM>
|
||||||
: mStartPoint(start)
|
Line<DIM>::Line(InputBufferType bufferType, const std::vector<double>& buffer)
|
||||||
{
|
{
|
||||||
if (bufferType == InputBufferType::XY_REL)
|
if (bufferType == InputBufferType::XY)
|
||||||
{
|
{
|
||||||
for (std::size_t idx = 0; idx < buffer.size(); idx += 2)
|
for (std::size_t idx = 0; idx < buffer.size(); idx += 2)
|
||||||
{
|
{
|
||||||
const auto x = buffer[idx];
|
const auto x = buffer[idx];
|
||||||
const auto y = buffer[idx + 1];
|
const auto y = buffer[idx + 1];
|
||||||
mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY() + y));
|
mPoints.addPoint(Point<DIM>(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bufferType == InputBufferType::XY_ABS)
|
else if (bufferType == InputBufferType::HORIZONTAL)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
for (std::size_t idx = 0; idx < buffer.size(); idx ++)
|
for (std::size_t idx = 0; idx < buffer.size(); idx ++)
|
||||||
{
|
{
|
||||||
const auto x = buffer[idx];
|
mPoints.addPoint(Point<DIM>(buffer[idx], 0.0));
|
||||||
mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (bufferType == InputBufferType::HORIZONTAL_ABS)
|
else if (bufferType == InputBufferType::VERTICAL)
|
||||||
{
|
{
|
||||||
for (std::size_t idx = 0; idx < buffer.size(); idx++)
|
for (std::size_t idx = 0; idx < buffer.size(); idx++)
|
||||||
{
|
{
|
||||||
const auto x = buffer[idx];
|
mPoints.addPoint(Point<DIM>(0.0, 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Line::toPostScriptString(std::size_t precision) const
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> Line<DIM>::getEndOffset() const
|
||||||
{
|
{
|
||||||
if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
|
return mPoints.getEndPoint().getOriginOffset();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point Line::getFirstPoint() const
|
template<std::size_t DIM>
|
||||||
{
|
const PointCollection<DIM>& Line<DIM>::getPoints() const
|
||||||
return getLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Line::getEndPoint() const
|
|
||||||
{
|
|
||||||
return mPoints.getEndPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PointCollection& Line::getPoints() const
|
|
||||||
{
|
{
|
||||||
return mPoints;
|
return mPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
Line::Type Line::getType() const
|
template<std::size_t DIM>
|
||||||
|
AbstractGeometricItem::Type Line<DIM>::getType() const
|
||||||
{
|
{
|
||||||
return Line::Type::LINE;
|
return AbstractGeometricItem::Type::LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Line::getLocation() const
|
template<std::size_t DIM>
|
||||||
{
|
Bounds Line<DIM>::getBounds() const
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bounds Line::getBounds() const
|
|
||||||
{
|
{
|
||||||
auto bounds = mPoints.getBounds();
|
auto bounds = mPoints.getBounds();
|
||||||
bounds.includePoint(mStartPoint.getX(), mStartPoint.getY(), mStartPoint.getZ());
|
bounds.includePoint(0.0, 0.0, 0.0);
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class Line<2>;
|
||||||
|
template class Line<3>;
|
||||||
|
|
||||||
|
|
|
@ -6,40 +6,31 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Line : public PathElement
|
template<std::size_t DIM>
|
||||||
|
class Line : public PathElement<DIM>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class InputBufferType
|
enum class InputBufferType
|
||||||
{
|
{
|
||||||
HORIZONTAL_REL,
|
HORIZONTAL,
|
||||||
HORIZONTAL_ABS,
|
VERTICAL,
|
||||||
VERTICAL_REL,
|
XY
|
||||||
VERTICAL_ABS,
|
|
||||||
XY_REL,
|
|
||||||
XY_ABS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Line(const Point& start, const PointCollection& points);
|
Line(const PointCollection<DIM>& points);
|
||||||
|
|
||||||
Line(const Point& start, InputBufferType bufferType, const std::vector<double>& buffer);
|
Line(InputBufferType bufferType, const std::vector<double>& buffer);
|
||||||
|
|
||||||
const PointCollection& getPoints() const;
|
const PointCollection<DIM>& getPoints() const;
|
||||||
|
|
||||||
Line::Type getType() const override;
|
AbstractGeometricItem::Type getType() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
Point getFirstPoint() const override;
|
Vector<double, DIM> getEndOffset() const override;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override {};
|
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mStartPoint;
|
PointCollection<DIM> mPoints;
|
||||||
PointCollection mPoints;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Line2 = Line<2>;
|
||||||
|
|
|
@ -1,87 +1,51 @@
|
||||||
#include "LineSegment.h"
|
#include "LineSegment.h"
|
||||||
|
|
||||||
#include "PointParser.h"
|
template<std::size_t DIM>
|
||||||
|
LineSegment<DIM>::LineSegment(const Point<DIM>& p0, const Point<DIM>& p1)
|
||||||
LineSegment::LineSegment(const Point& p0, const Point& p1)
|
|
||||||
: mP0(p0),
|
: mP0(p0),
|
||||||
mP1(p1)
|
mP1(p1)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<LineSegment> LineSegment::Create(const Point& p0, const Point& p1)
|
template<std::size_t DIM>
|
||||||
|
std::unique_ptr<LineSegment<DIM> > LineSegment<DIM> ::Create(const Point<DIM>& p0, const Point<DIM>& p1)
|
||||||
{
|
{
|
||||||
return std::make_unique<LineSegment>(p0, p1);
|
return std::make_unique<LineSegment<DIM> >(p0, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
double LineSegment::getLength() const
|
template<std::size_t DIM>
|
||||||
|
double LineSegment<DIM> ::getLength() const
|
||||||
{
|
{
|
||||||
return mP0.getDistance(mP1);
|
return mP0.getDistance(mP1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& LineSegment::getPoint0() const
|
template<std::size_t DIM>
|
||||||
|
const Point<DIM>& LineSegment<DIM> ::getPoint0() const
|
||||||
{
|
{
|
||||||
return mP0;
|
return mP0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& LineSegment::getPoint1() const
|
template<std::size_t DIM>
|
||||||
|
const Point<DIM>& LineSegment<DIM> ::getPoint1() const
|
||||||
{
|
{
|
||||||
return mP1;
|
return mP1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineSegment::sample(SparseGrid<bool>*) const
|
template<std::size_t DIM>
|
||||||
{
|
bool LineSegment<DIM>::isHorizontal() 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
|
|
||||||
{
|
{
|
||||||
return mP0.getDeltaY(mP1) == 0.0;
|
return mP0.getDeltaY(mP1) == 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LineSegment::isVertical() const
|
template<std::size_t DIM>
|
||||||
|
bool LineSegment<DIM>::isVertical() const
|
||||||
{
|
{
|
||||||
return mP0.getDeltaX(mP1) == 0.0;
|
return mP0.getDeltaX(mP1) == 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bounds LineSegment::getBounds() const
|
template<std::size_t DIM>
|
||||||
|
Bounds LineSegment<DIM>::getBounds() const
|
||||||
{
|
{
|
||||||
const auto minX = std::min(mP0.getX(), mP1.getX());
|
const auto minX = std::min(mP0.getX(), mP1.getX());
|
||||||
const auto maxX = std::max(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};
|
return {minX, maxX, minY, maxY};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& LineSegment::getLocation() const
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> LineSegment<DIM>::getEndOffset() const
|
||||||
{
|
{
|
||||||
return mP0;
|
return getPoint1().getOriginOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Point LineSegment::getFirstPoint() const
|
template<std::size_t DIM>
|
||||||
{
|
AbstractGeometricItem::Type LineSegment<DIM>::getType() const
|
||||||
return getPoint0();
|
|
||||||
}
|
|
||||||
|
|
||||||
Point LineSegment::getEndPoint() const
|
|
||||||
{
|
|
||||||
return getPoint1();
|
|
||||||
}
|
|
||||||
|
|
||||||
LineSegment::Type LineSegment::getType() const
|
|
||||||
{
|
{
|
||||||
return AbstractGeometricItem::Type::LINE_SEGMENT;
|
return AbstractGeometricItem::Type::LINE_SEGMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> LineSegment<DIM>::asVector() const
|
||||||
|
{
|
||||||
|
return mP1.getDelta(mP0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template class LineSegment<2>;
|
||||||
|
template class LineSegment<3>;
|
|
@ -1,41 +1,37 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "PathElement.h"
|
#include "PathElement.h"
|
||||||
|
#include "Point.h"
|
||||||
|
|
||||||
#include <string>
|
template<std::size_t DIM>
|
||||||
|
class LineSegment : public PathElement<DIM>
|
||||||
class LineSegment : public PathElement
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LineSegment(const Point& p0, const Point& p1);
|
LineSegment(const Point<DIM>& p0, const Point<DIM>& p1);
|
||||||
|
|
||||||
static std::unique_ptr<LineSegment> Create(const Point& p0, const Point& p1);
|
static std::unique_ptr<LineSegment<DIM> > Create(const Point<DIM>& p0, const Point<DIM>& p1);
|
||||||
|
|
||||||
double getLength() const;
|
double getLength() const;
|
||||||
|
|
||||||
const Point& getPoint0() const;
|
const Point<DIM>& getPoint0() const;
|
||||||
|
|
||||||
const Point& getPoint1() const;
|
const Point<DIM>& getPoint1() const;
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
Vector<double, DIM> asVector() const;
|
||||||
|
|
||||||
Point getFirstPoint() const override;
|
Vector<double, DIM> getEndOffset() const override;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
AbstractGeometricItem::Type getType() const override;
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
|
|
||||||
bool isHorizontal() const;
|
bool isHorizontal() const;
|
||||||
|
|
||||||
bool isVertical() const;
|
bool isVertical() const;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mP0;
|
Point<DIM> mP0;
|
||||||
Point mP1;
|
Point<DIM> mP1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using LineSegment2 = LineSegment<2>;
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
|
|
||||||
#include "StringUtils.h"
|
|
||||||
#include "FileLogger.h"
|
|
||||||
|
|
||||||
#include "Line.h"
|
|
||||||
#include "LineSegment.h"
|
|
||||||
#include "PathPostScriptConverter.h"
|
|
||||||
|
|
||||||
GeometryPath::~GeometryPath()
|
GeometryPath::~GeometryPath()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -17,22 +10,12 @@ const std::vector<GeometryPathFeaturePtr>& GeometryPath::getFeatures() const
|
||||||
return mFeatures;
|
return mFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryPath::buildFromPostscript(const std::string& psString)
|
|
||||||
{
|
|
||||||
PathPostScriptConverter converter;
|
|
||||||
converter.fromPostScript(this, psString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeometryPath::addFeature(GeometryPathFeaturePtr feature)
|
void GeometryPath::addFeature(GeometryPathFeaturePtr feature)
|
||||||
{
|
{
|
||||||
mFeatures.push_back(std::move(feature));
|
mFeatures.push_back(std::move(feature));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& GeometryPath::getLocation() const
|
|
||||||
{
|
|
||||||
return mLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bounds GeometryPath::getBounds() const
|
Bounds GeometryPath::getBounds() const
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
|
@ -42,14 +25,3 @@ GeometryPath::Type GeometryPath::getType() const
|
||||||
{
|
{
|
||||||
return GeometryPath::Type::PATH;
|
return GeometryPath::Type::PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryPath::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GeometryPath::getAsPostScript() const
|
|
||||||
{
|
|
||||||
PathPostScriptConverter converter;
|
|
||||||
return converter.toPostScript(this);
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,23 +6,24 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using PathElementPtr = std::unique_ptr<PathElement>;
|
using PathElementPtr = std::unique_ptr<PathElement<2> >;
|
||||||
|
|
||||||
class GeometryPathFeature
|
class GeometryPathFeature
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void setLocation(Vector2 offset)
|
||||||
|
{
|
||||||
|
mOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
void addElement(PathElementPtr element)
|
void addElement(PathElementPtr element)
|
||||||
{
|
{
|
||||||
if (mElements.empty())
|
|
||||||
{
|
|
||||||
mLocation = element->getFirstPoint();
|
|
||||||
}
|
|
||||||
mElements.push_back(std::move(element));
|
mElements.push_back(std::move(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& getLocation() const
|
const Vector2& getOffset() const
|
||||||
{
|
{
|
||||||
return mLocation;
|
return mOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<PathElementPtr>& getElements() const
|
const std::vector<PathElementPtr>& getElements() const
|
||||||
|
@ -30,8 +31,19 @@ public:
|
||||||
return mElements;
|
return mElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PathOffsetType getPathOffsetType() const
|
||||||
|
{
|
||||||
|
return mOffsetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPathOffsetType(PathOffsetType offsetType)
|
||||||
|
{
|
||||||
|
mOffsetType = offsetType;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mLocation;
|
Vector2 mOffset;
|
||||||
|
PathOffsetType mOffsetType{PathOffsetType::RELATIVE_TO};
|
||||||
std::vector<PathElementPtr> mElements;
|
std::vector<PathElementPtr> mElements;
|
||||||
};
|
};
|
||||||
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
|
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
|
||||||
|
@ -43,21 +55,12 @@ public:
|
||||||
|
|
||||||
void addFeature(GeometryPathFeaturePtr feature);
|
void addFeature(GeometryPathFeaturePtr feature);
|
||||||
|
|
||||||
void buildFromPostscript(const std::string& psString);
|
|
||||||
|
|
||||||
std::string getAsPostScript() const;
|
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
Type getType() const override;
|
Type getType() const override;
|
||||||
|
|
||||||
const std::vector<GeometryPathFeaturePtr>& getFeatures() const;
|
const std::vector<GeometryPathFeaturePtr>& getFeatures() const;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mLocation;
|
|
||||||
std::vector<GeometryPathFeaturePtr> mFeatures;
|
std::vector<GeometryPathFeaturePtr> mFeatures;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "PathElement.h"
|
#include "PathElement.h"
|
||||||
|
|
||||||
PathElement::~PathElement()
|
template<std::size_t DIM>
|
||||||
|
PathElement<DIM>::~PathElement()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class PathElement<2>;
|
||||||
|
template class PathElement<3>;
|
|
@ -1,31 +1,39 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AbstractGeometricItem.h"
|
#include "AbstractGeometricItem.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
#include <string>
|
enum class PathOffsetType
|
||||||
|
{
|
||||||
|
RELATIVE_TO,
|
||||||
|
ABSOLUTE_TO
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
class PathElement : public AbstractGeometricItem
|
class PathElement : public AbstractGeometricItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class PostscriptPositioning
|
|
||||||
{
|
|
||||||
RELATIVE_TO,
|
|
||||||
ABSOLUTE_TO
|
|
||||||
};
|
|
||||||
|
|
||||||
~PathElement();
|
~PathElement();
|
||||||
|
|
||||||
virtual Point getFirstPoint() const = 0;
|
virtual Vector<double, DIM> getEndOffset() const = 0;
|
||||||
|
|
||||||
virtual Point getEndPoint() const = 0;
|
PathOffsetType getPathOffsetType() const
|
||||||
|
|
||||||
void setPostscriptPositioning(PostscriptPositioning positioning)
|
|
||||||
{
|
{
|
||||||
mPostscriptPositioning = positioning;
|
return mOffsetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string toPostScriptString(std::size_t precision = 0) const = 0;
|
bool isRelativeOffset() const
|
||||||
|
{
|
||||||
|
return mOffsetType == PathOffsetType::RELATIVE_TO;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
void setPathOffsetType(PathOffsetType offsetType)
|
||||||
PostscriptPositioning mPostscriptPositioning{ PostscriptPositioning::RELATIVE_TO};
|
{
|
||||||
|
mOffsetType = offsetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PathOffsetType mOffsetType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using PathElement2 = PathElement<2>;
|
||||||
|
|
|
@ -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<GeometryPathFeature>();
|
|
||||||
}
|
|
||||||
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<LineSegment>(mCurrentPoint, Point(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
element = std::make_unique<LineSegment>(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<Line>(mCurrentPoint, buffer_type, mPointBuffer);
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
PathElementPtr PathPostScriptConverter::onVerticalLineTo()
|
|
||||||
{
|
|
||||||
PathElementPtr element;
|
|
||||||
if (mPointBuffer.size() == 1)
|
|
||||||
{
|
|
||||||
if (mPositionState == PositionState::RELATIVE)
|
|
||||||
{
|
|
||||||
element = std::make_unique<LineSegment>(mCurrentPoint, Point(mCurrentPoint.getX(), mCurrentPoint.getY() + mPointBuffer[0]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
element = std::make_unique<LineSegment>(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<Line>(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<LineSegment>(mCurrentPoint, next_point);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto next_point = Point(mPointBuffer[0], mPointBuffer[1]);
|
|
||||||
element = std::make_unique<LineSegment>(mCurrentPoint, next_point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Line::InputBufferType buffer_type = mPositionState == PositionState::RELATIVE ? Line::InputBufferType::XY_REL : Line::InputBufferType::XY_ABS;
|
|
||||||
element = std::make_unique<Line>(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<ntk::Arc>(mCurrentPoint, end_point, rx, ry, rotation, large_arc, sweep);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto end_point = Point(mPointBuffer[5], mPointBuffer[6]);
|
|
||||||
element = std::make_unique<ntk::Arc>(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<QuadraticBezierCurve>(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<QuadraticBezierCurve>(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<CubicBezierCurve>(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<CubicBezierCurve>(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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,63 +1,36 @@
|
||||||
#include "QuadraticBezierCurve.h"
|
#include "QuadraticBezierCurve.h"
|
||||||
|
|
||||||
#include "PointParser.h"
|
template<std::size_t DIM>
|
||||||
|
QuadraticBezierCurve<DIM>::QuadraticBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& controlOffset)
|
||||||
QuadraticBezierCurve::QuadraticBezierCurve(const Point& startPoint, const Point& endPoint, const Point& controlPoint)
|
: mEndOffset(endOffset),
|
||||||
: mStartPoint(startPoint),
|
mControlOffset(controlOffset)
|
||||||
mEndPoint(endPoint),
|
|
||||||
mControlPoint(controlPoint)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point QuadraticBezierCurve::getFirstPoint() const
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> QuadraticBezierCurve<DIM>::getEndOffset() const
|
||||||
{
|
{
|
||||||
return mStartPoint;
|
return mEndOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point QuadraticBezierCurve::getEndPoint() const
|
template<std::size_t DIM>
|
||||||
|
const Vector<double, DIM>& QuadraticBezierCurve<DIM>::getControlOffset() const
|
||||||
{
|
{
|
||||||
return mEndPoint;
|
return mControlOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point QuadraticBezierCurve::getControlPoint() const
|
template<std::size_t DIM>
|
||||||
{
|
Bounds QuadraticBezierCurve<DIM>::getBounds() 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
|
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& QuadraticBezierCurve::getLocation() const
|
template<std::size_t DIM>
|
||||||
{
|
CurveType QuadraticBezierCurve<DIM>::getCurveType() const
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QuadraticBezierCurve::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QuadraticBezierCurve::Type QuadraticBezierCurve::getType() const
|
|
||||||
{
|
|
||||||
return Type::CURVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
QuadraticBezierCurve::CurveType QuadraticBezierCurve::getCurveType() const
|
|
||||||
{
|
{
|
||||||
return CurveType::QUADRATIC_BEZIER;
|
return CurveType::QUADRATIC_BEZIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class QuadraticBezierCurve<2>;
|
||||||
|
template class QuadraticBezierCurve<3>;
|
|
@ -3,31 +3,21 @@
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
|
|
||||||
class QuadraticBezierCurve : public Curve
|
template<std::size_t DIM>
|
||||||
|
class QuadraticBezierCurve : public Curve<DIM>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QuadraticBezierCurve(const Point& startPoint, const Point& endPoint, const Point& controlPoint);
|
QuadraticBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& controlOffset);
|
||||||
|
|
||||||
Point getFirstPoint() const override;
|
const Vector<double, DIM>& getControlOffset() const;
|
||||||
|
|
||||||
Point getControlPoint() const;
|
Vector<double, DIM> getEndOffset() const override;
|
||||||
|
|
||||||
Point getEndPoint() const override;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
|
|
||||||
CurveType getCurveType() const override;
|
CurveType getCurveType() const override;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
std::string toPostScriptString(std::size_t precision = 0) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mStartPoint;
|
Vector<double, DIM> mEndOffset;
|
||||||
Point mEndPoint;
|
Vector<double, DIM> mControlOffset;
|
||||||
Point mControlPoint;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,51 +2,116 @@
|
||||||
|
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
Point::Point(double x, double y, double z)
|
template<std::size_t DIM>
|
||||||
: mX(x),
|
Point<DIM>::Point(const Point<2>& p)
|
||||||
mY(y),
|
: Point(p.getX(), p.getY())
|
||||||
mZ(z)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Point::Point(const DiscretePoint& point)
|
|
||||||
: mX(static_cast<double>(point.getX())),
|
|
||||||
mY(static_cast<double>(point.getY())),
|
|
||||||
mZ(0)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point::Point(const Point& reference, double offSetX, double offSetY, double offSetZ)
|
template<std::size_t DIM>
|
||||||
: mX(reference.getX() + offSetX),
|
Point<DIM>::Point(double x, double y, double z)
|
||||||
mY(reference.getY() + offSetY),
|
{
|
||||||
mZ(reference.getZ() + offSetZ)
|
mCoords = std::vector<double>(DIM);
|
||||||
|
if (DIM > 0)
|
||||||
|
{
|
||||||
|
mCoords[0] = x;
|
||||||
|
}
|
||||||
|
if (DIM > 1)
|
||||||
|
{
|
||||||
|
mCoords[1] = y;
|
||||||
|
}
|
||||||
|
if (DIM > 2)
|
||||||
|
{
|
||||||
|
mCoords[2] = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
Point<DIM>::Point(const Vector<double, DIM>& v)
|
||||||
|
{
|
||||||
|
mCoords = std::vector<double>(DIM);
|
||||||
|
for (std::size_t idx = 0; idx < DIM; idx++)
|
||||||
|
{
|
||||||
|
mCoords[idx] = v.getEntry(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
Point<DIM>::Point(const DiscretePoint& point)
|
||||||
|
: Point(static_cast<double>(point.getX()), static_cast<double>(point.getY()), 0.0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Point::~Point()
|
template<std::size_t DIM>
|
||||||
|
Point<DIM>::Point(const Point<DIM>& reference, double offSetX, double offSetY, double offSetZ)
|
||||||
|
{
|
||||||
|
mCoords = std::vector<double>(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<std::size_t DIM>
|
||||||
|
Point<DIM>::~Point()
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
double Point::getX() const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getX() const
|
||||||
{
|
{
|
||||||
return mX;
|
if (DIM > 0)
|
||||||
|
{
|
||||||
|
return mCoords[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getY() const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getY() const
|
||||||
{
|
{
|
||||||
return mY;
|
if (DIM > 1)
|
||||||
|
{
|
||||||
|
return mCoords[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getZ() const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getZ() const
|
||||||
{
|
{
|
||||||
return mZ;
|
if (DIM > 2)
|
||||||
|
{
|
||||||
|
return mCoords[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getDistance(const Point& point) const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getDistance(const Point& point) const
|
||||||
{
|
{
|
||||||
const auto deltaX = getDeltaX(point);
|
const auto deltaX = getDeltaX(point);
|
||||||
const auto deltaY = getDeltaY(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);
|
return std::sqrt(deltaX* deltaX + deltaY* deltaY + deltaZ* deltaZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector Point::getDelta(const Point& point) const
|
template<std::size_t DIM>
|
||||||
|
Vector<double, DIM> Point<DIM>::getDelta(const Point<DIM>& point) const
|
||||||
{
|
{
|
||||||
return Vector(point.mX - mX, point.mY - mY, point.mZ - mZ);
|
return Vector<double, DIM>({ point.getX() - getX(), point.getY() - getY(), point.getZ() - getZ() });
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getDeltaX(const Point& point) const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getDeltaX(const Point<DIM>& point) const
|
||||||
{
|
{
|
||||||
return point.getX() - mX;
|
return point.getX() - getX();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getDeltaY(const Point& point) const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getDeltaY(const Point<DIM>& point) const
|
||||||
{
|
{
|
||||||
return point.getY() - mY;
|
return point.getY() - getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Point::getDeltaZ(const Point& point) const
|
template<std::size_t DIM>
|
||||||
|
double Point<DIM>::getDeltaZ(const Point<DIM>& point) const
|
||||||
{
|
{
|
||||||
return point.getZ() - mZ;
|
return point.getZ() - getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Point::isAtOrigin() const
|
template<std::size_t DIM>
|
||||||
|
bool Point<DIM>::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<std::size_t DIM>
|
||||||
|
Vector<double, DIM> Point<DIM>::getOriginOffset() const
|
||||||
{
|
{
|
||||||
mX -= transform.getLocation().getX();
|
return Vector<double, DIM>(mCoords);
|
||||||
mY -= transform.getLocation().getY();
|
|
||||||
mZ -= transform.getLocation().getZ();
|
|
||||||
|
|
||||||
mX *= transform.getScale().mX;
|
|
||||||
mY *= transform.getScale().mY;
|
|
||||||
mZ *= transform.getScale().mZ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Point::move(double x, double y, double z)
|
template<std::size_t DIM>
|
||||||
|
void Point<DIM>::apply(const Transform& transform)
|
||||||
{
|
{
|
||||||
mX += x;
|
moveBy(-transform.getLocation().getX(), -transform.getLocation().getY(), -transform.getLocation().getZ());
|
||||||
mY += y;
|
scale(transform.getScale().mX, transform.getScale().mY, transform.getScale().mZ);
|
||||||
mZ += z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Point::move(const Vector& vector)
|
template<std::size_t DIM>
|
||||||
|
void Point<DIM>::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<std::size_t DIM>
|
||||||
|
void Point<DIM>::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<std::size_t DIM>
|
||||||
|
void Point<DIM>::moveBy(const Vector<double, DIM>& vector)
|
||||||
|
{
|
||||||
|
for (std::size_t idx = 0; idx < DIM; idx++)
|
||||||
|
{
|
||||||
|
mCoords[idx] += vector.getEntry(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
bool Point<DIM>::isEqual(const Point<DIM>& rhs) const
|
||||||
|
{
|
||||||
|
return mCoords == rhs.mCoords;
|
||||||
|
}
|
||||||
|
|
||||||
|
template class Point<2>;
|
||||||
|
template class Point<3>;
|
||||||
|
|
|
@ -7,14 +7,19 @@
|
||||||
|
|
||||||
class Transform;
|
class Transform;
|
||||||
|
|
||||||
|
template<std::size_t DIM = 3>
|
||||||
class Point
|
class Point
|
||||||
{
|
{
|
||||||
public:
|
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<double, DIM>& v);
|
||||||
|
|
||||||
|
Point(const Point<2>& p);
|
||||||
|
|
||||||
Point(const DiscretePoint& point);
|
Point(const DiscretePoint& point);
|
||||||
|
|
||||||
Point(const Point& reference, double offSetX, double offSetY, double offSetZ = 0);
|
Point(const Point<DIM>& reference, double offSetX, double offSetY, double offSetZ = 0);
|
||||||
|
|
||||||
~Point();
|
~Point();
|
||||||
|
|
||||||
|
@ -26,43 +31,56 @@ public:
|
||||||
|
|
||||||
double getZ() const;
|
double getZ() const;
|
||||||
|
|
||||||
double getDistance(const Point& point) const;
|
double getDistance(const Point<DIM>& point) const;
|
||||||
|
|
||||||
double getDeltaX(const Point& point) const;
|
double getDeltaX(const Point<DIM>& point) const;
|
||||||
|
|
||||||
double getDeltaY(const Point& point) const;
|
double getDeltaY(const Point<DIM>& point) const;
|
||||||
|
|
||||||
double getDeltaZ(const Point& point) const;
|
double getDeltaZ(const Point<DIM>& point) const;
|
||||||
|
|
||||||
Vector getDelta(const Point& point) const;
|
Vector<double, DIM> getOriginOffset() const;
|
||||||
|
|
||||||
|
Vector<double, DIM> getDelta(const Point<DIM>& point) const;
|
||||||
|
|
||||||
bool isAtOrigin() const;
|
bool isAtOrigin() const;
|
||||||
|
|
||||||
void move(const Vector& vector);
|
bool isEqual(const Point<DIM>& rhs) const;
|
||||||
|
|
||||||
void move(double x, double y = 0.0, double z = 0.0);
|
void moveBy(const Vector<double, DIM>& 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<DIM> operator+(const Vector<double, DIM>& vector)
|
||||||
{
|
{
|
||||||
move(vector);
|
Point<DIM> p(*this);
|
||||||
|
p += vector;
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Point& rhs) const
|
void operator+=(const Vector<double, DIM>& vector)
|
||||||
{
|
{
|
||||||
return (mX == rhs.mX)
|
moveBy(vector);
|
||||||
&& (mY == rhs.mY)
|
|
||||||
&& (mZ == rhs.mZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Point& rhs) const
|
bool operator==(const Point<DIM>& rhs) const
|
||||||
|
{
|
||||||
|
return isEqual(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Point<DIM>& rhs) const
|
||||||
{
|
{
|
||||||
return !operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double mX{0};
|
std::vector<double> mCoords;
|
||||||
double mY{0};
|
|
||||||
double mZ{0};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using PointPtr = std::unique_ptr<Point>;
|
using Point3 = Point<3>;
|
||||||
|
using Point2 = Point<2>;
|
||||||
|
|
||||||
|
using PointPtr3 = std::unique_ptr<Point<3> >;
|
||||||
|
using PointPtr2 = std::unique_ptr<Point<2> >;
|
|
@ -1,12 +1,14 @@
|
||||||
#include "PointCollection.h"
|
#include "PointCollection.h"
|
||||||
|
|
||||||
PointCollection::PointCollection(const std::vector<Point> points)
|
template<std::size_t DIM>
|
||||||
|
PointCollection<DIM>::PointCollection(const std::vector<Point<DIM> > points)
|
||||||
: mPoints(points)
|
: mPoints(points)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCollection::apply(const Transform& transform)
|
template<std::size_t DIM>
|
||||||
|
void PointCollection<DIM>::apply(const Transform& transform)
|
||||||
{
|
{
|
||||||
for (auto& point : mPoints)
|
for (auto& point : mPoints)
|
||||||
{
|
{
|
||||||
|
@ -14,12 +16,14 @@ void PointCollection::apply(const Transform& transform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCollection::addPoint(const Point& point)
|
template<std::size_t DIM>
|
||||||
|
void PointCollection<DIM>::addPoint(const Point<DIM>& point)
|
||||||
{
|
{
|
||||||
mPoints.push_back(point);
|
mPoints.push_back(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bounds PointCollection::getBounds() const
|
template<std::size_t DIM>
|
||||||
|
Bounds PointCollection<DIM>::getBounds() const
|
||||||
{
|
{
|
||||||
Bounds bounds{0.0, 0.0, 0.0, 0.0};
|
Bounds bounds{0.0, 0.0, 0.0, 0.0};
|
||||||
|
|
||||||
|
@ -36,7 +40,8 @@ Bounds PointCollection::getBounds() const
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point PointCollection::getEndPoint() const
|
template<std::size_t DIM>
|
||||||
|
Point<DIM> PointCollection<DIM>::getEndPoint() const
|
||||||
{
|
{
|
||||||
if (mPoints.empty())
|
if (mPoints.empty())
|
||||||
{
|
{
|
||||||
|
@ -48,7 +53,11 @@ Point PointCollection::getEndPoint() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Point>& PointCollection::getPoints() const
|
template<std::size_t DIM>
|
||||||
|
const std::vector<Point<DIM> >& PointCollection<DIM>::getPoints() const
|
||||||
{
|
{
|
||||||
return mPoints;
|
return mPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class PointCollection<2>;
|
||||||
|
template class PointCollection<3>;
|
|
@ -6,21 +6,22 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
class PointCollection
|
class PointCollection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PointCollection(const std::vector<Point> points = {});
|
PointCollection(const std::vector<Point<DIM> > points = {});
|
||||||
|
|
||||||
void addPoint(const Point& point);
|
void addPoint(const Point<DIM>& point);
|
||||||
|
|
||||||
void apply(const Transform& transform);
|
void apply(const Transform& transform);
|
||||||
|
|
||||||
Bounds getBounds() const;
|
Bounds getBounds() const;
|
||||||
|
|
||||||
Point getEndPoint() const;
|
Point<DIM> getEndPoint() const;
|
||||||
|
|
||||||
const std::vector<Point>& getPoints() const;
|
const std::vector<Point<DIM> >& getPoints() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Point> mPoints;
|
std::vector<Point<DIM> > mPoints;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,49 +2,27 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
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 (precision == 0)
|
||||||
{
|
{
|
||||||
if (dimensions == 1)
|
return std::to_string(x) + delimiter + std::to_string(y);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr.precision(precision);
|
sstr.precision(precision);
|
||||||
if (dimensions == 1)
|
sstr << x << delimiter << y;
|
||||||
{
|
|
||||||
sstr << x;
|
|
||||||
}
|
|
||||||
else if (dimensions == 2)
|
|
||||||
{
|
|
||||||
sstr << x << delimiter << y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sstr << x << delimiter << y << delimiter << z;
|
|
||||||
}
|
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
class PointParser
|
class PointParser
|
||||||
{
|
{
|
||||||
public:
|
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, 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, std::size_t precision = 0);
|
static std::string toString(double x, std::size_t precision = 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
#include "Circle.h"
|
#include "Circle.h"
|
||||||
|
|
||||||
Circle::Circle(const Point& centre, double radius)
|
Circle::Circle(double radius)
|
||||||
: mRadius(radius),
|
: mRadius(radius)
|
||||||
mCentre(centre)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
mMinorRadius = mRadius;
|
mMinorRadius = mRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Circle::getLocation() const
|
|
||||||
{
|
|
||||||
return mCentre;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Circle::getRadius() const
|
double Circle::getRadius() const
|
||||||
{
|
{
|
||||||
return mRadius;
|
return mRadius;
|
||||||
|
@ -28,11 +21,6 @@ void Circle::setMinorRadius(double radius)
|
||||||
mMinorRadius = radius;
|
mMinorRadius = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Circle::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Circle::isEllipse() const
|
bool Circle::isEllipse() const
|
||||||
{
|
{
|
||||||
return mRadius != mMinorRadius;
|
return mRadius != mMinorRadius;
|
||||||
|
@ -40,10 +28,10 @@ bool Circle::isEllipse() const
|
||||||
|
|
||||||
Bounds Circle::getBounds() const
|
Bounds Circle::getBounds() const
|
||||||
{
|
{
|
||||||
double minX = mCentre.getX() - mRadius;
|
double minX = -mRadius;
|
||||||
double maxX = mCentre.getX() + mRadius;
|
double maxX = mRadius;
|
||||||
double minY = mCentre.getY() - mMinorRadius;
|
double minY = -mMinorRadius;
|
||||||
double maxY = mCentre.getY() + mMinorRadius;
|
double maxY = mMinorRadius;
|
||||||
return { minX, maxX, minY, maxY };
|
return { minX, maxX, minY, maxY };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AbstractGeometricItem.h"
|
#include "AbstractGeometricItem.h"
|
||||||
#include "Point.h"
|
|
||||||
|
|
||||||
class Circle : public AbstractGeometricItem
|
class Circle : public AbstractGeometricItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Circle(const Point& centre, double radius = 0.5);
|
Circle(double radius = 0.5);
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
double getRadius() const;
|
double getRadius() const;
|
||||||
|
|
||||||
|
@ -22,10 +19,7 @@ public:
|
||||||
|
|
||||||
void setMinorRadius(double radius);
|
void setMinorRadius(double radius);
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double mMinorRadius{ 0.5 };
|
double mMinorRadius{ 0.5 };
|
||||||
double mRadius{ 0.5 };
|
double mRadius{ 0.5 };
|
||||||
Point mCentre;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,38 +1,31 @@
|
||||||
#include "Polygon.h"
|
#include "Polygon.h"
|
||||||
|
|
||||||
namespace ntk {
|
namespace ntk {
|
||||||
Polygon::Polygon(const std::vector<Point>& points)
|
template<std::size_t DIM>
|
||||||
|
Polygon<DIM>::Polygon(const std::vector<Point<DIM> >& points)
|
||||||
: AbstractGeometricItem()
|
: AbstractGeometricItem()
|
||||||
{
|
{
|
||||||
if (points.size() > 0)
|
mPoints = PointCollection<DIM>(points);
|
||||||
{
|
|
||||||
mStartPoint = points[0];
|
|
||||||
}
|
|
||||||
mPoints = PointCollection(points);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PointCollection& Polygon::getPoints() const
|
template<std::size_t DIM>
|
||||||
|
const PointCollection<DIM>& Polygon<DIM>::getPoints() const
|
||||||
{
|
{
|
||||||
return mPoints;
|
return mPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bounds Polygon::getBounds() const
|
template<std::size_t DIM>
|
||||||
|
Bounds Polygon<DIM>::getBounds() const
|
||||||
{
|
{
|
||||||
return mPoints.getBounds();
|
return mPoints.getBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Polygon::getLocation() const
|
template<std::size_t DIM>
|
||||||
{
|
AbstractGeometricItem::Type Polygon<DIM>::getType() const
|
||||||
return mStartPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Polygon::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Polygon::Type Polygon::getType() const
|
|
||||||
{
|
{
|
||||||
return Polygon::Type::POLYGON;
|
return Polygon::Type::POLYGON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class Polygon<2>;
|
||||||
|
template class Polygon<3>;
|
||||||
}
|
}
|
|
@ -5,23 +5,21 @@
|
||||||
#include "PointCollection.h"
|
#include "PointCollection.h"
|
||||||
|
|
||||||
namespace ntk{
|
namespace ntk{
|
||||||
|
template<std::size_t DIM>
|
||||||
class Polygon : public AbstractGeometricItem
|
class Polygon : public AbstractGeometricItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Polygon(const std::vector<Point>& points);
|
Polygon(const std::vector<Point<DIM> >& points);
|
||||||
|
|
||||||
const PointCollection& getPoints() const;
|
const PointCollection<DIM>& getPoints() const;
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
AbstractGeometricItem::Type getType() const override;
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mStartPoint;
|
PointCollection<DIM> mPoints;
|
||||||
PointCollection mPoints;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Polygon2 = ntk::Polygon<2>;
|
|
@ -1,18 +1,9 @@
|
||||||
#include "Rectangle.h"
|
#include "Rectangle.h"
|
||||||
|
|
||||||
namespace ntk {
|
namespace ntk {
|
||||||
Rectangle::Rectangle(const Point& bottomLeft, const Point& topRight)
|
Rectangle::Rectangle(double width, double height)
|
||||||
: mBottomLeft(bottomLeft)
|
: mWidth(width),
|
||||||
{
|
mHeight(height)
|
||||||
mHeight = mBottomLeft.getDeltaY(topRight);
|
|
||||||
mWidth = mBottomLeft.getDeltaX(topRight);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle::Rectangle(const Point& bottomLeft, double width, double height)
|
|
||||||
: mBottomLeft(bottomLeft),
|
|
||||||
mWidth(width),
|
|
||||||
mHeight(height)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,19 +15,14 @@ namespace ntk {
|
||||||
|
|
||||||
Bounds Rectangle::getBounds() const
|
Bounds Rectangle::getBounds() const
|
||||||
{
|
{
|
||||||
const auto minX = mBottomLeft.getX();
|
const auto minX = 0.0;
|
||||||
const auto maxX = mBottomLeft.getX() + mWidth;
|
const auto maxX = mWidth;
|
||||||
|
|
||||||
const auto minY = mBottomLeft.getY();
|
const auto minY = 0.0;
|
||||||
const auto maxY = mBottomLeft.getY() + mHeight;
|
const auto maxY = mHeight;
|
||||||
return { minX , maxX , minY , maxY };
|
return { minX , maxX , minY , maxY };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rectangle::sample(SparseGrid<bool>*) const
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
double Rectangle::getHeight() const
|
double Rectangle::getHeight() const
|
||||||
{
|
{
|
||||||
return mHeight;
|
return mHeight;
|
||||||
|
@ -47,11 +33,6 @@ namespace ntk {
|
||||||
return mWidth;
|
return mWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Rectangle::getLocation() const
|
|
||||||
{
|
|
||||||
return mBottomLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Rectangle::getRadius() const
|
double Rectangle::getRadius() const
|
||||||
{
|
{
|
||||||
return mRadius;
|
return mRadius;
|
||||||
|
|
|
@ -6,15 +6,12 @@ namespace ntk{
|
||||||
class Rectangle : public AbstractGeometricItem
|
class Rectangle : public AbstractGeometricItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Rectangle(const Point& bottomLeft, const Point& topRight);
|
Rectangle(double width, double height);
|
||||||
Rectangle(const Point& bottomLeft, double width, double height);
|
|
||||||
|
|
||||||
double getHeight() const;
|
double getHeight() const;
|
||||||
|
|
||||||
double getWidth() const;
|
double getWidth() const;
|
||||||
|
|
||||||
const Point& getLocation() const override;
|
|
||||||
|
|
||||||
Bounds getBounds() const override;
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
Type getType() const override;
|
Type getType() const override;
|
||||||
|
@ -23,10 +20,7 @@ public:
|
||||||
|
|
||||||
void setRadius(double radius);
|
void setRadius(double radius);
|
||||||
|
|
||||||
void sample(SparseGrid<bool>*) const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point mBottomLeft;
|
|
||||||
double mWidth{0};
|
double mWidth{0};
|
||||||
double mHeight{0};
|
double mHeight{0};
|
||||||
double mRadius{ 0.0 };
|
double mRadius{ 0.0 };
|
||||||
|
|
|
@ -60,7 +60,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression
|
||||||
node->setFont(mDefaultFont);
|
node->setFont(mDefaultFont);
|
||||||
addChild(node.get());
|
addChild(node.get());
|
||||||
|
|
||||||
mTextCursor.move(node->getContentWidth(sceneInfo), 0.0);
|
mTextCursor.moveBy(node->getContentWidth(sceneInfo), 0.0);
|
||||||
|
|
||||||
mText.push_back(std::move(node));
|
mText.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
@ -70,19 +70,19 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression
|
||||||
if (expression->getExpressions().size() == 2)
|
if (expression->getExpressions().size() == 2)
|
||||||
{
|
{
|
||||||
auto x_cache = mTextCursor.getX();
|
auto x_cache = mTextCursor.getX();
|
||||||
mTextCursor.move(0.0, -9.0);
|
mTextCursor.moveBy(0.0, -9.0);
|
||||||
addExpression(sceneInfo, expression->getExpressions()[0].get());
|
addExpression(sceneInfo, expression->getExpressions()[0].get());
|
||||||
|
|
||||||
mTextCursor.move(x_cache - mTextCursor.getX(), 16.0);
|
mTextCursor.moveBy(x_cache - mTextCursor.getX(), 16.0);
|
||||||
std::vector<Point> end_loc{ { 25.0, 0.0 } };
|
std::vector<Point2> end_loc{ { 25.0, 0.0 } };
|
||||||
auto dividing_line = std::make_unique<LineNode>(Transform(mTextCursor), end_loc);
|
auto dividing_line = std::make_unique<LineNode>(Transform(mTextCursor), end_loc);
|
||||||
addChild(dividing_line.get());
|
addChild(dividing_line.get());
|
||||||
mLines.push_back(std::move(dividing_line));
|
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());
|
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)
|
else if (expression->getType() == LatexMathExpression::Type::ENCLOSING)
|
||||||
|
@ -96,7 +96,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression
|
||||||
left_node->setFont(mDefaultFont);
|
left_node->setFont(mDefaultFont);
|
||||||
addChild(left_node.get());
|
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));
|
mText.push_back(std::move(left_node));
|
||||||
|
|
||||||
addExpression(sceneInfo, expression->getExpressions()[0].get());
|
addExpression(sceneInfo, expression->getExpressions()[0].get());
|
||||||
|
@ -107,7 +107,7 @@ void EquationNode::addExpression(SceneInfo* sceneInfo, const LatexMathExpression
|
||||||
right_node->setFont(mDefaultFont);
|
right_node->setFont(mDefaultFont);
|
||||||
addChild(right_node.get());
|
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));
|
mText.push_back(std::move(right_node));
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ protected:
|
||||||
FontItem mDefaultFont{ "Cambria Math", 14 };
|
FontItem mDefaultFont{ "Cambria Math", 14 };
|
||||||
//FontItem mDefaultFont{ "Latin Modern Math", 14 };
|
//FontItem mDefaultFont{ "Latin Modern Math", 14 };
|
||||||
|
|
||||||
Point mTextCursor;
|
Point2 mTextCursor;
|
||||||
|
|
||||||
LatexMathExpression* mContent{ nullptr };
|
LatexMathExpression* mContent{ nullptr };
|
||||||
bool mContentDirty{ true };
|
bool mContentDirty{ true };
|
||||||
|
|
|
@ -54,14 +54,14 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setData(const std::vector<Point>& data)
|
void setData(const std::vector<Point2>& data)
|
||||||
{
|
{
|
||||||
mData = data;
|
mData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mLabel;
|
std::string mLabel;
|
||||||
std::vector<Point> mData;
|
std::vector<Point2> mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Plot
|
class Plot
|
||||||
|
|
|
@ -44,14 +44,14 @@ void PlotNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
const double width = 100.0;
|
const double width = 100.0;
|
||||||
|
|
||||||
Point x_axis_start{ 0.0, height };
|
Point x_axis_start{ 0.0, height };
|
||||||
std::vector<Point> x_axis_points = { Point(width, 0.0) };
|
std::vector<Point2> x_axis_points = { Point2(width, 0.0) };
|
||||||
mXAxis = std::make_unique<LineNode>(Transform(x_axis_start), x_axis_points);
|
mXAxis = std::make_unique<LineNode>(Transform(x_axis_start), x_axis_points);
|
||||||
mXAxis->setEndEndStyle(mAxisEndStyle);
|
mXAxis->setEndEndStyle(mAxisEndStyle);
|
||||||
|
|
||||||
addChild(mXAxis.get());
|
addChild(mXAxis.get());
|
||||||
|
|
||||||
Point y_axis_start{ 0.0, height };
|
Point y_axis_start{ 0.0, height };
|
||||||
std::vector<Point> y_axis_points = { Point(0.0, -height) };
|
std::vector<Point2> y_axis_points = { Point2(0.0, -height) };
|
||||||
mYAxis = std::make_unique<LineNode>(Transform(y_axis_start), y_axis_points);
|
mYAxis = std::make_unique<LineNode>(Transform(y_axis_start), y_axis_points);
|
||||||
mYAxis->setEndEndStyle(mAxisEndStyle);
|
mYAxis->setEndEndStyle(mAxisEndStyle);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ void GlyphRunOutlines::addSegment(const GlyphRunSegment& segment)
|
||||||
mFeatures[mFeatures.size() - 1].mSegments.push_back(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;
|
GlyphRunFeature feature;
|
||||||
feature.mFilled = isFilled;
|
feature.mFilled = isFilled;
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct GlyphRunSegment
|
||||||
LINE,
|
LINE,
|
||||||
BEZIER
|
BEZIER
|
||||||
};
|
};
|
||||||
std::vector<Point> mPoints;
|
std::vector<Point2> mPoints;
|
||||||
Type mType{ Type::LINE };
|
Type mType{ Type::LINE };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ class GlyphRunOutlines
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void addSegment(const GlyphRunSegment& point);
|
void addSegment(const GlyphRunSegment& point);
|
||||||
void startFeature(const Point& point, bool isFilled);
|
void startFeature(const Point2& point, bool isFilled);
|
||||||
|
|
||||||
std::string toPostScriptPath();
|
std::string toPostScriptPath();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -80,7 +80,7 @@ void __stdcall GlyphOutlineGeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT verte
|
||||||
|
|
||||||
void __stdcall GlyphOutlineGeometrySink::BeginFigure(D2D1_POINT_2F startPoint, D2D1_FIGURE_BEGIN figureBegin)
|
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)
|
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++)
|
for (UINT32 idx = 0; idx < pointsCount; idx++)
|
||||||
{
|
{
|
||||||
auto point = points[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);
|
mGlyphRunOutline->addSegment(segment);
|
||||||
}
|
}
|
||||||
|
@ -103,9 +103,9 @@ void __stdcall GlyphOutlineGeometrySink::AddBeziers(_In_reads_(beziersCount) CON
|
||||||
segment.mType = GlyphRunSegment::Type::BEZIER;
|
segment.mType = GlyphRunSegment::Type::BEZIER;
|
||||||
|
|
||||||
auto bezier = beziers[idx];
|
auto bezier = beziers[idx];
|
||||||
segment.mPoints.push_back(Point(bezier.point1.x, bezier.point1.y));
|
segment.mPoints.push_back(Point2(bezier.point1.x, bezier.point1.y));
|
||||||
segment.mPoints.push_back(Point(bezier.point2.x, bezier.point2.y));
|
segment.mPoints.push_back(Point2(bezier.point2.x, bezier.point2.y));
|
||||||
segment.mPoints.push_back(Point(bezier.point3.x, bezier.point3.y));
|
segment.mPoints.push_back(Point2(bezier.point3.x, bezier.point3.y));
|
||||||
|
|
||||||
mGlyphRunOutline->addSegment(segment);
|
mGlyphRunOutline->addSegment(segment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,8 @@ void DirectX2dPainter::paintRect(SceneModel* model)
|
||||||
auto rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry());
|
auto rect = dynamic_cast<ntk::Rectangle*>(model->getGeometry());
|
||||||
|
|
||||||
const auto loc = model->getTransform().getLocation();
|
const auto loc = model->getTransform().getLocation();
|
||||||
const auto scale_x = model->getTransform().getScaleX();
|
const auto scale_x = model->getTransform().getScale().mX;
|
||||||
const auto scale_y = model->getTransform().getScaleY();
|
const auto scale_y = model->getTransform().getScale().mY;
|
||||||
|
|
||||||
const auto min_x = static_cast<float>(loc.getX());
|
const auto min_x = static_cast<float>(loc.getX());
|
||||||
const auto max_x = static_cast<float>(loc.getX() + rect->getWidth() * scale_x);
|
const auto max_x = static_cast<float>(loc.getX() + rect->getWidth() * scale_x);
|
||||||
|
@ -117,8 +117,8 @@ void DirectX2dPainter::paintRect(SceneModel* model)
|
||||||
void DirectX2dPainter::paintCircle(SceneModel* model)
|
void DirectX2dPainter::paintCircle(SceneModel* model)
|
||||||
{
|
{
|
||||||
const auto loc = model->getTransform().getLocation();
|
const auto loc = model->getTransform().getLocation();
|
||||||
const auto scale_x = model->getTransform().getScaleX();
|
const auto scale_x = model->getTransform().getScale().mX;
|
||||||
const auto scale_y = model->getTransform().getScaleY();
|
const auto scale_y = model->getTransform().getScale().mY;
|
||||||
|
|
||||||
auto circle = dynamic_cast<Circle*>(model->getGeometry());
|
auto circle = dynamic_cast<Circle*>(model->getGeometry());
|
||||||
const auto radius = circle->getRadius() * scale_x;
|
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<float>(point.getX()), static_cast<float>(point.getY()));
|
return D2D1::Point2F(static_cast<float>(point.getX()), static_cast<float>(point.getY()));
|
||||||
}
|
}
|
||||||
|
@ -155,9 +155,9 @@ void DirectX2dPainter::paintLine(SceneModel* model)
|
||||||
|
|
||||||
path_geom->Open(&path_sink);
|
path_geom->Open(&path_sink);
|
||||||
|
|
||||||
auto line = dynamic_cast<Line*>(model->getGeometry());
|
auto line = dynamic_cast<Line<2>*>(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());
|
onLine(line, path_sink.Get());
|
||||||
|
|
||||||
|
@ -194,9 +194,9 @@ void DirectX2dPainter::paintPolygon(SceneModel* model)
|
||||||
|
|
||||||
path_geom->Open(&path_sink);
|
path_geom->Open(&path_sink);
|
||||||
|
|
||||||
auto polygon = dynamic_cast<ntk::Polygon*>(model->getGeometry());
|
auto polygon = dynamic_cast<ntk::Polygon<2>*>(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 };
|
bool first{ true };
|
||||||
for (const auto& point : polygon->getPoints().getPoints())
|
for (const auto& point : polygon->getPoints().getPoints())
|
||||||
|
@ -245,7 +245,7 @@ void DirectX2dPainter::paintPath(SceneModel* model)
|
||||||
auto path_item = dynamic_cast<GeometryPath*>(model->getGeometry());
|
auto path_item = dynamic_cast<GeometryPath*>(model->getGeometry());
|
||||||
for (const auto& feature : path_item->getFeatures())
|
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);
|
path_sink->BeginFigure(toD2dPoint(loc), D2D1_FIGURE_BEGIN_FILLED);
|
||||||
|
|
||||||
for (const auto& element : feature->getElements())
|
for (const auto& element : feature->getElements())
|
||||||
|
@ -260,16 +260,16 @@ void DirectX2dPainter::paintPath(SceneModel* model)
|
||||||
}
|
}
|
||||||
else if (element->getType() == AbstractGeometricItem::Type::CURVE)
|
else if (element->getType() == AbstractGeometricItem::Type::CURVE)
|
||||||
{
|
{
|
||||||
auto curve = dynamic_cast<Curve*>(element.get());
|
auto curve = dynamic_cast<Curve<2>*>(element.get());
|
||||||
if (curve->getCurveType() == Curve::CurveType::ARC)
|
if (curve->getCurveType() == CurveType::ARC)
|
||||||
{
|
{
|
||||||
onArc(curve, path_sink.Get());
|
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());
|
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());
|
onQuadraticBezier(curve, path_sink.Get());
|
||||||
}
|
}
|
||||||
|
@ -299,11 +299,11 @@ void DirectX2dPainter::paintPath(SceneModel* model)
|
||||||
rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onArc(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onArc(Curve<2>* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
auto arc = dynamic_cast<ntk::Arc*>(element);
|
auto arc = dynamic_cast<ntk::Arc*>(element);
|
||||||
|
|
||||||
const auto end = toD2dPoint(arc->getEndPoint());
|
const auto end = toD2dPoint(arc->getEndOffset());
|
||||||
D2D1_SIZE_F size{static_cast<float>(arc->getRx()), static_cast<float>(arc->getRx()) };
|
D2D1_SIZE_F size{static_cast<float>(arc->getRx()), static_cast<float>(arc->getRx()) };
|
||||||
const auto angle = static_cast<float>(arc->getRotation());
|
const auto angle = static_cast<float>(arc->getRotation());
|
||||||
D2D1_SWEEP_DIRECTION direction = arc->getSweepParam() ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE;
|
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);
|
sink->AddArc(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onQuadraticBezier(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onQuadraticBezier(Curve<2>* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
auto bezier = dynamic_cast<QuadraticBezierCurve*>(element);
|
auto bezier = dynamic_cast<QuadraticBezierCurve<2>*>(element);
|
||||||
D2D1_QUADRATIC_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getControlPoint()) , toD2dPoint(bezier->getEndPoint()) };
|
D2D1_QUADRATIC_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getControlOffset()) , toD2dPoint(bezier->getEndOffset()) };
|
||||||
sink->AddQuadraticBezier(segment);
|
sink->AddQuadraticBezier(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onCubicBezier(Curve* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onCubicBezier(Curve<2>* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
auto bezier = dynamic_cast<CubicBezierCurve*>(element);
|
auto bezier = dynamic_cast<CubicBezierCurve<2>*>(element);
|
||||||
D2D1_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getStartControlPoint()), toD2dPoint(bezier->getEndControlPoint()), toD2dPoint(bezier->getEndPoint()) };
|
D2D1_BEZIER_SEGMENT segment{ toD2dPoint(bezier->getStartControlOffset()), toD2dPoint(bezier->getEndControlOffset()), toD2dPoint(bezier->getEndOffset()) };
|
||||||
sink->AddBezier(segment);
|
sink->AddBezier(segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::onLine(PathElement* element, ID2D1GeometrySink* sink)
|
void DirectX2dPainter::onLine(PathElement<2>* element, ID2D1GeometrySink* sink)
|
||||||
{
|
{
|
||||||
for (const auto& point : dynamic_cast<Line*>(element)->getPoints().getPoints())
|
for (const auto& point : dynamic_cast<Line<2>*>(element)->getPoints().getPoints())
|
||||||
{
|
{
|
||||||
sink->AddLine(toD2dPoint(point));
|
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));
|
sink->AddLine(toD2dPoint(loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
#include "PathElement.h"
|
||||||
|
|
||||||
#include <wrl.h>
|
#include <wrl.h>
|
||||||
|
|
||||||
class SceneModel;
|
class SceneModel;
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
class Point;
|
class Point;
|
||||||
|
|
||||||
class DirectX2dInterface;
|
class DirectX2dInterface;
|
||||||
|
|
||||||
class PathElement;
|
template<std::size_t DIM>
|
||||||
class Curve;
|
class Curve;
|
||||||
|
|
||||||
struct ID2D1SolidColorBrush;
|
struct ID2D1SolidColorBrush;
|
||||||
|
@ -34,15 +38,15 @@ public:
|
||||||
void setD2dInterface(DirectX2dInterface* d2dIterface);
|
void setD2dInterface(DirectX2dInterface* d2dIterface);
|
||||||
|
|
||||||
private:
|
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);
|
void paintRect(SceneModel* model);
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ private:
|
||||||
|
|
||||||
static D2D1::ColorF toD2dColor(const Color& color);
|
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<ID2D1SolidColorBrush> mSolidBrush;
|
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> mSolidBrush;
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ void DirectXMesh::update(DrawingContext* context, ID3D12Device* device)
|
||||||
{
|
{
|
||||||
for (const auto& loc : face->getNodeLocations(AbstractFace::Orientation::CW))
|
for (const auto& loc : face->getNodeLocations(AbstractFace::Orientation::CW))
|
||||||
{
|
{
|
||||||
auto x = loc.getX() * transform.getScaleX() + transform.getLocation().getX();
|
auto x = loc.getX() * transform.getScale().mX + transform.getLocation().getX();
|
||||||
auto y = loc.getY() * transform.getScaleY() + transform.getLocation().getY();
|
auto y = loc.getY() * transform.getScale().mY + transform.getLocation().getY();
|
||||||
x = 2 * x - 1;
|
x = 2 * x - 1;
|
||||||
y = 2 * y - 1;
|
y = 2 * y - 1;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
|
|
||||||
virtual std::vector<std::size_t> getEdgeIds() const = 0;
|
virtual std::vector<std::size_t> getEdgeIds() const = 0;
|
||||||
|
|
||||||
virtual std::vector<Point> getNodeLocations(Orientation orientation = Orientation::CCW) const = 0;
|
virtual std::vector<Point3> getNodeLocations(Orientation orientation = Orientation::CCW) const = 0;
|
||||||
|
|
||||||
virtual void replaceEdge(Edge* original, Edge* replacement) = 0;
|
virtual void replaceEdge(Edge* original, Edge* replacement) = 0;
|
||||||
|
|
||||||
|
|
|
@ -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());
|
translate(offset.getX(), offset.getY(), offset.getZ());
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
void scale(double scaleX, double scaleY);
|
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);
|
void translate(double offsetX, double offsetY, double offsetZ = 0.0);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
using EdgeIds = std::vector<std::pair<std::size_t, std::size_t> >;
|
using EdgeIds = std::vector<std::pair<std::size_t, std::size_t> >;
|
||||||
using FaceIds = std::vector<std::vector<std::size_t> >;
|
using FaceIds = std::vector<std::vector<std::size_t> >;
|
||||||
using VecPoints = std::vector<Point>;
|
using VecPoints = std::vector<Point3>;
|
||||||
|
|
||||||
class MeshBuilder
|
class MeshBuilder
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
|
|
||||||
std::unique_ptr<Node> Node::Create(const Point& p, std::size_t index)
|
std::unique_ptr<Node> Node::Create(const Point3& p, std::size_t index)
|
||||||
{
|
{
|
||||||
return std::make_unique<Node>(p, index);
|
return std::make_unique<Node>(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),
|
: mIndex(index),
|
||||||
mPoint(p)
|
mPoint(p)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ std::vector<double> Node::getVectorAttribute(const std::string& tag) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Point& Node::getPoint() const
|
const Point3& Node::getPoint() const
|
||||||
{
|
{
|
||||||
return mPoint;
|
return mPoint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ public:
|
||||||
DIRTY
|
DIRTY
|
||||||
};
|
};
|
||||||
|
|
||||||
Node(const Point& p, std::size_t index = 0);
|
Node(const Point3& p, std::size_t index = 0);
|
||||||
|
|
||||||
static std::unique_ptr<Node> Create(const Point& p, std::size_t index = 0);
|
static std::unique_ptr<Node> Create(const Point3& p, std::size_t index = 0);
|
||||||
|
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
State getState() const;
|
State getState() const;
|
||||||
|
|
||||||
const Point& getPoint() const;
|
const Point3& getPoint() const;
|
||||||
|
|
||||||
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
std::vector<double> getVectorAttribute(const std::string& tag) const;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public:
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
|
||||||
std::size_t mIndex{0};
|
std::size_t mIndex{0};
|
||||||
Point mPoint;
|
Point3 mPoint;
|
||||||
|
|
||||||
std::vector<std::size_t> mAssociatedEdgeIds;
|
std::vector<std::size_t> mAssociatedEdgeIds;
|
||||||
std::vector<std::size_t> mAssociatedFaceIds;
|
std::vector<std::size_t> mAssociatedFaceIds;
|
||||||
|
|
|
@ -75,7 +75,7 @@ void TriFace::associateWidthEdges()
|
||||||
mEdge2->associateFace(mId);
|
mEdge2->associateFace(mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Point> TriFace::getNodeLocations(Orientation orientation) const
|
std::vector<Point3> TriFace::getNodeLocations(Orientation orientation) const
|
||||||
{
|
{
|
||||||
if (orientation != getOrientation())
|
if (orientation != getOrientation())
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ std::vector<Point> TriFace::getNodeLocations(Orientation orientation) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector TriFace::getNormal() const
|
Vector3 TriFace::getNormal() const
|
||||||
{
|
{
|
||||||
auto v0 = mEdge0->getNode0()->getPoint().getDelta(mEdge0->getNode1()->getPoint());
|
auto v0 = mEdge0->getNode0()->getPoint().getDelta(mEdge0->getNode1()->getPoint());
|
||||||
auto v1 = mEdge0->getNode0()->getPoint().getDelta(mEdge1->getNode1()->getPoint());
|
auto v1 = mEdge0->getNode0()->getPoint().getDelta(mEdge1->getNode1()->getPoint());
|
||||||
|
@ -96,8 +96,10 @@ Vector TriFace::getNormal() const
|
||||||
|
|
||||||
AbstractFace::Orientation TriFace::getOrientation() const
|
AbstractFace::Orientation TriFace::getOrientation() const
|
||||||
{
|
{
|
||||||
Vector z_norm(0, 0, 1);
|
return Orientation::CW;
|
||||||
if (z_norm.dotProduct(getNormal()) < 0.0)
|
/*
|
||||||
|
Vector3 z_norm(0, 0, 1);
|
||||||
|
if (z_norm.innerProduct(getNormal()) < 0.0)
|
||||||
{
|
{
|
||||||
return Orientation::CW;
|
return Orientation::CW;
|
||||||
}
|
}
|
||||||
|
@ -105,4 +107,5 @@ AbstractFace::Orientation TriFace::getOrientation() const
|
||||||
{
|
{
|
||||||
return Orientation::CCW;
|
return Orientation::CCW;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ public:
|
||||||
std::size_t getEdge2Id () const;
|
std::size_t getEdge2Id () const;
|
||||||
std::vector<std::size_t> getEdgeIds() const override;
|
std::vector<std::size_t> getEdgeIds() const override;
|
||||||
|
|
||||||
std::vector<Point> getNodeLocations(Orientation orientation = Orientation::CCW) const override;
|
std::vector<Point3> getNodeLocations(Orientation orientation = Orientation::CCW) const override;
|
||||||
|
|
||||||
Vector getNormal() const;
|
Vector3 getNormal() const;
|
||||||
|
|
||||||
AbstractFace::Orientation getOrientation() const;
|
AbstractFace::Orientation getOrientation() const;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,10 @@ list(APPEND visual_elements_LIB_INCLUDES
|
||||||
nodes/GeometryNode.cpp
|
nodes/GeometryNode.cpp
|
||||||
nodes/AbstractVisualNode.h
|
nodes/AbstractVisualNode.h
|
||||||
nodes/AbstractVisualNode.cpp
|
nodes/AbstractVisualNode.cpp
|
||||||
|
postscript/PostscriptReader.h
|
||||||
|
postscript/PostscriptReader.cpp
|
||||||
|
postscript/PostscriptWriter.h
|
||||||
|
postscript/PostscriptWriter.cpp
|
||||||
Material.h
|
Material.h
|
||||||
BasicMaterial.h
|
BasicMaterial.h
|
||||||
BasicMaterial.cpp
|
BasicMaterial.cpp
|
||||||
|
@ -67,6 +71,7 @@ target_include_directories(${MODULE_NAME} PUBLIC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/basic_shapes
|
${CMAKE_CURRENT_SOURCE_DIR}/basic_shapes
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene
|
${CMAKE_CURRENT_SOURCE_DIR}/scene
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes
|
${CMAKE_CURRENT_SOURCE_DIR}/nodes
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/postscript
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/svg
|
${CMAKE_CURRENT_SOURCE_DIR}/svg
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/svg/elements
|
${CMAKE_CURRENT_SOURCE_DIR}/svg/elements
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include "CircleNode.h"
|
#include "CircleNode.h"
|
||||||
|
|
||||||
#include "SceneModel.h"
|
#include "SceneModel.h"
|
||||||
#include "AbstractMesh.h"
|
|
||||||
#include "MeshPrimitives.h"
|
|
||||||
#include "SceneInfo.h"
|
#include "SceneInfo.h"
|
||||||
|
|
||||||
#include "Circle.h"
|
#include "Circle.h"
|
||||||
|
@ -47,43 +45,18 @@ void CircleNode::setMinorRadius(double radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<AbstractGeometricItem> CircleNode::createGeometryPrimitive() const
|
void CircleNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
{
|
{
|
||||||
auto circle = std::make_unique<Circle>(Point{ 0, 0 }, mRadius);
|
auto circle = std::make_unique<Circle>(mRadius);
|
||||||
circle->setMinorRadius(mMinorRadius);
|
circle->setMinorRadius(mMinorRadius);
|
||||||
return circle;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<AbstractMesh> CircleNode::createMeshPrimitive() const
|
|
||||||
{
|
|
||||||
return MeshPrimitives::buildCircleAsTriMesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CircleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
|
||||||
{
|
|
||||||
if (!mBackgroundItem)
|
if (!mBackgroundItem)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(circle));
|
||||||
{
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(createGeometryPrimitive());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(createMeshPrimitive());
|
|
||||||
mBackgroundItem->setMeshTransform(Transform({}, mRadius, mRadius));
|
|
||||||
}
|
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem->updateGeometry(std::move(circle));
|
||||||
{
|
|
||||||
mBackgroundItem->updateGeometry(createGeometryPrimitive());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mBackgroundItem->updateMesh(createMeshPrimitive());
|
|
||||||
mBackgroundItem->setMeshTransform(Transform({}, mRadius, mRadius));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,6 @@ public:
|
||||||
private:
|
private:
|
||||||
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
||||||
|
|
||||||
std::unique_ptr<AbstractGeometricItem> createGeometryPrimitive() const;
|
|
||||||
std::unique_ptr<AbstractMesh> createMeshPrimitive() const;
|
|
||||||
|
|
||||||
double mRadius{1.0};
|
double mRadius{1.0};
|
||||||
double mMinorRadius{ 1.0 };
|
double mMinorRadius{ 1.0 };
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "SceneModel.h"
|
#include "SceneModel.h"
|
||||||
|
|
||||||
LineNode::LineNode(const Transform& transform, const std::vector<Point>& points)
|
LineNode::LineNode(const Transform& transform, const std::vector<Point2>& points)
|
||||||
: GeometryNode(transform),
|
: GeometryNode(transform),
|
||||||
mPoints(points)
|
mPoints(points)
|
||||||
{
|
{
|
||||||
|
@ -16,35 +16,32 @@ LineNode::Type LineNode::getType()
|
||||||
|
|
||||||
void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
auto line = std::make_unique<Line2>(mPoints);
|
||||||
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
|
||||||
|
|
||||||
|
if (mStartEndStyle != LineEndNode::Style::NONE)
|
||||||
{
|
{
|
||||||
auto line = std::make_unique<Line>(Point{ 0, 0 }, mPoints);
|
if (!mStartNode)
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
|
|
||||||
|
|
||||||
if (mStartEndStyle != LineEndNode::Style::NONE)
|
|
||||||
{
|
{
|
||||||
if (!mStartNode)
|
mStartNode = std::make_unique<LineEndNode>();
|
||||||
{
|
addChild(mStartNode.get());
|
||||||
mStartNode = std::make_unique<LineEndNode>(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<LineEndNode>(end_loc);
|
|
||||||
addChild(mEndNode.get());
|
|
||||||
}
|
|
||||||
mEndNode->setStyle(mEndEndStyle);
|
|
||||||
mEndNode->setSize(mEndEndSize);
|
|
||||||
}
|
}
|
||||||
|
mStartNode->setStyle(mStartEndStyle);
|
||||||
|
mStartNode->setSize(mStartEndSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mEndEndStyle != LineEndNode::Style::NONE)
|
||||||
|
{
|
||||||
|
if (!mEndNode)
|
||||||
|
{
|
||||||
|
auto end_loc = mPoints[mPoints.size() - 1];
|
||||||
|
mEndNode = std::make_unique<LineEndNode>(Transform(end_loc));
|
||||||
|
addChild(mEndNode.get());
|
||||||
|
}
|
||||||
|
mEndNode->setStyle(mEndEndStyle);
|
||||||
|
mEndNode->setSize(mEndEndSize);
|
||||||
|
}
|
||||||
|
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
class LineNode : public GeometryNode
|
class LineNode : public GeometryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LineNode(const Transform& transform, const std::vector<Point>& points);
|
LineNode(const Transform& transform, const std::vector<Point2>& points);
|
||||||
|
|
||||||
Type getType() override;
|
Type getType() override;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ private:
|
||||||
LineEndNode::Style mStartEndStyle{ LineEndNode::Style::NONE };
|
LineEndNode::Style mStartEndStyle{ LineEndNode::Style::NONE };
|
||||||
LineEndNode::Style mEndEndStyle{ LineEndNode::Style::NONE };
|
LineEndNode::Style mEndEndStyle{ LineEndNode::Style::NONE };
|
||||||
|
|
||||||
std::vector<Point> mPoints;
|
std::vector<Point2> mPoints;
|
||||||
|
|
||||||
std::unique_ptr<LineEndNode> mStartNode;
|
std::unique_ptr<LineEndNode> mStartNode;
|
||||||
std::unique_ptr<LineEndNode> mEndNode;
|
std::unique_ptr<LineEndNode> mEndNode;
|
||||||
|
|
|
@ -20,7 +20,7 @@ PolygonNode::Type PolygonNode::getType()
|
||||||
return Type::Polygon;
|
return Type::Polygon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolygonNode::setPoints(const std::vector<Point>& points)
|
void PolygonNode::setPoints(const std::vector<Point2>& points)
|
||||||
{
|
{
|
||||||
mPoints = points;
|
mPoints = points;
|
||||||
mGeometryIsDirty = true;
|
mGeometryIsDirty = true;
|
||||||
|
@ -28,26 +28,15 @@ void PolygonNode::setPoints(const std::vector<Point>& points)
|
||||||
|
|
||||||
void PolygonNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
void PolygonNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
{
|
{
|
||||||
|
auto polygon = std::make_unique<Polygon2>(mPoints);
|
||||||
|
|
||||||
if (!mBackgroundItem)
|
if (!mBackgroundItem)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(polygon));
|
||||||
{
|
|
||||||
auto polygon = std::make_unique<ntk::Polygon>(mPoints);
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(polygon));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
|
|
||||||
//mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
|
|
||||||
}
|
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem->updateGeometry(std::move(polygon));
|
||||||
{
|
|
||||||
auto polygon = std::make_unique<ntk::Polygon>(mPoints);
|
|
||||||
mBackgroundItem->updateGeometry(std::move(polygon));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,9 +11,9 @@ public:
|
||||||
|
|
||||||
Type getType() override;
|
Type getType() override;
|
||||||
|
|
||||||
void setPoints(const std::vector<Point>& points);
|
void setPoints(const std::vector<Point2>& points);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
||||||
std::vector<Point> mPoints;
|
std::vector<Point2> mPoints;
|
||||||
};
|
};
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
#include "Rectangle.h"
|
#include "Rectangle.h"
|
||||||
|
|
||||||
#include "MeshPrimitives.h"
|
|
||||||
|
|
||||||
#include "SceneInfo.h"
|
#include "SceneInfo.h"
|
||||||
#include "SceneModel.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<ntk::Rectangle>(mWidth, mHeight);
|
||||||
|
rect->setRadius(mRadius);
|
||||||
|
|
||||||
if (!mBackgroundItem)
|
if (!mBackgroundItem)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
|
||||||
{
|
|
||||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
|
|
||||||
rect->setRadius(mRadius);
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
|
|
||||||
|
|
||||||
}
|
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem->updateGeometry(std::move(rect));
|
||||||
{
|
|
||||||
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, mWidth, mHeight);
|
|
||||||
rect->setRadius(mRadius);
|
|
||||||
mBackgroundItem->updateGeometry(std::move(rect));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,9 +34,9 @@ void LineEndNode::createOrUpdateGeometry(SceneInfo*)
|
||||||
if (mStyle == Style::CLOSED_ARROW)
|
if (mStyle == Style::CLOSED_ARROW)
|
||||||
{
|
{
|
||||||
auto polygon = std::make_unique<PolygonNode>();
|
auto polygon = std::make_unique<PolygonNode>();
|
||||||
auto p0 = Point(0.0, -mSize / 2.0);
|
auto p0 = Point2(0.0, -mSize / 2.0);
|
||||||
auto p1 = Point(mSize, 0.0);
|
auto p1 = Point2(mSize, 0.0);
|
||||||
auto p2 = Point(0.0, mSize / 2.0);
|
auto p2 = Point2(0.0, mSize / 2.0);
|
||||||
polygon->setPoints({ p0, p1, p2 });
|
polygon->setPoints({ p0, p1, p2 });
|
||||||
polygon->setFillColor({ 0, 0, 0 });
|
polygon->setFillColor({ 0, 0, 0 });
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<GeometryNode> mContentNode;
|
std::unique_ptr<GeometryNode> mContentNode;
|
||||||
|
|
||||||
Vector mDirection;
|
Vector3 mDirection;
|
||||||
|
|
||||||
bool mContentDirty{ true };
|
bool mContentDirty{ true };
|
||||||
double mSize{ 5.0 };
|
double mSize{ 5.0 };
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SceneInfo.h"
|
#include "SceneInfo.h"
|
||||||
|
|
||||||
#include "SceneModel.h"
|
#include "SceneModel.h"
|
||||||
|
#include "PostscriptReader.h"
|
||||||
|
|
||||||
PathNode::PathNode(const Transform& transform, const std::string& psPath)
|
PathNode::PathNode(const Transform& transform, const std::string& psPath)
|
||||||
: GeometryNode(transform),
|
: GeometryNode(transform),
|
||||||
|
@ -34,23 +35,17 @@ void PathNode::setPathString(const std::string& psPath)
|
||||||
|
|
||||||
void PathNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
void PathNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
{
|
{
|
||||||
|
auto path = std::make_unique<GeometryPath>();
|
||||||
|
PostscriptReader reader;
|
||||||
|
reader.read(path.get(), mPathString);
|
||||||
|
|
||||||
if (!mBackgroundItem)
|
if (!mBackgroundItem)
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(path));
|
||||||
{
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
auto path = std::make_unique<GeometryPath>();
|
|
||||||
path->buildFromPostscript(mPathString);
|
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(path));
|
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sceneInfo->mSupportsGeometryPrimitives)
|
mBackgroundItem->updateGeometry(std::move(path));
|
||||||
{
|
|
||||||
auto path = std::make_unique<GeometryPath>();
|
|
||||||
path->buildFromPostscript(mPathString);
|
|
||||||
mBackgroundItem->updateGeometry(std::move(path));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -224,7 +224,7 @@ void TextNode::update(SceneInfo* sceneInfo)
|
||||||
|
|
||||||
if (mRenderNodeBounds)
|
if (mRenderNodeBounds)
|
||||||
{
|
{
|
||||||
auto rect = std::make_unique<ntk::Rectangle>(Point(0.0, 0.0), mWidth, mHeight);
|
auto rect = std::make_unique<ntk::Rectangle>(mWidth, mHeight);
|
||||||
mNodeBounds = std::make_unique<SceneModel>();
|
mNodeBounds = std::make_unique<SceneModel>();
|
||||||
mNodeBounds->updateGeometry(std::move(rect));
|
mNodeBounds->updateGeometry(std::move(rect));
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ void TextNode::update(SceneInfo* sceneInfo)
|
||||||
|
|
||||||
if (mRenderTextBounds)
|
if (mRenderTextBounds)
|
||||||
{
|
{
|
||||||
auto rect = std::make_unique<ntk::Rectangle>(Point(0.0, 0.0), mContentWidth, mContentHeight);
|
auto rect = std::make_unique<ntk::Rectangle>(mContentWidth, mContentHeight);
|
||||||
mTextBounds = std::make_unique<SceneModel>();
|
mTextBounds = std::make_unique<SceneModel>();
|
||||||
mTextBounds->updateGeometry(std::move(rect));
|
mTextBounds->updateGeometry(std::move(rect));
|
||||||
|
|
||||||
|
|
313
src/rendering/visual_elements/postscript/PostscriptReader.cpp
Normal file
313
src/rendering/visual_elements/postscript/PostscriptReader.cpp
Normal file
|
@ -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<GeometryPathFeature>();
|
||||||
|
}
|
||||||
|
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<LineSegment2>(mCurrentPoint, Point2(mCurrentPoint.getX() + mPointBuffer[0], mCurrentPoint.getY()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = std::make_unique<LineSegment2>(mCurrentPoint, Point2(mPointBuffer[0], mCurrentPoint.getY()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = std::make_unique<Line2>(Line<2>::InputBufferType::HORIZONTAL, mPointBuffer);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathElementPtr PostscriptReader::onVerticalLineTo()
|
||||||
|
{
|
||||||
|
PathElementPtr element;
|
||||||
|
if (mPointBuffer.size() == 1)
|
||||||
|
{
|
||||||
|
if (mPositionState == PositionState::RELATIVE)
|
||||||
|
{
|
||||||
|
//element = std::make_unique<LineSegment2>(Point2(mCurrentPoint.getX(), mCurrentPoint.getY() + mPointBuffer[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//element = std::make_unique<LineSegment2>(Point2(mCurrentPoint.getX(), mPointBuffer[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = std::make_unique<Line2>(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<LineSegment2>(mCurrentPoint, next_point);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto next_point = Point2(mPointBuffer[0], mPointBuffer[1]);
|
||||||
|
element = std::make_unique<LineSegment2>(mCurrentPoint, next_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = std::make_unique<Line2>(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<ntk::Arc>(end_point, rx, ry, rotation, large_arc, sweep);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto end_point = Vector2({ mPointBuffer[5], mPointBuffer[6] });
|
||||||
|
element = std::make_unique<ntk::Arc>(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<QuadraticBezierCurve<2> >(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<QuadraticBezierCurve<2> >(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<CubicBezierCurve<2> >(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<CubicBezierCurve<2> >(end_point, control_point0, control_point1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
}
|
|
@ -8,17 +8,15 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GeometryPath;
|
class GeometryPath;
|
||||||
using PathElementPtr = std::unique_ptr<PathElement>;
|
using PathElementPtr = std::unique_ptr<PathElement<2> >;
|
||||||
|
|
||||||
class GeometryPathFeature;
|
class GeometryPathFeature;
|
||||||
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
|
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
|
||||||
|
|
||||||
class PathPostScriptConverter
|
class PostscriptReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void fromPostScript(GeometryPath* targetPath, const std::string& postScriptPath);
|
void read(GeometryPath* targetPath, const std::string& postScriptPath);
|
||||||
|
|
||||||
std::string toPostScript(const GeometryPath* targetPath);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class LineState
|
enum class LineState
|
||||||
|
@ -61,7 +59,7 @@ private:
|
||||||
std::vector<double> mPointBuffer;
|
std::vector<double> mPointBuffer;
|
||||||
|
|
||||||
GeometryPathFeaturePtr mWorkingFeature;
|
GeometryPathFeaturePtr mWorkingFeature;
|
||||||
Point mCurrentPoint;
|
Point2 mCurrentPoint;
|
||||||
|
|
||||||
std::size_t mPrecision{ 3 };
|
std::size_t mPrecision{ 3 };
|
||||||
};
|
};
|
217
src/rendering/visual_elements/postscript/PostscriptWriter.cpp
Normal file
217
src/rendering/visual_elements/postscript/PostscriptWriter.cpp
Normal file
|
@ -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<Curve<2>*>(pathElement); curve)
|
||||||
|
{
|
||||||
|
if (curve->getCurveType() == CurveType::ARC)
|
||||||
|
{
|
||||||
|
return toString(dynamic_cast<ntk::Arc*>(pathElement));
|
||||||
|
}
|
||||||
|
else if (curve->getCurveType() == CurveType::CUBIC_BEZIER)
|
||||||
|
{
|
||||||
|
return toString(dynamic_cast<CubicBezierCurve<2> *>(pathElement));
|
||||||
|
}
|
||||||
|
else if (curve->getCurveType() == CurveType::QUADRATIC_BEZIER)
|
||||||
|
{
|
||||||
|
return toString(dynamic_cast<QuadraticBezierCurve<2> *>(pathElement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pathElement->getType() == AbstractGeometricItem::Type::LINE)
|
||||||
|
{
|
||||||
|
if (auto line = dynamic_cast<Line<2>*>(pathElement); line)
|
||||||
|
{
|
||||||
|
return toString(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pathElement->getType() == AbstractGeometricItem::Type::LINE_SEGMENT)
|
||||||
|
{
|
||||||
|
if (auto line = dynamic_cast<LineSegment<2>*>(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
src/rendering/visual_elements/postscript/PostscriptWriter.h
Normal file
50
src/rendering/visual_elements/postscript/PostscriptWriter.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Point.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ntk
|
||||||
|
{
|
||||||
|
class Arc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
class QuadraticBezierCurve;
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
class CubicBezierCurve;
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
class Line;
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
class LineSegment;
|
||||||
|
|
||||||
|
template<std::size_t DIM>
|
||||||
|
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;
|
||||||
|
};
|
|
@ -125,12 +125,12 @@ void SvgNode::onCircle(XmlElement* element, std::unique_ptr<GeometryNode>& node)
|
||||||
if (element->hasAttribute("transform"))
|
if (element->hasAttribute("transform"))
|
||||||
{
|
{
|
||||||
const auto transform = svg_circle->getTransform();
|
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;
|
radius *= transform.getScale().mX;
|
||||||
minor_radius *= transform.getScale().mY;
|
minor_radius *= transform.getScale().mY;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto circle_node = std::make_unique<CircleNode>(loc, radius);
|
auto circle_node = std::make_unique<CircleNode>(Transform(loc), radius);
|
||||||
circle_node->setMinorRadius(minor_radius);
|
circle_node->setMinorRadius(minor_radius);
|
||||||
node = std::move(circle_node);
|
node = std::move(circle_node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "SvgTextElement.h"
|
#include "SvgTextElement.h"
|
||||||
#include "XmlAttribute.h"
|
#include "XmlAttribute.h"
|
||||||
|
|
||||||
|
#include "PostscriptWriter.h"
|
||||||
|
|
||||||
std::unique_ptr<SvgDocument> SvgPainter::paint(Scene* scene, double width, double height) const
|
std::unique_ptr<SvgDocument> SvgPainter::paint(Scene* scene, double width, double height) const
|
||||||
{
|
{
|
||||||
auto doc = std::make_unique<SvgDocument>();
|
auto doc = std::make_unique<SvgDocument>();
|
||||||
|
@ -65,7 +67,7 @@ void SvgPainter::paintMesh(SvgDocument* document, SceneModel* model, bool showOu
|
||||||
{
|
{
|
||||||
auto svg_tri = std::make_unique<SvgPolygon>();
|
auto svg_tri = std::make_unique<SvgPolygon>();
|
||||||
|
|
||||||
std::vector<Point> points(3);
|
std::vector<Point2> points(3);
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
auto face_locs = face->getNodeLocations();
|
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
|
void SvgPainter::paintPolygon(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
auto model_polygon = dynamic_cast<ntk::Polygon*>(model->getGeometry());
|
auto model_polygon = dynamic_cast<Polygon2*>(model->getGeometry());
|
||||||
|
|
||||||
auto svg_polygon = std::make_unique<SvgPolygon>();
|
auto svg_polygon = std::make_unique<SvgPolygon>();
|
||||||
svg_polygon->setPoints(model_polygon->getPoints().getPoints());
|
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
|
void SvgPainter::paintLine(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
auto model_line = dynamic_cast<Line*>(model->getGeometry());
|
auto model_line = dynamic_cast<Line2*>(model->getGeometry());
|
||||||
auto svg_line = std::make_unique<SvgPolyline>();
|
auto svg_line = std::make_unique<SvgPolyline>();
|
||||||
svg_line->setPoints(model_line->getFirstPoint(), model_line->getPoints().getPoints());
|
svg_line->setPoints(model_line->getPoints().getPoints());
|
||||||
|
|
||||||
setStyle(model, svg_line.get());
|
setStyle(model, svg_line.get());
|
||||||
document->getRoot()->addChild(std::move(svg_line));
|
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
|
void SvgPainter::paintLineSegment(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
auto model_line = dynamic_cast<LineSegment*>(model->getGeometry());
|
auto model_line = dynamic_cast<LineSegment2*>(model->getGeometry());
|
||||||
auto svg_line = std::make_unique<SvgLine>(model_line->getFirstPoint(), model_line->getEndPoint());
|
auto svg_line = std::make_unique<SvgLine>(model_line->getPoint0(), model_line->getPoint1());
|
||||||
|
|
||||||
setStyle(model, svg_line.get());
|
setStyle(model, svg_line.get());
|
||||||
document->getRoot()->addChild(std::move(svg_line));
|
document->getRoot()->addChild(std::move(svg_line));
|
||||||
|
@ -222,7 +224,8 @@ void SvgPainter::paintPath(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
auto model_path = dynamic_cast<GeometryPath*>(model->getGeometry());
|
auto model_path = dynamic_cast<GeometryPath*>(model->getGeometry());
|
||||||
|
|
||||||
auto path_string = model_path->getAsPostScript();
|
PostscriptWriter writer;
|
||||||
|
const auto path_string = writer.toString(model_path);
|
||||||
|
|
||||||
auto svg_path = std::make_unique<SvgPath>();
|
auto svg_path = std::make_unique<SvgPath>();
|
||||||
svg_path->setPath(path_string);
|
svg_path->setPath(path_string);
|
||||||
|
@ -236,7 +239,7 @@ void SvgPainter::paintText(SvgDocument* document, SceneText* text) const
|
||||||
auto svg_text = std::make_unique<SvgTextElement>();
|
auto svg_text = std::make_unique<SvgTextElement>();
|
||||||
svg_text->setContent(text->getTextData().mContent);
|
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->setLocation(centre);
|
||||||
svg_text->setFontFamily(text->getTextData().mFont.getFaceName());
|
svg_text->setFontFamily(text->getTextData().mFont.getFaceName());
|
||||||
|
|
||||||
|
|
|
@ -73,11 +73,10 @@ std::string SvgShapeElement::getLabelledContent(const std::string& key, const st
|
||||||
return content.substr(key.size(), content.size() - key.size() - 2);
|
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 x = defaultVal;
|
||||||
double y = defaultVal;
|
double y = defaultVal;
|
||||||
double z = defaultVal;
|
|
||||||
|
|
||||||
const auto split = StringUtils::split(pointString);
|
const auto split = StringUtils::split(pointString);
|
||||||
for (std::size_t idx = 0; idx < split.size(); idx++)
|
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]);
|
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
|
bool SvgShapeElement::hasTransform() const
|
||||||
|
|
|
@ -30,5 +30,5 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string getLabelledContent(const std::string& key, const std::string& content) const;
|
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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ void SvgTextElement::setFillOpacity(float opacity)
|
||||||
addAttribute(std::move(attr));
|
addAttribute(std::move(attr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgTextElement::setLocation(const Point& loc)
|
void SvgTextElement::setLocation(const Point2& loc)
|
||||||
{
|
{
|
||||||
auto x = std::make_unique<XmlAttribute>("x");
|
auto x = std::make_unique<XmlAttribute>("x");
|
||||||
auto y = std::make_unique<XmlAttribute>("y");
|
auto y = std::make_unique<XmlAttribute>("y");
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SvgTextElement : public SvgElement
|
||||||
public:
|
public:
|
||||||
SvgTextElement();
|
SvgTextElement();
|
||||||
|
|
||||||
void setLocation(const Point& loc);
|
void setLocation(const Point2& loc);
|
||||||
|
|
||||||
void setContent(const std::string& content);
|
void setContent(const std::string& content);
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue