Initial plotting support.
This commit is contained in:
parent
df450a7be0
commit
c2027801be
34 changed files with 756 additions and 20 deletions
|
@ -20,6 +20,7 @@ public:
|
||||||
POINT,
|
POINT,
|
||||||
PATH,
|
PATH,
|
||||||
CIRCLE,
|
CIRCLE,
|
||||||
|
POLYGON,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ list(APPEND HEADERS
|
||||||
points/PointCollection.h
|
points/PointCollection.h
|
||||||
points/DiscretePoint.h
|
points/DiscretePoint.h
|
||||||
primitives/Circle.h
|
primitives/Circle.h
|
||||||
primitives/Quad.h
|
primitives/Polygon.h
|
||||||
primitives/Rectangle.h
|
primitives/Rectangle.h
|
||||||
primitives/Triangle.h
|
primitives/Triangle.h
|
||||||
)
|
)
|
||||||
|
@ -49,7 +49,7 @@ list(APPEND SOURCES
|
||||||
points/PointCollection.cpp
|
points/PointCollection.cpp
|
||||||
points/DiscretePoint.cpp
|
points/DiscretePoint.cpp
|
||||||
primitives/Circle.cpp
|
primitives/Circle.cpp
|
||||||
primitives/Quad.cpp
|
primitives/Polygon.cpp
|
||||||
primitives/Rectangle.cpp
|
primitives/Rectangle.cpp
|
||||||
primitives/Triangle.cpp
|
primitives/Triangle.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
class Rotation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Axis
|
||||||
|
{
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
USER
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Rotation(double angle = 0.0, Axis axis = Axis::Z, const Point& loc = {}, const Vector& customAxis = {})
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double mAngle{ 0 };
|
||||||
|
Axis mAxis{ Axis::Z };
|
||||||
|
Point mPoint;
|
||||||
|
Vector mCustomAxis;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Scale
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Transform
|
class Transform
|
||||||
{
|
{
|
||||||
|
|
38
src/base/geometry/primitives/Polygon.cpp
Normal file
38
src/base/geometry/primitives/Polygon.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include "Polygon.h"
|
||||||
|
|
||||||
|
namespace ntk {
|
||||||
|
Polygon::Polygon(const std::vector<Point>& points)
|
||||||
|
: AbstractGeometricItem()
|
||||||
|
{
|
||||||
|
if (points.size() > 0)
|
||||||
|
{
|
||||||
|
mStartPoint = points[0];
|
||||||
|
}
|
||||||
|
mPoints = PointCollection(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PointCollection& Polygon::getPoints() const
|
||||||
|
{
|
||||||
|
return mPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bounds Polygon::getBounds() const
|
||||||
|
{
|
||||||
|
return mPoints.getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point& Polygon::getLocation() const
|
||||||
|
{
|
||||||
|
return mStartPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Polygon::sample(SparseGrid<bool>*) const
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygon::Type Polygon::getType() const
|
||||||
|
{
|
||||||
|
return Polygon::Type::POLYGON;
|
||||||
|
}
|
||||||
|
}
|
27
src/base/geometry/primitives/Polygon.h
Normal file
27
src/base/geometry/primitives/Polygon.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AbstractGeometricItem.h"
|
||||||
|
|
||||||
|
#include "PointCollection.h"
|
||||||
|
|
||||||
|
namespace ntk{
|
||||||
|
class Polygon : public AbstractGeometricItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Polygon(const std::vector<Point>& points);
|
||||||
|
|
||||||
|
const PointCollection& getPoints() const;
|
||||||
|
|
||||||
|
Bounds getBounds() const override;
|
||||||
|
|
||||||
|
const Point& getLocation() const override;
|
||||||
|
|
||||||
|
void sample(SparseGrid<bool>*) const override;
|
||||||
|
|
||||||
|
Type getType() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Point mStartPoint;
|
||||||
|
PointCollection mPoints;
|
||||||
|
};
|
||||||
|
}
|
|
@ -11,7 +11,10 @@ list(APPEND publishing_HEADERS
|
||||||
pdf/PdfWriter.h
|
pdf/PdfWriter.h
|
||||||
plotting/GraphPlotter.h
|
plotting/GraphPlotter.h
|
||||||
plotting/PlotNode.h
|
plotting/PlotNode.h
|
||||||
|
plotting/Plot.h
|
||||||
plotting/EquationNode.h
|
plotting/EquationNode.h
|
||||||
|
plotting/PlotSeriesNode.h
|
||||||
|
plotting/PlotCaptionNode.h
|
||||||
latex/LatexDocument.h
|
latex/LatexDocument.h
|
||||||
latex/LatexMathExpression.h
|
latex/LatexMathExpression.h
|
||||||
latex/LatexSymbols.h
|
latex/LatexSymbols.h
|
||||||
|
@ -34,7 +37,10 @@ list(APPEND publishing_LIB_INCLUDES
|
||||||
latex/LatexSymbols.cpp
|
latex/LatexSymbols.cpp
|
||||||
plotting/GraphPlotter.h
|
plotting/GraphPlotter.h
|
||||||
plotting/PlotNode.cpp
|
plotting/PlotNode.cpp
|
||||||
|
plotting/Plot.cpp
|
||||||
plotting/EquationNode.cpp
|
plotting/EquationNode.cpp
|
||||||
|
plotting/PlotSeriesNode.cpp
|
||||||
|
plotting/PlotCaptionNode.cpp
|
||||||
DocumentConverter.cpp
|
DocumentConverter.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#include "EquationNode.h"
|
||||||
|
|
||||||
|
EquationNode::EquationNode(const Transform& t)
|
||||||
|
: AbstractVisualNode(t)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AbstractVisualNode.h"
|
||||||
|
|
||||||
|
class EquationNode : public AbstractVisualNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EquationNode(const Transform& t = {});
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
#pragma once
|
||||||
|
|
91
src/publishing/plotting/Plot.h
Normal file
91
src/publishing/plotting/Plot.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Point.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class TextSpan
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
PLAIN,
|
||||||
|
EQUATION
|
||||||
|
};
|
||||||
|
|
||||||
|
TextSpan(const std::string& content, Type type = Type::PLAIN)
|
||||||
|
: mType(type),
|
||||||
|
mContent(content)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type mType{ Type::PLAIN };
|
||||||
|
std::string mContent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlotCaption
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlotCaption() = default;
|
||||||
|
|
||||||
|
void setContent(const std::string& plainContent)
|
||||||
|
{
|
||||||
|
mContent = { plainContent };
|
||||||
|
}
|
||||||
|
|
||||||
|
void setContent(const std::vector<TextSpan>& content)
|
||||||
|
{
|
||||||
|
mContent = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<TextSpan> mContent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlotSeries
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlotSeries(const std::string& label = {})
|
||||||
|
: mLabel(label)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void setData(const std::vector<Point>& data)
|
||||||
|
{
|
||||||
|
mData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mLabel;
|
||||||
|
std::vector<Point> mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Plot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Plot() = default;
|
||||||
|
|
||||||
|
void setXAxisCaption(const std::string& caption)
|
||||||
|
{
|
||||||
|
mXAxisCaption.setContent(caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setYAxisCaption(const std::string& caption)
|
||||||
|
{
|
||||||
|
mYAxisCaption.setContent(caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSeries(const PlotSeries& series)
|
||||||
|
{
|
||||||
|
mSeries.push_back(series);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PlotCaption mXAxisCaption;
|
||||||
|
PlotCaption mYAxisCaption;
|
||||||
|
std::vector<PlotSeries> mSeries;
|
||||||
|
};
|
16
src/publishing/plotting/PlotCaptionNode.cpp
Normal file
16
src/publishing/plotting/PlotCaptionNode.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "PlotCaptionNode.h"
|
||||||
|
|
||||||
|
#include "TextNode.h"
|
||||||
|
#include "EquationNode.h"
|
||||||
|
|
||||||
|
PlotCaptionNode::PlotCaptionNode(const Transform& transform)
|
||||||
|
: AbstractVisualNode(transform)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotCaptionNode::setContent(const PlotCaption& content)
|
||||||
|
{
|
||||||
|
mContent = content;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
23
src/publishing/plotting/PlotCaptionNode.h
Normal file
23
src/publishing/plotting/PlotCaptionNode.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AbstractVisualNode.h"
|
||||||
|
|
||||||
|
#include "Plot.h"
|
||||||
|
|
||||||
|
class TextNode;
|
||||||
|
class EquationNode;
|
||||||
|
|
||||||
|
class PlotCaptionNode : public AbstractVisualNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlotCaptionNode(const Transform& transform = {});
|
||||||
|
|
||||||
|
void setContent(const PlotCaption& content);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PlotCaption mContent;
|
||||||
|
bool mContentDirty{ true };
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<TextNode> > mTextContent;
|
||||||
|
std::vector<std::unique_ptr<EquationNode> > mEquationContent;
|
||||||
|
};
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include "PlotNode.h"
|
||||||
|
|
||||||
|
#include "PlotCaptionNode.h"
|
||||||
|
#include "PlotSeriesNode.h"
|
||||||
|
|
||||||
|
#include "LineNode.h"
|
||||||
|
|
||||||
|
|
||||||
|
PlotNode::PlotNode(const Transform& transform)
|
||||||
|
: AbstractVisualNode(transform)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotNode::setContent(Plot* content)
|
||||||
|
{
|
||||||
|
mContent = content;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotNode::update(SceneInfo* sceneInfo)
|
||||||
|
{
|
||||||
|
if (mContentDirty)
|
||||||
|
{
|
||||||
|
createOrUpdateGeometry(sceneInfo);
|
||||||
|
mContentDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotNode::setAxisEndStyle(LineEndNode::Style style)
|
||||||
|
{
|
||||||
|
if (mAxisEndStyle != style)
|
||||||
|
{
|
||||||
|
mAxisEndStyle = style;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
|
{
|
||||||
|
const double height = 100.0;
|
||||||
|
const double width = 100.0;
|
||||||
|
|
||||||
|
Point x_axis_start{ 0.0, height };
|
||||||
|
std::vector<Point> x_axis_points = { Point(width, 0.0) };
|
||||||
|
mXAxis = std::make_unique<LineNode>(Transform(x_axis_start), x_axis_points);
|
||||||
|
mXAxis->setEndEndStyle(mAxisEndStyle);
|
||||||
|
|
||||||
|
addChild(mXAxis.get());
|
||||||
|
|
||||||
|
Point y_axis_start{ 0.0, height };
|
||||||
|
std::vector<Point> y_axis_points = { Point(0.0, -height) };
|
||||||
|
mYAxis = std::make_unique<LineNode>(Transform(y_axis_start), y_axis_points);
|
||||||
|
mYAxis->setEndEndStyle(mAxisEndStyle);
|
||||||
|
|
||||||
|
addChild(mYAxis.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LineEndNode.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Plot;
|
||||||
|
class LineNode;
|
||||||
|
class PlotCaptionNode;
|
||||||
|
class PlotSeriesNode;
|
||||||
|
|
||||||
|
|
||||||
|
class PlotNode : public AbstractVisualNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlotNode(const Transform& transform = {});
|
||||||
|
|
||||||
|
void setContent(Plot* content);
|
||||||
|
|
||||||
|
void setAxisEndStyle(LineEndNode::Style style);
|
||||||
|
|
||||||
|
void update(SceneInfo* sceneInfo) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void createOrUpdateGeometry(SceneInfo* sceneInfo);
|
||||||
|
|
||||||
|
Plot* mContent{ nullptr };
|
||||||
|
bool mContentDirty = true;
|
||||||
|
|
||||||
|
std::unique_ptr<LineNode> mXAxis;
|
||||||
|
std::unique_ptr<LineNode> mYAxis;
|
||||||
|
LineEndNode::Style mAxisEndStyle{ LineEndNode::Style::NONE };
|
||||||
|
|
||||||
|
std::unique_ptr<PlotCaptionNode> mXAxisCaption;
|
||||||
|
std::unique_ptr<PlotCaptionNode> mYAxisCaption;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<PlotSeriesNode> > mSeries;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
13
src/publishing/plotting/PlotSeriesNode.cpp
Normal file
13
src/publishing/plotting/PlotSeriesNode.cpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "PlotSeriesNode.h"
|
||||||
|
|
||||||
|
PlotSeriesNode::PlotSeriesNode(const Transform& transform)
|
||||||
|
: AbstractVisualNode(transform)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlotSeriesNode::setContent(const PlotSeries& content)
|
||||||
|
{
|
||||||
|
mContent = content;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
17
src/publishing/plotting/PlotSeriesNode.h
Normal file
17
src/publishing/plotting/PlotSeriesNode.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AbstractVisualNode.h"
|
||||||
|
|
||||||
|
#include "Plot.h"
|
||||||
|
|
||||||
|
class PlotSeriesNode : public AbstractVisualNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlotSeriesNode(const Transform& transform = {});
|
||||||
|
|
||||||
|
void setContent(const PlotSeries& content);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PlotSeries mContent;
|
||||||
|
bool mContentDirty{ true };
|
||||||
|
};
|
|
@ -5,11 +5,10 @@
|
||||||
#include "AbstractGeometricItem.h"
|
#include "AbstractGeometricItem.h"
|
||||||
#include "Rectangle.h"
|
#include "Rectangle.h"
|
||||||
#include "Circle.h"
|
#include "Circle.h"
|
||||||
#include "Path.h"
|
|
||||||
|
|
||||||
#include "LineSegment.h"
|
#include "LineSegment.h"
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
|
#include "Polygon.h"
|
||||||
|
|
||||||
#include "Curve.h"
|
#include "Curve.h"
|
||||||
#include "Arc.h"
|
#include "Arc.h"
|
||||||
|
@ -61,6 +60,10 @@ void DirectX2dPainter::paint(SceneModel* model)
|
||||||
{
|
{
|
||||||
paintLine(model);
|
paintLine(model);
|
||||||
}
|
}
|
||||||
|
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::POLYGON)
|
||||||
|
{
|
||||||
|
paintPolygon(model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectX2dPainter::paintRect(SceneModel* model)
|
void DirectX2dPainter::paintRect(SceneModel* model)
|
||||||
|
@ -158,6 +161,54 @@ void DirectX2dPainter::paintLine(SceneModel* model)
|
||||||
|
|
||||||
onLine(line, path_sink.Get());
|
onLine(line, path_sink.Get());
|
||||||
|
|
||||||
|
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
|
||||||
|
path_sink->Close();
|
||||||
|
|
||||||
|
auto rt = mD2dInterface->getRenderTarget();
|
||||||
|
|
||||||
|
const auto loc = model->getTransform().getLocation();
|
||||||
|
D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(static_cast<float>(loc.getX()), static_cast<float>(loc.getY()));
|
||||||
|
rt->SetTransform(translation);
|
||||||
|
|
||||||
|
const auto material = model->getSolidMaterial();
|
||||||
|
if (material.hasFillColor())
|
||||||
|
{
|
||||||
|
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
|
||||||
|
rt->FillGeometry(path_geom.Get(), mSolidBrush.Get());
|
||||||
|
}
|
||||||
|
if (material.hasStrokeColor())
|
||||||
|
{
|
||||||
|
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
|
||||||
|
rt->DrawGeometry(path_geom.Get(), mSolidBrush.Get(), 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt->SetTransform(D2D1::Matrix3x2F::Identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectX2dPainter::paintPolygon(SceneModel* model)
|
||||||
|
{
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1PathGeometry> path_geom;
|
||||||
|
mD2dInterface->getFactory()->CreatePathGeometry(&path_geom);
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1GeometrySink> path_sink;
|
||||||
|
|
||||||
|
path_geom->Open(&path_sink);
|
||||||
|
|
||||||
|
auto polygon = dynamic_cast<ntk::Polygon*>(model->getGeometry());
|
||||||
|
|
||||||
|
path_sink->BeginFigure(toD2dPoint(polygon->getLocation()), D2D1_FIGURE_BEGIN_FILLED);
|
||||||
|
|
||||||
|
bool first{ true };
|
||||||
|
for (const auto& point : polygon->getPoints().getPoints())
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
path_sink->AddLine(toD2dPoint(point));
|
||||||
|
}
|
||||||
|
|
||||||
path_sink->EndFigure(D2D1_FIGURE_END_CLOSED);
|
path_sink->EndFigure(D2D1_FIGURE_END_CLOSED);
|
||||||
path_sink->Close();
|
path_sink->Close();
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ private:
|
||||||
|
|
||||||
void paintLine(SceneModel* model);
|
void paintLine(SceneModel* model);
|
||||||
|
|
||||||
|
void paintPolygon(SceneModel* model);
|
||||||
|
|
||||||
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& point);
|
||||||
|
|
|
@ -7,6 +7,8 @@ list(APPEND visual_elements_LIB_INCLUDES
|
||||||
basic_shapes/CircleNode.cpp
|
basic_shapes/CircleNode.cpp
|
||||||
basic_shapes/LineNode.h
|
basic_shapes/LineNode.h
|
||||||
basic_shapes/LineNode.cpp
|
basic_shapes/LineNode.cpp
|
||||||
|
basic_shapes/PolygonNode.h
|
||||||
|
basic_shapes/PolygonNode.cpp
|
||||||
scene/Scene.h
|
scene/Scene.h
|
||||||
scene/Scene.cpp
|
scene/Scene.cpp
|
||||||
scene/SceneInfo.h
|
scene/SceneInfo.h
|
||||||
|
@ -40,6 +42,8 @@ list(APPEND visual_elements_LIB_INCLUDES
|
||||||
nodes/PathNode.cpp
|
nodes/PathNode.cpp
|
||||||
nodes/ImageNode.h
|
nodes/ImageNode.h
|
||||||
nodes/ImageNode.cpp
|
nodes/ImageNode.cpp
|
||||||
|
nodes/LineEndNode.h
|
||||||
|
nodes/LineEndNode.cpp
|
||||||
nodes/MeshNode.h
|
nodes/MeshNode.h
|
||||||
nodes/MeshNode.cpp
|
nodes/MeshNode.cpp
|
||||||
nodes/TextNode.h
|
nodes/TextNode.h
|
||||||
|
|
|
@ -20,6 +20,48 @@ void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
{
|
{
|
||||||
auto line = std::make_unique<Line>(Point{ 0, 0 }, mPoints);
|
auto line = std::make_unique<Line>(Point{ 0, 0 }, mPoints);
|
||||||
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
|
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
|
||||||
|
|
||||||
|
if (mStartEndStyle != LineEndNode::Style::NONE)
|
||||||
|
{
|
||||||
|
if (!mStartNode)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mBackgroundItem->setName(mName + "_Model");
|
mBackgroundItem->setName(mName + "_Model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LineNode::setStartEndStyle(LineEndNode::Style style)
|
||||||
|
{
|
||||||
|
if (mStartEndStyle != style)
|
||||||
|
{
|
||||||
|
mStartEndStyle = style;
|
||||||
|
mGeometryIsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineNode::setEndEndStyle(LineEndNode::Style style)
|
||||||
|
{
|
||||||
|
if (mStartEndStyle != style)
|
||||||
|
{
|
||||||
|
mEndEndStyle = style;
|
||||||
|
mGeometryIsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
#include "SceneInfo.h"
|
#include "SceneInfo.h"
|
||||||
|
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
|
#include "LineEndNode.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -14,8 +15,21 @@ public:
|
||||||
|
|
||||||
Type getType() override;
|
Type getType() override;
|
||||||
|
|
||||||
|
void setStartEndStyle(LineEndNode::Style style);
|
||||||
|
|
||||||
|
void setEndEndStyle(LineEndNode::Style style);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
||||||
|
|
||||||
|
double mStartEndSize{ 5.0 };
|
||||||
|
double mEndEndSize{ 5.0 };
|
||||||
|
|
||||||
|
LineEndNode::Style mStartEndStyle{ LineEndNode::Style::NONE };
|
||||||
|
LineEndNode::Style mEndEndStyle{ LineEndNode::Style::NONE };
|
||||||
|
|
||||||
std::vector<Point> mPoints;
|
std::vector<Point> mPoints;
|
||||||
|
|
||||||
|
std::unique_ptr<LineEndNode> mStartNode;
|
||||||
|
std::unique_ptr<LineEndNode> mEndNode;
|
||||||
};
|
};
|
||||||
|
|
53
src/rendering/visual_elements/basic_shapes/PolygonNode.cpp
Normal file
53
src/rendering/visual_elements/basic_shapes/PolygonNode.cpp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#include "PolygonNode.h"
|
||||||
|
|
||||||
|
#include "Polygon.h"
|
||||||
|
#include "SceneInfo.h"
|
||||||
|
#include "SceneModel.h"
|
||||||
|
|
||||||
|
PolygonNode::PolygonNode(const Transform& t)
|
||||||
|
: GeometryNode(t)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PolygonNode::~PolygonNode()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PolygonNode::Type PolygonNode::getType()
|
||||||
|
{
|
||||||
|
return Type::Polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolygonNode::setPoints(const std::vector<Point>& points)
|
||||||
|
{
|
||||||
|
mPoints = points;
|
||||||
|
mGeometryIsDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolygonNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
|
{
|
||||||
|
if (!mBackgroundItem)
|
||||||
|
{
|
||||||
|
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sceneInfo->mSupportsGeometryPrimitives)
|
||||||
|
{
|
||||||
|
auto polygon = std::make_unique<ntk::Polygon>(mPoints);
|
||||||
|
mBackgroundItem->updateGeometry(std::move(polygon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/rendering/visual_elements/basic_shapes/PolygonNode.h
Normal file
19
src/rendering/visual_elements/basic_shapes/PolygonNode.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GeometryNode.h"
|
||||||
|
|
||||||
|
class PolygonNode : public GeometryNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolygonNode(const Transform& t = {});
|
||||||
|
|
||||||
|
virtual ~PolygonNode();
|
||||||
|
|
||||||
|
Type getType() override;
|
||||||
|
|
||||||
|
void setPoints(const std::vector<Point>& points);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
|
||||||
|
std::vector<Point> mPoints;
|
||||||
|
};
|
|
@ -14,7 +14,8 @@ public:
|
||||||
Rectangle,
|
Rectangle,
|
||||||
Circle,
|
Circle,
|
||||||
Arc,
|
Arc,
|
||||||
Line
|
Line,
|
||||||
|
Polygon
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
63
src/rendering/visual_elements/nodes/LineEndNode.cpp
Normal file
63
src/rendering/visual_elements/nodes/LineEndNode.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#include "LineEndNode.h"
|
||||||
|
|
||||||
|
#include "GeometryNode.h"
|
||||||
|
#include "PolygonNode.h"
|
||||||
|
|
||||||
|
LineEndNode::LineEndNode(const Transform& t)
|
||||||
|
: MaterialNode(t)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEndNode::setStyle(LineEndNode::Style style)
|
||||||
|
{
|
||||||
|
if (mStyle != style)
|
||||||
|
{
|
||||||
|
mStyle = style;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEndNode::setSize(double size)
|
||||||
|
{
|
||||||
|
if (mSize != size)
|
||||||
|
{
|
||||||
|
mSize = size;
|
||||||
|
mContentDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEndNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||||
|
{
|
||||||
|
if (!mContentNode)
|
||||||
|
{
|
||||||
|
if (mStyle == Style::CLOSED_ARROW)
|
||||||
|
{
|
||||||
|
auto polygon = std::make_unique<PolygonNode>();
|
||||||
|
auto p0 = Point(0.0, -mSize / 2.0);
|
||||||
|
auto p1 = Point(mSize, 0.0);
|
||||||
|
auto p2 = Point(0.0, mSize / 2.0);
|
||||||
|
polygon->setPoints({ p0, p1, p2 });
|
||||||
|
polygon->setFillColor({ 0, 0, 0 });
|
||||||
|
|
||||||
|
mContentNode = std::move(polygon);
|
||||||
|
addChild(mContentNode.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEndNode::update(SceneInfo* sceneInfo)
|
||||||
|
{
|
||||||
|
if (mContentDirty)
|
||||||
|
{
|
||||||
|
createOrUpdateGeometry(sceneInfo);
|
||||||
|
mContentDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMaterialIsDirty)
|
||||||
|
{
|
||||||
|
//updateMaterial();
|
||||||
|
mMaterialIsDirty = false;
|
||||||
|
}
|
||||||
|
}
|
38
src/rendering/visual_elements/nodes/LineEndNode.h
Normal file
38
src/rendering/visual_elements/nodes/LineEndNode.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MaterialNode.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
class GeometryNode;
|
||||||
|
|
||||||
|
class LineEndNode : public MaterialNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Style
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
CIRCLE,
|
||||||
|
CLOSED_ARROW,
|
||||||
|
OPEN_ARROW,
|
||||||
|
CURVED_ARROW
|
||||||
|
};
|
||||||
|
|
||||||
|
LineEndNode(const Transform& t = {});
|
||||||
|
|
||||||
|
void setStyle(LineEndNode::Style style);
|
||||||
|
|
||||||
|
void setSize(double size);
|
||||||
|
|
||||||
|
void update(SceneInfo* sceneInfo) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createOrUpdateGeometry(SceneInfo* sceneInfo);
|
||||||
|
|
||||||
|
std::unique_ptr<GeometryNode> mContentNode;
|
||||||
|
|
||||||
|
Vector mDirection;
|
||||||
|
|
||||||
|
bool mContentDirty{ true };
|
||||||
|
double mSize{ 5.0 };
|
||||||
|
Style mStyle{ Style::NONE };
|
||||||
|
};
|
|
@ -17,6 +17,7 @@
|
||||||
#include "Path.h"
|
#include "Path.h"
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
#include "LineSegment.h"
|
#include "LineSegment.h"
|
||||||
|
#include "Polygon.h"
|
||||||
|
|
||||||
#include "SvgShapeElements.h"
|
#include "SvgShapeElements.h"
|
||||||
#include "SvgTextElement.h"
|
#include "SvgTextElement.h"
|
||||||
|
@ -149,6 +150,21 @@ void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
|
||||||
{
|
{
|
||||||
paintLineSegment(document, model);
|
paintLineSegment(document, model);
|
||||||
}
|
}
|
||||||
|
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::POLYGON)
|
||||||
|
{
|
||||||
|
paintPolygon(document, model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgPainter::paintPolygon(SvgDocument* document, SceneModel* model) const
|
||||||
|
{
|
||||||
|
auto model_polygon = dynamic_cast<ntk::Polygon*>(model->getGeometry());
|
||||||
|
|
||||||
|
auto svg_polygon = std::make_unique<SvgPolygon>();
|
||||||
|
svg_polygon->setPoints(model_polygon->getPoints().getPoints());
|
||||||
|
|
||||||
|
setStyle(model, svg_polygon.get());
|
||||||
|
document->getRoot()->addChild(std::move(svg_polygon));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SvgPainter::paintRect(SvgDocument* document, SceneModel* model) const
|
void SvgPainter::paintRect(SvgDocument* document, SceneModel* model) const
|
||||||
|
|
|
@ -32,6 +32,8 @@ private:
|
||||||
|
|
||||||
void paintPath(SvgDocument* document, SceneModel* model) const;
|
void paintPath(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
|
void paintPolygon(SvgDocument* document, SceneModel* model) const;
|
||||||
|
|
||||||
void paintText(SvgDocument* document, SceneText* model) const;
|
void paintText(SvgDocument* document, SceneText* model) const;
|
||||||
|
|
||||||
void setStyle(SceneModel* model, SvgShapeElement* element) const;
|
void setStyle(SceneModel* model, SvgShapeElement* element) const;
|
||||||
|
|
|
@ -2,6 +2,7 @@ add_subdirectory(test_utils)
|
||||||
|
|
||||||
add_subdirectory(geometry)
|
add_subdirectory(geometry)
|
||||||
add_subdirectory(graphics)
|
add_subdirectory(graphics)
|
||||||
|
add_subdirectory(publishing)
|
||||||
add_subdirectory(ui_controls)
|
add_subdirectory(ui_controls)
|
||||||
|
|
||||||
file(COPY data/ DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_data)
|
file(COPY data/ DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_data)
|
||||||
|
@ -17,7 +18,6 @@ set(TEST_MODULES
|
||||||
ipc
|
ipc
|
||||||
network
|
network
|
||||||
mesh
|
mesh
|
||||||
publishing
|
|
||||||
video
|
video
|
||||||
web
|
web
|
||||||
windows)
|
windows)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "CircleNode.h"
|
#include "CircleNode.h"
|
||||||
#include "LineNode.h"
|
#include "LineNode.h"
|
||||||
#include "PathNode.h"
|
#include "PathNode.h"
|
||||||
|
#include "PolygonNode.h"
|
||||||
|
|
||||||
void addRect(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, double radius = 0.0)
|
void addRect(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, double radius = 0.0)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +44,17 @@ void addPath(const Point& loc, const std::string& path, std::vector<std::unique_
|
||||||
nodes.push_back(std::move(node));
|
nodes.push_back(std::move(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addPolygon(const Point& loc, std::vector<std::unique_ptr<MaterialNode> >& nodes)
|
||||||
|
{
|
||||||
|
auto p0 = Point{ 0.0, 0.0 };
|
||||||
|
auto p1 = Point{ 150.0, 0.0 };
|
||||||
|
auto p2 = Point{ 75.0, 75.0 };
|
||||||
|
|
||||||
|
auto node = std::make_unique<PolygonNode>(loc);
|
||||||
|
node->setPoints({ p0, p1, p2 });
|
||||||
|
nodes.push_back(std::move(node));
|
||||||
|
}
|
||||||
|
|
||||||
void addShapes(const Point& start_loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, bool use_fill = false)
|
void addShapes(const Point& start_loc, std::vector<std::unique_ptr<MaterialNode> >& nodes, bool use_fill = false)
|
||||||
{
|
{
|
||||||
auto loc = start_loc;
|
auto loc = start_loc;
|
||||||
|
@ -57,6 +69,9 @@ void addShapes(const Point& start_loc, std::vector<std::unique_ptr<MaterialNode>
|
||||||
loc.move(100, 0);
|
loc.move(100, 0);
|
||||||
addLine(loc, nodes);
|
addLine(loc, nodes);
|
||||||
|
|
||||||
|
loc.move(200, 0);
|
||||||
|
addPolygon(loc, nodes);
|
||||||
|
|
||||||
loc = Point(10, 150);
|
loc = Point(10, 150);
|
||||||
addRect(loc, nodes, 10.0);
|
addRect(loc, nodes, 10.0);
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
set(PUBLISHING_UNIT_TEST_FILES
|
set(MODULE_NAME publishing)
|
||||||
publishing/TestPdfWriter.cpp
|
|
||||||
publishing/TestDocumentConverter.cpp
|
list(APPEND UNIT_TEST_FILES
|
||||||
publishing/TestSvgConverter.cpp
|
TestPdfWriter.cpp
|
||||||
publishing/TestSvgToNodeConverter.cpp
|
TestDocumentConverter.cpp
|
||||||
publishing/TestLatexConverter.cpp
|
TestSvgConverter.cpp
|
||||||
PARENT_SCOPE
|
TestSvgToNodeConverter.cpp
|
||||||
|
TestLatexConverter.cpp
|
||||||
|
TestPlotting.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PUBLISHING_UNIT_TEST_DEPENDENCIES
|
set(UNIT_TEST_TARGET_NAME ${MODULE_NAME}_unit_tests)
|
||||||
publishing
|
|
||||||
PARENT_SCOPE
|
add_executable(${UNIT_TEST_TARGET_NAME} ${CMAKE_SOURCE_DIR}/test/test_runner.cpp ${UNIT_TEST_FILES})
|
||||||
)
|
target_link_libraries(${UNIT_TEST_TARGET_NAME} PUBLIC test_utils publishing)
|
||||||
|
set_property(TARGET ${UNIT_TEST_TARGET_NAME} PROPERTY FOLDER test/${MODULE_NAME})
|
33
test/publishing/TestPlotting.cpp
Normal file
33
test/publishing/TestPlotting.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include "TestFramework.h"
|
||||||
|
#include "TestUtils.h"
|
||||||
|
#include "TestRenderUtils.h"
|
||||||
|
|
||||||
|
#include "Plot.h"
|
||||||
|
#include "PlotNode.h"
|
||||||
|
|
||||||
|
TEST_CASE(TestPlotting, "[publishing]")
|
||||||
|
{
|
||||||
|
auto plot = std::make_unique<Plot>();
|
||||||
|
plot->setXAxisCaption("X Axis");
|
||||||
|
plot->setYAxisCaption("Y Axis");
|
||||||
|
|
||||||
|
PlotSeries series("Series-1");
|
||||||
|
|
||||||
|
std::vector<Point> data{ {0.0, 0.0}, {10.0, 40.0}, {20.0, 80.0} };
|
||||||
|
series.setData(data);
|
||||||
|
plot->addSeries(series);
|
||||||
|
|
||||||
|
Point loc(10, 10);
|
||||||
|
auto plot_node = std::make_unique<PlotNode>(Transform(loc));
|
||||||
|
plot_node->setAxisEndStyle(LineEndNode::Style::CLOSED_ARROW);
|
||||||
|
|
||||||
|
plot_node->setContent(plot.get());
|
||||||
|
|
||||||
|
TestRenderer renderer(800, 800);
|
||||||
|
|
||||||
|
auto scene = renderer.getScene();
|
||||||
|
scene->addNode(plot_node.get());
|
||||||
|
|
||||||
|
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "plot.svg");
|
||||||
|
renderer.write(TestUtils::getTestOutputDir(__FILE__) / "plot.png");
|
||||||
|
}
|
Loading…
Reference in a new issue