2016-05-17 03:04:11 +12:00
|
|
|
#pragma once
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
#ifndef TELLIPTIC_BRUSH_P_H
|
|
|
|
#define TELLIPTIC_BRUSH_P_H
|
|
|
|
|
|
|
|
#include "tcurves.h"
|
|
|
|
#include "tstroke.h"
|
2016-06-15 18:43:10 +12:00
|
|
|
#include "tgl.h" //tglPixelSize
|
2016-03-19 06:57:51 +13:00
|
|
|
#include "tstrokeoutline.h"
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
namespace tellipticbrush {
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
//! Tolerance parameter used somewhere throughout this code.
|
2016-03-19 06:57:51 +13:00
|
|
|
const double tolPar = 1e-6;
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Geometric Helper Functions
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
double dist(const TPointD &P1, const TPointD &P2);
|
|
|
|
double dist(const TThickPoint &P1, const TThickPoint &P2);
|
|
|
|
double angle(const TPointD &v1, const TPointD &v2);
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TPointD intersectionCoords(const TPointD &P0, const TPointD &d0,
|
|
|
|
const TPointD &P1, const TPointD &d1,
|
|
|
|
double detTol = 1e-2);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void buildEnvelopeDirection(const TThickPoint &p, const TThickPoint &d,
|
|
|
|
bool left, TPointD &res);
|
|
|
|
void buildEnvelopeDirections(const TThickPoint &p, const TThickPoint &d,
|
|
|
|
TPointD &resL, TPointD &resR);
|
|
|
|
void buildEnvelopeVector(const TThickPoint &p, const TThickPoint &d, bool left,
|
|
|
|
TPointD &res);
|
|
|
|
void buildEnvelopeVectors(const TThickPoint &p, const TThickPoint &d,
|
|
|
|
TPointD &resL, TPointD &resR);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void buildAngularSubdivision(double radius, double angle, double err,
|
|
|
|
int &nAngles);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
TRectD computeBBox(const TStroke &stroke);
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Options structure
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
/*
|
|
|
|
Structure needed to hold both external and internal outlinization parameters.
|
|
|
|
*/
|
|
|
|
struct OutlinizationData {
|
2016-06-15 18:43:10 +12:00
|
|
|
TOutlineUtil::OutlineParameter m_options;
|
|
|
|
double m_pixSize;
|
|
|
|
|
|
|
|
OutlinizationData() : m_options(), m_pixSize(0.0) {}
|
|
|
|
OutlinizationData(const TOutlineUtil::OutlineParameter &options)
|
|
|
|
: m_options(options), m_pixSize(sqrt(tglGetPixelSize2())) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Centerline Point struct
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
/*!
|
2016-06-15 18:43:10 +12:00
|
|
|
CenterlinePoint contains the data a about a discretized centerline stroke
|
|
|
|
point -
|
2016-03-19 06:57:51 +13:00
|
|
|
which includes its position, and eventual forward and backward derivative-like
|
|
|
|
directions. Thickness data is included in the structure.
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
These informations are necessary and sufficient to build associated outline
|
|
|
|
points,
|
2016-03-19 06:57:51 +13:00
|
|
|
and eventual additional points related to caps.
|
|
|
|
*/
|
|
|
|
struct CenterlinePoint {
|
2016-06-15 18:43:10 +12:00
|
|
|
int m_chunkIdx; //!< The quadratic chunk index containing this point
|
|
|
|
double m_t; //!< The quadratic parameter where this point can be found
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThickPoint m_p; //!< The point's thick coordinates
|
|
|
|
bool m_posBuilt; //!< Wheteher m_p has been calculated
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThickPoint m_prevD; //!< The backward direction
|
|
|
|
bool m_hasPrevD; //!< If the point has (envelopable) backward direction
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TThickPoint m_nextD; //!< The forward direction
|
|
|
|
bool m_hasNextD; //!< If the point has (envelopable) forward direction
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool m_dirsBuilt; //!< Whether directions have been calculated
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool m_covered; //!< Whether this point's outline can't be seen
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int m_countIdx; //!< Additional index needed by some procedural style...
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
CenterlinePoint() : m_chunkIdx(-1), m_posBuilt(false), m_dirsBuilt(false) {}
|
|
|
|
CenterlinePoint(int chunk, double t)
|
|
|
|
: m_chunkIdx(chunk)
|
|
|
|
, m_t(t)
|
|
|
|
, m_posBuilt(false)
|
|
|
|
, m_dirsBuilt(false)
|
|
|
|
, m_countIdx(0) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
~CenterlinePoint() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void buildPos(const TStroke &stroke);
|
|
|
|
void buildDirs(const TStroke &stroke);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool operator<(const CenterlinePoint &cp) const {
|
|
|
|
return m_chunkIdx < cp.m_chunkIdx
|
|
|
|
? true
|
|
|
|
: m_chunkIdx > cp.m_chunkIdx ? false : m_t < cp.m_t;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Linearizator Classes
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
/*!
|
|
|
|
The StrokeLinearizator class models a stroke linearization interface that
|
|
|
|
extracts points of interest from a succession of stroke quadratics.
|
|
|
|
*/
|
2016-06-15 18:43:10 +12:00
|
|
|
class StrokeLinearizator {
|
2016-03-19 06:57:51 +13:00
|
|
|
protected:
|
2016-06-15 18:43:10 +12:00
|
|
|
const TStroke *m_stroke;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
StrokeLinearizator(const TStroke *stroke) : m_stroke(stroke) {}
|
|
|
|
virtual ~StrokeLinearizator() {}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Adds interesting stroke points to be discretized in the
|
|
|
|
chunk-th TThickQuadratic stroke.
|
|
|
|
|
|
|
|
\note The initial point (P0) of the quadratic is always added by the
|
|
|
|
outlinization algorithm before these linearization functions are invoked
|
|
|
|
(whereas P2 belongs to the next quadratic).
|
|
|
|
*/
|
|
|
|
virtual void linearize(std::vector<CenterlinePoint> &cPoints, int chunk) = 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Outline Builder classes
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
/*!
|
|
|
|
The OutlineBuilder class is the object used to translate centerline points
|
|
|
|
into outline points. The purpose of this class is to take a CenterlinePoint
|
|
|
|
instance and build a couple of outline points - at either side of the
|
|
|
|
centerline - eventually adding (cap) points to form a smooth outline.
|
|
|
|
*/
|
2016-06-15 18:43:10 +12:00
|
|
|
class OutlineBuilder {
|
|
|
|
double m_pixSize;
|
|
|
|
TStroke::OutlineOptions m_oOptions;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int m_lastChunk;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
private:
|
2016-06-15 18:43:10 +12:00
|
|
|
typedef void (OutlineBuilder::*OutlineBuilderFunc)(
|
|
|
|
std::vector<TOutlinePoint> &outPoints, const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
OutlineBuilderFunc m_addBeginCap;
|
|
|
|
OutlineBuilderFunc m_addEndCap;
|
|
|
|
OutlineBuilderFunc m_addSideCaps;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
typedef void (OutlineBuilder::*BBoxBuilderFunc)(
|
|
|
|
TRectD &bbox, const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
BBoxBuilderFunc m_addBeginCap_ext;
|
|
|
|
BBoxBuilderFunc m_addEndCap_ext;
|
|
|
|
BBoxBuilderFunc m_addSideCaps_ext;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
private:
|
2016-06-15 18:43:10 +12:00
|
|
|
/*
|
|
|
|
Type-specific outline container functions.
|
|
|
|
Used with outline building sub-routines that may be used to supply
|
|
|
|
different outline container types.
|
|
|
|
For example, a TRectD may be considered a container class to be used
|
|
|
|
when building the outline bbox.
|
|
|
|
*/
|
|
|
|
template <typename T>
|
|
|
|
void addEnvelopePoint(T &container, const TPointD &oPoint, int countIdx = 0);
|
|
|
|
template <typename T>
|
|
|
|
void addExtensionPoint(T &container, const TPointD &oPoint, int countIdx = 0);
|
|
|
|
template <typename T>
|
|
|
|
void addOutlineBuilderFunc(OutlineBuilder::OutlineBuilderFunc func,
|
|
|
|
T &container, const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
public:
|
2016-06-15 18:43:10 +12:00
|
|
|
OutlineBuilder(const OutlinizationData &data, const TStroke &stroke);
|
|
|
|
~OutlineBuilder() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
/*!
|
|
|
|
Transforms the specified centerline point into outline points, and adds them to
|
|
|
|
the supplied outline points vector.
|
|
|
|
*/
|
|
|
|
void buildOutlinePoints(std::vector<TOutlinePoint> &outPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void buildOutlineExtensions(TRectD &bbox, const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
private:
|
2016-06-15 18:43:10 +12:00
|
|
|
void addCircle(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
void addCircularArcPoints(int idx, std::vector<TOutlinePoint> &outPoints,
|
|
|
|
const TPointD ¢er, const TPointD &ray,
|
|
|
|
double angle, int nAngles, int countIdx);
|
|
|
|
|
|
|
|
void addRoundBeginCap(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
void addRoundEndCap(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
|
|
|
|
void addButtBeginCap(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
void addButtEndCap(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void addProjectingBeginCap(T &oPoints, const CenterlinePoint &cPoint);
|
|
|
|
template <typename T>
|
|
|
|
void addProjectingEndCap(T &oPoints, const CenterlinePoint &cPoint);
|
|
|
|
|
|
|
|
void addRoundSideCaps(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
void addBevelSideCaps(std::vector<TOutlinePoint> &oPoints,
|
|
|
|
const CenterlinePoint &cPoint);
|
|
|
|
template <typename T>
|
|
|
|
void addMiterSideCaps(T &oPoints, const CenterlinePoint &cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
};
|
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Explicit specializations of OutlineBuilder's methods
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
// Container of Outline Points (for common outline extraction)
|
|
|
|
|
|
|
|
template <>
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void OutlineBuilder::addEnvelopePoint(
|
|
|
|
std::vector<TOutlinePoint> &oPoints, const TPointD &oPoint, int countIdx) {
|
|
|
|
oPoints.push_back(TOutlinePoint(oPoint, countIdx));
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void OutlineBuilder::addExtensionPoint(
|
|
|
|
std::vector<TOutlinePoint> &oPoints, const TPointD &oPoint, int countIdx) {
|
|
|
|
oPoints.push_back(TOutlinePoint(oPoint, countIdx));
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline void OutlineBuilder::addOutlineBuilderFunc(
|
2016-06-15 18:43:10 +12:00
|
|
|
OutlineBuilder::OutlineBuilderFunc func,
|
|
|
|
std::vector<TOutlinePoint> &oPoints, const CenterlinePoint &cPoint) {
|
|
|
|
(this->*func)(oPoints, cPoint);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================================
|
|
|
|
|
|
|
|
// Rect (for bounding box extraction)
|
|
|
|
|
|
|
|
template <>
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void OutlineBuilder::addEnvelopePoint(TRectD &bbox,
|
|
|
|
const TPointD &oPoint,
|
|
|
|
int countIdx) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
template <>
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void OutlineBuilder::addExtensionPoint(TRectD &bbox,
|
|
|
|
const TPointD &oPoint,
|
|
|
|
int countIdx) {
|
|
|
|
bbox.x0 = std::min(bbox.x0, oPoint.x);
|
|
|
|
bbox.y0 = std::min(bbox.y0, oPoint.y);
|
|
|
|
bbox.x1 = std::max(bbox.x1, oPoint.x);
|
|
|
|
bbox.y1 = std::max(bbox.y1, oPoint.y);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline void OutlineBuilder::addOutlineBuilderFunc(
|
2016-06-15 18:43:10 +12:00
|
|
|
OutlineBuilder::OutlineBuilderFunc func, TRectD &container,
|
|
|
|
const CenterlinePoint &cPoint) {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//********************************************************************************
|
|
|
|
// Standard Outline Builder (from Centerline Points)
|
|
|
|
//********************************************************************************
|
|
|
|
|
|
|
|
void buildOutline(const TStroke &stroke, std::vector<CenterlinePoint> &cPoints,
|
2016-06-15 18:43:10 +12:00
|
|
|
TStrokeOutline &outline, const OutlinizationData &data);
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
} // namespace tellipticbrush
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
#endif // TELLIPTIC_BRUSH_P_H
|