Switch to template types for vectors

This commit is contained in:
jmsgrogan 2023-01-30 14:53:49 +00:00
parent 9f036d6438
commit 8192ef78e8
105 changed files with 1614 additions and 1424 deletions

View file

@ -1,10 +1,6 @@
#pragma once
#include "Bounds.h"
#include "Point.h"
template<typename T>
class SparseGrid;
class AbstractGeometricItem
{
@ -28,9 +24,5 @@ public:
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; };
};

View file

@ -16,7 +16,6 @@ list(APPEND HEADERS
path/Line.h
path/LineSegment.h
path/Path.h
path/PathPostScriptConverter.h
path/PathElement.h
path/Arc.h
path/QuadraticBezierCurve.h
@ -43,7 +42,6 @@ list(APPEND SOURCES
path/Line.cpp
path/LineSegment.cpp
path/Path.cpp
path/PathPostScriptConverter.cpp
path/PathElement.cpp
path/Arc.cpp
path/QuadraticBezierCurve.cpp

View file

@ -1,16 +1,16 @@
#include "Rotation.h"
Rotation::Rotation(double angle, Axis axis, const Point& loc, const Vector& customAxis)
Rotation::Rotation(double angle, Axis axis, const Point3& loc, const Vector3& customAxis)
: mAngle(angle),
mAxis(axis),
mPoint(loc),
mCustomAxis(customAxis),
mMatrix(3, 3)
mMatrix()
{
updateMatrix();
}
const Matrix& Rotation::getMatrix() const
const SquareMatrix3& Rotation::getMatrix() const
{
return mMatrix;
}

View file

@ -15,9 +15,9 @@ public:
USER
};
Rotation(double angle = 0.0, Axis axis = Axis::Z, const Point& loc = {}, const Vector& customAxis = {});
Rotation(double angle = 0.0, Axis axis = Axis::Z, const Point3& loc = {}, const Vector3& customAxis = {});
const Matrix& getMatrix() const;
const SquareMatrix3& getMatrix() const;
bool isIdentity() const;
@ -38,8 +38,8 @@ private:
double mAngle{ 0 };
Axis mAxis{ Axis::Z };
Point mPoint;
Vector mCustomAxis;
Point3 mPoint;
Vector3 mCustomAxis;
Matrix mMatrix;
SquareMatrix3 mMatrix;
};

View file

@ -18,22 +18,22 @@ bool Scale::isEqual(const Scale& scale) const
return mX == scale.mX && mY == scale.mY && mZ == scale.mZ;
}
Transform::Transform(const Point& location, const Scale& scale, const Rotation& rotation)
Transform::Transform(const Point3& location, const Scale& scale, const Rotation& rotation)
: mLocation(location),
mScale(scale),
mRotation(rotation),
mMatrix(4, 4)
mMatrix()
{
}
void Transform::applyPre(const Transform& transform)
{
mLocation.move(transform.getLocation().getX(), transform.getLocation().getY(), transform.getLocation().getZ());
mLocation.moveBy(transform.getLocation().getX(), transform.getLocation().getY(), transform.getLocation().getZ());
mScale *= transform.getScale();
}
const Point& Transform::getLocation() const
const Point3& Transform::getLocation() const
{
return mLocation;
}
@ -58,7 +58,7 @@ bool Transform::isIdentityTransform() const
return mLocation.isAtOrigin() && mScale.isIdentity();
}
void Transform::setLocation(const Point& loc)
void Transform::setLocation(const Point3& loc)
{
if (mLocation != loc)
{

View file

@ -35,23 +35,23 @@ struct Scale
class Transform
{
public:
Transform(const Point& location = {}, const Scale& scale = {}, const Rotation& rotation = {});
Transform(const Point3& location = {}, const Scale& scale = {}, const Rotation& rotation = {});
void applyPre(const Transform& transform);
const Point& getLocation() const;
const Point3& getLocation() const;
const Scale& getScale() const;
const Rotation& getRotation() const;
const Matrix& getMatrix() const;
const SquareMatrix4& getMatrix() const;
bool isEqual(const Transform& transform) const;
bool isIdentityTransform() const;
void setLocation(const Point& loc);
void setLocation(const Point3& loc);
void setScale(const Scale& scale);
@ -70,8 +70,8 @@ public:
private:
void updateMatrix();
Point mLocation;
Point3 mLocation;
Scale mScale;
Rotation mRotation;
Matrix mMatrix;
SquareMatrix4 mMatrix;
};

View file

@ -1,11 +1,8 @@
#include "Linalg.h"
double Linalg::dotProduct(const Vector& v0, const Vector& v1)
{
return v0.dotProduct(v1);
}
Vector Linalg::crossProduct(const Vector& v0, const Vector& v1)
template<std::size_t DIM>
Vector<double, DIM> Linalg::crossProduct(const Vector<double, DIM>& v0, const Vector<double, DIM>& v1)
{
return v0.crossProduct(v1);
}

View file

@ -4,7 +4,6 @@
class Linalg
{
static double dotProduct(const Vector& v0, const Vector& v1);
static Vector crossProduct(const Vector& v0, const Vector& v1);
template<std::size_t DIM>
static Vector<double, DIM> crossProduct(const Vector<double, DIM>& v0, const Vector<double, DIM>& v1);
};

View file

@ -3,23 +3,86 @@
#include <string>
#include <stdexcept>
Matrix::Matrix(std::size_t numRows, std::size_t numColumns)
: mNumRows(numRows),
mNumColumns(numColumns)
template<typename T, std::size_t M, std::size_t N>
Matrix<T, M, N>::Matrix(T value)
{
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())
{
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)
{
@ -40,7 +103,8 @@ bool Matrix::isIdentity() const
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);
if (index >= mData.size())
@ -50,17 +114,27 @@ double Matrix::getItem(std::size_t rowId, std::size_t columnId) const
return mData[getFlatIndex(rowId, columnId)];
}
bool Matrix::isSquare() const
template<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;
}
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>;

View file

@ -1,35 +1,63 @@
#pragma once
#include "Vector.h"
#include <vector>
#include <vector>
#include <complex>
template<typename T, std::size_t M = 3, std::size_t N = 3>
class Matrix
{
public:
Matrix(std::size_t numRows, std::size_t numColumns);
enum class InputType
{
UNIFORM,
DIAGONAL
};
Matrix(T value = 0.0);
Matrix(T value, InputType inputType);
void applyTo(Vector<T, N>& v) const;
std::size_t getFlatIndex(std::size_t rowId, std::size_t columnId) const;
double getItem(std::size_t rowId, std::size_t columnId) const;
T getItem(std::size_t rowId, std::size_t columnId) const;
bool isIdentity() const;
bool isSquare() const;
bool isEqual(const Matrix& matrix) const;
bool isEqual(const Matrix<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);
}
bool operator!=(const Matrix& rhs) const
bool operator!=(const Matrix<T, M, N>& rhs) const
{
return !operator==(rhs);
}
private:
std::size_t mNumRows{0};
std::size_t mNumColumns{0};
std::vector<double> mData;
std::vector<T> 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>;

View file

@ -1,92 +1,156 @@
#include "Vector.h"
#include <cmath>
#include <algorithm>
#include <numeric>
#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)
{
case Primitive::UNIT_X:
mX = 1.0;
mData[0] = 1.0;
break;
case Primitive::UNIT_Y:
mY = 1.0;
mData[1] = 1.0;
break;
case Primitive::UNIT_Z:
mZ = 1.0;
mData[2] = 1.0;
break;
case Primitive::NEGATIVE_X:
mX = -1.0;
mData[0] = -1.0;
break;
case Primitive::NEGATIVE_Y:
mY = -1.0;
mData[1] = -1.0;
break;
case Primitive::NEGATIVE_Z:
mZ = -1.0;
mData[2] = -1.0;
break;
}
}
Vector::Vector(double x, double y, double z)
: mX(x),
mY(y),
mZ(z)
template<typename T, std::size_t DIM>
Vector<T, DIM>::Vector(const std::vector<T>& values)
{
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();
if (length == 0.0)
{
throw std::logic_error("Divide by zero getting normalizing vector");
}
return Vector(mX / length, mY / length, mZ / length);
return (*this).multiply(1.0 / length);
}
void Vector::scale(double x, double y, double z)
template<typename T, std::size_t DIM>
void Vector<T, DIM>::scale(const std::vector<double>& factors)
{
mX = x * mX;
mY = y * mY;
mZ = z * mZ;
//std::transform(mData.begin(), mData.end(), factors.begin(), mData.begin(), std::multiplies<double>());
}
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>;

View file

@ -1,5 +1,9 @@
#pragma once
#include <vector>
#include <complex>
template<typename T, std::size_t DIM = 3>
class Vector
{
public:
@ -15,56 +19,79 @@ public:
Vector(Primitive p);
Vector(double x = 0, double y = 0, double z = 0);
Vector(const std::vector<T>& values = {});
~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();
double getX() const;
double getY() const;
double getZ() const;
T getEntry(std::size_t idx) 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;
mY *= d;
mZ *= d;
return add(v);
}
void operator+=(const Vector& vector)
Vector<T, DIM> operator*(double s) const
{
mX += vector.mX;
mY += vector.mY;
mZ += vector.mZ;
return multiply(s);
}
bool operator==(const Vector& rhs) const
void operator*=(double s)
{
return (mX == rhs.mX)
&& (mY == rhs.mY)
&& (mZ == rhs.mZ);
inPlaceMultiply(s);
}
bool operator!=(const Vector& rhs) const
void operator+=(const Vector<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);
}
T operator[](std::size_t idx) const
{
return getEntry(idx);
}
private:
double mX{ 0 };
double mY{ 0 };
double mZ{ 0 };
std::vector<T> mData;
};
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>;

View file

@ -4,9 +4,8 @@
#include <sstream>
namespace ntk {
Arc::Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation, bool largeArc, bool sweep)
: mStartPoint(startPoint),
mEndPoint(endPoint),
Arc::Arc(const Vector2& endoffset, double rX, double rY, double rotation, bool largeArc, bool sweep)
: mEndOffset(endoffset),
mRx(rX),
mRy(rY),
mRotation(rotation),
@ -16,43 +15,9 @@ namespace ntk {
}
Point Arc::getFirstPoint() const
Vector2 Arc::getEndOffset() const
{
return mStartPoint;
}
Point Arc::getEndPoint() const
{
return mEndPoint;
}
std::string Arc::toPostScriptString(std::size_t precision) const
{
const auto large = mLargeArc ? "1" : "0";
const auto sweep = mSweep ? "1" : "0";
std::stringstream sstr;
if (precision > 0)
{
sstr.precision(precision);
}
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
{
sstr << "a";
}
else
{
sstr << "A";
}
sstr << mRx << " " << mRy << " " << mRotation << " " << large << " " << sweep << " ";
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
{
sstr << PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision);
}
else
{
sstr << PointParser::toString(mEndPoint, 2, " ", precision);
}
return sstr.str();
return mEndOffset;
}
Bounds Arc::getBounds() const
@ -60,22 +25,7 @@ namespace ntk {
return {};
}
const Point& Arc::getLocation() const
{
return mStartPoint;
}
void Arc::sample(SparseGrid<bool>*) const
{
}
Arc::Type Arc::getType() const
{
return Type::CURVE;
}
Arc::CurveType Arc::getCurveType() const
CurveType Arc::getCurveType() const
{
return CurveType::ARC;
}

View file

@ -1,24 +1,18 @@
#pragma once
#include "Curve.h"
#include "Point.h"
#include "Vector.h"
namespace ntk{
class Arc : public Curve
class Arc : public Curve<2>
{
public:
Arc(const Point& startPoint, const Point& endPoint, double rX, double rY, double rotation = 0, bool largeArc = false, bool sweep = false);
Arc(const Vector2& endoffset, double rX, double rY, double rotation = 0, bool largeArc = false, bool sweep = false);
Point getFirstPoint() const override;
Point getEndPoint() const override;
Vector2 getEndOffset() const override;
Bounds getBounds() const override;
const Point& getLocation() const override;
Type getType() const override;
CurveType getCurveType() const override;
double getRx() const;
@ -31,13 +25,8 @@ public:
bool getSweepParam() const;
void sample(SparseGrid<bool>*) const override;
std::string toPostScriptString(std::size_t precision = 0) const override;
private:
Point mStartPoint;
Point mEndPoint;
Vector2 mEndOffset;
double mRx{ 0.0 };
double mRy{ 0.0 };
double mRotation{ 0 };

View file

@ -1,75 +1,43 @@
#include "CubicBezierCurve.h"
#include "PointParser.h"
CubicBezierCurve::CubicBezierCurve(const Point& startPoint, const Point& endPoint, const Point& startControlPoint, const Point& endControlPoint)
: mStartPoint(startPoint),
mEndPoint(endPoint),
mStartControlPoint(startControlPoint),
mEndControlPoint(endControlPoint)
template<std::size_t DIM>
CubicBezierCurve<DIM>::CubicBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& startControlOffset, const Vector<double, DIM>& endControlOffset)
: mEndOffset(endOffset),
mStartControlOffset(startControlOffset),
mEndControlOffset(endControlOffset)
{
}
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
{
return mEndControlPoint;
}
std::string CubicBezierCurve::toPostScriptString(std::size_t precision) const
{
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
{
const auto start_control = PointParser::toStringRelative(mStartControlPoint, mStartPoint, 2, " ", precision);
const auto end_control = PointParser::toStringRelative(mEndControlPoint, mStartPoint, 2, " ", precision);
const auto end = PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision);
return "c" + start_control + " " + end_control + " " + end;
}
else
{
const auto start_control = PointParser::toString(mStartControlPoint, 2, " ", precision);
const auto end_control = PointParser::toString(mEndControlPoint, 2, " ", precision);
const auto end = PointParser::toString(mEndPoint, 2, " ", precision);
return "C" + start_control + " " + end_control + " " + end;
}
}
Bounds CubicBezierCurve::getBounds() const
template<std::size_t DIM>
Bounds CubicBezierCurve<DIM>::getBounds() const
{
return {};
}
const Point& CubicBezierCurve::getLocation() const
{
return mStartPoint;
}
void CubicBezierCurve::sample(SparseGrid<bool>*) const
{
}
CubicBezierCurve::Type CubicBezierCurve::getType() const
{
return Type::CURVE;
}
CubicBezierCurve::CurveType CubicBezierCurve::getCurveType() const
template<std::size_t DIM>
CurveType CubicBezierCurve<DIM>::getCurveType() const
{
return CurveType::CUBIC_BEZIER;
}
template class CubicBezierCurve<2>;
template class CubicBezierCurve<3>;

View file

@ -1,36 +1,26 @@
#pragma once
#include "Curve.h"
#include "Point.h"
#include "Vector.h"
class CubicBezierCurve : public Curve
template<std::size_t DIM>
class CubicBezierCurve : public Curve<DIM>
{
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 Point& getEndControlPoint() const;
const Vector<double, DIM>& getEndControlOffset() const;
Bounds getBounds() const override;
const Point& getLocation() const override;
Type getType() const override;
CurveType getCurveType() const override;
void sample(SparseGrid<bool>*) const override;
std::string toPostScriptString(std::size_t precision = 0) const override;
private:
Point mStartPoint;
Point mEndPoint;
Point mStartControlPoint;
Point mEndControlPoint;
Vector<double, DIM> mEndOffset;
Vector<double, DIM> mStartControlOffset;
Vector<double, DIM> mEndControlOffset;
};

View file

@ -2,16 +2,22 @@
#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:
enum class CurveType
Curve::Type getType() const override
{
ARC,
QUADRATIC_BEZIER,
CUBIC_BEZIER,
UNKNOWN
};
return Curve::Type::CURVE;
}
virtual CurveType getCurveType() const = 0;
};

View file

@ -1,119 +1,66 @@
#include "Line.h"
#include "PointParser.h"
Line::Line(const Point& start, const PointCollection& points)
: mStartPoint(start),
mPoints(points)
template<std::size_t DIM>
Line<DIM>::Line(const PointCollection<DIM>& points)
: mPoints(points)
{
}
Line::Line(const Point& start, InputBufferType bufferType, const std::vector<double>& buffer)
: mStartPoint(start)
template<std::size_t DIM>
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)
{
const auto x = buffer[idx];
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)
{
for (std::size_t idx = 0; idx < buffer.size(); idx += 2)
{
const auto x = buffer[idx];
const auto y = buffer[idx + 1];
mPoints.addPoint(Point(x, y));
}
}
else if (bufferType == InputBufferType::HORIZONTAL_REL)
else if (bufferType == InputBufferType::HORIZONTAL)
{
for (std::size_t idx = 0; idx < buffer.size(); idx ++)
{
const auto x = buffer[idx];
mPoints.addPoint(Point(mStartPoint.getX() + x, mStartPoint.getY()));
mPoints.addPoint(Point<DIM>(buffer[idx], 0.0));
}
}
else if (bufferType == InputBufferType::HORIZONTAL_ABS)
else if (bufferType == InputBufferType::VERTICAL)
{
for (std::size_t idx = 0; idx < buffer.size(); idx++)
{
const auto x = buffer[idx];
mPoints.addPoint(Point(x, mStartPoint.getY()));
}
}
else if (bufferType == InputBufferType::VERTICAL_REL)
{
for (std::size_t idx = 0; idx < buffer.size(); idx++)
{
const auto y = buffer[idx];
mPoints.addPoint(Point(mStartPoint.getX(), mStartPoint.getY() + y));
}
}
else if (bufferType == InputBufferType::VERTICAL_ABS)
{
for (std::size_t idx = 0; idx < buffer.size(); idx++)
{
const auto y = buffer[idx];
mPoints.addPoint(Point(mStartPoint.getX(), y));
mPoints.addPoint(Point<DIM>(0.0, buffer[idx]));
}
}
}
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)
{
std::string path = "L";
for (const auto& point : mPoints.getPoints())
{
path += PointParser::toString(point, 2, " ", precision) + " ";
}
return path;
}
else
{
std::string path = "l";
for (const auto& point : mPoints.getPoints())
{
path += PointParser::toStringRelative(point, mStartPoint, 2, " ", precision) + " ";
}
return path;
}
return mPoints.getEndPoint().getOriginOffset();
}
Point Line::getFirstPoint() const
{
return getLocation();
}
Point Line::getEndPoint() const
{
return mPoints.getEndPoint();
}
const PointCollection& Line::getPoints() const
template<std::size_t DIM>
const PointCollection<DIM>& Line<DIM>::getPoints() const
{
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
{
return mStartPoint;
}
Bounds Line::getBounds() const
template<std::size_t DIM>
Bounds Line<DIM>::getBounds() const
{
auto bounds = mPoints.getBounds();
bounds.includePoint(mStartPoint.getX(), mStartPoint.getY(), mStartPoint.getZ());
bounds.includePoint(0.0, 0.0, 0.0);
return bounds;
}
}
template class Line<2>;
template class Line<3>;

View file

@ -6,40 +6,31 @@
#include <vector>
#include <string>
class Line : public PathElement
template<std::size_t DIM>
class Line : public PathElement<DIM>
{
public:
enum class InputBufferType
{
HORIZONTAL_REL,
HORIZONTAL_ABS,
VERTICAL_REL,
VERTICAL_ABS,
XY_REL,
XY_ABS
HORIZONTAL,
VERTICAL,
XY
};
Line(const Point& start, const PointCollection& points);
Line(const PointCollection<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;
const Point& getLocation() const override;
AbstractGeometricItem::Type getType() const override;
Bounds getBounds() const override;
Point getFirstPoint() const override;
Point getEndPoint() const override;
void sample(SparseGrid<bool>*) const override {};
std::string toPostScriptString(std::size_t precision = 0) const override;
Vector<double, DIM> getEndOffset() const override;
private:
Point mStartPoint;
PointCollection mPoints;
PointCollection<DIM> mPoints;
};
using Line2 = Line<2>;

View file

@ -1,87 +1,51 @@
#include "LineSegment.h"
#include "PointParser.h"
LineSegment::LineSegment(const Point& p0, const Point& p1)
template<std::size_t DIM>
LineSegment<DIM>::LineSegment(const Point<DIM>& p0, const Point<DIM>& p1)
: mP0(p0),
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);
}
const Point& LineSegment::getPoint0() const
template<std::size_t DIM>
const Point<DIM>& LineSegment<DIM> ::getPoint0() const
{
return mP0;
}
const Point& LineSegment::getPoint1() const
template<std::size_t DIM>
const Point<DIM>& LineSegment<DIM> ::getPoint1() const
{
return mP1;
}
void LineSegment::sample(SparseGrid<bool>*) const
{
}
std::string LineSegment::toPostScriptString(std::size_t precision) const
{
if (isHorizontal())
{
if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
{
return "H" + PointParser::toString(mP1.getX(), precision);
}
else
{
return "h" + PointParser::toString(mP0.getDeltaX(mP1), precision);
}
}
else if (isVertical())
{
if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
{
return "V" + PointParser::toString(mP1.getY(), precision);
}
else
{
return "v" + PointParser::toString(mP0.getDeltaY(mP1), precision);
}
}
else
{
if (mPostscriptPositioning == PostscriptPositioning::ABSOLUTE_TO)
{
return "L" + PointParser::toString(mP1, 2, " ", precision);
}
else
{
return "l" + PointParser::toStringRelative(mP1, mP0, 2, " ", precision);
}
}
}
bool LineSegment::isHorizontal() const
template<std::size_t DIM>
bool LineSegment<DIM>::isHorizontal() const
{
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;
}
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 maxX = std::max(mP0.getX(), mP1.getX());
@ -92,22 +56,23 @@ Bounds LineSegment::getBounds() const
return {minX, maxX, minY, maxY};
}
const Point& LineSegment::getLocation() const
template<std::size_t DIM>
Vector<double, DIM> LineSegment<DIM>::getEndOffset() const
{
return mP0;
return getPoint1().getOriginOffset();
}
Point LineSegment::getFirstPoint() const
{
return getPoint0();
}
Point LineSegment::getEndPoint() const
{
return getPoint1();
}
LineSegment::Type LineSegment::getType() const
template<std::size_t DIM>
AbstractGeometricItem::Type LineSegment<DIM>::getType() const
{
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>;

View file

@ -1,41 +1,37 @@
#pragma once
#include "PathElement.h"
#include "Point.h"
#include <string>
class LineSegment : public PathElement
template<std::size_t DIM>
class LineSegment : public PathElement<DIM>
{
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;
const Point& getPoint0() const;
const Point<DIM>& getPoint0() const;
const Point& getPoint1() const;
const Point<DIM>& getPoint1() const;
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;
Type getType() const override;
AbstractGeometricItem::Type getType() const override;
bool isHorizontal() const;
bool isVertical() const;
void sample(SparseGrid<bool>*) const override;
std::string toPostScriptString(std::size_t precision = 0) const override;
private:
Point mP0;
Point mP1;
Point<DIM> mP0;
Point<DIM> mP1;
};
using LineSegment2 = LineSegment<2>;

View file

@ -1,12 +1,5 @@
#include "Path.h"
#include "StringUtils.h"
#include "FileLogger.h"
#include "Line.h"
#include "LineSegment.h"
#include "PathPostScriptConverter.h"
GeometryPath::~GeometryPath()
{
@ -17,22 +10,12 @@ const std::vector<GeometryPathFeaturePtr>& GeometryPath::getFeatures() const
return mFeatures;
}
void GeometryPath::buildFromPostscript(const std::string& psString)
{
PathPostScriptConverter converter;
converter.fromPostScript(this, psString);
}
void GeometryPath::addFeature(GeometryPathFeaturePtr feature)
{
mFeatures.push_back(std::move(feature));
}
const Point& GeometryPath::getLocation() const
{
return mLocation;
}
Bounds GeometryPath::getBounds() const
{
return {};
@ -41,15 +24,4 @@ Bounds GeometryPath::getBounds() const
GeometryPath::Type GeometryPath::getType() const
{
return GeometryPath::Type::PATH;
}
void GeometryPath::sample(SparseGrid<bool>*) const
{
}
std::string GeometryPath::getAsPostScript() const
{
PathPostScriptConverter converter;
return converter.toPostScript(this);
}
}

View file

@ -6,23 +6,24 @@
#include <memory>
#include <string>
using PathElementPtr = std::unique_ptr<PathElement>;
using PathElementPtr = std::unique_ptr<PathElement<2> >;
class GeometryPathFeature
{
public:
void setLocation(Vector2 offset)
{
mOffset = offset;
}
void addElement(PathElementPtr element)
{
if (mElements.empty())
{
mLocation = element->getFirstPoint();
}
mElements.push_back(std::move(element));
}
const Point& getLocation() const
const Vector2& getOffset() const
{
return mLocation;
return mOffset;
}
const std::vector<PathElementPtr>& getElements() const
@ -30,8 +31,19 @@ public:
return mElements;
}
PathOffsetType getPathOffsetType() const
{
return mOffsetType;
}
void setPathOffsetType(PathOffsetType offsetType)
{
mOffsetType = offsetType;
}
private:
Point mLocation;
Vector2 mOffset;
PathOffsetType mOffsetType{PathOffsetType::RELATIVE_TO};
std::vector<PathElementPtr> mElements;
};
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
@ -43,21 +55,12 @@ public:
void addFeature(GeometryPathFeaturePtr feature);
void buildFromPostscript(const std::string& psString);
std::string getAsPostScript() const;
const Point& getLocation() const override;
Bounds getBounds() const override;
Type getType() const override;
const std::vector<GeometryPathFeaturePtr>& getFeatures() const;
void sample(SparseGrid<bool>*) const override;
private:
Point mLocation;
std::vector<GeometryPathFeaturePtr> mFeatures;
};

View file

@ -1,6 +1,10 @@
#include "PathElement.h"
PathElement::~PathElement()
template<std::size_t DIM>
PathElement<DIM>::~PathElement()
{
}
}
template class PathElement<2>;
template class PathElement<3>;

View file

@ -1,31 +1,39 @@
#pragma once
#include "AbstractGeometricItem.h"
#include "Vector.h"
#include <string>
enum class PathOffsetType
{
RELATIVE_TO,
ABSOLUTE_TO
};
template<std::size_t DIM>
class PathElement : public AbstractGeometricItem
{
public:
enum class PostscriptPositioning
{
RELATIVE_TO,
ABSOLUTE_TO
};
~PathElement();
virtual Point getFirstPoint() const = 0;
virtual Vector<double, DIM> getEndOffset() const = 0;
virtual Point getEndPoint() const = 0;
void setPostscriptPositioning(PostscriptPositioning positioning)
PathOffsetType getPathOffsetType() const
{
mPostscriptPositioning = positioning;
return mOffsetType;
}
virtual std::string toPostScriptString(std::size_t precision = 0) const = 0;
bool isRelativeOffset() const
{
return mOffsetType == PathOffsetType::RELATIVE_TO;
}
protected:
PostscriptPositioning mPostscriptPositioning{ PostscriptPositioning::RELATIVE_TO};
void setPathOffsetType(PathOffsetType offsetType)
{
mOffsetType = offsetType;
}
private:
PathOffsetType mOffsetType;
};
using PathElement2 = PathElement<2>;

View file

@ -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;
}

View file

@ -1,67 +0,0 @@
#pragma once
#include "PathElement.h"
#include "Point.h"
#include <memory>
#include <vector>
#include <string>
class GeometryPath;
using PathElementPtr = std::unique_ptr<PathElement>;
class GeometryPathFeature;
using GeometryPathFeaturePtr = std::unique_ptr<GeometryPathFeature>;
class PathPostScriptConverter
{
public:
void fromPostScript(GeometryPath* targetPath, const std::string& postScriptPath);
std::string toPostScript(const GeometryPath* targetPath);
private:
enum class LineState
{
START,
IN_FIRST_POINT,
IN_HORIZONTAL,
IN_VERTICAL,
IN_LINE,
IN_CUBIC_BEZIER,
IN_QUADRATIC_BEZIER,
IN_ARC,
IN_UNSUPPORTED
};
enum class PositionState
{
ABSOLUTE,
RELATIVE
};
PositionState getPositionState(char c) const;
void onNewElement(char c);
void onNonNumeric();
void onElementEnd();
void onMoveTo();
PathElementPtr onHorizontalLineTo();
PathElementPtr onVerticalLineTo();
PathElementPtr onLineTo();
PathElementPtr onArc();
PathElementPtr onQuadraticBezier();
PathElementPtr onCubicBezier();
LineState mLineState{ LineState::START };
PositionState mPositionState{ PositionState::ABSOLUTE };
std::string mBuffer;
std::vector<double> mPointBuffer;
GeometryPathFeaturePtr mWorkingFeature;
Point mCurrentPoint;
std::size_t mPrecision{ 3 };
};

View file

@ -1,63 +1,36 @@
#include "QuadraticBezierCurve.h"
#include "PointParser.h"
QuadraticBezierCurve::QuadraticBezierCurve(const Point& startPoint, const Point& endPoint, const Point& controlPoint)
: mStartPoint(startPoint),
mEndPoint(endPoint),
mControlPoint(controlPoint)
template<std::size_t DIM>
QuadraticBezierCurve<DIM>::QuadraticBezierCurve(const Vector<double, DIM>& endOffset, const Vector<double, DIM>& controlOffset)
: mEndOffset(endOffset),
mControlOffset(controlOffset)
{
}
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
{
return mControlPoint;
}
std::string QuadraticBezierCurve::toPostScriptString(std::size_t precision) const
{
if (mPostscriptPositioning == PostscriptPositioning::RELATIVE_TO)
{
return "q" + PointParser::toStringRelative(mControlPoint, mStartPoint, 2, " ", precision) + " " + PointParser::toStringRelative(mEndPoint, mStartPoint, 2, " ", precision);
}
else
{
return "Q" + PointParser::toString(mControlPoint, 2, " ", precision) + " " + PointParser::toString(mEndPoint, 2, " ", precision);
}
}
Bounds QuadraticBezierCurve::getBounds() const
template<std::size_t DIM>
Bounds QuadraticBezierCurve<DIM>::getBounds() const
{
return {};
}
const Point& QuadraticBezierCurve::getLocation() const
{
return mStartPoint;
}
void QuadraticBezierCurve::sample(SparseGrid<bool>*) const
{
}
QuadraticBezierCurve::Type QuadraticBezierCurve::getType() const
{
return Type::CURVE;
}
QuadraticBezierCurve::CurveType QuadraticBezierCurve::getCurveType() const
template<std::size_t DIM>
CurveType QuadraticBezierCurve<DIM>::getCurveType() const
{
return CurveType::QUADRATIC_BEZIER;
}
template class QuadraticBezierCurve<2>;
template class QuadraticBezierCurve<3>;

View file

@ -3,31 +3,21 @@
#include "Curve.h"
#include "Point.h"
class QuadraticBezierCurve : public Curve
template<std::size_t DIM>
class QuadraticBezierCurve : public Curve<DIM>
{
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;
Point getEndPoint() const override;
Vector<double, DIM> getEndOffset() const override;
Bounds getBounds() const override;
const Point& getLocation() const override;
Type getType() const override;
CurveType getCurveType() const override;
void sample(SparseGrid<bool>*) const override;
std::string toPostScriptString(std::size_t precision = 0) const override;
private:
Point mStartPoint;
Point mEndPoint;
Point mControlPoint;
Vector<double, DIM> mEndOffset;
Vector<double, DIM> mControlOffset;
};

View file

@ -2,51 +2,116 @@
#include "Transform.h"
#include <algorithm>
#include <cmath>
#include <numeric>
Point::Point(double x, double y, double z)
: mX(x),
mY(y),
mZ(z)
{
}
Point::Point(const DiscretePoint& point)
: mX(static_cast<double>(point.getX())),
mY(static_cast<double>(point.getY())),
mZ(0)
template<std::size_t DIM>
Point<DIM>::Point(const Point<2>& p)
: Point(p.getX(), p.getY())
{
}
Point::Point(const Point& reference, double offSetX, double offSetY, double offSetZ)
: mX(reference.getX() + offSetX),
mY(reference.getY() + offSetY),
mZ(reference.getZ() + offSetZ)
template<std::size_t DIM>
Point<DIM>::Point(double x, double y, double z)
{
mCoords = std::vector<double>(DIM);
if (DIM > 0)
{
mCoords[0] = x;
}
if (DIM > 1)
{
mCoords[1] = y;
}
if (DIM > 2)
{
mCoords[2] = z;
}
}
Point::~Point()
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)
{
}
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 deltaY = getDeltaY(point);
@ -54,50 +119,97 @@ double Point::getDistance(const Point& point) const
return std::sqrt(deltaX* deltaX + deltaY* deltaY + deltaZ* deltaZ);
}
Vector Point::getDelta(const Point& point) const
template<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();
mY -= transform.getLocation().getY();
mZ -= transform.getLocation().getZ();
mX *= transform.getScale().mX;
mY *= transform.getScale().mY;
mZ *= transform.getScale().mZ;
return Vector<double, DIM>(mCoords);
}
void Point::move(double x, double y, double z)
template<std::size_t DIM>
void Point<DIM>::apply(const Transform& transform)
{
mX += x;
mY += y;
mZ += z;
moveBy(-transform.getLocation().getX(), -transform.getLocation().getY(), -transform.getLocation().getZ());
scale(transform.getScale().mX, transform.getScale().mY, transform.getScale().mZ);
}
void Point::move(const Vector& vector)
template<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>;

View file

@ -7,14 +7,19 @@
class Transform;
template<std::size_t DIM = 3>
class Point
{
public:
Point(double x = 0, double y = 0, double z = 0);
Point(double x = 0, double y = 0, double z = 0.0);
Point(const Vector<double, DIM>& v);
Point(const Point<2>& p);
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();
@ -26,43 +31,56 @@ public:
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;
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)
&& (mY == rhs.mY)
&& (mZ == rhs.mZ);
moveBy(vector);
}
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);
}
private:
double mX{0};
double mY{0};
double mZ{0};
std::vector<double> mCoords;
};
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> >;

View file

@ -1,12 +1,14 @@
#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)
{
}
void PointCollection::apply(const Transform& transform)
template<std::size_t DIM>
void PointCollection<DIM>::apply(const Transform& transform)
{
for (auto& point : mPoints)
{
@ -14,12 +16,14 @@ void PointCollection::apply(const Transform& transform)
}
}
void PointCollection::addPoint(const Point& point)
template<std::size_t DIM>
void PointCollection<DIM>::addPoint(const Point<DIM>& 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};
@ -36,7 +40,8 @@ Bounds PointCollection::getBounds() const
return bounds;
}
Point PointCollection::getEndPoint() const
template<std::size_t DIM>
Point<DIM> PointCollection<DIM>::getEndPoint() const
{
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;
}
}
template class PointCollection<2>;
template class PointCollection<3>;

View file

@ -6,21 +6,22 @@
#include <vector>
template<std::size_t DIM>
class PointCollection
{
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);
Bounds getBounds() const;
Point getEndPoint() const;
Point<DIM> getEndPoint() const;
const std::vector<Point>& getPoints() const;
const std::vector<Point<DIM> >& getPoints() const;
private:
std::vector<Point> mPoints;
std::vector<Point<DIM> > mPoints;
};

View file

@ -2,49 +2,27 @@
#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 (dimensions == 1)
{
return std::to_string(x);
}
else if (dimensions == 2)
{
return std::to_string(x) + delimiter + std::to_string(y);
}
else
{
return std::to_string(x) + delimiter + std::to_string(y) + delimiter + std::to_string(z);
}
return std::to_string(x) + delimiter + std::to_string(y);
}
else
{
std::stringstream sstr;
sstr.precision(precision);
if (dimensions == 1)
{
sstr << x;
}
else if (dimensions == 2)
{
sstr << x << delimiter << y;
}
else
{
sstr << x << delimiter << y << delimiter << z;
}
sstr << x << delimiter << y;
return sstr.str();
}
}

View file

@ -7,12 +7,11 @@
class PointParser
{
public:
static std::string toString(const Point2& p, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toString(const Point& p, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toString(const Vector2& v, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toStringRelative(const Point& p, const Point& relativeTo, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toString(double x, double y, double z, std::size_t dimensions = 3, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toString(double x, double y, const std::string& delimiter = " ", std::size_t precision = 0);
static std::string toString(double x, std::size_t precision = 0);
};

View file

@ -1,18 +1,11 @@
#include "Circle.h"
Circle::Circle(const Point& centre, double radius)
: mRadius(radius),
mCentre(centre)
Circle::Circle(double radius)
: mRadius(radius)
{
mMinorRadius = mRadius;
}
const Point& Circle::getLocation() const
{
return mCentre;
}
double Circle::getRadius() const
{
return mRadius;
@ -28,11 +21,6 @@ void Circle::setMinorRadius(double radius)
mMinorRadius = radius;
}
void Circle::sample(SparseGrid<bool>*) const
{
}
bool Circle::isEllipse() const
{
return mRadius != mMinorRadius;
@ -40,10 +28,10 @@ bool Circle::isEllipse() const
Bounds Circle::getBounds() const
{
double minX = mCentre.getX() - mRadius;
double maxX = mCentre.getX() + mRadius;
double minY = mCentre.getY() - mMinorRadius;
double maxY = mCentre.getY() + mMinorRadius;
double minX = -mRadius;
double maxX = mRadius;
double minY = -mMinorRadius;
double maxY = mMinorRadius;
return { minX, maxX, minY, maxY };
}

View file

@ -1,14 +1,11 @@
#pragma once
#include "AbstractGeometricItem.h"
#include "Point.h"
class Circle : public AbstractGeometricItem
{
public:
Circle(const Point& centre, double radius = 0.5);
const Point& getLocation() const override;
Circle(double radius = 0.5);
double getRadius() const;
@ -22,10 +19,7 @@ public:
void setMinorRadius(double radius);
void sample(SparseGrid<bool>*) const override;
private:
double mMinorRadius{ 0.5 };
double mRadius{ 0.5 };
Point mCentre;
};

View file

@ -1,38 +1,31 @@
#include "Polygon.h"
namespace ntk {
Polygon::Polygon(const std::vector<Point>& points)
template<std::size_t DIM>
Polygon<DIM>::Polygon(const std::vector<Point<DIM> >& points)
: AbstractGeometricItem()
{
if (points.size() > 0)
{
mStartPoint = points[0];
}
mPoints = PointCollection(points);
mPoints = PointCollection<DIM>(points);
}
const PointCollection& Polygon::getPoints() const
template<std::size_t DIM>
const PointCollection<DIM>& Polygon<DIM>::getPoints() const
{
return mPoints;
}
Bounds Polygon::getBounds() const
template<std::size_t DIM>
Bounds Polygon<DIM>::getBounds() const
{
return mPoints.getBounds();
}
const Point& Polygon::getLocation() const
{
return mStartPoint;
}
void Polygon::sample(SparseGrid<bool>*) const
{
}
Polygon::Type Polygon::getType() const
template<std::size_t DIM>
AbstractGeometricItem::Type Polygon<DIM>::getType() const
{
return Polygon::Type::POLYGON;
}
template class Polygon<2>;
template class Polygon<3>;
}

View file

@ -5,23 +5,21 @@
#include "PointCollection.h"
namespace ntk{
template<std::size_t DIM>
class Polygon : public AbstractGeometricItem
{
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;
const Point& getLocation() const override;
void sample(SparseGrid<bool>*) const override;
Type getType() const override;
AbstractGeometricItem::Type getType() const override;
private:
Point mStartPoint;
PointCollection mPoints;
PointCollection<DIM> mPoints;
};
}
}
using Polygon2 = ntk::Polygon<2>;

View file

@ -1,18 +1,9 @@
#include "Rectangle.h"
namespace ntk {
Rectangle::Rectangle(const Point& bottomLeft, const Point& topRight)
: mBottomLeft(bottomLeft)
{
mHeight = mBottomLeft.getDeltaY(topRight);
mWidth = mBottomLeft.getDeltaX(topRight);
}
Rectangle::Rectangle(const Point& bottomLeft, double width, double height)
: mBottomLeft(bottomLeft),
mWidth(width),
mHeight(height)
Rectangle::Rectangle(double width, double height)
: mWidth(width),
mHeight(height)
{
}
@ -24,19 +15,14 @@ namespace ntk {
Bounds Rectangle::getBounds() const
{
const auto minX = mBottomLeft.getX();
const auto maxX = mBottomLeft.getX() + mWidth;
const auto minX = 0.0;
const auto maxX = mWidth;
const auto minY = mBottomLeft.getY();
const auto maxY = mBottomLeft.getY() + mHeight;
const auto minY = 0.0;
const auto maxY = mHeight;
return { minX , maxX , minY , maxY };
}
void Rectangle::sample(SparseGrid<bool>*) const
{
}
double Rectangle::getHeight() const
{
return mHeight;
@ -47,11 +33,6 @@ namespace ntk {
return mWidth;
}
const Point& Rectangle::getLocation() const
{
return mBottomLeft;
}
double Rectangle::getRadius() const
{
return mRadius;

View file

@ -6,15 +6,12 @@ namespace ntk{
class Rectangle : public AbstractGeometricItem
{
public:
Rectangle(const Point& bottomLeft, const Point& topRight);
Rectangle(const Point& bottomLeft, double width, double height);
Rectangle(double width, double height);
double getHeight() const;
double getWidth() const;
const Point& getLocation() const override;
Bounds getBounds() const override;
Type getType() const override;
@ -23,10 +20,7 @@ public:
void setRadius(double radius);
void sample(SparseGrid<bool>*) const override;
private:
Point mBottomLeft;
double mWidth{0};
double mHeight{0};
double mRadius{ 0.0 };