Start cleaning geometry module.

This commit is contained in:
jmsgrogan 2023-01-13 11:47:48 +00:00
parent 26ecae46b3
commit cd688f608f
52 changed files with 493 additions and 277 deletions

View file

@ -36,9 +36,13 @@ void BlochSphereNode::update(SceneInfo* sceneInfo)
auto loc = Point(mSize / 2.0, mSize / 2.0);
mInnerCircle = std::make_unique<CircleNode>(loc, mSize / 2.0);
mInnerCircle->setMinorRadius(mSize / 4.0);
mInnerCircle->setStrokeThickness(0.5);
mOuterCircle = std::make_unique<CircleNode>(loc, mSize/2.0);
const auto end_point_x = Point(loc.getX() + 1.2 * mSize / 2.0, loc.getY());
mXAxis = std::make_unique<LineNode>(loc, { end_point_x });
mCentreCircle = std::make_unique<CircleNode>(loc, mSize / 50.0);
mCentreCircle->setFillColor(Color(0, 0, 0));
mCentreCircle->setHasStrokeColor(false);

View file

@ -0,0 +1,12 @@
#pragma once
#include <string>
class AbstractNamedItem
{
public:
~AbstractNamedItem() = default;
protected:
std::string mName;
std::string mSymbol;
};

View file

@ -2,6 +2,7 @@ set(MODULE_NAME core)
list(APPEND core_HEADERS
AbstractApp.h
AbstractNamedItem.h
AbstractWebApp.h
Dictionary.h
Event.h

View file

@ -1,9 +1,8 @@
#pragma once
class Rectangle;
class Point;
#include "Bounds.h"
#include "Point.h"
template<class T>
class Grid;
class AbstractGeometricItem
@ -13,6 +12,8 @@ public:
enum class Type
{
LINE,
LINE_SEGMENT,
CURVE,
RECTANGLE,
TRIANGLE,
POINT,
@ -21,26 +22,13 @@ public:
UNKNOWN
};
struct Bounds
{
Bounds(double width, double height)
: mWidth(width),
mHeight(height)
{
}
double mWidth{0.0};
double mHeight{0.0};
};
virtual ~AbstractGeometricItem() = default;
virtual Bounds getSize() const = 0;
virtual Bounds getBounds() const = 0;
virtual const Point& getLocation() const = 0;
virtual void sample(Grid<unsigned char>* grid) const = 0;
virtual void sample(Grid* grid) const = 0;
virtual Type getType() const { return Type::UNKNOWN; };
};

21
src/geometry/Bounds.h Normal file
View file

@ -0,0 +1,21 @@
#pragma once
struct Bounds
{
Bounds(double minX, double maxX, double minY, double maxY, double minZ = 0.0, double maxZ = 0.0)
: mMinX(minX),
mMaxX(maxX),
mMinY(minY),
mMaxY(maxY),
mMinZ(minZ),
mMaxZ(maxZ)
{
}
double mMinX{ 0.0 };
double mMaxX{ 0.0 };
double mMinY{ 0.0 };
double mMaxY{ 0.0 };
double mMinZ{ 0.0 };
double mMaxZ{ 0.0 };
};

View file

@ -1,36 +1,48 @@
set(MODULE_NAME geometry)
list(APPEND geometry_LIB_INCLUDES
AbstractGeometricItem.h
Circle.h
Circle.cpp
Bounds.h
DiscretePoint.h
DiscretePoint.cpp
Grid.h
Grid.cpp
Line.h
Linalg.h
Linalg.cpp
Line.cpp
LineSegment.cpp
Matrix.h
Matrix.cpp
Path.h
Path.cpp
Point.h
Point.cpp
Quad.cpp
Rectangle.h
Rectangle.cpp
Triangle.h
Triangle.cpp
Transform.cpp
Vector.h
Vector.cpp)
math/Linalg.h
math/Linalg.cpp
math/Matrix.h
math/Matrix.cpp
math/Vector.h
math/Vector.cpp
path/Curve.h
path/Curve.cpp
path/Line.h
path/Line.cpp
path/LineSegment.h
path/LineSegment.cpp
path/Path.h
path/Path.cpp
path/PathElement.h
primitives/Circle.h
primitives/Circle.cpp
primitives/Quad.h
primitives/Quad.cpp
primitives/Rectangle.h
primitives/Rectangle.cpp
primitives/Triangle.h
primitives/Triangle.cpp
)
add_library(${MODULE_NAME} SHARED ${geometry_LIB_INCLUDES})
# add the library
add_library(geometry SHARED ${geometry_LIB_INCLUDES})
target_include_directories(${MODULE_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/math
${CMAKE_CURRENT_SOURCE_DIR}/path
${CMAKE_CURRENT_SOURCE_DIR}/primitives
)
target_include_directories(geometry PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
set_target_properties( geometry PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
set_property(TARGET geometry PROPERTY FOLDER src)
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)

View file

@ -17,12 +17,12 @@ std::shared_ptr<DiscretePoint> DiscretePoint::Create(unsigned x, unsigned y)
return std::make_shared<DiscretePoint>(x, y);
}
unsigned DiscretePoint::GetX() const
unsigned DiscretePoint::getX() const
{
return mX;
}
unsigned DiscretePoint::GetY() const
unsigned DiscretePoint::getY() const
{
return mY;
}

View file

@ -4,20 +4,16 @@
class DiscretePoint
{
unsigned mX;
unsigned mY;
public:
DiscretePoint(unsigned x = 0, unsigned y = 0);
~DiscretePoint();
std::shared_ptr<DiscretePoint> Create(unsigned x, unsigned y);
unsigned GetX() const;
unsigned getX() const;
unsigned GetY() const;
unsigned getY() const;
bool operator==(const DiscretePoint& rhs) const
{
@ -28,6 +24,10 @@ public:
{
return !operator==(rhs);
}
private:
unsigned mX{ 0 };
unsigned mY{ 0 };
};
using Pixel = DiscretePoint;

View file

@ -1,50 +1,43 @@
#include "Grid.h"
template<typename T>
Grid<T>::Grid(const ntk::Rectangle& bounds)
Grid::Grid(const Bounds& bounds)
: mBounds(bounds)
{
mValues = std::vector<T>(mNumX*mNumY, T());
mValues = std::vector<double>(mNumX*mNumY, 0.0);
}
template<typename T>
const ntk::Rectangle& Grid<T>::getBounds() const
const Bounds& Grid::getBounds() const
{
return mBounds;
}
template<typename T>
double Grid<T>::getXSpacing() const
double Grid::getXSpacing() const
{
return mBounds.getWidth()/double(mNumX);
const auto width = mBounds.mMaxX - mBounds.mMinX;
return width/double(mNumX);
}
template<typename T>
double Grid<T>::getYSpacing() const
double Grid::getYSpacing() const
{
return mBounds.getHeight()/double(mNumY);
const auto height = mBounds.mMaxY - mBounds.mMinY;
return height/double(mNumY);
}
template<typename T>
const std::vector<T>& Grid<T>::getValues() const
const std::vector<double>& Grid::getValues() const
{
return mValues;
}
template<typename T>
void Grid<T>::resetBounds(const ntk::Rectangle& bounds)
void Grid::resetBounds(const Bounds& bounds)
{
mBounds = bounds;
mValues = std::vector<T>(mNumX*mNumY, T());
mValues = std::vector<double>(mNumX*mNumY, 0.0);
}
template<typename T>
void Grid<T>::setValues(const std::vector<std::size_t>& indices, T value)
void Grid::setValues(const std::vector<std::size_t>& indices, double value)
{
for (auto index : indices)
{
mValues[index] = value;
}
}
template class Grid<unsigned char>;

View file

@ -1,29 +1,29 @@
#pragma once
#include "Rectangle.h"
#include "Bounds.h"
#include <vector>
template<typename T>
class Grid
{
public:
Grid(const ntk::Rectangle& bounds);
Grid(const Bounds& bounds);
const ntk::Rectangle& getBounds() const;
const Bounds& getBounds() const;
double getXSpacing() const;
double getYSpacing() const;
const std::vector<T>& getValues() const;
const std::vector<double>& getValues() const;
void resetBounds(const ntk::Rectangle& bounds);
void resetBounds(const Bounds& bounds);
void setValues(const std::vector<std::size_t>& indices, T value);
void setValues(const std::vector<std::size_t>& indices, double value);
private:
ntk::Rectangle mBounds;
std::vector<T> mValues;
Bounds mBounds;
std::vector<double> mValues;
unsigned mNumX{5};
unsigned mNumY{5};
};

View file

View file

View file

View file

@ -1,5 +1,7 @@
#include "Point.h"
#include <cmath>
Point::Point(double x, double y, double z)
: mX(x),
mY(y),
@ -8,8 +10,8 @@ Point::Point(double x, double y, double z)
}
Point::Point(const DiscretePoint& point)
: mX(point.GetX()),
mY(point.GetY()),
: mX(static_cast<double>(point.getX())),
mY(static_cast<double>(point.getY())),
mZ(0)
{

View file

@ -4,12 +4,10 @@
#include "Vector.h"
#include <memory>
#include <cmath>
class Point
{
public:
Point(double x = 0, double y = 0, double z = 0);
Point(const DiscretePoint& point);

View file

@ -0,0 +1,14 @@
#pragma once
#include <vector>
class Matrix
{
public:
Matrix(unsigned numRows, unsigned numColumns)
{
mData = std::vector<double>(numRows * numColumns, 0.0);
}
private:
std::vector<double> mData;
};

13
src/geometry/path/Curve.h Normal file
View file

@ -0,0 +1,13 @@
#pragma once
#include "PathElement.h"
class Curve : public PathElement
{
public:
enum class CurveType
{
ARC,
CUBIC_BEZIER
};
};

View file

@ -0,0 +1,53 @@
#include "Line.h"
Line::Line(const Point& start, const std::vector<Point>& points)
: mStartPoint(start),
mPoints(points)
{
}
const std::vector<Point>& Line::getPoints() const
{
return mPoints;
}
Line::Type Line::getType() const
{
return Line::Type::LINE;
}
const Point& Line::getLocation() const
{
return mStartPoint;
}
Bounds Line::getBounds() const
{
double minX = mStartPoint.getX();
double maxX = mStartPoint.getX();
double minY = mStartPoint.getY();
double maxY = mStartPoint.getY();
for (const auto& point : mPoints)
{
if (point.getX() > maxX)
{
maxX = point.getX();
}
if (point.getX() < minX)
{
minX = point.getX();
}
if (point.getY() > maxY)
{
maxY = point.getX();
}
if (point.getY() < minY)
{
minY = point.getY();
}
}
return { minX, maxX, minY, maxY };
}

23
src/geometry/path/Line.h Normal file
View file

@ -0,0 +1,23 @@
#pragma once
#include "PathElement.h"
#include <vector>
class Line : public PathElement
{
public:
Line(const Point& start, const std::vector<Point>& points);
const std::vector<Point>& getPoints() const;
Line::Type getType() const override;
const Point& getLocation() const override;
Bounds getBounds() const override;
private:
Point mStartPoint;
std::vector<Point> mPoints;
};

View file

@ -27,14 +27,20 @@ const Point& LineSegment::getPoint1() const
return mP1;
}
void LineSegment::sample(Grid<unsigned char>* grid) const
void LineSegment::sample(Grid* grid) const
{
}
LineSegment::Bounds LineSegment::getSize() const
Bounds LineSegment::getBounds() const
{
return {mP0.getDeltaX(mP1), mP0.getDeltaY(mP1)};
const auto minX = std::min(mP0.getX(), mP1.getX());
const auto maxX = std::max(mP0.getX(), mP1.getX());
const auto minY = std::min(mP0.getY(), mP1.getY());
const auto maxY = std::max(mP0.getY(), mP1.getY());
return {minX, maxX, minY, maxY};
}
const Point& LineSegment::getLocation() const

View file

@ -1,12 +1,8 @@
#pragma once
#include "AbstractGeometricItem.h"
#include "Point.h"
#include "PathElement.h"
template<class T>
class Grid;
class LineSegment : public AbstractGeometricItem
class LineSegment : public PathElement
{
public:
LineSegment(const Point& p0, const Point& p1);
@ -19,9 +15,9 @@ public:
const Point& getPoint1() const;
void sample(Grid<unsigned char>* grid) const override;
void sample(Grid* grid) const override;
Bounds getSize() const override;
Bounds getBounds() const override;
const Point& getLocation() const override;

View file

@ -0,0 +1,6 @@
#include "Path.h"
const std::vector<PathElementPtr> Path::getElements() const
{
return mElements;
}

17
src/geometry/path/Path.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "PathElement.h"
#include <vector>
#include <memory>
using PathElementPtr = std::unique_ptr<PathElement>;
class Path : public AbstractGeometricItem
{
public:
const std::vector<PathElementPtr> getElements() const;
private:
std::vector<PathElementPtr> mElements;
};

View file

@ -0,0 +1,9 @@
#pragma once
#include "AbstractGeometricItem.h"
class PathElement : public AbstractGeometricItem
{
public:
~PathElement() = default;
};

View file

@ -27,14 +27,23 @@ void Circle::setMinorRadius(double radius)
mMinorRadius = radius;
}
void Circle::sample(Grid<unsigned char>* grid) const
void Circle::sample(Grid* grid) const
{
}
Circle::Bounds Circle::getSize() const
bool Circle::isEllipse() const
{
return Bounds{ 2.0 * mRadius, 2.0 * mMinorRadius };
return mRadius != mMinorRadius;
}
Bounds Circle::getBounds() const
{
double minX = mCentre.getX() - mRadius;
double maxX = mCentre.getX() + mRadius;
double minY = mCentre.getY() - mMinorRadius;
double maxY = mCentre.getY() + mMinorRadius;
return { minX, maxX, minY, maxY };
}
Circle::Type Circle::getType() const

View file

@ -14,14 +14,16 @@ public:
double getMinorRadius() const;
void setMinorRadius(double radius);
void sample(Grid<unsigned char>* grid) const override;
Bounds getSize() const override;
Bounds getBounds() const override;
Type getType() const override;
bool isEllipse() const;
void setMinorRadius(double radius);
void sample(Grid* grid) const override;
private:
double mMinorRadius{ 0.5 };
double mRadius{ 0.5 };

View file

@ -16,12 +16,22 @@ namespace ntk {
}
Rectangle Rectangle::getBounds() const
Rectangle::Type Rectangle::getType() const
{
return Rectangle(mBottomLeft, Point(mBottomLeft, mWidth, mHeight));
return AbstractGeometricItem::Type::RECTANGLE;
}
void Rectangle::sample(Grid<unsigned char>* grid) const
Bounds Rectangle::getBounds() const
{
const auto minX = mBottomLeft.getX();
const auto maxX = mBottomLeft.getX() + mWidth;
const auto minY = mBottomLeft.getY();
const auto maxY = mBottomLeft.getY() + mHeight;
return { minX , maxX , minY , maxY };
}
void Rectangle::sample(Grid* grid) const
{
}
@ -40,9 +50,4 @@ namespace ntk {
{
return mBottomLeft;
}
Rectangle::Bounds Rectangle::getSize() const
{
return { mWidth, mHeight };
}
}

View file

@ -1,10 +1,6 @@
#pragma once
#include "AbstractGeometricItem.h"
#include "Point.h"
template<class T>
class Grid;
namespace ntk{
class Rectangle : public AbstractGeometricItem
@ -19,16 +15,11 @@ public:
const Point& getLocation() const override;
Bounds getSize() const override;
Bounds getBounds() const override;
Rectangle getBounds() const;
Type getType() const override;
Type getType() const
{
return AbstractGeometricItem::Type::RECTANGLE;
}
void sample(Grid<unsigned char>* grid) const override;
void sample(Grid* grid) const override;
private:
Point mBottomLeft;

View file

@ -0,0 +1,8 @@
#pragma once
#include "AbstractGeometricItem.h"
class Triangle : public AbstractGeometricItem
{
};

View file

@ -102,7 +102,7 @@ void SvgConverter::setStyle(SceneModel* model, SvgShapeElement* element) const
if (model->hasOutlineColor())
{
element->setStrokeColor(model->getOutlineColor());
element->setStrokeWidth(1.0 / transform.getScaleX());
element->setStrokeWidth(model->getOutlineThickness() / transform.getScaleX());
}
else
{
@ -126,8 +126,13 @@ void SvgConverter::convertPrimitive(SvgDocument* document, SceneModel* model) co
{
auto model_circle = dynamic_cast<Circle*>(model->getGeometry());
auto circle = std::make_unique<SvgCircle>();
auto is_ellipse = model_circle->getMinorRadius() != model_circle->getRadius();
auto circle = std::make_unique<SvgCircle>(model_circle->isEllipse() ? SvgCircle::Type::ELLIPSE : SvgCircle::Type::REGULAR);
circle->setRadius(model_circle->getRadius());
if (model_circle->isEllipse())
{
circle->setMinorRadius(model_circle->getMinorRadius());
}
setStyle(model, circle.get());
document->getRoot()->addChild(std::move(circle));

View file

@ -1,6 +1,5 @@
#include "CircleNode.h"
#include "FontsManager.h"
#include "SceneModel.h"
#include "AbstractMesh.h"
#include "MeshPrimitives.h"
@ -11,7 +10,7 @@ CircleNode::CircleNode(const Point& location, double radius)
: GeometryNode(location),
mRadius(radius)
{
mMinorRadius = mRadius;
}
CircleNode::Type CircleNode::getType()
@ -24,23 +23,6 @@ double CircleNode::getRadius() const
return mRadius;
}
SceneItem* CircleNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mBackgroundItem.get();
}
else
{
return nullptr;
}
}
std::size_t CircleNode::getNumSceneItems() const
{
return 1;
}
void CircleNode::setRadius(double radius)
{
if (mRadius != radius)
@ -63,8 +45,9 @@ void CircleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto circle = std::make_unique<Circle>(Point{ 0, 0 }, 0.5);
circle->setMinorRadius(mMinorRadius);
double unit_circle_radius = 0.5;
auto circle = std::make_unique<Circle>(Point{ 0, 0 }, unit_circle_radius);
circle->setMinorRadius(unit_circle_radius*mMinorRadius/mRadius);
mBackgroundItem = std::make_unique<SceneModel>(std::move(circle));
}
else
@ -75,40 +58,7 @@ void CircleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
mBackgroundItem->setName(mName + "_Model");
}
void CircleNode::updateMaterial()
{
if (!mBackgroundItem)
{
return;
}
if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
}
}
void CircleNode::update(SceneInfo* sceneInfo)
{
if (!mBackgroundItem || mGeometryIsDirty)
{
createOrUpdateGeometry(sceneInfo);
mGeometryIsDirty = false;
}
if (mTransformIsDirty)
void CircleNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation, 2 * mRadius, 2 * mRadius });
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
updateMaterial();
mMaterialIsDirty = false;
}
}

View file

@ -8,22 +8,14 @@ public:
CircleNode(const Point& location, double radius);
Type getType() override;
double getRadius() const;
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
void setMinorRadius(double radius);
void setRadius(double radius);
void update(SceneInfo* sceneInfo) override;
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo);
void updateMaterial();
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
void updateTransform() override;
double mRadius{1.0};
double mMinorRadius{ 1.0 };
std::unique_ptr<SceneModel> mBackgroundItem;
std::unique_ptr<SceneModel> mOutlineItem;
};

View file

@ -1,12 +1,18 @@
#pragma once
#include "GeometryNode.h"
#include "SceneInfo.h"
#include "Line.h"
#include <vector>
class LineNode : public GeometryNode
{
public:
LineNode(const Point& location)
: GeometryNode(location)
LineNode(const Point& location, const std::vector<Point>& points)
: GeometryNode(location),
mPoints(points)
{
}
@ -15,4 +21,22 @@ public:
{
return Type::Line;
}
void createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto line = std::make_unique<Line>(Point{ 0, 0 }, 1, 1);
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
}
mBackgroundItem->setName(mName + "_Model");
}
void updateTransform()
{
mBackgroundItem->updateTransform({ mLocation });
}
private:
std::vector<Point> mPoints;
};

View file

@ -5,8 +5,6 @@
#include "MeshPrimitives.h"
#include "SceneInfo.h"
#include <iostream>
RectangleNode::RectangleNode(const Point& loc, double width, double height)
: GeometryNode(loc),
mWidth(width),
@ -25,23 +23,6 @@ GeometryNode::Type RectangleNode::getType()
return GeometryNode::Type::Rectangle;
}
SceneItem* RectangleNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mBackgroundItem.get();
}
else
{
return nullptr;
}
}
std::size_t RectangleNode::getNumSceneItems() const
{
return 1;
}
double RectangleNode::getWidth() const
{
return mWidth;
@ -86,40 +67,7 @@ void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
mBackgroundItem->setName(mName + "_Model");
}
void RectangleNode::updateMaterial()
{
if (!mBackgroundItem)
{
return;
}
if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
}
}
void RectangleNode::update(SceneInfo* sceneInfo)
{
if (!mBackgroundItem || mGeometryIsDirty)
{
createOrUpdateGeometry(sceneInfo);
mGeometryIsDirty = false;
}
if (mTransformIsDirty)
void RectangleNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation, mWidth, mHeight });
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
updateMaterial();
mMaterialIsDirty = false;
}
}

View file

@ -9,27 +9,20 @@ class RectangleNode : public GeometryNode
public:
RectangleNode(const Point& loc, double width, double height);
static std::unique_ptr<RectangleNode> Create(const Point& loc, double width, double height);
GeometryNode::Type getType() override;
double getWidth() const;
double getHeight() const;
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
void setWidth(double width);
void setHeight(double height);
void update(SceneInfo* sceneInfo) override;
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo);
void updateMaterial();
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
void updateTransform() override;
double mWidth{1};
double mHeight{1};
std::unique_ptr<SceneModel> mBackgroundItem;
std::unique_ptr<SceneModel> mOutlineItem;
};
using RectangleNodePtr = std::unique_ptr<RectangleNode>;

View file

@ -1,19 +1,45 @@
#include "GeometryNode.h"
#include "SceneInfo.h"
#include "SceneModel.h"
GeometryNode::GeometryNode(const Point& location)
: MaterialNode(location),
mStrokeThickness(1),
mStrokeThickness(1.0),
mType(Type::Path)
{
}
unsigned GeometryNode::getStrokeThickness() const
GeometryNode::~GeometryNode()
{
}
SceneItem* GeometryNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mBackgroundItem.get();
}
else
{
return nullptr;
}
}
std::size_t GeometryNode::getNumSceneItems() const
{
return 1;
}
double GeometryNode::getStrokeThickness() const
{
return mStrokeThickness;
}
void GeometryNode::setStrokeThickness(unsigned thickness)
void GeometryNode::setStrokeThickness(double thickness)
{
if (mStrokeThickness != thickness)
{
@ -21,3 +47,43 @@ void GeometryNode::setStrokeThickness(unsigned thickness)
mStrokeThickness = thickness;
}
}
void GeometryNode::updateMaterial()
{
if (!mBackgroundItem)
{
return;
}
if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
mBackgroundItem->setOutlineThickness(mStrokeThickness);
}
}
void GeometryNode::update(SceneInfo* sceneInfo)
{
if (!mBackgroundItem || mGeometryIsDirty)
{
createOrUpdateGeometry(sceneInfo);
mGeometryIsDirty = false;
}
if (mTransformIsDirty)
{
updateTransform();
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
updateMaterial();
mMaterialIsDirty = false;
}
}

View file

@ -2,6 +2,9 @@
#include "MaterialNode.h"
struct SceneInfo;
class SceneModel;
class GeometryNode : public MaterialNode
{
public:
@ -11,23 +14,33 @@ public:
Rectangle,
Circle,
Arc,
Line,
Polyline
Line
};
public:
GeometryNode(const Point& location);
virtual ~GeometryNode() = default;
virtual ~GeometryNode();
virtual Type getType() = 0;
unsigned getStrokeThickness() const;
void setStrokeThickness(unsigned thickness);
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
double getStrokeThickness() const;
void setStrokeThickness(double thickness);
void update(SceneInfo* sceneInfo) override;
protected:
unsigned mStrokeThickness{0};
virtual void createOrUpdateGeometry(SceneInfo* sceneInfo) = 0;
virtual void updateMaterial();
virtual void updateTransform() = 0;
double mStrokeThickness{0};
Type mType;
bool mGeometryIsDirty{true};
std::unique_ptr<SceneModel> mBackgroundItem;
};
using GeometryNodePtr = std::unique_ptr<GeometryNode>;

View file

@ -20,6 +20,11 @@ const Transform& SceneItem::getTransform() const
return mTransform;
}
double SceneItem::getOutlineThickness() const
{
return mOutlineThickness;
}
bool SceneItem::isVisible() const
{
return mIsVisible;
@ -40,6 +45,11 @@ void SceneItem::setIsVisible(bool isVisible)
mIsVisible = isVisible;
}
void SceneItem::setOutlineThickness(double thickness)
{
mOutlineThickness = thickness;
}
void SceneItem::setFillColor(const Color& color)
{
if (!mHasFillColor || mFillColor != color)

View file

@ -28,6 +28,8 @@ public:
virtual Type getType() const = 0;
double getOutlineThickness() const;
bool hasFillColor() const;
bool hasOutlineColor() const;
@ -38,6 +40,8 @@ public:
void setOutlineColor(const Color& color);
void setOutlineThickness(double thickness);
void setFillColor(const Color& color);
void updateTransform(const Transform& transform);
@ -60,6 +64,7 @@ protected:
bool mHasOutlineColor{ false };
Color mOutlineColor;
double mOutlineThickness{ 1.0 };
bool mColorIsDirty{true};
bool mTransformIsDirty{true};

View file

@ -2,8 +2,9 @@
#include <sstream>
SvgCircle::SvgCircle()
: SvgShapeElement("circle")
SvgCircle::SvgCircle(Type type)
: SvgShapeElement(type == Type::REGULAR ? "circle" : "ellipse"),
mType(type)
{
}
@ -21,11 +22,27 @@ void SvgCircle::setLocation(const Point& loc)
}
void SvgCircle::setRadius(double rad)
{
if (mType == Type::REGULAR)
{
auto r = std::make_unique<XmlAttribute>("r");
r->setValue(std::to_string(rad));
addAttribute(std::move(r));
}
else
{
auto r = std::make_unique<XmlAttribute>("rx");
r->setValue(std::to_string(rad));
addAttribute(std::move(r));
}
}
void SvgCircle::setMinorRadius(double rad)
{
auto r = std::make_unique<XmlAttribute>("ry");
r->setValue(std::to_string(rad));
addAttribute(std::move(r));
}
SvgRectangle::SvgRectangle()
: SvgShapeElement("rect")

View file

@ -8,11 +8,21 @@
class SvgCircle : public SvgShapeElement
{
public:
SvgCircle();
enum class Type
{
REGULAR,
ELLIPSE
};
SvgCircle(Type type = Type::REGULAR);
void setLocation(const Point& loc);
void setRadius(double rad);
void setMinorRadius(double rad);
private:
Type mType{ Type::REGULAR };
};
class SvgRectangle : public SvgShapeElement