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,
|
||||
PATH,
|
||||
CIRCLE,
|
||||
POLYGON,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ list(APPEND HEADERS
|
|||
points/PointCollection.h
|
||||
points/DiscretePoint.h
|
||||
primitives/Circle.h
|
||||
primitives/Quad.h
|
||||
primitives/Polygon.h
|
||||
primitives/Rectangle.h
|
||||
primitives/Triangle.h
|
||||
)
|
||||
|
@ -49,7 +49,7 @@ list(APPEND SOURCES
|
|||
points/PointCollection.cpp
|
||||
points/DiscretePoint.cpp
|
||||
primitives/Circle.cpp
|
||||
primitives/Quad.cpp
|
||||
primitives/Polygon.cpp
|
||||
primitives/Rectangle.cpp
|
||||
primitives/Triangle.cpp
|
||||
)
|
||||
|
|
|
@ -1,6 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#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
|
||||
{
|
||||
|
|
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
|
||||
plotting/GraphPlotter.h
|
||||
plotting/PlotNode.h
|
||||
plotting/Plot.h
|
||||
plotting/EquationNode.h
|
||||
plotting/PlotSeriesNode.h
|
||||
plotting/PlotCaptionNode.h
|
||||
latex/LatexDocument.h
|
||||
latex/LatexMathExpression.h
|
||||
latex/LatexSymbols.h
|
||||
|
@ -34,7 +37,10 @@ list(APPEND publishing_LIB_INCLUDES
|
|||
latex/LatexSymbols.cpp
|
||||
plotting/GraphPlotter.h
|
||||
plotting/PlotNode.cpp
|
||||
plotting/Plot.cpp
|
||||
plotting/EquationNode.cpp
|
||||
plotting/PlotSeriesNode.cpp
|
||||
plotting/PlotCaptionNode.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 "Rectangle.h"
|
||||
#include "Circle.h"
|
||||
#include "Path.h"
|
||||
|
||||
#include "LineSegment.h"
|
||||
#include "Line.h"
|
||||
#include "Path.h"
|
||||
#include "Polygon.h"
|
||||
|
||||
#include "Curve.h"
|
||||
#include "Arc.h"
|
||||
|
@ -61,6 +60,10 @@ void DirectX2dPainter::paint(SceneModel* model)
|
|||
{
|
||||
paintLine(model);
|
||||
}
|
||||
else if (model->getGeometry()->getType() == AbstractGeometricItem::Type::POLYGON)
|
||||
{
|
||||
paintPolygon(model);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectX2dPainter::paintRect(SceneModel* model)
|
||||
|
@ -158,6 +161,54 @@ void DirectX2dPainter::paintLine(SceneModel* model)
|
|||
|
||||
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->Close();
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ private:
|
|||
|
||||
void paintLine(SceneModel* model);
|
||||
|
||||
void paintPolygon(SceneModel* model);
|
||||
|
||||
static D2D1::ColorF toD2dColor(const Color& color);
|
||||
|
||||
static D2D_POINT_2F toD2dPoint(const Point& point);
|
||||
|
|
|
@ -7,6 +7,8 @@ list(APPEND visual_elements_LIB_INCLUDES
|
|||
basic_shapes/CircleNode.cpp
|
||||
basic_shapes/LineNode.h
|
||||
basic_shapes/LineNode.cpp
|
||||
basic_shapes/PolygonNode.h
|
||||
basic_shapes/PolygonNode.cpp
|
||||
scene/Scene.h
|
||||
scene/Scene.cpp
|
||||
scene/SceneInfo.h
|
||||
|
@ -40,6 +42,8 @@ list(APPEND visual_elements_LIB_INCLUDES
|
|||
nodes/PathNode.cpp
|
||||
nodes/ImageNode.h
|
||||
nodes/ImageNode.cpp
|
||||
nodes/LineEndNode.h
|
||||
nodes/LineEndNode.cpp
|
||||
nodes/MeshNode.h
|
||||
nodes/MeshNode.cpp
|
||||
nodes/TextNode.h
|
||||
|
|
|
@ -20,6 +20,48 @@ void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
|||
{
|
||||
auto line = std::make_unique<Line>(Point{ 0, 0 }, mPoints);
|
||||
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");
|
||||
}
|
||||
|
||||
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 "Line.h"
|
||||
#include "LineEndNode.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -14,8 +15,21 @@ public:
|
|||
|
||||
Type getType() override;
|
||||
|
||||
void setStartEndStyle(LineEndNode::Style style);
|
||||
|
||||
void setEndEndStyle(LineEndNode::Style style);
|
||||
|
||||
private:
|
||||
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::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,
|
||||
Circle,
|
||||
Arc,
|
||||
Line
|
||||
Line,
|
||||
Polygon
|
||||
};
|
||||
|
||||
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 "Line.h"
|
||||
#include "LineSegment.h"
|
||||
#include "Polygon.h"
|
||||
|
||||
#include "SvgShapeElements.h"
|
||||
#include "SvgTextElement.h"
|
||||
|
@ -149,6 +150,21 @@ void SvgPainter::paintPrimitive(SvgDocument* document, SceneModel* model) const
|
|||
{
|
||||
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
|
||||
|
|
|
@ -32,6 +32,8 @@ private:
|
|||
|
||||
void paintPath(SvgDocument* document, SceneModel* model) const;
|
||||
|
||||
void paintPolygon(SvgDocument* document, SceneModel* model) const;
|
||||
|
||||
void paintText(SvgDocument* document, SceneText* model) const;
|
||||
|
||||
void setStyle(SceneModel* model, SvgShapeElement* element) const;
|
||||
|
|
|
@ -2,6 +2,7 @@ add_subdirectory(test_utils)
|
|||
|
||||
add_subdirectory(geometry)
|
||||
add_subdirectory(graphics)
|
||||
add_subdirectory(publishing)
|
||||
add_subdirectory(ui_controls)
|
||||
|
||||
file(COPY data/ DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_data)
|
||||
|
@ -17,7 +18,6 @@ set(TEST_MODULES
|
|||
ipc
|
||||
network
|
||||
mesh
|
||||
publishing
|
||||
video
|
||||
web
|
||||
windows)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "CircleNode.h"
|
||||
#include "LineNode.h"
|
||||
#include "PathNode.h"
|
||||
#include "PolygonNode.h"
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto loc = start_loc;
|
||||
|
@ -57,6 +69,9 @@ void addShapes(const Point& start_loc, std::vector<std::unique_ptr<MaterialNode>
|
|||
loc.move(100, 0);
|
||||
addLine(loc, nodes);
|
||||
|
||||
loc.move(200, 0);
|
||||
addPolygon(loc, nodes);
|
||||
|
||||
loc = Point(10, 150);
|
||||
addRect(loc, nodes, 10.0);
|
||||
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
set(PUBLISHING_UNIT_TEST_FILES
|
||||
publishing/TestPdfWriter.cpp
|
||||
publishing/TestDocumentConverter.cpp
|
||||
publishing/TestSvgConverter.cpp
|
||||
publishing/TestSvgToNodeConverter.cpp
|
||||
publishing/TestLatexConverter.cpp
|
||||
PARENT_SCOPE
|
||||
set(MODULE_NAME publishing)
|
||||
|
||||
list(APPEND UNIT_TEST_FILES
|
||||
TestPdfWriter.cpp
|
||||
TestDocumentConverter.cpp
|
||||
TestSvgConverter.cpp
|
||||
TestSvgToNodeConverter.cpp
|
||||
TestLatexConverter.cpp
|
||||
TestPlotting.cpp
|
||||
)
|
||||
|
||||
set(PUBLISHING_UNIT_TEST_DEPENDENCIES
|
||||
publishing
|
||||
PARENT_SCOPE
|
||||
)
|
||||
set(UNIT_TEST_TARGET_NAME ${MODULE_NAME}_unit_tests)
|
||||
|
||||
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