|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Toonz includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tgeometry.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcolorutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "ttoonzimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop_borders.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstrokeutil.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//template includes
|
|
Toshihiro Shimizu |
890ddd |
#define INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg_wrap.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_vertex.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_edge.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_face.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_mesh.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_hash.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_polylineops.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_sequence_ops.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_cyclic.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Toonz includes
|
|
Toshihiro Shimizu |
890ddd |
#include "../common/trop/raster_edge_evaluator.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#undef INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//STL includes
|
|
Toshihiro Shimizu |
890ddd |
#include <set></set>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcenterlinevectorizer.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
// Colors stuff
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
Pix transparent();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <>
|
|
Toshihiro Shimizu |
890ddd |
inline TPixel32 transparent<tpixel32>() { return TPixel32::Transparent; }</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
template <>
|
|
Toshihiro Shimizu |
890ddd |
inline TPixelGR16 transparent<tpixelgr16>() { return TPixelGR16::Black; }</tpixelgr16>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
// Mesh stuff
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class Edge : public tcg::Edge
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPoint m_dirs[2];
|
|
Toshihiro Shimizu |
890ddd |
TStroke *m_s;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
Edge() : tcg::Edge(), m_s(0) {}
|
|
Toshihiro Shimizu |
890ddd |
Edge(int v1, const TPoint &dir1, int v2, const TPoint &dir2)
|
|
Toshihiro Shimizu |
890ddd |
: tcg::Edge(v1, v2), m_s(0) { m_dirs[0] = dir1, m_dirs[1] = dir2; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TPoint &direction(int i) const { return m_dirs[i]; }
|
|
Toshihiro Shimizu |
890ddd |
TPoint &direction(int i) { return m_dirs[i]; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TStroke *stroke() const { return m_s; }
|
|
Toshihiro Shimizu |
890ddd |
void setStroke(TStroke *s) { m_s = s; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef tcg::Mesh<tcg::vertex<tpoint>, Edge, tcg::Face> LocalMesh;</tcg::vertex<tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int hashPoint(const TPoint &point)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return point.x ^ point.y;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef int (*PointHashType)(const TPoint &);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
size_t hashStroke(const TStroke *stroke)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (size_t)stroke;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef size_t (*StrokeHashType)(const TStroke *);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
// Vertex Adjustment
|
|
Toshihiro Shimizu |
890ddd |
//===========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct Sums {
|
|
Toshihiro Shimizu |
890ddd |
double m_sums_x, m_sums_y;
|
|
Toshihiro Shimizu |
890ddd |
double m_sums2_x, m_sums2_y;
|
|
Toshihiro Shimizu |
890ddd |
double m_sums_xy;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct SumsBuilder {
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &m_sums_x, &m_sums_y, &m_sums2_x, &m_sums2_y, &m_sums_xy;</double>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SumsBuilder(const std::vector<double> &sums_x, const std::vector<double> &sums_y,</double></double>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &sums2_x, const std::vector<double> &sums2_y,</double></double>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &sums_xy)</double>
|
|
Toshihiro Shimizu |
890ddd |
: m_sums_x(sums_x), m_sums_y(sums_y), m_sums2_x(sums2_x), m_sums2_y(sums2_y), m_sums_xy(sums_xy)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void build(Sums &sums, int idx0, int idx1) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
sums.m_sums_x = m_sums_x[idx1] - m_sums_x[idx0];
|
|
Toshihiro Shimizu |
890ddd |
sums.m_sums_y = m_sums_y[idx1] - m_sums_y[idx0];
|
|
Toshihiro Shimizu |
890ddd |
sums.m_sums2_x = m_sums2_x[idx1] - m_sums2_x[idx0];
|
|
Toshihiro Shimizu |
890ddd |
sums.m_sums2_y = m_sums2_y[idx1] - m_sums2_y[idx0];
|
|
Toshihiro Shimizu |
890ddd |
sums.m_sums_xy = m_sums_xy[idx1] - m_sums_xy[idx0];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename p1_type,="" p2_type="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void adjustVertex(const TPointD &origin, TPointD &point,
|
|
Toshihiro Shimizu |
890ddd |
P1_type p0, Sums &sums0, int n0, P2_type p1, Sums &sums1, int n1)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Find the 2 best-fit lines
|
|
Toshihiro Shimizu |
890ddd |
TPointD v0, v1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::point_ops::bestFit(p0, v0,
|
|
Toshihiro Shimizu |
890ddd |
sums0.m_sums_x, sums0.m_sums_y, sums0.m_sums2_x, sums0.m_sums2_y, sums0.m_sums_xy, n0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::point_ops::bestFit(p1, v1,
|
|
Toshihiro Shimizu |
890ddd |
sums1.m_sums_x, sums1.m_sums_y, sums1.m_sums2_x, sums1.m_sums2_y, sums1.m_sums_xy, n1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Get the intersecting point
|
|
Toshihiro Shimizu |
890ddd |
double s, t;
|
|
Toshihiro Shimizu |
890ddd |
tcg::point_ops::intersectionCoords(p0, v0, p1, v1, s, t, 1e-3);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (s == tcg::numeric_ops::NaN<double>())</double>
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Adjust vertex - inside a 0.5 radius disc
|
|
Toshihiro Shimizu |
890ddd |
TPointD newPoint(origin + p0 + s * v0), diff(newPoint - point);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double distance = norm(diff);
|
|
Toshihiro Shimizu |
890ddd |
if (distance < 0.5)
|
|
Toshihiro Shimizu |
890ddd |
point = newPoint;
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
point += (0.5 / distance) * diff;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void adjustVertices(const TPointD &origin,
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpointd> &points, const std::vector<int> &indices,</int></tpointd>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &sums_x, const std::vector<double> &sums_y,</double></double>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &sums2_x, const std::vector<double> &sums2_y,</double></double>
|
|
Toshihiro Shimizu |
890ddd |
const std::vector<double> &sums_xy)</double>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i, last = points.size() - 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
SumsBuilder sumsBuilder(sums_x, sums_y, sums2_x, sums2_y, sums_xy);
|
|
Toshihiro Shimizu |
890ddd |
Sums sums0, sums1;
|
|
Toshihiro Shimizu |
890ddd |
int prev0, prev1, next0, next1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD a0, a1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (points.front() == points.back()) {
|
|
Toshihiro Shimizu |
890ddd |
prev0 = indices[last - 1] - 1, prev1 = indices[last], next0 = indices[0] - 1, next1 = indices[1];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums0, prev0, prev1);
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums1, next0, next1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
adjustVertex<tpointd &="" &,="" tpointd="">(</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
origin, points[0],
|
|
Toshihiro Shimizu |
890ddd |
a0, sums0, prev1 - prev0,
|
|
Toshihiro Shimizu |
890ddd |
a1, sums1, next1 - next0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
points[last] = points[0];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (i = 1; i < last; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
prev0 = indices[i - 1] - 1, prev1 = indices[i], next0 = indices[i] - 1, next1 = indices[i + 1];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums0, prev0, prev1);
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums1, next0, next1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
adjustVertex<tpointd &="" &,="" tpointd="">(</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
origin, points[i],
|
|
Toshihiro Shimizu |
890ddd |
a0, sums0, prev1 - prev0,
|
|
Toshihiro Shimizu |
890ddd |
a1, sums1, next1 - next0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
prev0 = indices[0], prev1 = indices[1], next0 = indices[1] - 1, next1 = indices[2];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums0, prev0, prev1);
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums1, next0, next1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
a0 = points[0];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
adjustVertex<const &="" &,="" tpointd="">(</const>
|
|
Toshihiro Shimizu |
890ddd |
origin, points[1],
|
|
Toshihiro Shimizu |
890ddd |
a0, sums0, prev1 - prev0 + 1,
|
|
Toshihiro Shimizu |
890ddd |
a1, sums1, next1 - next0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int end = last - 1;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 2; i < end; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
prev0 = indices[i - 1] - 1, prev1 = indices[i], next0 = indices[i] - 1, next1 = indices[i + 1];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums0, prev0, prev1);
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums1, next0, next1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
adjustVertex<tpointd &="" &,="" tpointd="">(</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
origin, points[i],
|
|
Toshihiro Shimizu |
890ddd |
a0, sums0, prev1 - prev0,
|
|
Toshihiro Shimizu |
890ddd |
a1, sums1, next1 - next0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
prev0 = indices[end - 1], prev1 = indices[end], next0 = indices[end] - 1, next1 = indices[last];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums0, prev0, prev1);
|
|
Toshihiro Shimizu |
890ddd |
sumsBuilder.build(sums1, next0, next1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
a1 = points[last];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
adjustVertex<const &="" &,="" tpointd="">(</const>
|
|
Toshihiro Shimizu |
890ddd |
origin, points[1],
|
|
Toshihiro Shimizu |
890ddd |
a1, sums1, next1 - next0,
|
|
Toshihiro Shimizu |
890ddd |
a0, sums0, prev1 - prev0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Borders Reader declaration
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename ranit=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class PolylineReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const NewOutlineConfiguration &m_conf;
|
|
Toshihiro Shimizu |
890ddd |
double m_adherenceTol, m_angleTol, m_relativeTol, m_mergeTol;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP m_vi;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpointd> m_points;</tpointd>
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> m_indices;</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const RasterEdgeEvaluator<ranit> *m_eval;</ranit>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
PolylineReader(TVectorImageP vi, const NewOutlineConfiguration &conf)
|
|
Toshihiro Shimizu |
890ddd |
: m_vi(vi), m_conf(conf), m_adherenceTol(2.0 * (1.0 - m_conf.m_adherenceTol)), m_angleTol(cos(TConsts::pi * m_conf.m_angleTol)), m_relativeTol(conf.m_relativeTol), m_mergeTol(m_conf.m_mergeTol) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void setEvaluator(const RasterEdgeEvaluator<ranit> *eval) { m_eval = eval; }</ranit>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const RanIt &it);
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const RanIt &it);
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const TPoint &p) { addElement(p); }
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const TPoint &p) { m_points.push_back(TPointD(p.x, p.y)); }
|
|
Toshihiro Shimizu |
890ddd |
void closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Borders Reader declaration
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class BordersReader : public TRop::borders::BordersReader
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
typedef Pix pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef TPoint point_type;
|
|
Toshihiro Shimizu |
890ddd |
typedef tcg::hash<tpoint, int,="" pointhashtype=""> points_hash;</tpoint,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef typename std::pair<pixel_type, pixel_type=""> stroke_colors_type;</pixel_type,>
|
|
Toshihiro Shimizu |
890ddd |
typedef typename tcg::hash<const *,="" stroke_colors_type,="" strokehashtype="" tstroke=""> stroke_colors_hash;</const>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef typename std::vector<tpoint>::iterator point_iterator;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
typedef typename tcg::cyclic_iterator<point_iterator> cyclic_point_iterator;</point_iterator>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Toshihiro Shimizu |
890ddd |
const TRasterPT<pixel_type> &m_ras;</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
int m_lx, m_ly, m_wrap;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LocalMesh *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
PolylineReader<point_iterator> m_polylineReader;</point_iterator>
|
|
Toshihiro Shimizu |
890ddd |
PolylineReader<cyclic_point_iterator> m_loopReader;</cyclic_point_iterator>
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP m_vi;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
points_hash m_vHash;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
pixel_type m_innerColor, m_outerColor;
|
|
Toshihiro Shimizu |
890ddd |
stroke_colors_hash m_scHash;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Current data
|
|
Toshihiro Shimizu |
890ddd |
TPoint m_pos;
|
|
Toshihiro Shimizu |
890ddd |
pixel_type *m_pix;
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpoint> m_points;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Last vertex data
|
|
Toshihiro Shimizu |
890ddd |
TPoint m_dir;
|
|
Toshihiro Shimizu |
890ddd |
int m_vIdx;
|
|
Toshihiro Shimizu |
890ddd |
int m_nDirections;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//First vertex data
|
|
Toshihiro Shimizu |
890ddd |
TPoint m_firstPos, m_firstDir, m_firstOppDir;
|
|
Toshihiro Shimizu |
890ddd |
int m_firstVIdx;
|
|
Toshihiro Shimizu |
890ddd |
int m_firstNDirections;
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tpoint> m_firstPoints;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
BordersReader(const TRasterPT<pixel_type> &ras, LocalMesh *mesh, TVectorImageP vi,</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
const NewOutlineConfiguration &conf)
|
|
Toshihiro Shimizu |
890ddd |
: m_mesh(mesh), m_polylineReader(vi, conf), m_loopReader(vi, conf), m_vi(vi), m_vHash(&hashPoint), m_scHash(&hashStroke), m_ras(ras), m_lx(ras->getLx()), m_ly(ras->getLy()), m_wrap(ras->getWrap()) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void openContainer(const TPoint &pos, const TPoint &dir,
|
|
Toshihiro Shimizu |
890ddd |
const pixel_type &innerColor, const pixel_type &outerColor);
|
|
Toshihiro Shimizu |
890ddd |
void addElement(const TPoint &pos, const TPoint &dir, const pixel_type &outerColor);
|
|
Toshihiro Shimizu |
890ddd |
void closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int surroundingEdges();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int touchVertex(const TPoint &pos);
|
|
Toshihiro Shimizu |
890ddd |
void touchEdge(int v0, const TPoint &d0, int nd0, int v1, const TPoint &d1, int nd1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const stroke_colors_hash &scHash() const { return m_scHash; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// BordersReader implementation
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
int ::BordersReader<pix>::surroundingEdges()</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
static const Pix transp(transparent<pix>());</pix>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Pix ll((m_pos.x > 0 && m_pos.y > 0) ? *(m_pix - m_wrap - 1) : transp);
|
|
Toshihiro Shimizu |
890ddd |
Pix lr((m_pos.x < m_lx && m_pos.y > 0) ? *(m_pix - m_wrap) : transp);
|
|
Toshihiro Shimizu |
890ddd |
Pix ul((m_pos.x > 0 && m_pos.y < m_ly) ? *(m_pix - 1) : transp);
|
|
Toshihiro Shimizu |
890ddd |
Pix ur((m_pos.x < m_lx && m_pos.y < m_ly) ? *(m_pix) : transp);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (ll == ur || lr == ul)
|
|
Toshihiro Shimizu |
890ddd |
return 2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nEquals = (int)(ll == lr) + (int)(lr == ur) + (int)(ur == ul) + (int)(ul == ll);
|
|
Toshihiro Shimizu |
890ddd |
return 4 - nEquals;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
int ::BordersReader<pix>::touchVertex(const TPoint &pos)</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
points_hash::iterator it = m_vHash.find(pos);
|
|
Toshihiro Shimizu |
890ddd |
if (it == m_vHash.end())
|
|
Toshihiro Shimizu |
890ddd |
//No vertex found, add it now.
|
|
Toshihiro Shimizu |
890ddd |
it = m_vHash.insert(m_pos, m_mesh->addVertex(LocalMesh::vertex_type(pos)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return it->m_val;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::BordersReader<pix>::touchEdge(int v0, const TPoint &d0, int nd0, int v1, const TPoint &d1, int nd1)</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
typedef tcg::vertex_traits<localmesh::vertex_type>::edges_const_iterator edge_const_it;</localmesh::vertex_type>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Ensure that an associated edge is present, in case it should
|
|
Toshihiro Shimizu |
890ddd |
const LocalMesh::vertex_type &vx0 = m_mesh->vertex(v0);
|
|
Toshihiro Shimizu |
890ddd |
const LocalMesh::vertex_type &vx1 = m_mesh->vertex(v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Peek each vertex edge, for the one with the right direction
|
|
Toshihiro Shimizu |
890ddd |
int e;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
edge_const_it it, end = vx1.edgesEnd();
|
|
Toshihiro Shimizu |
890ddd |
for (it = vx1.edgesBegin(); it != end; ++it) {
|
|
Toshihiro Shimizu |
890ddd |
Edge &ed = m_mesh->edge(*it);
|
|
Toshihiro Shimizu |
890ddd |
int side = (int)(ed.vertex(1) == v1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (ed.direction(side) == d1) {
|
|
Toshihiro Shimizu |
890ddd |
e = ed.getIndex();
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//If none was found, the edge must be added
|
|
Toshihiro Shimizu |
890ddd |
if (it == end) {
|
|
Toshihiro Shimizu |
890ddd |
e = m_mesh->addEdge(Edge(v0, d0, v1, d1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Also, insert it in the output vector image
|
|
Toshihiro Shimizu |
890ddd |
if (m_points.size() == 2) {
|
|
Toshihiro Shimizu |
890ddd |
m_polylineReader.openContainer(m_points[0]);
|
|
Toshihiro Shimizu |
890ddd |
m_polylineReader.addElement(m_points[1]);
|
|
Toshihiro Shimizu |
890ddd |
m_polylineReader.closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
if (m_points.front() == m_points.back()) {
|
|
Toshihiro Shimizu |
890ddd |
point_iterator b = m_points.begin(), e = m_points.end() - 1;
|
|
Toshihiro Shimizu |
890ddd |
cyclic_point_iterator beginC(b, b, e, 0), endC(b + 1, b, e, 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RasterEdgeEvaluator<cyclic_point_iterator> eval(</cyclic_point_iterator>
|
|
Toshihiro Shimizu |
890ddd |
beginC - 1, endC + 1, 1.0, (std::numeric_limits<double>::max)());</double>
|
|
Toshihiro Shimizu |
890ddd |
m_loopReader.setEvaluator(&eval);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::sequence_ops::minimalPath(beginC, endC, eval, m_loopReader);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
RasterEdgeEvaluator<point_iterator> eval(</point_iterator>
|
|
Toshihiro Shimizu |
890ddd |
m_points.begin(), m_points.end(), 1.0, (std::numeric_limits<double>::max)());</double>
|
|
Toshihiro Shimizu |
890ddd |
m_polylineReader.setEvaluator(&eval);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::sequence_ops::minimalPath(m_points.begin(), m_points.end(), eval, m_polylineReader);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Edge &ed = m_mesh->edge(e);
|
|
Toshihiro Shimizu |
890ddd |
ed.setStroke(m_vi->getStroke(m_vi->getStrokeCount() - 1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Also, associate the extracted colors to the built stroke.
|
|
Toshihiro Shimizu |
890ddd |
stroke_colors_type &colors = m_scHash[ed.stroke()];
|
|
Toshihiro Shimizu |
890ddd |
colors.first = m_outerColor;
|
|
Toshihiro Shimizu |
890ddd |
colors.second = m_innerColor;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, if the number of each vertex's incident edges has been reached,
|
|
Toshihiro Shimizu |
890ddd |
//erase the corresponding hash entry.
|
|
Toshihiro Shimizu |
890ddd |
/*{
|
|
Toshihiro Shimizu |
890ddd |
if(nd0 == vx0.edgesCount())
|
|
Toshihiro Shimizu |
890ddd |
m_vHash.erase(vx0.P());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if(nd1 == vx1.edgesCount())
|
|
Toshihiro Shimizu |
890ddd |
m_vHash.erase(vx1.P());
|
|
Toshihiro Shimizu |
890ddd |
}*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::BordersReader<pix>::openContainer(const TPoint &pos, const TPoint &dir,</pix>
|
|
Toshihiro Shimizu |
890ddd |
const pixel_type &innerColor, const pixel_type &outerColor)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Store the associated color if not already present
|
|
Toshihiro Shimizu |
890ddd |
m_innerColor = innerColor;
|
|
Toshihiro Shimizu |
890ddd |
m_outerColor = outerColor;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build the initial pixel
|
|
Toshihiro Shimizu |
890ddd |
m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
m_pix = m_ras->pixels(0) + m_ras->getWrap() * m_pos.y + m_pos.x;
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_dir = dir;
|
|
Toshihiro Shimizu |
890ddd |
m_vIdx = -1;
|
|
Toshihiro Shimizu |
890ddd |
m_nDirections = surroundingEdges();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_firstPos = m_pos;
|
|
Toshihiro Shimizu |
890ddd |
m_firstDir = m_dir;
|
|
Toshihiro Shimizu |
890ddd |
m_firstVIdx = -1;
|
|
Toshihiro Shimizu |
890ddd |
m_firstNDirections = m_nDirections;
|
|
Toshihiro Shimizu |
890ddd |
m_firstOppDir = TPoint(1, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_nDirections > 2) {
|
|
Toshihiro Shimizu |
890ddd |
//Found mesh vertex. Retrieve the associated vertex
|
|
Toshihiro Shimizu |
890ddd |
m_vIdx = touchVertex(m_pos);
|
|
Toshihiro Shimizu |
890ddd |
m_firstVIdx = m_vIdx;
|
|
Toshihiro Shimizu |
890ddd |
m_firstPoints = m_points;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::BordersReader<pix>::addElement(const TPoint &pos, const TPoint &dir, const Pix &outerColor)</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Build opposite direction
|
|
Toshihiro Shimizu |
890ddd |
bool horizontal = (pos.y == m_pos.y);
|
|
Toshihiro Shimizu |
890ddd |
TPoint oppDir = horizontal ? TPoint((pos.x > m_pos.x) ? -1 : 1, 0)
|
|
Toshihiro Shimizu |
890ddd |
: TPoint(0, (pos.y > m_pos.y) ? -1 : 1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Update position
|
|
Toshihiro Shimizu |
890ddd |
m_pix += horizontal ? (pos.x - m_pos.x) : (pos.y - m_pos.y) * m_wrap;
|
|
Toshihiro Shimizu |
890ddd |
m_pos = pos;
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Check the new pos
|
|
Toshihiro Shimizu |
890ddd |
int nDirections = surroundingEdges();
|
|
Toshihiro Shimizu |
890ddd |
if (nDirections > 2) {
|
|
Toshihiro Shimizu |
890ddd |
//Found mesh vertex. First, check the hash for an associated vertex
|
|
Toshihiro Shimizu |
890ddd |
int vIdx = touchVertex(m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Ensure that an associated edge is present, in case it should
|
|
Toshihiro Shimizu |
890ddd |
if (m_vIdx >= 0)
|
|
Toshihiro Shimizu |
890ddd |
touchEdge(m_vIdx, m_dir, m_nDirections, vIdx, oppDir, nDirections);
|
|
Toshihiro Shimizu |
890ddd |
else {
|
|
Toshihiro Shimizu |
890ddd |
m_firstPos = m_pos;
|
|
Toshihiro Shimizu |
890ddd |
m_firstDir = dir;
|
|
Toshihiro Shimizu |
890ddd |
m_firstOppDir = oppDir;
|
|
Toshihiro Shimizu |
890ddd |
m_firstVIdx = vIdx;
|
|
Toshihiro Shimizu |
890ddd |
m_firstNDirections = nDirections;
|
|
Toshihiro Shimizu |
890ddd |
m_firstPoints = m_points;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_dir = dir;
|
|
Toshihiro Shimizu |
890ddd |
m_vIdx = vIdx;
|
|
Toshihiro Shimizu |
890ddd |
m_nDirections = nDirections;
|
|
Toshihiro Shimizu |
890ddd |
m_outerColor = outerColor;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_points.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(m_pos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::BordersReader<pix>::closeContainer()</pix>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//If no vertex was found, build one on the first position.
|
|
Toshihiro Shimizu |
890ddd |
if (m_firstVIdx < 0) {
|
|
Toshihiro Shimizu |
890ddd |
//Add a vertex at the first position.
|
|
Toshihiro Shimizu |
890ddd |
m_firstVIdx = m_vIdx = touchVertex(m_firstPos);
|
|
Toshihiro Shimizu |
890ddd |
m_dir = m_firstDir;
|
|
Toshihiro Shimizu |
890ddd |
m_nDirections = m_firstNDirections;
|
|
Toshihiro Shimizu |
890ddd |
m_firstPoints.push_back(m_firstPos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Connect the last vertex to the first.
|
|
Toshihiro Shimizu |
890ddd |
m_points.insert(m_points.end(), m_firstPoints.begin(), m_firstPoints.end());
|
|
Toshihiro Shimizu |
890ddd |
touchEdge(m_vIdx, m_dir, m_nDirections, m_firstVIdx, m_firstOppDir, m_firstNDirections);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_points.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_firstPoints.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename ranit=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::PolylineReader<ranit>::openContainer(const RanIt &it)</ranit>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TPoint &p = *it;
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(TPointD(p.x, p.y));
|
|
Toshihiro Shimizu |
890ddd |
m_indices.push_back(it - m_eval->begin());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename ranit=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::PolylineReader<ranit>::addElement(const RanIt &it)</ranit>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TPoint &p = *it;
|
|
Toshihiro Shimizu |
890ddd |
m_points.push_back(TPointD(p.x, p.y));
|
|
Toshihiro Shimizu |
890ddd |
m_indices.push_back(it - m_eval->begin());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename ranit=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
void ::PolylineReader<ranit>::closeContainer()</ranit>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_indices.empty()) {
|
|
Toshihiro Shimizu |
890ddd |
const TPoint &origI(*m_eval->begin());
|
|
Toshihiro Shimizu |
890ddd |
TPointD origin(origI.x, origI.y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::adjustVertices(origin, m_points, m_indices,
|
|
Toshihiro Shimizu |
890ddd |
m_eval->sums_x(), m_eval->sums_y(),
|
|
Toshihiro Shimizu |
890ddd |
m_eval->sums2_x(), m_eval->sums2_y(),
|
|
Toshihiro Shimizu |
890ddd |
m_eval->sums_xy());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<tthickpoint> cps;</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
polylineToQuadratics(m_points, cps, m_adherenceTol, m_angleTol,
|
|
Toshihiro Shimizu |
890ddd |
m_relativeTol, 0.75, m_mergeTol);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_vi->addStroke(new TStroke(cps));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_points.clear();
|
|
Toshihiro Shimizu |
890ddd |
m_indices.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Palette functions
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void discretizeColors(TRaster32P &ras, TPalette *palette, int nColors, TPixel32 transparentColor)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Extract the palette
|
|
Toshihiro Shimizu |
890ddd |
std::set<tpixel32> colors;</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
TColorUtils::buildPalette(colors, ras, nColors);
|
|
Toshihiro Shimizu |
890ddd |
colors.erase(TPixel::Black); //Black is automatically inserted by TPalette's constructor
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<tpixel32>::const_iterator it = colors.begin();</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
for (; it != colors.end(); ++it)
|
|
Toshihiro Shimizu |
890ddd |
palette->getPage(0)->addStyle(*it);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Flatten ras to the specified palette
|
|
Toshihiro Shimizu |
890ddd |
TPixel32 *pix, *line, *lineEnd;
|
|
Toshihiro Shimizu |
890ddd |
int y, lx = ras->getLx(), ly = ras->getLy();
|
|
Toshihiro Shimizu |
890ddd |
for (y = 0; y < ly; ++y) {
|
|
Toshihiro Shimizu |
890ddd |
line = ras->pixels(y), lineEnd = line + lx;
|
|
Toshihiro Shimizu |
890ddd |
for (pix = line; pix < lineEnd; ++pix)
|
|
Toshihiro Shimizu |
890ddd |
*pix = (*pix == transparentColor) ? TPixel32::Transparent : palette->getStyle(palette->getClosestStyle(*pix))->getMainColor();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void copyCM(TRasterGR16P &dst, const TRasterCM32P &src, int toneTol)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(dst->getLx() == src->getLx() && dst->getLy() == src->getLy());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int y, lx = src->getLx(), ly = src->getLy();
|
|
Toshihiro Shimizu |
890ddd |
TPixelCM32 *pixIn, *lineInEnd;
|
|
Toshihiro Shimizu |
890ddd |
TPixelGR16 *pixOut;
|
|
Toshihiro Shimizu |
890ddd |
for (y = 0; y < ly; ++y) {
|
|
Toshihiro Shimizu |
890ddd |
pixIn = src->pixels(y), lineInEnd = pixIn + lx;
|
|
Toshihiro Shimizu |
890ddd |
pixOut = dst->pixels(y);
|
|
Toshihiro Shimizu |
890ddd |
for (; pixIn < lineInEnd; ++pixIn, ++pixOut)
|
|
Toshihiro Shimizu |
890ddd |
pixOut->value = (pixIn->getTone() < toneTol) ? pixIn->getInk() : pixIn->getPaint();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef BordersReader<tpixel32>::stroke_colors_type stroke_colors_typeRGBM;</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
typedef BordersReader<tpixel32>::stroke_colors_hash stroke_colors_hashRGBM;</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef BordersReader<tpixelgr16>::stroke_colors_type stroke_colors_typeCM;</tpixelgr16>
|
|
Toshihiro Shimizu |
890ddd |
typedef BordersReader<tpixelgr16>::stroke_colors_hash stroke_colors_hashCM;</tpixelgr16>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void buildColorsRGBM(TRegion *r, const stroke_colors_hashRGBM &scHash, const TPaletteP palette)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Build r's color
|
|
Toshihiro Shimizu |
890ddd |
UINT i, edgeCount = r->getEdgeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < edgeCount; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TEdge *ed = r->getEdge(i);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke_colors_hashRGBM::const_iterator it = scHash.find(ed->m_s);
|
|
Toshihiro Shimizu |
890ddd |
if (it == scHash.end())
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const stroke_colors_typeRGBM &colors = it->m_val;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int style;
|
|
Toshihiro Shimizu |
890ddd |
if (ed->m_w0 < ed->m_w1) {
|
|
Toshihiro Shimizu |
890ddd |
style = palette->getClosestStyle(colors.first);
|
|
Toshihiro Shimizu |
890ddd |
ed->setStyle(style);
|
|
Toshihiro Shimizu |
890ddd |
ed->m_s->setStyle(style ? style : palette->getClosestStyle(colors.second));
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
style = palette->getClosestStyle(colors.second);
|
|
Toshihiro Shimizu |
890ddd |
ed->setStyle(style);
|
|
Toshihiro Shimizu |
890ddd |
ed->m_s->setStyle(style ? style : palette->getClosestStyle(colors.first));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build the color for its sub-regions
|
|
Toshihiro Shimizu |
890ddd |
int j, rCount = r->getSubregionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (j = 0; j < rCount; ++j)
|
|
Toshihiro Shimizu |
890ddd |
buildColorsRGBM(r->getSubregion(j), scHash, palette);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void buildColorsRGBM(TVectorImageP vi, const stroke_colors_hashRGBM &scHash)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//For every region, find its color
|
|
Toshihiro Shimizu |
890ddd |
int i, rCount = vi->getRegionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < rCount; ++i)
|
|
Toshihiro Shimizu |
890ddd |
buildColorsRGBM(vi->getRegion(i), scHash, vi->getPalette());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void buildColorsCM(TRegion *r, const stroke_colors_hashCM &scHash)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Build r's color
|
|
Toshihiro Shimizu |
890ddd |
UINT i, edgeCount = r->getEdgeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < edgeCount; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
TEdge *ed = r->getEdge(i);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
stroke_colors_hashCM::const_iterator it = scHash.find(ed->m_s);
|
|
Toshihiro Shimizu |
890ddd |
if (it == scHash.end())
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const stroke_colors_typeCM &colors = it->m_val;
|
|
Toshihiro Shimizu |
890ddd |
if (ed->m_w0 < ed->m_w1)
|
|
Toshihiro Shimizu |
890ddd |
ed->setStyle(colors.first.value);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
ed->setStyle(colors.second.value);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ed->m_s->setStyle(colors.first.value ? colors.first.value : colors.second.value);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build the color for its sub-regions
|
|
Toshihiro Shimizu |
890ddd |
int j, rCount = r->getSubregionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (j = 0; j < rCount; ++j)
|
|
Toshihiro Shimizu |
890ddd |
buildColorsCM(r->getSubregion(j), scHash);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void buildColorsCM(TVectorImageP vi, const stroke_colors_hashCM &scHash)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//For every region, find its color
|
|
Toshihiro Shimizu |
890ddd |
int i, rCount = vi->getRegionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < rCount; ++i)
|
|
Toshihiro Shimizu |
890ddd |
buildColorsCM(vi->getRegion(i), scHash);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Main functions
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void outlineVectorize(TVectorImageP &vi, const TRasterImageP &ri,
|
|
Toshihiro Shimizu |
890ddd |
const NewOutlineConfiguration &conf, TPalette *palette)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//Make a copy of ri's raster - a 32-bit raster
|
|
Toshihiro Shimizu |
890ddd |
TRasterP ras(ri->getRaster());
|
|
Toshihiro Shimizu |
890ddd |
TRaster32P ras32(ras->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::copy(ras32, ras);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build palette color and discretize the raster
|
|
Toshihiro Shimizu |
890ddd |
discretizeColors(ras32, palette, conf.m_maxColors, conf.m_transparentColor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Perform despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (conf.m_despeckling > 0)
|
|
Toshihiro Shimizu |
890ddd |
TRop::majorityDespeckle(ras32, conf.m_despeckling);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Examinate the discretized raster. Build a mesh structure representing the image's
|
|
Toshihiro Shimizu |
890ddd |
//colors geometry. Build strokes as mesh edges are extracted.
|
|
Toshihiro Shimizu |
890ddd |
LocalMesh mesh;
|
|
Toshihiro Shimizu |
890ddd |
BordersReader<tpixel32> reader(ras32, &mesh, vi, conf);</tpixel32>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders_simple(ras32, reader, false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Build regions
|
|
Toshihiro Shimizu |
890ddd |
vi->transform(conf.m_affine);
|
|
Toshihiro Shimizu |
890ddd |
vi->setAutocloseTolerance(-100.0);
|
|
Toshihiro Shimizu |
890ddd |
vi->findRegions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!conf.m_leaveUnpainted)
|
|
Toshihiro Shimizu |
890ddd |
//Finally, build region colors.
|
|
Toshihiro Shimizu |
890ddd |
buildColorsRGBM(vi, reader.scHash());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void outlineVectorize(TVectorImageP &vi, const TToonzImageP &ti,
|
|
Toshihiro Shimizu |
890ddd |
const NewOutlineConfiguration &conf, TPalette *palette)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32P ras(ti->getRaster());
|
|
Toshihiro Shimizu |
890ddd |
TRasterGR16P rasGR16(ras->getSize());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::copyCM(rasGR16, ras, conf.m_toneTol);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Perform despeckling
|
|
Toshihiro Shimizu |
890ddd |
if (conf.m_despeckling > 0)
|
|
Toshihiro Shimizu |
890ddd |
TRop::majorityDespeckle(rasGR16, conf.m_despeckling);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LocalMesh mesh;
|
|
Toshihiro Shimizu |
890ddd |
BordersReader<tpixelgr16> reader(rasGR16, &mesh, vi, conf);</tpixelgr16>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRop::borders::readBorders_simple(rasGR16, reader, TPixelGR16::Black, false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
vi->transform(conf.m_affine);
|
|
Toshihiro Shimizu |
890ddd |
vi->setAutocloseTolerance(-100.0);
|
|
Toshihiro Shimizu |
890ddd |
vi->findRegions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!conf.m_leaveUnpainted)
|
|
Toshihiro Shimizu |
890ddd |
buildColorsCM(vi, reader.scHash());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} //namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP VectorizerCore::newOutlineVectorize(
|
|
Toshihiro Shimizu |
890ddd |
const TImageP &image, const NewOutlineConfiguration &conf, TPalette *palette)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TVectorImageP output(new TVectorImage);
|
|
Toshihiro Shimizu |
890ddd |
output->setPalette(palette);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRasterImageP ri(image);
|
|
Toshihiro Shimizu |
890ddd |
TToonzImageP ti(image);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Deal with palette (observe that if image is colormap, the input palette is directly copied to output)
|
|
Toshihiro Shimizu |
890ddd |
if (ri)
|
|
Toshihiro Shimizu |
890ddd |
::outlineVectorize(output, ri, conf, palette);
|
|
Toshihiro Shimizu |
890ddd |
else if (ti)
|
|
Toshihiro Shimizu |
890ddd |
::outlineVectorize(output, ti, conf, palette);
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return output;
|
|
Toshihiro Shimizu |
890ddd |
}
|