|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcenterlinevectorizer.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstopwatch.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "timage_io.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tstrokeutil.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "tspecialstyleid.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trastercm.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "ttoonzimage.h"
|
|
Toshihiro Shimizu |
890ddd |
//#include "dpiscale.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define SEARCH_WINDOW 3
|
|
Toshihiro Shimizu |
890ddd |
#define JUNCTION_THICKNESS_RATIO 0.7
|
|
Toshihiro Shimizu |
890ddd |
#define JOIN_LIMIT 0.8
|
|
Toshihiro Shimizu |
890ddd |
#define THICKNESS_LIMIT 0.2
|
|
Toshihiro Shimizu |
890ddd |
#define THICKNESS_LIMIT_2 0.04
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#undef DEBUG
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct ControlPoint {
|
|
Shinya Kitaoka |
120a6e |
TStroke *m_stroke;
|
|
Shinya Kitaoka |
120a6e |
int m_index;
|
|
Shinya Kitaoka |
120a6e |
ControlPoint(TStroke *stroke, int index) : m_stroke(stroke), m_index(index) {}
|
|
Shinya Kitaoka |
120a6e |
TPointD getPoint() const { return m_stroke->getControlPoint(m_index); }
|
|
Shinya Kitaoka |
120a6e |
void setPoint(const TPointD &p) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point = m_stroke->getControlPoint(m_index);
|
|
Shinya Kitaoka |
120a6e |
point.x = p.x;
|
|
Shinya Kitaoka |
120a6e |
point.y = p.y;
|
|
Shinya Kitaoka |
120a6e |
m_stroke->setControlPoint(m_index, point);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void renormalizeImage(TVectorImage *vi) {
|
|
Shinya Kitaoka |
120a6e |
int i, j;
|
|
Shinya Kitaoka |
120a6e |
int n = vi->getStrokeCount();
|
|
Shinya Kitaoka |
120a6e |
std::vector<controlpoint> points;</controlpoint>
|
|
Shinya Kitaoka |
120a6e |
points.reserve(n * 2);
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke = vi->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
int m = stroke->getControlPointCount();
|
|
Shinya Kitaoka |
120a6e |
if (m > 0) {
|
|
Shinya Kitaoka |
120a6e |
if (m == 1)
|
|
Shinya Kitaoka |
120a6e |
points.push_back(ControlPoint(stroke, 0));
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
points.push_back(ControlPoint(stroke, 0));
|
|
Shinya Kitaoka |
120a6e |
points.push_back(ControlPoint(stroke, m - 1));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int count = points.size();
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < count; i++) {
|
|
Shinya Kitaoka |
120a6e |
ControlPoint &pi = points[i];
|
|
Shinya Kitaoka |
120a6e |
TPointD posi = pi.getPoint();
|
|
Shinya Kitaoka |
120a6e |
TPointD center = posi;
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> neighbours;</int>
|
|
Shinya Kitaoka |
120a6e |
neighbours.push_back(i);
|
|
Shinya Kitaoka |
120a6e |
for (j = i + 1; j < count; j++) {
|
|
Shinya Kitaoka |
120a6e |
TPointD posj = points[j].getPoint();
|
|
Shinya Kitaoka |
120a6e |
double d = tdistance(posj, posi);
|
|
Shinya Kitaoka |
120a6e |
if (d < 0.01) {
|
|
Shinya Kitaoka |
120a6e |
/*if(d>0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
int yy = 123;
|
|
Shinya Kitaoka |
120a6e |
}*/
|
|
Shinya Kitaoka |
120a6e |
neighbours.push_back(j);
|
|
Shinya Kitaoka |
120a6e |
center += posj;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int m = neighbours.size();
|
|
Shinya Kitaoka |
120a6e |
if (m == 1) continue;
|
|
Shinya Kitaoka |
120a6e |
center = center * (1.0 / m);
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < m; j++) points[neighbours[j]].setPoint(center);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class Node;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class DataPixel {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TPoint m_pos;
|
|
Shinya Kitaoka |
120a6e |
int m_value;
|
|
Shinya Kitaoka |
120a6e |
bool m_ink;
|
|
Shinya Kitaoka |
120a6e |
// int m_index;
|
|
Shinya Kitaoka |
120a6e |
Node *m_node;
|
|
Shinya Kitaoka |
120a6e |
DataPixel() : m_value(0), m_ink(false), /*m_index(0), */ m_node(0) {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
#ifdef WIN32
|
|
Toshihiro Shimizu |
890ddd |
template class DV_EXPORT_API TSmartPointerT<trastert<datapixel>>;</trastert<datapixel>
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
typedef TRasterPT<datapixel> DataRasterP;</datapixel>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class Junction;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class Node {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Node *m_other;
|
|
Shinya Kitaoka |
120a6e |
DataPixel *m_pixel;
|
|
Shinya Kitaoka |
120a6e |
Node *m_prev, *m_next;
|
|
Shinya Kitaoka |
120a6e |
Junction *m_junction;
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
bool m_flag;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
bool m_visited;
|
|
Shinya Kitaoka |
120a6e |
Node()
|
|
Shinya Kitaoka |
120a6e |
: m_pixel(0)
|
|
Shinya Kitaoka |
120a6e |
, m_prev(0)
|
|
Shinya Kitaoka |
120a6e |
, m_next(0)
|
|
Shinya Kitaoka |
120a6e |
, m_junction(0)
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
m_flag(false)
|
|
Shinya Kitaoka |
120a6e |
,
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
m_visited(false) {
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class ProtoStroke;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class Junction {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TThickPoint m_center;
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *=""> m_nodes;</node>
|
|
Shinya Kitaoka |
120a6e |
int m_junctionOrder;
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *=""> m_protoStrokes;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
bool m_locked;
|
|
Shinya Kitaoka |
120a6e |
Junction()
|
|
Shinya Kitaoka |
120a6e |
: m_center()
|
|
Shinya Kitaoka |
120a6e |
, m_nodes()
|
|
Shinya Kitaoka |
120a6e |
, m_junctionOrder(0)
|
|
Shinya Kitaoka |
120a6e |
, m_protoStrokes()
|
|
Shinya Kitaoka |
120a6e |
, m_locked(false) {}
|
|
Shinya Kitaoka |
120a6e |
bool isConvex();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class ProtoStroke {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TPointD m_startDirection, m_endDirection;
|
|
Shinya Kitaoka |
120a6e |
Junction *m_startJunction, *m_endJunction;
|
|
Shinya Kitaoka |
120a6e |
std::deque<tthickpoint> m_points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke()
|
|
Shinya Kitaoka |
120a6e |
: m_points()
|
|
Shinya Kitaoka |
120a6e |
, m_startDirection()
|
|
Shinya Kitaoka |
120a6e |
, m_endDirection()
|
|
Shinya Kitaoka |
120a6e |
, m_startJunction(0)
|
|
Shinya Kitaoka |
120a6e |
, m_endJunction(0) {}
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke(std::deque<tthickpoint>::iterator it_b,</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
std::deque<tthickpoint>::iterator it_e)</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
: m_points(it_b, it_e)
|
|
Shinya Kitaoka |
120a6e |
, m_startDirection()
|
|
Shinya Kitaoka |
120a6e |
, m_endDirection()
|
|
Shinya Kitaoka |
120a6e |
, m_startJunction(0)
|
|
Shinya Kitaoka |
120a6e |
, m_endJunction(0) {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class ProtoRegion {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TPointD m_center;
|
|
Shinya Kitaoka |
120a6e |
bool m_isConvex;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> m_points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
ProtoRegion(bool isConvex) : m_points(), m_isConvex(isConvex), m_center() {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class JunctionMerge {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Junction *m_junction;
|
|
Shinya Kitaoka |
120a6e |
Node *m_startNode, *m_endNode;
|
|
Shinya Kitaoka |
120a6e |
bool m_isNext;
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(Junction *junction)
|
|
Shinya Kitaoka |
120a6e |
: m_junction(junction), m_startNode(0), m_endNode(0), m_isNext(true) {}
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(Junction *junction, Node *startNode, Node *endNode, bool isNext)
|
|
Shinya Kitaoka |
120a6e |
: m_junction(junction)
|
|
Shinya Kitaoka |
120a6e |
, m_startNode(startNode)
|
|
Shinya Kitaoka |
120a6e |
, m_endNode(endNode)
|
|
Shinya Kitaoka |
120a6e |
, m_isNext(isNext) {}
|
|
Shinya Kitaoka |
120a6e |
bool operator==(const JunctionMerge &op2) {
|
|
Shinya Kitaoka |
120a6e |
return (m_junction == op2.m_junction);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class JunctionLink {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
Junction *m_first;
|
|
Shinya Kitaoka |
120a6e |
Junction *m_second;
|
|
Shinya Kitaoka |
120a6e |
int m_order;
|
|
Shinya Kitaoka |
120a6e |
JunctionLink(Junction *first, Junction *second)
|
|
Shinya Kitaoka |
120a6e |
: m_first(first), m_second(second), m_order(0) {}
|
|
Shinya Kitaoka |
120a6e |
bool operator==(const JunctionLink &op2) const {
|
|
Shinya Kitaoka |
120a6e |
return (m_first == op2.m_first && m_second == op2.m_second) ||
|
|
Shinya Kitaoka |
120a6e |
(m_first == op2.m_second && m_second == op2.m_first);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class CenterLineVectorizer {
|
|
Shinya Kitaoka |
120a6e |
TPalette *m_palette;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
// int m_delta[8];
|
|
Shinya Kitaoka |
120a6e |
// int m_radius;
|
|
Shinya Kitaoka |
120a6e |
TRasterP m_src;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
VectorizerConfiguration m_configuration;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
TRaster32P m_output;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
DataRasterP m_dataRaster;
|
|
Shinya Kitaoka |
120a6e |
vector<pair<int, datarasterp="">> m_dataRasterArray;</pair<int,>
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP m_vimage;
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP m_rimage;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
vector<vector<tthickpoint>> m_outlines;</vector<tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
vector<tpointd> m_unvisitedNodes;</tpointd>
|
|
Shinya Kitaoka |
120a6e |
vector<vector<node *="">> m_junctionPolygons;</vector<node>
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
vector<node *=""> m_nodes;</node>
|
|
Shinya Kitaoka |
120a6e |
vector<junction *=""> m_junctions;</junction>
|
|
Shinya Kitaoka |
120a6e |
vector<junctionlink> m_links;</junctionlink>
|
|
Shinya Kitaoka |
120a6e |
list<protostroke> m_protoStrokes;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
list<protoregion> m_protoRegions;</protoregion>
|
|
Shinya Kitaoka |
120a6e |
// list< std::vector<tthickpoint> > m_protoHoles;</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Node *findOtherSide(Node *node);
|
|
Shinya Kitaoka |
120a6e |
bool testOtherSide(Node *na1, Node *nb1, double &startDist2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD computeCenter(Node *na, Node *nb, double &r);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool isHole(Node *startNode);
|
|
Shinya Kitaoka |
120a6e |
void traceLine(DataPixel *pix); // , vector<tthickpoint> &points);</tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPoint computeGradient(DataPixel *pix) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_dataRaster);
|
|
Shinya Kitaoka |
120a6e |
const int wrap = m_dataRaster->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPoint g(0, 0);
|
|
Shinya Kitaoka |
120a6e |
int n, s, w, e, nw, sw, ne, se;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
w = pix[-1].m_value;
|
|
Shinya Kitaoka |
120a6e |
nw = pix[-1 + wrap].m_value;
|
|
Shinya Kitaoka |
120a6e |
sw = pix[-1 - wrap].m_value;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
e = pix[+1].m_value;
|
|
Shinya Kitaoka |
120a6e |
ne = pix[+1 + wrap].m_value;
|
|
Shinya Kitaoka |
120a6e |
se = pix[+1 - wrap].m_value;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
n = pix[+wrap].m_value;
|
|
Shinya Kitaoka |
120a6e |
s = pix[-wrap].m_value;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
g.y = -sw + ne - se + nw + 2 * (n - s);
|
|
Shinya Kitaoka |
120a6e |
g.x = -sw + ne + se - nw + 2 * (e - w);
|
|
Shinya Kitaoka |
120a6e |
return g;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
CenterLineVectorizer(const VectorizerConfiguration &configuration,
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette)
|
|
Shinya Kitaoka |
120a6e |
: m_configuration(configuration), m_palette(palette) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
~CenterLineVectorizer();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void clearNodes();
|
|
Shinya Kitaoka |
120a6e |
void createNodes();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void clearJunctions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void makeOutputRaster();
|
|
Shinya Kitaoka |
120a6e |
void makeDataRaster(const TRasterP &src);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DataPixel *findUnvisitedInkPixel();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool linkNextProtoStroke(ProtoStroke *const dstProtoStroke,
|
|
Shinya Kitaoka |
120a6e |
Junction *const currJunction, const int k);
|
|
Shinya Kitaoka |
120a6e |
void joinProtoStrokes(ProtoStroke *const dstProtoStroke);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void resolveUnvisitedNode(Node *node);
|
|
Shinya Kitaoka |
120a6e |
Junction *mergeJunctions(const std::list<junctionmerge> &junctions);</junctionmerge>
|
|
Shinya Kitaoka |
120a6e |
void joinJunctions();
|
|
Shinya Kitaoka |
120a6e |
void createJunctionPolygon(Junction *junction);
|
|
Shinya Kitaoka |
120a6e |
void handleLinks();
|
|
Shinya Kitaoka |
120a6e |
void handleJunctions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void createStrokes();
|
|
Shinya Kitaoka |
120a6e |
void createRegions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void vectorize();
|
|
Shinya Kitaoka |
120a6e |
void init();
|
|
Shinya Kitaoka |
120a6e |
// void click(const TPoint &p);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Node *createNode(DataPixel *pix);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void link(DataPixel *pix, DataPixel *from, DataPixel *to);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/*#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
inline TPixel32 &getOutPix(DataPixel*pix) {return
|
|
Toshihiro Shimizu |
890ddd |
m_output->pixels()[pix->m_index]; }
|
|
Shinya Kitaoka |
120a6e |
void outputNodes(Node *node);
|
|
Shinya Kitaoka |
120a6e |
void outputInks();
|
|
Toshihiro Shimizu |
890ddd |
#endif*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
CenterLineVectorizer(const CenterLineVectorizer &);
|
|
Shinya Kitaoka |
120a6e |
CenterLineVectorizer &operator=(const CenterLineVectorizer &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class CompareJunctionNodes {
|
|
Shinya Kitaoka |
120a6e |
TPointD m_center;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
CompareJunctionNodes(TPointD center) : m_center(center) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool operator()(const Node *n1, const Node *n2) {
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = convert(n1->m_pixel->m_pos) - m_center;
|
|
Shinya Kitaoka |
120a6e |
TPointD p2 = convert(n2->m_pixel->m_pos) - m_center;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double alpha1, alpha2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (p1.x > 0)
|
|
Shinya Kitaoka |
120a6e |
alpha1 = -p1.y / sqrt(norm2(p1));
|
|
Shinya Kitaoka |
120a6e |
else if (p1.x < 0)
|
|
Shinya Kitaoka |
120a6e |
alpha1 = 2 + p1.y / sqrt(norm2(p1));
|
|
Shinya Kitaoka |
120a6e |
else //(p1.x = 0)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (p1.y > 0)
|
|
Shinya Kitaoka |
120a6e |
alpha1 = -1;
|
|
Shinya Kitaoka |
120a6e |
else if (p1.y < 0)
|
|
Shinya Kitaoka |
120a6e |
alpha1 = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (p2.x > 0)
|
|
Shinya Kitaoka |
120a6e |
alpha2 = -p2.y / sqrt(norm2(p2));
|
|
Shinya Kitaoka |
120a6e |
else if (p2.x < 0)
|
|
Shinya Kitaoka |
120a6e |
alpha2 = 2 + p2.y / sqrt(norm2(p2));
|
|
Shinya Kitaoka |
120a6e |
else //(p2.x = 0)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (p2.y > 0)
|
|
Shinya Kitaoka |
120a6e |
alpha2 = -1;
|
|
Shinya Kitaoka |
120a6e |
else if (p2.y < 0)
|
|
Shinya Kitaoka |
120a6e |
alpha2 = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (alpha2 - alpha1 > 0)
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
else if (alpha2 - alpha1 < 0)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return false; // n1->m_pixel->m_pos == n2->m_pixel->m_pos!!
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline bool collinear(const TPointD &a, const TPointD &b, const TPointD &c) {
|
|
Shinya Kitaoka |
120a6e |
double area = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
|
|
Shinya Kitaoka |
120a6e |
return area == 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline bool right(const TPointD &a, const TPointD &b, const TPointD &c) {
|
|
Shinya Kitaoka |
120a6e |
double area = (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
|
|
Shinya Kitaoka |
120a6e |
return area < 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
enum RectIntersectionResult { parallel, coincident, intersected };
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RectIntersectionResult rectsIntersect(const TPointD &a1, const TPointD &a2,
|
|
Shinya Kitaoka |
120a6e |
const TPointD &b1, const TPointD &b2,
|
|
Shinya Kitaoka |
120a6e |
TPointD &intersection) {
|
|
Shinya Kitaoka |
120a6e |
double ma, mb, ca, cb;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (a2.x == a1.x && b2.x == b1.x) {
|
|
Shinya Kitaoka |
120a6e |
if (collinear(a1, a2, b1) && collinear(a1, a2, b2))
|
|
Shinya Kitaoka |
120a6e |
return coincident;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return parallel;
|
|
Shinya Kitaoka |
120a6e |
} else if (a1.x == a2.x) {
|
|
Shinya Kitaoka |
120a6e |
mb = (b2.y - b1.y) / (b2.x - b1.x);
|
|
Shinya Kitaoka |
120a6e |
cb = b1.y - mb * b1.x;
|
|
Shinya Kitaoka |
120a6e |
intersection.x = a1.x;
|
|
Shinya Kitaoka |
120a6e |
intersection.y = mb * intersection.x + cb;
|
|
Shinya Kitaoka |
120a6e |
return intersected;
|
|
Shinya Kitaoka |
120a6e |
} else if (b1.x == b2.x) {
|
|
Shinya Kitaoka |
120a6e |
ma = (a2.y - a1.y) / (a2.x - a1.x);
|
|
Shinya Kitaoka |
120a6e |
ca = a1.y - ma * a1.x;
|
|
Shinya Kitaoka |
120a6e |
intersection.x = b1.x;
|
|
Shinya Kitaoka |
120a6e |
intersection.y = ma * intersection.x + ca;
|
|
Shinya Kitaoka |
120a6e |
return intersected;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
ma = (a2.y - a1.y) / (a2.x - a1.x);
|
|
Shinya Kitaoka |
120a6e |
mb = (b2.y - b1.y) / (b2.x - b1.x);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (ma == mb) {
|
|
Shinya Kitaoka |
120a6e |
if (collinear(a1, a2, b1) && collinear(a1, a2, b2))
|
|
Shinya Kitaoka |
120a6e |
return coincident;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return parallel;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ca = a1.y - ma * a1.x;
|
|
Shinya Kitaoka |
120a6e |
cb = b1.y - mb * b1.x;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
intersection.x = (ca - cb) / (mb - ma);
|
|
Shinya Kitaoka |
120a6e |
intersection.y = ma * intersection.x + ca;
|
|
Shinya Kitaoka |
120a6e |
return intersected;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool Junction::isConvex() {
|
|
Shinya Kitaoka |
120a6e |
int nonConvexAngles = 0;
|
|
Shinya Kitaoka |
120a6e |
assert(m_nodes.size() > 2);
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it = m_nodes.begin();</node>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_e = m_nodes.end() - 2;</node>
|
|
Shinya Kitaoka |
120a6e |
for (; it != it_e; ++it) {
|
|
Shinya Kitaoka |
120a6e |
if (right(convert((*(it))->m_pixel->m_pos),
|
|
Shinya Kitaoka |
120a6e |
convert((*(it + 1))->m_pixel->m_pos),
|
|
Shinya Kitaoka |
120a6e |
convert((*(it + 2))->m_pixel->m_pos)))
|
|
Shinya Kitaoka |
120a6e |
nonConvexAngles++;
|
|
Shinya Kitaoka |
120a6e |
if (nonConvexAngles > 1) return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (right(convert((*(it))->m_pixel->m_pos),
|
|
Shinya Kitaoka |
120a6e |
convert((*(it + 1))->m_pixel->m_pos),
|
|
Shinya Kitaoka |
120a6e |
convert((*(m_nodes.begin()))->m_pixel->m_pos)))
|
|
Shinya Kitaoka |
120a6e |
nonConvexAngles++;
|
|
Shinya Kitaoka |
120a6e |
if (nonConvexAngles > 1) return false;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
CenterLineVectorizer::~CenterLineVectorizer() {
|
|
Shinya Kitaoka |
120a6e |
clearNodes();
|
|
Shinya Kitaoka |
120a6e |
clearJunctions();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
m_outlines.clear();
|
|
Shinya Kitaoka |
120a6e |
m_unvisitedNodes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_junctionPolygons.clear();
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_links.clear();
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_protoRegions.clear();
|
|
Shinya Kitaoka |
120a6e |
// m_protoHoles.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::clearNodes() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_nodes.size(); i++) delete m_nodes[i];
|
|
Shinya Kitaoka |
120a6e |
m_nodes.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::clearJunctions() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_junctions.size(); i++) delete m_junctions[i];
|
|
Shinya Kitaoka |
120a6e |
m_junctions.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::link(DataPixel *pix, DataPixel *srcPix,
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dstPix) {
|
|
Shinya Kitaoka |
120a6e |
Node *srcNode = 0, *dstNode = 0, *node = 0;
|
|
Shinya Kitaoka |
120a6e |
Node *tmp;
|
|
Shinya Kitaoka |
120a6e |
for (tmp = pix->m_node; tmp; tmp = tmp->m_other) {
|
|
Shinya Kitaoka |
120a6e |
if (tmp->m_pixel == 0) continue;
|
|
Shinya Kitaoka |
120a6e |
if (tmp->m_prev && tmp->m_prev->m_pixel == srcPix) {
|
|
Shinya Kitaoka |
120a6e |
assert(srcNode == 0);
|
|
Shinya Kitaoka |
120a6e |
if (node) {
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next->m_pixel == dstPix);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev == 0);
|
|
Shinya Kitaoka |
120a6e |
node->m_prev = tmp->m_prev;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_prev->m_next = node;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_next = tmp->m_prev = 0;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_pixel = 0;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert(tmp->m_next == 0);
|
|
Shinya Kitaoka |
120a6e |
srcNode = tmp->m_prev;
|
|
Shinya Kitaoka |
120a6e |
node = tmp;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (tmp->m_next && tmp->m_next->m_pixel == dstPix) {
|
|
Shinya Kitaoka |
120a6e |
assert(dstNode == 0);
|
|
Shinya Kitaoka |
120a6e |
if (node) {
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev->m_pixel == srcPix);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next == 0);
|
|
Shinya Kitaoka |
120a6e |
node->m_next = tmp->m_next;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_next->m_prev = node;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_next = tmp->m_prev = 0;
|
|
Shinya Kitaoka |
120a6e |
tmp->m_pixel = 0;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert(tmp->m_prev == 0);
|
|
Shinya Kitaoka |
120a6e |
dstNode = tmp->m_next;
|
|
Shinya Kitaoka |
120a6e |
node = tmp;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!node) node = createNode(pix);
|
|
Shinya Kitaoka |
120a6e |
if (!srcNode) srcNode = createNode(srcPix);
|
|
Shinya Kitaoka |
120a6e |
if (!dstNode) dstNode = createNode(dstPix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!node->m_next) {
|
|
Shinya Kitaoka |
120a6e |
node->m_next = dstNode;
|
|
Shinya Kitaoka |
120a6e |
assert(dstNode->m_prev == 0);
|
|
Shinya Kitaoka |
120a6e |
dstNode->m_prev = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!node->m_prev) {
|
|
Shinya Kitaoka |
120a6e |
node->m_prev = srcNode;
|
|
Shinya Kitaoka |
120a6e |
assert(srcNode->m_next == 0);
|
|
Shinya Kitaoka |
120a6e |
srcNode->m_next = node;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next == dstNode);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev == srcNode);
|
|
Shinya Kitaoka |
120a6e |
assert(dstNode->m_prev == node);
|
|
Shinya Kitaoka |
120a6e |
assert(srcNode->m_next == node);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline int colorDistance2(const TPixel32 &c0, const TPixel32 &c1) {
|
|
Shinya Kitaoka |
120a6e |
return ((c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) +
|
|
Shinya Kitaoka |
120a6e |
(c0.b - c1.b) * (c0.b - c1.b));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
#define MAX_TOLERANCE 20
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tcolorstyles.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::makeDataRaster(const TRasterP &src) {
|
|
Shinya Kitaoka |
120a6e |
m_vimage = new TVectorImage();
|
|
Shinya Kitaoka |
120a6e |
if (!src) return;
|
|
Shinya Kitaoka |
120a6e |
m_src = src;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
clearNodes();
|
|
Shinya Kitaoka |
120a6e |
clearJunctions();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int ii, x, y = 0;
|
|
Shinya Kitaoka |
120a6e |
TRaster32P srcRGBM = (TRaster32P)m_src;
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P srcCM = (TRasterCM32P)m_src;
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P srcGR = (TRasterGR8P)m_src;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DataRasterP dataRaster(m_src->getSize().lx + 2, m_src->getSize().ly + 2);
|
|
Shinya Kitaoka |
120a6e |
int ly = dataRaster->getLy();
|
|
Shinya Kitaoka |
120a6e |
int lx = dataRaster->getLx();
|
|
Shinya Kitaoka |
120a6e |
int wrap = dataRaster->getWrap();
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dataPix0 = dataRaster->pixels(0);
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dataPix1 = dataRaster->pixels(0) + m_src->getLx() + 1;
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < ly; y++, dataPix0 += wrap, dataPix1 += wrap) {
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_pos.x = 0;
|
|
Shinya Kitaoka |
120a6e |
dataPix1->m_pos.x = lx - 1;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_pos.y = dataPix1->m_pos.y = y;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_value = dataPix1->m_value = 0;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_ink = dataPix1->m_ink = false;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_node = dataPix1->m_node = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
dataPix0 = dataRaster->pixels(0);
|
|
Shinya Kitaoka |
120a6e |
dataPix1 = dataRaster->pixels(ly - 1);
|
|
Shinya Kitaoka |
120a6e |
for (x = 0; x < lx; x++, dataPix0++, dataPix1++) {
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_pos.x = dataPix1->m_pos.x = x;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_pos.y = 0;
|
|
Shinya Kitaoka |
120a6e |
dataPix1->m_pos.y = ly - 1;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_value = dataPix1->m_value = 0;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_ink = dataPix1->m_ink = false;
|
|
Shinya Kitaoka |
120a6e |
dataPix0->m_node = dataPix1->m_node = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (srcRGBM) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_palette);
|
|
Shinya Kitaoka |
120a6e |
int inkId = m_palette->addStyle(m_configuration.m_inkColor);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_dataRasterArray.push_back(pair<int, datarasterp="">(inkId, dataRaster));</int,>
|
|
Shinya Kitaoka |
120a6e |
int maxDistance2 =
|
|
Shinya Kitaoka |
120a6e |
m_configuration.m_threshold * m_configuration.m_threshold;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < m_src->getLy(); y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inPix = srcRGBM->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *inEndPix = inPix + srcRGBM->getLx();
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dataPix = dataRaster->pixels(y + 1) + 1;
|
|
Shinya Kitaoka |
120a6e |
x = 0;
|
|
Shinya Kitaoka |
120a6e |
while (inPix < inEndPix) {
|
|
Shinya Kitaoka |
120a6e |
*dataPix = DataPixel();
|
|
Shinya Kitaoka |
120a6e |
int distance2 = colorDistance2(m_configuration.m_inkColor, *inPix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
|
|
Shinya Kitaoka |
120a6e |
if (y == 0 || y == m_src->getLy() - 1 || x == 0 ||
|
|
Shinya Kitaoka |
120a6e |
x == m_src->getLx() - 1) {
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_value = 255;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_ink = false;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_value = (inPix->r + 2 * inPix->g + inPix->b) >> 2;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_ink = (distance2 < maxDistance2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.x = x++;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.y = y;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_node = 0;
|
|
Shinya Kitaoka |
120a6e |
// dataPix->m_index = index++;
|
|
Shinya Kitaoka |
120a6e |
inPix++;
|
|
Shinya Kitaoka |
120a6e |
dataPix++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (srcGR) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_palette);
|
|
Shinya Kitaoka |
120a6e |
int inkId = m_palette->addStyle(m_configuration.m_inkColor);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_dataRasterArray.push_back(pair<int, datarasterp="">(inkId, dataRaster));</int,>
|
|
Shinya Kitaoka |
120a6e |
int threshold = m_configuration.m_threshold;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < m_src->getLy(); y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelGR8 *inPix = srcGR->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelGR8 *inEndPix = inPix + srcGR->getLx();
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dataPix = dataRaster->pixels(y + 1) + 1;
|
|
Shinya Kitaoka |
120a6e |
x = 0;
|
|
Shinya Kitaoka |
120a6e |
while (inPix < inEndPix) {
|
|
Shinya Kitaoka |
120a6e |
*dataPix = DataPixel();
|
|
Shinya Kitaoka |
120a6e |
// int distance2 = colorDistance2(m_configuration.m_inkColor, *inPix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
|
|
Shinya Kitaoka |
120a6e |
if (y == 0 || y == m_src->getLy() - 1 || x == 0 ||
|
|
Shinya Kitaoka |
120a6e |
x == m_src->getLx() - 1) {
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_value = 255;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_ink = false;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_value = inPix->value;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_ink = (inPix->value < threshold);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.x = x++;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.y = y;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_node = 0;
|
|
Shinya Kitaoka |
120a6e |
// dataPix->m_index = index++;
|
|
Shinya Kitaoka |
120a6e |
inPix++;
|
|
Shinya Kitaoka |
120a6e |
dataPix++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
else if (srcCM) {
|
|
Shinya Kitaoka |
120a6e |
int currInk, nextInk = 0;
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
int threshold =
|
|
Shinya Kitaoka |
120a6e |
m_configuration.m_threshold; // tolerance: 1->MAX thresh: 1-255
|
|
Shinya Kitaoka |
120a6e |
currInk = nextInk;
|
|
Shinya Kitaoka |
120a6e |
nextInk = 0;
|
|
Shinya Kitaoka |
120a6e |
m_dataRasterArray.push_back(pair<int, datarasterp="">(currInk, dataRaster));</int,>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// inizializza la parte centrale
|
|
Shinya Kitaoka |
120a6e |
for (y = 0; y < srcCM->getLy(); y++) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *inPix = srcCM->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 *inEndPix = inPix + m_src->getLx();
|
|
Shinya Kitaoka |
120a6e |
DataPixel *dataPix = dataRaster->pixels(y + 1) + 1;
|
|
Shinya Kitaoka |
120a6e |
x = 0;
|
|
Shinya Kitaoka |
120a6e |
while (inPix < inEndPix) {
|
|
Shinya Kitaoka |
120a6e |
*dataPix = DataPixel();
|
|
Shinya Kitaoka |
120a6e |
int value = inPix->getTone();
|
|
Shinya Kitaoka |
120a6e |
if (value < 255 && !m_configuration.m_ignoreInkColors) {
|
|
Shinya Kitaoka |
120a6e |
int ink = inPix->getInk();
|
|
Shinya Kitaoka |
120a6e |
if (currInk == 0) {
|
|
Shinya Kitaoka |
120a6e |
currInk = ink;
|
|
Shinya Kitaoka |
120a6e |
m_dataRasterArray.back().first = ink;
|
|
Shinya Kitaoka |
120a6e |
} else if (ink != currInk) {
|
|
Shinya Kitaoka |
120a6e |
value = 255;
|
|
Shinya Kitaoka |
120a6e |
if (nextInk == 0) {
|
|
Shinya Kitaoka |
120a6e |
for (ii = 0; ii < (int)m_dataRasterArray.size() - 1; ii++)
|
|
Shinya Kitaoka |
120a6e |
if (m_dataRasterArray[ii].first == ink) break;
|
|
Shinya Kitaoka |
120a6e |
if (ii == (int)m_dataRasterArray.size() - 1) nextInk = ink;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// TPixel col = m_palette->getStyle(inPix->getInk())->getMainColor();
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.x = x++;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_pos.y = y;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_value = value;
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_ink = (value < threshold);
|
|
Shinya Kitaoka |
120a6e |
dataPix->m_node = 0;
|
|
Shinya Kitaoka |
120a6e |
// dataPix->m_index = index++;
|
|
Shinya Kitaoka |
120a6e |
inPix++;
|
|
Shinya Kitaoka |
120a6e |
dataPix++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} while (nextInk != 0);
|
|
Shinya Kitaoka |
120a6e |
if (m_configuration.m_ignoreInkColors) {
|
|
Shinya Kitaoka |
120a6e |
assert(m_dataRasterArray.size() == 1);
|
|
Shinya Kitaoka |
120a6e |
m_dataRasterArray.back().first = 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::init() {
|
|
Shinya Kitaoka |
120a6e |
int y;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*m_links.clear();
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
m_protoRegions.clear();
|
|
Shinya Kitaoka |
120a6e |
clearNodes();
|
|
Shinya Kitaoka |
120a6e |
clearJunctions();*/
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DataRasterP dataRaster = m_dataRaster;
|
|
Shinya Kitaoka |
120a6e |
const int wrap = dataRaster->getWrap();
|
|
Shinya Kitaoka |
120a6e |
const int delta[] = {-wrap - 1, -wrap, -wrap + 1, 1,
|
|
Shinya Kitaoka |
120a6e |
wrap + 1, wrap, wrap - 1, -1};
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (y = 1; y < dataRaster->getLy() - 1; y++) {
|
|
Shinya Kitaoka |
120a6e |
DataPixel *pix = dataRaster->pixels(y);
|
|
Shinya Kitaoka |
120a6e |
DataPixel *endPix = pix + dataRaster->getLx() - 1;
|
|
Shinya Kitaoka |
120a6e |
pix++;
|
|
Shinya Kitaoka |
120a6e |
for (pix++; pix < endPix; ++pix) {
|
|
Shinya Kitaoka |
120a6e |
if ((pix->m_ink == false) || (pix[-wrap].m_ink && pix[wrap].m_ink &&
|
|
Shinya Kitaoka |
120a6e |
pix[-1].m_ink && pix[1].m_ink))
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < 8; i++)
|
|
Shinya Kitaoka |
120a6e |
if (pix[delta[i]].m_ink && pix[delta[(i + 1) & 0x7]].m_ink == false)
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
int start = i;
|
|
Shinya Kitaoka |
120a6e |
if (i == 8) continue; // punto isolato
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
int j = (i + 1) & 0x7;
|
|
Shinya Kitaoka |
120a6e |
assert(i < 8 && pix[delta[i]].m_ink);
|
|
Shinya Kitaoka |
120a6e |
assert(j < 8 && pix[delta[j]].m_ink == false);
|
|
Shinya Kitaoka |
120a6e |
do
|
|
Shinya Kitaoka |
120a6e |
j = (j + 1) & 0x7;
|
|
Shinya Kitaoka |
120a6e |
while (pix[delta[j]].m_ink == false);
|
|
Shinya Kitaoka |
120a6e |
assert(j < 8 && pix[delta[j]].m_ink);
|
|
Shinya Kitaoka |
120a6e |
if (((i + 2) & 0x7) != j || (i & 1) == 0) {
|
|
Shinya Kitaoka |
120a6e |
// il bianco comprende anche un fianco
|
|
Shinya Kitaoka |
120a6e |
link(pix, pix + delta[i], pix + delta[j]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
i = j;
|
|
Shinya Kitaoka |
120a6e |
assert(i < 8);
|
|
Shinya Kitaoka |
120a6e |
while (pix[delta[(i + 1) & 0x7]].m_ink) i = (i + 1) & 0x7;
|
|
Shinya Kitaoka |
120a6e |
assert(i < 8 && pix[delta[i]].m_ink);
|
|
Shinya Kitaoka |
120a6e |
assert(pix[delta[(i + 1) & 0x7]].m_ink == false);
|
|
Shinya Kitaoka |
120a6e |
if (i == start) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for(i = 0;i<(int)m_nodes.size();i++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[i];
|
|
Shinya Kitaoka |
120a6e |
if(node->m_pixel==0) continue;
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev->m_next == node);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next->m_prev == node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for(i = 0;i<m_dataraster->getLx()*m_dataRaster->getLy(); i++)</m_dataraster->
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
DataPixel *pix = m_dataRaster->pixels()+i;
|
|
Shinya Kitaoka |
120a6e |
for(Node *node = pix->m_node; node; node=node->m_other)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if(node->m_pixel==0) continue;
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_pixel == pix);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_prev->m_next == node);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_next->m_prev == node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD CenterLineVectorizer::computeCenter(Node *na, Node *nb, double &r) {
|
|
Shinya Kitaoka |
120a6e |
TPointD pa = convert(na->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
TPointD pb = convert(nb->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
r = THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
if (pa == pb) return pa;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD center((pa + pb) * 0.5);
|
|
Shinya Kitaoka |
120a6e |
r = norm(pa - pb) * 0.5;
|
|
Shinya Kitaoka |
120a6e |
return center;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* double vsum = 0.0;
|
|
Shinya Kitaoka |
120a6e |
TPointD d = pa-pb;
|
|
Shinya Kitaoka |
120a6e |
if(fabs(d.x)>fabs(d.y))
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
if(pa.x>pb.x) tswap(pa,pb);
|
|
Shinya Kitaoka |
120a6e |
for(int x = pa.x; x<=pb.x; x++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
int y = pa.y + (pb.y-pa.y)*(x-pa.x)/(pb.x-pa.x);
|
|
Shinya Kitaoka |
120a6e |
int v = 255-m_dataRaster->pixels(y)[x].m_value;
|
|
Shinya Kitaoka |
120a6e |
center += v * TPointD(x,y);
|
|
Shinya Kitaoka |
120a6e |
vsum += v;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if(pa.y>pb.y) tswap(pa,pb);
|
|
Shinya Kitaoka |
120a6e |
for(int y = pa.y; y<=pb.y; y++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
int x = pa.x + (pb.x-pa.x)*(y-pa.y)/(pb.y-pa.y);
|
|
Shinya Kitaoka |
120a6e |
int v = 255-m_dataRaster->pixels(y)[x].m_value;
|
|
Shinya Kitaoka |
120a6e |
center += v * TPointD(x,y);
|
|
Shinya Kitaoka |
120a6e |
vsum += v;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert(vsum>0);
|
|
Shinya Kitaoka |
120a6e |
r = 0.5*vsum/255.0;
|
|
Shinya Kitaoka |
120a6e |
return center * (1/vsum);
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double computeDistance2(Node *na, Node *nb) {
|
|
Shinya Kitaoka |
120a6e |
assert(na->m_pixel);
|
|
Shinya Kitaoka |
120a6e |
assert(nb->m_pixel);
|
|
Shinya Kitaoka |
120a6e |
TPointD d = convert(na->m_pixel->m_pos - nb->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
return d * d;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Node *CenterLineVectorizer::findOtherSide(Node *node) {
|
|
Shinya Kitaoka |
120a6e |
DataPixel *pix = node->m_pixel;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPoint dir = -computeGradient(pix);
|
|
Shinya Kitaoka |
120a6e |
if (dir == TPoint(0, 0)) return 0;
|
|
Shinya Kitaoka |
120a6e |
TPoint d1(tsign(dir.x), 0), d2(0, tsign(dir.y));
|
|
Shinya Kitaoka |
120a6e |
int num = abs(dir.y), den = abs(dir.x);
|
|
Shinya Kitaoka |
120a6e |
if (num > den) {
|
|
Shinya Kitaoka |
120a6e |
tswap(d1, d2);
|
|
Shinya Kitaoka |
120a6e |
tswap(num, den);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPoint pos = pix->m_pos;
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0;; i++) {
|
|
Shinya Kitaoka |
120a6e |
TPoint q(pos.x + d1.x * i + d2.x * num * i / den,
|
|
Shinya Kitaoka |
120a6e |
pos.y + d1.y * i + d2.y * num * i / den);
|
|
Shinya Kitaoka |
120a6e |
// if (!m_dataRaster->getBounds().contains(q)) break;
|
|
Shinya Kitaoka |
120a6e |
DataPixel *nextPix = m_dataRaster->pixels(q.y) + q.x;
|
|
Shinya Kitaoka |
120a6e |
if (nextPix->m_ink == false) break;
|
|
Shinya Kitaoka |
120a6e |
pix = nextPix;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
assert(pix);
|
|
Shinya Kitaoka |
120a6e |
if (!pix->m_node) {
|
|
Shinya Kitaoka |
120a6e |
const int wrap = m_dataRaster->getWrap();
|
|
Shinya Kitaoka |
120a6e |
if (pix[-1].m_node)
|
|
Shinya Kitaoka |
120a6e |
pix--;
|
|
Shinya Kitaoka |
120a6e |
else if (pix[1].m_node)
|
|
Shinya Kitaoka |
120a6e |
pix++;
|
|
Shinya Kitaoka |
120a6e |
else if (pix[wrap].m_node)
|
|
Shinya Kitaoka |
120a6e |
pix += wrap;
|
|
Shinya Kitaoka |
120a6e |
else if (pix[-wrap].m_node)
|
|
Shinya Kitaoka |
120a6e |
pix -= wrap;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
assert(0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!pix->m_node) return 0;
|
|
Shinya Kitaoka |
120a6e |
Node *q = pix->m_node;
|
|
Shinya Kitaoka |
120a6e |
while (q->m_pixel == 0 && q->m_other) q = q->m_other;
|
|
Shinya Kitaoka |
120a6e |
assert(q && q->m_pixel == pix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < 5; i++) {
|
|
Shinya Kitaoka |
120a6e |
if (!q->m_prev) break;
|
|
Shinya Kitaoka |
120a6e |
q = q->m_prev;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *best = q;
|
|
Shinya Kitaoka |
120a6e |
double bestDist2 = computeDistance2(q, node);
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < 10; i++) {
|
|
Shinya Kitaoka |
120a6e |
q = q->m_next;
|
|
Shinya Kitaoka |
120a6e |
if (!q) break;
|
|
Shinya Kitaoka |
120a6e |
double dist2 = computeDistance2(q, node);
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < bestDist2) {
|
|
Shinya Kitaoka |
120a6e |
bestDist2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
best = q;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return best;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD findDirection(Node *na, Node *nb, int skip) {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < skip; i++) {
|
|
Shinya Kitaoka |
120a6e |
na = na->m_next;
|
|
Shinya Kitaoka |
120a6e |
nb = nb->m_prev;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 =
|
|
Shinya Kitaoka |
120a6e |
0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
|
|
Shinya Kitaoka |
120a6e |
na = na->m_next;
|
|
Shinya Kitaoka |
120a6e |
nb = nb->m_prev;
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 =
|
|
Shinya Kitaoka |
120a6e |
0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
|
|
Shinya Kitaoka |
120a6e |
na = na->m_next;
|
|
Shinya Kitaoka |
120a6e |
nb = nb->m_prev;
|
|
Shinya Kitaoka |
120a6e |
TPointD p2 =
|
|
Shinya Kitaoka |
120a6e |
0.5 * (convert(na->m_pixel->m_pos) + convert(nb->m_pixel->m_pos));
|
|
Shinya Kitaoka |
120a6e |
TPointD dir = 0.25 * (3 * (p1 - p0) + (p2 - p1));
|
|
Shinya Kitaoka |
120a6e |
double dirn = norm(dir);
|
|
Shinya Kitaoka |
120a6e |
if (dirn > 0)
|
|
Shinya Kitaoka |
120a6e |
return dir * (1 / dirn);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return dir;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void setEndpointsDirections(ProtoStroke &protoStroke) {
|
|
Shinya Kitaoka |
120a6e |
assert(!protoStroke.m_points.empty());
|
|
Shinya Kitaoka |
120a6e |
int size = protoStroke.m_points.size();
|
|
Shinya Kitaoka |
120a6e |
double startThickness = 0, endThickness = 0;
|
|
Shinya Kitaoka |
120a6e |
if (size == 1) return;
|
|
Shinya Kitaoka |
120a6e |
if (size < 5) {
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[0] - protoStroke.m_points[1];
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 1] - protoStroke.m_points[size - 2];
|
|
Shinya Kitaoka |
120a6e |
} else if (size < 10) {
|
|
Shinya Kitaoka |
120a6e |
assert(protoStroke.m_points.front() != protoStroke.m_points.back());
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[0] - protoStroke.m_points[2];
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 1] - protoStroke.m_points[size - 3];
|
|
Shinya Kitaoka |
120a6e |
startThickness =
|
|
Shinya Kitaoka |
120a6e |
0.5 * (protoStroke.m_points[1].thick + protoStroke.m_points[2].thick);
|
|
Shinya Kitaoka |
120a6e |
endThickness = 0.5 * (protoStroke.m_points[size - 2].thick +
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 3].thick);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection = 4 * protoStroke.m_points[0];
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection = 4 * protoStroke.m_points[size - 1];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < 4; ++i) {
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection -= protoStroke.m_points[3 + i];
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection -= protoStroke.m_points[size - 4 - i];
|
|
Shinya Kitaoka |
120a6e |
startThickness += protoStroke.m_points[i].thick;
|
|
Shinya Kitaoka |
120a6e |
endThickness += protoStroke.m_points[size - i - 1].thick;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection = protoStroke.m_startDirection * (1 / 4.0);
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection = protoStroke.m_endDirection * (1 / 4.0);
|
|
Shinya Kitaoka |
120a6e |
startThickness *= (1 / 4.0);
|
|
Shinya Kitaoka |
120a6e |
endThickness *= (1 / 4.0);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double startNorm = norm(protoStroke.m_startDirection);
|
|
Shinya Kitaoka |
120a6e |
if (startNorm)
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_startDirection * (1 / startNorm);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double endNorm = norm(protoStroke.m_endDirection);
|
|
Shinya Kitaoka |
120a6e |
if (endNorm)
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_endDirection = protoStroke.m_endDirection * (1 / endNorm);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (startThickness != 0)
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[0].thick = protoStroke.m_points[1].thick =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[2].thick = startThickness;
|
|
Shinya Kitaoka |
120a6e |
if (endThickness != 0)
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 1].thick =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 2].thick =
|
|
Shinya Kitaoka |
120a6e |
protoStroke.m_points[size - 3].thick = endThickness;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool CenterLineVectorizer::testOtherSide(Node *na1, Node *nb1,
|
|
Shinya Kitaoka |
120a6e |
double &startDist2) {
|
|
Shinya Kitaoka |
120a6e |
if (na1->m_pixel->m_pos == nb1->m_pixel->m_pos || na1->m_next == nb1 ||
|
|
Shinya Kitaoka |
120a6e |
na1->m_prev == nb1 || na1->m_next->m_next == nb1 ||
|
|
Shinya Kitaoka |
120a6e |
na1->m_prev->m_prev == nb1)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *na2 = na1->m_next;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 1; i < 3; ++i) {
|
|
Shinya Kitaoka |
120a6e |
na2 = na2->m_next;
|
|
Shinya Kitaoka |
120a6e |
Node *nb2 = findOtherSide(na2);
|
|
Shinya Kitaoka |
120a6e |
if (nb2 == 0 && i == 3) return true;
|
|
Shinya Kitaoka |
120a6e |
if (nb2 == 0) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double newStartDist2 = computeDistance2(na2, nb2);
|
|
Shinya Kitaoka |
120a6e |
if (newStartDist2 > startDist2) startDist2 = newStartDist2;
|
|
Shinya Kitaoka |
120a6e |
for (int j = 0; j < 3 * i + 1; ++j) {
|
|
Shinya Kitaoka |
120a6e |
if (nb2 == nb1) return true;
|
|
Shinya Kitaoka |
120a6e |
nb2 = nb2->m_next;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
bool CenterLineVectorizer::isHole(Node *startNode)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
Node *node = startNode;
|
|
Shinya Kitaoka |
120a6e |
for(int i=0; i<20; ++i)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
node = node->m_next;
|
|
Shinya Kitaoka |
120a6e |
if(node == startNode)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
do
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
node = node->m_next;
|
|
Shinya Kitaoka |
120a6e |
node->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
node->m_flag = true;
|
|
Shinya Kitaoka |
120a6e |
points.push_back(convert(node->m_pixel->m_pos));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
while(node != startNode);
|
|
Shinya Kitaoka |
120a6e |
m_protoHoles.push_back(points);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool isJunction(const Node *na, const Node *nb) {
|
|
Shinya Kitaoka |
120a6e |
TPointD pa = convert(na->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
TPointD pb = convert(nb->m_pixel->m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Node *na0 = na->m_prev;
|
|
Shinya Kitaoka |
120a6e |
Node *na1 = na->m_next;
|
|
Shinya Kitaoka |
120a6e |
Node *nb0 = nb->m_next;
|
|
Shinya Kitaoka |
120a6e |
Node *nb1 = nb->m_prev;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD da = convert(na1->m_pixel->m_pos) - pa;
|
|
Shinya Kitaoka |
120a6e |
TPointD db = convert(nb1->m_pixel->m_pos) - pb;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD da0 = pa - convert(na0->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
TPointD db0 = pb - convert(nb0->m_pixel->m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if ((da0.x * da.x + da0.y * da.y) / (norm(da0) * norm(da)) <= 0) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((db0.x * db.x + db0.y * db.y) / (norm(db0) * norm(db)) <= 0) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (right(TPointD(0, 0), da, db)) {
|
|
Shinya Kitaoka |
120a6e |
if ((da.x * db.x + da.y * db.y) / (norm(da) * norm(db)) <= 0) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if ((da.x * db.x + da.y * db.y) / (norm(da) * norm(db)) <= -0.5) {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::traceLine(DataPixel *pix) {
|
|
Shinya Kitaoka |
120a6e |
Junction *startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
Junction *endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
assert(m_dataRaster);
|
|
Shinya Kitaoka |
120a6e |
const int wrap = m_dataRaster->getWrap();
|
|
Shinya Kitaoka |
120a6e |
// TRect bounds = m_dataRaster->getBounds();
|
|
Shinya Kitaoka |
120a6e |
if (!pix->m_ink) return;
|
|
Shinya Kitaoka |
120a6e |
while (pix->m_node == 0) pix -= wrap;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *node = pix->m_node;
|
|
Shinya Kitaoka |
120a6e |
while (node && node->m_pixel == 0 && node->m_other) node = node->m_other;
|
|
Shinya Kitaoka |
120a6e |
assert(node && node->m_pixel == pix);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *naa = node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isSamePixel;
|
|
Shinya Kitaoka |
120a6e |
if (node->m_other && node->m_other->m_pixel &&
|
|
Shinya Kitaoka |
120a6e |
(node->m_pixel->m_pos == node->m_other->m_pixel->m_pos)) {
|
|
Shinya Kitaoka |
120a6e |
node = node->m_other;
|
|
Shinya Kitaoka |
120a6e |
isSamePixel = true;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
node = findOtherSide(node);
|
|
Shinya Kitaoka |
120a6e |
isSamePixel = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (node == 0) return;
|
|
Shinya Kitaoka |
120a6e |
Node *nbb = node;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (naa->m_visited || nbb->m_visited) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double startDist2 = computeDistance2(naa, nbb);
|
|
Shinya Kitaoka |
120a6e |
if (startDist2 > 2000) return;
|
|
Shinya Kitaoka |
120a6e |
if (startDist2 < THICKNESS_LIMIT_2) startDist2 = THICKNESS_LIMIT_2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// try to detect errors in findOtherSide
|
|
Shinya Kitaoka |
120a6e |
if (!isSamePixel && !testOtherSide(naa, nbb, startDist2)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double minDist2 = 0;
|
|
Shinya Kitaoka |
120a6e |
double maxDist2 = startDist2 + 3.0;
|
|
Shinya Kitaoka |
120a6e |
if (startDist2 > 36) {
|
|
Shinya Kitaoka |
120a6e |
minDist2 = startDist2 / 2;
|
|
Shinya Kitaoka |
120a6e |
maxDist2 = startDist2 + 0.25 * startDist2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (naa->m_next == nbb || naa->m_prev == nbb) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
naa->m_visited = nbb->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
std::deque<tthickpoint> dpoints;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (int k = 0; k < 2; k++) {
|
|
Shinya Kitaoka |
120a6e |
Node *na = naa;
|
|
Shinya Kitaoka |
120a6e |
Node *nb = nbb;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
TPoint &pa = na->m_pixel->m_pos;
|
|
Shinya Kitaoka |
120a6e |
TPoint &pb = nb->m_pixel->m_pos;
|
|
Shinya Kitaoka |
120a6e |
TPoint ba = pb - pa;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *na1 = na->m_next;
|
|
Shinya Kitaoka |
120a6e |
Node *nb1 = nb->m_prev;
|
|
Shinya Kitaoka |
120a6e |
// if (!na1 || !nb1) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPoint da = na1->m_pixel->m_pos - pb;
|
|
Shinya Kitaoka |
120a6e |
TPoint db = nb1->m_pixel->m_pos - pa;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (na1->m_junction || nb1->m_junction) {
|
|
Shinya Kitaoka |
120a6e |
na1->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
nb1->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
TPointD p1;
|
|
Shinya Kitaoka |
120a6e |
if (na1->m_junction && nb1->m_junction) {
|
|
Shinya Kitaoka |
120a6e |
// assert(na1->m_junction ==
|
|
Shinya Kitaoka |
38fd86 |
// nb1->m_junction);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (na1->m_junction) {
|
|
Shinya Kitaoka |
120a6e |
p1 = convert(nb1->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
nb1->m_junction = na1->m_junction;
|
|
Shinya Kitaoka |
120a6e |
na1->m_junction->m_nodes.push_front(nb1);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
p1 = convert(na1->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
na1->m_junction = nb1->m_junction;
|
|
Shinya Kitaoka |
120a6e |
nb1->m_junction->m_nodes.push_back(na1);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double r;
|
|
Shinya Kitaoka |
120a6e |
TPointD center;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
center = computeCenter(na, nb, r);
|
|
Shinya Kitaoka |
120a6e |
if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
point = TThickPoint(center, r);
|
|
Shinya Kitaoka |
120a6e |
if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_front(point);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
center = computeCenter(na1, nb1, r);
|
|
Shinya Kitaoka |
120a6e |
if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
point = TThickPoint(center, r);
|
|
Shinya Kitaoka |
120a6e |
if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_front(point);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
startJunction = na1->m_junction;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
endJunction = na1->m_junction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if(da*ba>-db*ba)
|
|
Shinya Kitaoka |
120a6e |
if (norm2(db) >= norm2(da)) {
|
|
Shinya Kitaoka |
120a6e |
if (na1->m_visited) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
na = na1;
|
|
Shinya Kitaoka |
120a6e |
na->m_visited = true;
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
getOutPix(na->m_pixel) = TPixel32::Red;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (nb1->m_visited) break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
nb = nb1;
|
|
Shinya Kitaoka |
120a6e |
nb->m_visited = true;
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
getOutPix(nb->m_pixel) = TPixel32::Green;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double distance2 = computeDistance2(na, nb);
|
|
Shinya Kitaoka |
120a6e |
if (distance2 < 0.25) distance2 = 0.25;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double r;
|
|
Shinya Kitaoka |
120a6e |
TPointD center = computeCenter(na, nb, r);
|
|
Shinya Kitaoka |
120a6e |
if (r < THICKNESS_LIMIT) r = THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point(center, r);
|
|
Shinya Kitaoka |
120a6e |
TPointI pos = convert(center);
|
|
Shinya Kitaoka |
120a6e |
// TPixel32 *inPix = m_src->pixels(pos.y);
|
|
Shinya Kitaoka |
120a6e |
// inPix += pos.x;
|
|
Shinya Kitaoka |
120a6e |
// int value = (inPix->r + 2*inPix->g + inPix->b)>>2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (distance2 > maxDist2 || distance2 < minDist2 || na->m_next == nb ||
|
|
Shinya Kitaoka |
120a6e |
na->m_prev == nb
|
|
Shinya Kitaoka |
120a6e |
//|| isJunction(na, nb)
|
|
Shinya Kitaoka |
120a6e |
//|| !(value<200)
|
|
Shinya Kitaoka |
120a6e |
) {
|
|
Shinya Kitaoka |
120a6e |
if (na->m_next == nb || na->m_prev == nb || na->m_next->m_next == nb ||
|
|
Shinya Kitaoka |
120a6e |
na->m_prev->m_prev == nb) {
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (!dpoints.empty()) dpoints.pop_front();
|
|
Shinya Kitaoka |
120a6e |
if (!dpoints.empty()) dpoints.pop_front();
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (!dpoints.empty()) dpoints.pop_back();
|
|
Shinya Kitaoka |
120a6e |
if (!dpoints.empty()) dpoints.pop_back();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// if(k==0) dpoints.push_front(point);
|
|
Shinya Kitaoka |
120a6e |
// else dpoints.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
na->m_junction = nb->m_junction = new Junction();
|
|
Shinya Kitaoka |
120a6e |
na->m_junction->m_nodes.push_back(nb);
|
|
Shinya Kitaoka |
120a6e |
nb->m_junction->m_nodes.push_back(na);
|
|
Shinya Kitaoka |
120a6e |
m_junctions.push_back(na->m_junction);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
startJunction = na->m_junction;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
endJunction = na->m_junction;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_front(point);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
dpoints.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tswap(naa, nbb);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (dpoints.size() == 0)
|
|
Shinya Kitaoka |
120a6e |
naa->m_visited = nbb->m_visited = false;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.push_back(ProtoStroke(dpoints.begin(), dpoints.end()));
|
|
Shinya Kitaoka |
120a6e |
setEndpointsDirections(m_protoStrokes.back());
|
|
Shinya Kitaoka |
120a6e |
if (startJunction) {
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.back().m_startJunction = startJunction;
|
|
Shinya Kitaoka |
120a6e |
startJunction->m_protoStrokes.push_back(&m_protoStrokes.back());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (endJunction) {
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.back().m_endJunction = endJunction;
|
|
Shinya Kitaoka |
120a6e |
endJunction->m_protoStrokes.push_back(&m_protoStrokes.back());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Node *CenterLineVectorizer::createNode(DataPixel *pix) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = new Node();
|
|
Shinya Kitaoka |
120a6e |
node->m_pixel = pix;
|
|
Shinya Kitaoka |
120a6e |
node->m_other = pix->m_node;
|
|
Shinya Kitaoka |
120a6e |
pix->m_node = node;
|
|
Shinya Kitaoka |
120a6e |
m_nodes.push_back(node);
|
|
Shinya Kitaoka |
120a6e |
return node;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::createNodes() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::outputNodes(Node *node) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
Node *start = node, *curr = node;
|
|
Shinya Kitaoka |
120a6e |
int i = 0;
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point(convert(curr->m_pixel->m_pos), 0);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
curr->m_flag = true;
|
|
Shinya Kitaoka |
120a6e |
assert(curr->m_next);
|
|
Shinya Kitaoka |
120a6e |
curr = curr->m_next;
|
|
Shinya Kitaoka |
120a6e |
i++;
|
|
Shinya Kitaoka |
120a6e |
} while (curr != start);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point(convert(curr->m_pixel->m_pos), 0);
|
|
Shinya Kitaoka |
120a6e |
points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
m_outlines.push_back(points);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool CenterLineVectorizer::linkNextProtoStroke(
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke *const dstProtoStroke, Junction *const currJunction, int k) {
|
|
Shinya Kitaoka |
120a6e |
assert(dstProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
assert(currJunction);
|
|
Shinya Kitaoka |
120a6e |
// if(dstProtoStroke->m_startJunction == dstProtoStroke->m_endJunction)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
if (k == 0 && dstProtoStroke->m_startJunction->m_locked ||
|
|
Shinya Kitaoka |
120a6e |
k == 1 && dstProtoStroke->m_endJunction->m_locked)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke *srcProtoStroke = 0;
|
|
Shinya Kitaoka |
120a6e |
Junction *nextJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_e =</protostroke>
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_protoStrokes.end();
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_candidate = it_e;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
double candidateProbability = JOIN_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
int candidate_k;
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_protoStrokes.begin(); it != it_e; it++) {
|
|
Shinya Kitaoka |
120a6e |
// erase dstProtoStroke in currJunction
|
|
Shinya Kitaoka |
120a6e |
if (*it == dstProtoStroke) {
|
|
Shinya Kitaoka |
120a6e |
it = currJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
it_e = currJunction->m_protoStrokes.end();
|
|
Shinya Kitaoka |
120a6e |
if (candidateProbability == JOIN_LIMIT) it_candidate = it_e;
|
|
Shinya Kitaoka |
120a6e |
if (it == it_e) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double probability;
|
|
Shinya Kitaoka |
120a6e |
int next_k;
|
|
Shinya Kitaoka |
120a6e |
if (((*it))->m_startJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 0;
|
|
Shinya Kitaoka |
120a6e |
else if ((*it)->m_endJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (next_k == 0)
|
|
Shinya Kitaoka |
120a6e |
probability = 1 - norm2(dstProtoStroke->m_startDirection +
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_startDirection);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
probability =
|
|
Shinya Kitaoka |
120a6e |
1 - norm2(dstProtoStroke->m_startDirection + (*it)->m_endDirection);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (next_k == 0)
|
|
Shinya Kitaoka |
120a6e |
probability =
|
|
Shinya Kitaoka |
120a6e |
1 - norm2(dstProtoStroke->m_endDirection + (*it)->m_startDirection);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
probability =
|
|
Shinya Kitaoka |
120a6e |
1 - norm2(dstProtoStroke->m_endDirection + (*it)->m_endDirection);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (probability > candidateProbability ||
|
|
Shinya Kitaoka |
120a6e |
// currJunction->m_junctionOrder == 2 ||
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.size() < 3) {
|
|
Shinya Kitaoka |
120a6e |
it_candidate = it;
|
|
Shinya Kitaoka |
120a6e |
candidateProbability = probability;
|
|
Shinya Kitaoka |
120a6e |
candidate_k = next_k;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (it_candidate == it_e) return false;
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke = *it_candidate;
|
|
Shinya Kitaoka |
120a6e |
assert(srcProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((*it_candidate)->m_startJunction == (*it_candidate)->m_endJunction)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
/* if(k==0)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if( candidate_k == 0 && dstProtoStroke->m_startJunction ==
|
|
Toshihiro Shimizu |
890ddd |
(*it_candidate)->m_endJunction ||
|
|
Shinya Kitaoka |
120a6e |
candidate_k == 1 && dstProtoStroke->m_startJunction ==
|
|
Toshihiro Shimizu |
890ddd |
(*it_candidate)->m_startJunction )
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else if(k==1)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if( candidate_k == 0 && dstProtoStroke->m_endJunction ==
|
|
Toshihiro Shimizu |
890ddd |
(*it_candidate)->m_endJunction ||
|
|
Shinya Kitaoka |
120a6e |
candidate_k == 1 && dstProtoStroke->m_endJunction ==
|
|
Toshihiro Shimizu |
890ddd |
(*it_candidate)->m_startJunction )
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
if (candidate_k == 0)
|
|
Shinya Kitaoka |
120a6e |
nextJunction = (*it_candidate)->m_endJunction;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
nextJunction = (*it_candidate)->m_startJunction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (candidate_k == 0) {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_points.insert(dstProtoStroke->m_points.begin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.rbegin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.rend());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_points.insert(dstProtoStroke->m_points.begin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.begin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.end());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (candidate_k == 0) {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_points.insert(dstProtoStroke->m_points.end(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.begin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.end());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_points.insert(dstProtoStroke->m_points.end(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.rbegin(),
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.rend());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
srcProtoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// refresh currJunction
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_protoStrokes.erase(it_candidate);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// refresh nextJunction
|
|
Shinya Kitaoka |
120a6e |
if (nextJunction) {
|
|
Shinya Kitaoka |
120a6e |
it = std::find(nextJunction->m_protoStrokes.begin(),
|
|
Shinya Kitaoka |
120a6e |
nextJunction->m_protoStrokes.end(), srcProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
assert(it != nextJunction->m_protoStrokes.end());
|
|
Shinya Kitaoka |
120a6e |
nextJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
nextJunction->m_protoStrokes.push_back(dstProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startJunction = nextJunction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (candidate_k == 0)
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startDirection = srcProtoStroke->m_endDirection;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startDirection = srcProtoStroke->m_startDirection;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endJunction = nextJunction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (candidate_k == 0)
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endDirection = srcProtoStroke->m_endDirection;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endDirection = srcProtoStroke->m_startDirection;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (!nextJunction) return false;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::joinProtoStrokes(ProtoStroke *const dstProtoStroke) {
|
|
Shinya Kitaoka |
120a6e |
// std::deque<tthickpoint> &dstPoints = dstProtoStroke->m_points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
for (int k = 0; k < 2; k++) {
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
Junction *currJunction;
|
|
Shinya Kitaoka |
120a6e |
if (k == 0 && !dstProtoStroke->m_startJunction)
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
else if (k == 0)
|
|
Shinya Kitaoka |
120a6e |
currJunction = dstProtoStroke->m_startJunction;
|
|
Shinya Kitaoka |
120a6e |
else if (!dstProtoStroke->m_endJunction)
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
currJunction = dstProtoStroke->m_endJunction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!linkNextProtoStroke(dstProtoStroke, currJunction, k)) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
if (dstProtoStroke->m_startJunction) {
|
|
Shinya Kitaoka |
120a6e |
it = std::find(dstProtoStroke->m_startJunction->m_protoStrokes.begin(),
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startJunction->m_protoStrokes.end(),
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
if (it != dstProtoStroke->m_startJunction->m_protoStrokes.end())
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (dstProtoStroke->m_endJunction) {
|
|
Shinya Kitaoka |
120a6e |
it = std::find(dstProtoStroke->m_endJunction->m_protoStrokes.begin(),
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endJunction->m_protoStrokes.end(),
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
if (it != dstProtoStroke->m_endJunction->m_protoStrokes.end())
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
dstProtoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool y_intersect(const double y0, const TPointD p1, const TPointD p2,
|
|
Shinya Kitaoka |
120a6e |
double &x0) {
|
|
Shinya Kitaoka |
120a6e |
if ((y0 < p1.y && y0 < p2.y) || (y0 > p1.y && y0 > p2.y)) return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
x0 = (p1.x * (p2.y - y0) + p2.x * (y0 - p1.y)) / (p2.y - p1.y);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool isContained(TThickPoint point, std::deque<node *=""> &polygon) {</node>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_b = polygon.begin();</node>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_e = polygon.end();</node>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it;</node>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int intersectionsNumber = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (it = it_b; it < it_e; ++it) {
|
|
Shinya Kitaoka |
120a6e |
double x;
|
|
Shinya Kitaoka |
120a6e |
TPointD p1, p2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
p1 = convert((*it)->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
if ((it + 1) == it_e)
|
|
Shinya Kitaoka |
120a6e |
p2 = convert((*it_b)->m_pixel->m_pos);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
p2 = convert((*(it + 1))->m_pixel->m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (point.y == p1.y || point.y == p2.y || p1.y == p2.y) continue;
|
|
Shinya Kitaoka |
120a6e |
if (y_intersect(point.y, p1, p2, x) && x >= point.x) ++intersectionsNumber;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return (intersectionsNumber % 2 == 0) ? false : true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Junction *CenterLineVectorizer::mergeJunctions(
|
|
Shinya Kitaoka |
120a6e |
const std::list<junctionmerge> &junctions) {</junctionmerge>
|
|
Shinya Kitaoka |
120a6e |
Junction *newJunction = new Junction();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::list<junctionmerge>::const_iterator it_junction;</junctionmerge>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_startNode, it_endNode;</node>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (it_junction = junctions.begin(); it_junction != junctions.end();
|
|
Shinya Kitaoka |
120a6e |
++it_junction) {
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_center += it_junction->m_junction->m_center;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_node;</node>
|
|
Shinya Kitaoka |
120a6e |
if (it_junction->m_startNode == 0 && it_junction->m_endNode == 0) {
|
|
Shinya Kitaoka |
120a6e |
for (it_node = it_junction->m_junction->m_nodes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_node != it_junction->m_junction->m_nodes.end(); ++it_node) {
|
|
Shinya Kitaoka |
120a6e |
(*it_node)->m_junction = newJunction;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_nodes.push_back(*it_node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
// if(
|
|
Shinya Kitaoka |
38fd86 |
// isContained(it_junction->m_junction->m_center, newJunction->m_nodes) )
|
|
Shinya Kitaoka |
38fd86 |
// continue;
|
|
Shinya Kitaoka |
120a6e |
/* if(
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction->m_nodes.size() < 3)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke*>::iterator it_protoStroke;</protostroke*>
|
|
Shinya Kitaoka |
120a6e |
bool ignoreJunction = false;
|
|
Shinya Kitaoka |
120a6e |
for(it_protoStroke =
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_protoStroke!=it_junction->m_junction->m_protoStrokes.end();
|
|
Shinya Kitaoka |
120a6e |
++it_protoStroke)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
38fd86 |
if( (*it_protoStroke)->m_startJunction ==
|
|
Shinya Kitaoka |
38fd86 |
newJunction
|
|
Shinya Kitaoka |
120a6e |
||
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_endJunction == newJunction )
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
ignoreJunction = true;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if(ignoreJunction) continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
it_startNode =
|
|
Shinya Kitaoka |
120a6e |
std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_startNode);
|
|
Shinya Kitaoka |
120a6e |
assert(it_startNode != newJunction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
it_endNode = std::find(it_junction->m_junction->m_nodes.begin(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction->m_nodes.end(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_endNode);
|
|
Shinya Kitaoka |
120a6e |
assert(it_endNode != it_junction->m_junction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (it_node = it_junction->m_junction->m_nodes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_node != it_junction->m_junction->m_nodes.end(); ++it_node) {
|
|
Shinya Kitaoka |
120a6e |
(*it_node)->m_junction = newJunction;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (it_junction->m_isNext) {
|
|
Shinya Kitaoka |
120a6e |
++it_startNode;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_nodes.insert(
|
|
Shinya Kitaoka |
120a6e |
it_startNode, it_junction->m_junction->m_nodes.begin(), it_endNode);
|
|
Shinya Kitaoka |
120a6e |
it_startNode =
|
|
Shinya Kitaoka |
120a6e |
std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_startNode);
|
|
Shinya Kitaoka |
120a6e |
assert(it_startNode != newJunction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
++it_startNode;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_nodes.insert(it_startNode, it_endNode,
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
++it_endNode;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_nodes.insert(
|
|
Shinya Kitaoka |
120a6e |
it_startNode, it_junction->m_junction->m_nodes.begin(), it_endNode);
|
|
Shinya Kitaoka |
120a6e |
it_startNode =
|
|
Shinya Kitaoka |
120a6e |
std::find(newJunction->m_nodes.begin(), newJunction->m_nodes.end(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_startNode);
|
|
Shinya Kitaoka |
120a6e |
assert(it_startNode != newJunction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_nodes.insert(it_startNode, it_endNode,
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_protoStroke;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
for (it_protoStroke = it_junction->m_junction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_protoStroke != it_junction->m_junction->m_protoStrokes.end();
|
|
Shinya Kitaoka |
120a6e |
++it_protoStroke) {
|
|
Shinya Kitaoka |
120a6e |
if ((*it_protoStroke)->m_startJunction == it_junction->m_junction) {
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_startJunction = newJunction;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_protoStrokes.push_back(*it_protoStroke);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if ((*it_protoStroke)->m_endJunction == it_junction->m_junction) {
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_endJunction = newJunction;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_protoStrokes.push_back(*it_protoStroke);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::vector<junctionlink>::iterator it_links;</junctionlink>
|
|
Shinya Kitaoka |
120a6e |
for (it_links = m_links.begin(); it_links != m_links.end(); ++it_links) {
|
|
Shinya Kitaoka |
120a6e |
if (it_links->m_first == it_junction->m_junction)
|
|
Shinya Kitaoka |
120a6e |
it_links->m_first = newJunction;
|
|
Shinya Kitaoka |
120a6e |
if (it_links->m_second == it_junction->m_junction)
|
|
Shinya Kitaoka |
120a6e |
it_links->m_second = newJunction;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// erase old junction
|
|
Shinya Kitaoka |
120a6e |
std::vector<junction *="">::iterator it;</junction>
|
|
Shinya Kitaoka |
120a6e |
it = std::find(m_junctions.begin(), m_junctions.end(),
|
|
Shinya Kitaoka |
120a6e |
it_junction->m_junction);
|
|
Shinya Kitaoka |
120a6e |
assert(it != m_junctions.end());
|
|
Shinya Kitaoka |
120a6e |
delete it_junction->m_junction;
|
|
Shinya Kitaoka |
120a6e |
m_junctions.erase(it);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double size = junctions.size();
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_center = newJunction->m_center * (1 / size);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_protoStroke;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
for (it_protoStroke = newJunction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_protoStroke != newJunction->m_protoStrokes.end(); ++it_protoStroke) {
|
|
Shinya Kitaoka |
120a6e |
if ((*it_protoStroke)->m_points.size() < 6 &&
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_startJunction == newJunction &&
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_endJunction == newJunction) {
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
(*it_protoStroke)->m_startJunction = (*it_protoStroke)->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke *protoStroke = *it_protoStroke;
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
it = std::find(newJunction->m_protoStrokes.begin(),
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_protoStrokes.end(), protoStroke);
|
|
Shinya Kitaoka |
120a6e |
if (it == newJunction->m_protoStrokes.end()) break;
|
|
Shinya Kitaoka |
120a6e |
newJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (newJunction->m_protoStrokes.empty()) break;
|
|
Shinya Kitaoka |
120a6e |
it_protoStroke = newJunction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return newJunction;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::joinJunctions() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)m_junctions.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Junction *currJunction = m_junctions[i];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if(currJunction->m_nodes.size() <= 2) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::list<junctionmerge> joinJunctions;</junctionmerge>
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.push_back(JunctionMerge(currJunction));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// std::sort(currJunction->m_nodes.begin(),
|
|
Shinya Kitaoka |
38fd86 |
// currJunction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it;</node>
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_nodes.begin(); it != currJunction->m_nodes.end();
|
|
Shinya Kitaoka |
120a6e |
it++) {
|
|
Shinya Kitaoka |
120a6e |
Node *currNode = *it;
|
|
Shinya Kitaoka |
120a6e |
Node *prevNode = *it;
|
|
Shinya Kitaoka |
120a6e |
Node *nextNode = *it;
|
|
Shinya Kitaoka |
120a6e |
std::vector<junctionlink>::iterator it_link;</junctionlink>
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; true; ++j) {
|
|
Shinya Kitaoka |
120a6e |
prevNode = prevNode->m_prev;
|
|
Shinya Kitaoka |
120a6e |
prevNode->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
if (prevNode->m_junction != 0 && prevNode->m_junction != currJunction) {
|
|
Shinya Kitaoka |
120a6e |
// double junctionMaxDist = 3.5*currJunction->m_center.thick;
|
|
Shinya Kitaoka |
120a6e |
it_link = std::find(m_links.begin(), m_links.end(),
|
|
Shinya Kitaoka |
120a6e |
JunctionLink(currJunction, prevNode->m_junction));
|
|
Shinya Kitaoka |
120a6e |
/* if( j >= 1*SEARCH_WINDOW &&
|
|
Toshihiro Shimizu |
890ddd |
norm(currJunction->m_center - prevNode->m_junction->m_center) >=
|
|
Toshihiro Shimizu |
890ddd |
junctionMaxDist)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
if(it_link == m_links.end())
|
|
Toshihiro Shimizu |
890ddd |
m_links.push_back(JunctionLink(currJunction, prevNode->m_junction));
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
++(it_link->m_order);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
else*/ if (it_link == m_links.end() &&
|
|
Shinya Kitaoka |
120a6e |
std::find(
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.begin(),
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.end(),
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(
|
|
Shinya Kitaoka |
120a6e |
prevNode
|
|
Shinya Kitaoka |
120a6e |
->m_junction)) ==
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.end()) {
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.push_back(
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(prevNode->m_junction, currNode, prevNode, false));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (prevNode->m_visited) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; true; ++j) {
|
|
Shinya Kitaoka |
120a6e |
nextNode = nextNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
prevNode->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
if (nextNode->m_junction != 0 && nextNode->m_junction != currJunction) {
|
|
Shinya Kitaoka |
120a6e |
// double junctionMaxDist = 3.5*currJunction->m_center.thick;
|
|
Shinya Kitaoka |
120a6e |
it_link = std::find(m_links.begin(), m_links.end(),
|
|
Shinya Kitaoka |
120a6e |
JunctionLink(currJunction, nextNode->m_junction));
|
|
Shinya Kitaoka |
120a6e |
/* if( j >= 1*SEARCH_WINDOW &&
|
|
Toshihiro Shimizu |
890ddd |
norm(currJunction->m_center - nextNode->m_junction->m_center) >=
|
|
Toshihiro Shimizu |
890ddd |
junctionMaxDist )
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(false);
|
|
Toshihiro Shimizu |
890ddd |
if(it_link == m_links.end())
|
|
Toshihiro Shimizu |
890ddd |
m_links.push_back(JunctionLink(currJunction, nextNode->m_junction));
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
++(it_link->m_order);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
else*/ if (it_link == m_links.end() &&
|
|
Shinya Kitaoka |
120a6e |
std::find(
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.begin(),
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.end(),
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(
|
|
Shinya Kitaoka |
120a6e |
nextNode
|
|
Shinya Kitaoka |
120a6e |
->m_junction)) ==
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.end()) {
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.push_back(
|
|
Shinya Kitaoka |
120a6e |
JunctionMerge(nextNode->m_junction, currNode, nextNode, true));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (nextNode->m_visited) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (joinJunctions.size() > 1) {
|
|
Shinya Kitaoka |
120a6e |
// erase duplicate junctions
|
|
Shinya Kitaoka |
120a6e |
// joinJunctions.sort();
|
|
Shinya Kitaoka |
120a6e |
// std::sort(joinJunctions.begin(),
|
|
Shinya Kitaoka |
38fd86 |
// joinJunctions.end());
|
|
Shinya Kitaoka |
120a6e |
// std::list<junctionmerge>::iterator it_newEnd;</junctionmerge>
|
|
Shinya Kitaoka |
120a6e |
// it_newEnd = std::unique(joinJunctions.begin(),
|
|
Shinya Kitaoka |
38fd86 |
// joinJunctions.end());
|
|
Shinya Kitaoka |
120a6e |
// assert(it_newEnd == joinJunctions.end());
|
|
Shinya Kitaoka |
120a6e |
// joinJunctions.erase(it_newEnd,
|
|
Shinya Kitaoka |
38fd86 |
// joinJunctions.end());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Junction *newJunction = mergeJunctions(joinJunctions);
|
|
Shinya Kitaoka |
120a6e |
assert(newJunction);
|
|
Shinya Kitaoka |
120a6e |
m_junctions.push_back(newJunction);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
joinJunctions.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
/*
|
|
Toshihiro Shimizu |
890ddd |
void CenterLineVectorizer::resolveUnvisitedNode(Node *node)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_visited == false);
|
|
Shinya Kitaoka |
120a6e |
assert(node->m_junction == 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
JunctionLink link(0,0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node* currNode = node;
|
|
Shinya Kitaoka |
120a6e |
for(int i=0; i<4*SEARCH_WINDOW; i++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
assert(currNode);
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_junction)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
link.m_first = currNode->m_junction;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_visited) break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if(!link.m_first) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int steps = 0;
|
|
Shinya Kitaoka |
120a6e |
for(i=0; i<4*SEARCH_WINDOW; i++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_prev;
|
|
Shinya Kitaoka |
120a6e |
assert(currNode);
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_junction)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
link.m_second = currNode->m_junction;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_visited) break;
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
++steps;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if( (link.m_first) && (link.m_second) && (link.m_first !=
|
|
Shinya Kitaoka |
120a6e |
link.m_second)
|
|
Shinya Kitaoka |
120a6e |
&& steps >= 2*SEARCH_WINDOW && norm(link.m_first->m_center -
|
|
Toshihiro Shimizu |
890ddd |
link.m_second->m_center) > 2.5 &&
|
|
Shinya Kitaoka |
120a6e |
std::find(m_links.begin(), m_links.end(), link) == m_links.end()
|
|
Shinya Kitaoka |
120a6e |
&&
|
|
Shinya Kitaoka |
120a6e |
std::find(m_links.begin(), m_links.end(),
|
|
Shinya Kitaoka |
120a6e |
JunctionLink(link.m_second,
|
|
Toshihiro Shimizu |
890ddd |
link.m_first) ) == m_links.end() )
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
m_links.push_back(link);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
for(int i=0; i<4*SEARCH_WINDOW; i++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
assert(currNode);
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_junction) break;
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::createJunctionPolygon(Junction *junction) {
|
|
Shinya Kitaoka |
120a6e |
// int size = junction->m_nodes.size();
|
|
Shinya Kitaoka |
120a6e |
// std::sort(junction->m_nodes.begin(), junction->m_nodes.end(),
|
|
Shinya Kitaoka |
38fd86 |
// CompareJunctionNodes(junction->m_center));
|
|
Shinya Kitaoka |
120a6e |
// std::reverse(junction->m_nodes.begin(), junction->m_nodes.end());
|
|
Shinya Kitaoka |
38fd86 |
// std::deque<node*>::iterator it, it_temp;</node*>
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it, it_temp;</node>
|
|
Shinya Kitaoka |
120a6e |
for (it = junction->m_nodes.begin(); it != junction->m_nodes.end(); it++) {
|
|
Shinya Kitaoka |
120a6e |
int step = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Node *currNode;
|
|
Shinya Kitaoka |
120a6e |
Node *otherNode;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (it + 1 == junction->m_nodes.end())
|
|
Shinya Kitaoka |
120a6e |
otherNode = *junction->m_nodes.begin();
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
otherNode = *(it + 1);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/* currNode = (*it)->m_prev;
|
|
Shinya Kitaoka |
120a6e |
if(!currNode->m_visited)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
step=0;
|
|
Shinya Kitaoka |
120a6e |
while(!currNode->m_visited && currNode->m_junction != junction)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
it = junction->m_nodes.insert(it+1, currNode);
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_prev;
|
|
Shinya Kitaoka |
120a6e |
++step;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if(currNode->m_junction != junction)
|
|
Shinya Kitaoka |
120a6e |
for(int i=0; i
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = false;
|
|
Shinya Kitaoka |
120a6e |
it = junction->m_nodes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
--it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if(currNode != otherNode)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
it_temp = std::find(junction->m_nodes.begin(),
|
|
Shinya Kitaoka |
120a6e |
junction->m_nodes.end(),
|
|
Toshihiro Shimizu |
890ddd |
currNode);
|
|
Shinya Kitaoka |
120a6e |
if(it+1 == junction->m_nodes.end())
|
|
Shinya Kitaoka |
120a6e |
std::swap(*junction->m_nodes.begin(),
|
|
Shinya Kitaoka |
120a6e |
*it_temp);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
std::swap(*(it+1), *it_temp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
currNode = (*it)->m_next;
|
|
Shinya Kitaoka |
120a6e |
if (!currNode->m_visited) {
|
|
Shinya Kitaoka |
120a6e |
step = 0;
|
|
Shinya Kitaoka |
120a6e |
while (!currNode->m_visited && currNode->m_junction != junction) {
|
|
Shinya Kitaoka |
120a6e |
it = junction->m_nodes.insert(it + 1, currNode);
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
++step;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (currNode->m_junction != junction) //|| currNode != otherNode)
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < step; ++i) {
|
|
Shinya Kitaoka |
120a6e |
currNode = currNode->m_prev;
|
|
Shinya Kitaoka |
120a6e |
currNode->m_visited = false;
|
|
Shinya Kitaoka |
120a6e |
it = junction->m_nodes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
--it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
// assert(*(it+1) == otherNode || (it+1 ==
|
|
Shinya Kitaoka |
38fd86 |
// junction->m_nodes.end() && *junction->m_nodes.begin() == otherNode)
|
|
Shinya Kitaoka |
38fd86 |
// );
|
|
Shinya Kitaoka |
120a6e |
if (currNode != otherNode) {
|
|
Shinya Kitaoka |
120a6e |
Node tempNode = *otherNode;
|
|
Shinya Kitaoka |
120a6e |
*otherNode = *currNode;
|
|
Shinya Kitaoka |
120a6e |
*currNode = tempNode;
|
|
Shinya Kitaoka |
38fd86 |
// it_temp =
|
|
Shinya Kitaoka |
d1f6c4 |
// std::find(junction->m_nodes.begin(),
|
|
Shinya Kitaoka |
38fd86 |
// junction->m_nodes.end(), currNode);
|
|
Shinya Kitaoka |
120a6e |
// assert(it_temp !=
|
|
Shinya Kitaoka |
38fd86 |
// junction->m_nodes.end());
|
|
Shinya Kitaoka |
120a6e |
// if(it+1 ==
|
|
Shinya Kitaoka |
38fd86 |
// junction->m_nodes.end())
|
|
Shinya Kitaoka |
120a6e |
// std::swap(*junction->m_nodes.begin(),
|
|
Shinya Kitaoka |
120a6e |
//*it_temp);
|
|
Shinya Kitaoka |
120a6e |
// else
|
|
Shinya Kitaoka |
120a6e |
// std::swap(*(it+1),
|
|
Shinya Kitaoka |
120a6e |
//*it_temp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::handleLinks() {
|
|
Shinya Kitaoka |
120a6e |
std::vector<junctionlink>::iterator it_links;</junctionlink>
|
|
Shinya Kitaoka |
120a6e |
for (it_links = m_links.begin(); it_links != m_links.end(); ++it_links) {
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke linkingProtoStroke;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// initialize points
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p1 = it_links->m_first->m_center;
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p2 = it_links->m_second->m_center - p1;
|
|
Shinya Kitaoka |
120a6e |
linkingProtoStroke.m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(p1, JUNCTION_THICKNESS_RATIO * p1.thick));
|
|
Shinya Kitaoka |
120a6e |
linkingProtoStroke.m_points.push_back(TThickPoint(
|
|
Shinya Kitaoka |
120a6e |
p1 + 0.5 * p2, JUNCTION_THICKNESS_RATIO * (p1.thick + 0.5 * p2.thick)));
|
|
Shinya Kitaoka |
120a6e |
linkingProtoStroke.m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(p1 + p2, JUNCTION_THICKNESS_RATIO * (p1.thick + p2.thick)));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// initialize directions
|
|
Shinya Kitaoka |
120a6e |
setEndpointsDirections(linkingProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// initialize junctions
|
|
Shinya Kitaoka |
120a6e |
/* linkingProtoStroke.m_startJunction = it_links->first;
|
|
Shinya Kitaoka |
120a6e |
linkingProtoStroke.m_endJunction = it_links->second;*/
|
|
Shinya Kitaoka |
120a6e |
m_protoStrokes.push_back(linkingProtoStroke);
|
|
Shinya Kitaoka |
120a6e |
/* it_links->first->m_protoStrokes.push_back(&m_protoStrokes.back());
|
|
Shinya Kitaoka |
120a6e |
it_links->second->m_protoStrokes.push_back(&m_protoStrokes.back());*/
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool isFalseBranch(int k, ProtoStroke *protoStroke, int recursionOrder,
|
|
Shinya Kitaoka |
120a6e |
TThickPoint &edge) {
|
|
Shinya Kitaoka |
120a6e |
if (recursionOrder > 3) return false;
|
|
Shinya Kitaoka |
120a6e |
++recursionOrder;
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_points.front().thick > 3.0) return false;
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_points.size() <= 20) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_endJunction) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_endJunction->m_protoStrokes.size() == 1) {
|
|
Shinya Kitaoka |
120a6e |
edge = protoStroke->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction->m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} else if (protoStroke->m_endJunction->m_protoStrokes.size() == 2) {
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke *nextProtoStroke;
|
|
Shinya Kitaoka |
120a6e |
int next_k;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_endJunction->m_protoStrokes[0] == protoStroke)
|
|
Shinya Kitaoka |
120a6e |
nextProtoStroke = protoStroke->m_endJunction->m_protoStrokes[1];
|
|
Shinya Kitaoka |
120a6e |
else if (protoStroke->m_endJunction->m_protoStrokes[1] == protoStroke)
|
|
Shinya Kitaoka |
120a6e |
nextProtoStroke = protoStroke->m_endJunction->m_protoStrokes[0];
|
|
Shinya Kitaoka |
120a6e |
if (nextProtoStroke->m_startJunction == protoStroke->m_endJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 0;
|
|
Shinya Kitaoka |
120a6e |
else if (nextProtoStroke->m_endJunction == protoStroke->m_endJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isFalseBranch(next_k, nextProtoStroke, recursionOrder, edge)) {
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction->m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
edge = protoStroke->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (k == 1) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_points.back().thick > 3.0) return false;
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_points.size() <= 20) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_startJunction) {
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_startJunction->m_protoStrokes.size() == 1) {
|
|
Shinya Kitaoka |
120a6e |
edge = protoStroke->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction->m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} else if (protoStroke->m_startJunction->m_protoStrokes.size() == 2) {
|
|
Shinya Kitaoka |
120a6e |
ProtoStroke *nextProtoStroke;
|
|
Shinya Kitaoka |
120a6e |
int next_k;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (protoStroke->m_startJunction->m_protoStrokes[0] == protoStroke)
|
|
Shinya Kitaoka |
120a6e |
nextProtoStroke = protoStroke->m_startJunction->m_protoStrokes[1];
|
|
Shinya Kitaoka |
120a6e |
else if (protoStroke->m_startJunction->m_protoStrokes[1] ==
|
|
Shinya Kitaoka |
120a6e |
protoStroke)
|
|
Shinya Kitaoka |
120a6e |
nextProtoStroke = protoStroke->m_startJunction->m_protoStrokes[0];
|
|
Shinya Kitaoka |
120a6e |
if (nextProtoStroke->m_startJunction == protoStroke->m_startJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 0;
|
|
Shinya Kitaoka |
120a6e |
else if (nextProtoStroke->m_endJunction ==
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isFalseBranch(next_k, nextProtoStroke, recursionOrder, edge)) {
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction->m_protoStrokes.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
edge = protoStroke->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
protoStroke->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::handleJunctions() {
|
|
Shinya Kitaoka |
120a6e |
std::vector<junction *="">::iterator it_junction = m_junctions.begin();</junction>
|
|
Shinya Kitaoka |
120a6e |
for (it_junction = m_junctions.begin(); it_junction < m_junctions.end();
|
|
Shinya Kitaoka |
120a6e |
it_junction++) {
|
|
Shinya Kitaoka |
120a6e |
Junction *currJunction = *it_junction;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_protoStrokes.empty()) {
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_node;</node>
|
|
Shinya Kitaoka |
120a6e |
for (it_node = currJunction->m_nodes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_node != currJunction->m_nodes.end(); ++it_node) {
|
|
Shinya Kitaoka |
120a6e |
(*it_node)->m_junction = 0;
|
|
Shinya Kitaoka |
120a6e |
(*it_node)->m_visited = false;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
delete currJunction;
|
|
Shinya Kitaoka |
120a6e |
it_junction = m_junctions.erase(it_junction);
|
|
Shinya Kitaoka |
120a6e |
--it_junction;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// set polygon center
|
|
Shinya Kitaoka |
120a6e |
/* double size = currJunction->m_nodes.size();
|
|
Shinya Kitaoka |
120a6e |
std::deque<node*>::iterator it_node;</node*>
|
|
Shinya Kitaoka |
120a6e |
for(it_node = currJunction->m_nodes.begin();
|
|
Toshihiro Shimizu |
890ddd |
it_node!=currJunction->m_nodes.end(); it_node++)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center += convert( (*it_node)->m_pixel->m_pos );
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center = currJunction->m_center * (1/size);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
size = currJunction->m_protoStrokes.size();
|
|
Shinya Kitaoka |
120a6e |
if(size == 0)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center.thick = THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
continue;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
double size = currJunction->m_protoStrokes.size();
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it != currJunction->m_protoStrokes.end(); it++) {
|
|
Shinya Kitaoka |
120a6e |
if (((*it))->m_startJunction == currJunction &&
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_endJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center += 0.5 * (*it)->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center += 0.5 * (*it)->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
} else if (((*it))->m_startJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center += (*it)->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
} else if ((*it)->m_endJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center += (*it)->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center = currJunction->m_center * (1 / size);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
int j = 0;
|
|
Shinya Kitaoka |
120a6e |
for (; j < (int)m_nodes.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[j];
|
|
Shinya Kitaoka |
120a6e |
if (!node->m_visited && node->m_pixel) {
|
|
Shinya Kitaoka |
120a6e |
m_unvisitedNodes.push_back(convert(node->m_pixel->m_pos));
|
|
Shinya Kitaoka |
120a6e |
// resolveUnvisitedNode(node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)m_nodes.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[j];
|
|
Shinya Kitaoka |
120a6e |
// assert(node->m_visited || !node->m_pixel);
|
|
Shinya Kitaoka |
120a6e |
if (node->m_pixel == 0 || node->m_flag) continue;
|
|
Shinya Kitaoka |
120a6e |
outputNodes(node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
joinJunctions();
|
|
Shinya Kitaoka |
120a6e |
// return;
|
|
Shinya Kitaoka |
120a6e |
for (it_junction = m_junctions.begin(); it_junction < m_junctions.end();
|
|
Shinya Kitaoka |
120a6e |
it_junction++) {
|
|
Shinya Kitaoka |
120a6e |
Junction *currJunction = *it_junction;
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_center.thick < 2 * THICKNESS_LIMIT)
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center.thick = 2 * THICKNESS_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it, it_next;</protostroke>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
createJunctionPolygon(currJunction);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_junctionOrder = currJunction->m_protoStrokes.size();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_protoStrokes.size() == 3) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_e =</protostroke>
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_protoStrokes.end();
|
|
Shinya Kitaoka |
120a6e |
std::vector<protostroke *="">::iterator it_candidate1 = it_e,</protostroke>
|
|
Shinya Kitaoka |
120a6e |
it_candidate2 = it_e;
|
|
Shinya Kitaoka |
120a6e |
int candidate1_k, candidate2_k;
|
|
Shinya Kitaoka |
120a6e |
double candidateProbability = JOIN_LIMIT;
|
|
Shinya Kitaoka |
120a6e |
int k, next_k;
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_protoStrokes.begin(); it != it_e; it++) {
|
|
Shinya Kitaoka |
120a6e |
if (((*it))->m_startJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
k = 0;
|
|
Shinya Kitaoka |
120a6e |
else if ((*it)->m_endJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
k = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isFalseBranch(k, *it, 0, currJunction->m_center)) {
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_protoStrokes.erase(it);
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_locked = true;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
it_next = it;
|
|
Shinya Kitaoka |
120a6e |
it_next++;
|
|
Shinya Kitaoka |
120a6e |
for (; it_next != it_e; it_next++) {
|
|
Shinya Kitaoka |
120a6e |
double probability;
|
|
Shinya Kitaoka |
120a6e |
if (((*it_next))->m_startJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 0;
|
|
Shinya Kitaoka |
120a6e |
else if ((*it_next)->m_endJunction == currJunction)
|
|
Shinya Kitaoka |
120a6e |
next_k = 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (k == 0) {
|
|
Shinya Kitaoka |
120a6e |
if (next_k == 0)
|
|
Shinya Kitaoka |
120a6e |
probability = 1 - norm2((*it)->m_startDirection +
|
|
Shinya Kitaoka |
120a6e |
(*it_next)->m_startDirection);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
probability = 1 - norm2((*it)->m_startDirection +
|
|
Shinya Kitaoka |
120a6e |
(*it_next)->m_endDirection);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (next_k == 0)
|
|
Shinya Kitaoka |
120a6e |
probability = 1 - norm2((*it)->m_endDirection +
|
|
Shinya Kitaoka |
120a6e |
(*it_next)->m_startDirection);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
probability =
|
|
Shinya Kitaoka |
120a6e |
1 - norm2((*it)->m_endDirection + (*it_next)->m_endDirection);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (probability > candidateProbability ||
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.size() < 3) {
|
|
Shinya Kitaoka |
120a6e |
candidateProbability = probability;
|
|
Shinya Kitaoka |
120a6e |
it_candidate1 = it;
|
|
Shinya Kitaoka |
120a6e |
it_candidate2 = it_next;
|
|
Shinya Kitaoka |
120a6e |
candidate1_k = k;
|
|
Shinya Kitaoka |
120a6e |
candidate2_k = next_k;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_protoStrokes.size() == 3 && it_candidate1 != it_e &&
|
|
Shinya Kitaoka |
120a6e |
it_candidate2 != it_e) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p1 = (candidate1_k == 0)
|
|
Shinya Kitaoka |
120a6e |
? (*it_candidate1)->m_points.front()
|
|
Shinya Kitaoka |
120a6e |
: (*it_candidate1)->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
TThickPoint p2 = (candidate2_k == 0)
|
|
Shinya Kitaoka |
120a6e |
? (*it_candidate2)->m_points.front()
|
|
Shinya Kitaoka |
120a6e |
: (*it_candidate2)->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_center = 0.5 * (p1 + p2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (false || currJunction->m_protoStrokes.size() == 2) {
|
|
Shinya Kitaoka |
120a6e |
TPointD a1, a2, b1, b2;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_protoStrokes[0]->m_startJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
a1 = currJunction->m_protoStrokes[0]->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
a2 = currJunction->m_protoStrokes[0]->m_startDirection - a1;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(currJunction->m_protoStrokes[0]->m_endJunction == currJunction);
|
|
Shinya Kitaoka |
120a6e |
a1 = currJunction->m_protoStrokes[0]->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
a2 = currJunction->m_protoStrokes[0]->m_endDirection - a1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (currJunction->m_protoStrokes[1]->m_startJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
b1 = currJunction->m_protoStrokes[1]->m_points.front();
|
|
Shinya Kitaoka |
120a6e |
b2 = currJunction->m_protoStrokes[1]->m_startDirection - b1;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
assert(currJunction->m_protoStrokes[1]->m_endJunction == currJunction);
|
|
Shinya Kitaoka |
120a6e |
b1 = currJunction->m_protoStrokes[1]->m_points.back();
|
|
Shinya Kitaoka |
120a6e |
b2 = currJunction->m_protoStrokes[1]->m_endDirection - b1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/* TPointD intersection;
|
|
Toshihiro Shimizu |
890ddd |
RectIntersectionResult res;
|
|
Toshihiro Shimizu |
890ddd |
res = rectsIntersect(a1, a2, b1, b2, intersection);
|
|
Toshihiro Shimizu |
890ddd |
// assert(res == intersected);
|
|
Toshihiro Shimizu |
890ddd |
if( norm(intersection - currJunction->m_center) < 5 && res ==
|
|
Toshihiro Shimizu |
890ddd |
intersected)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
currJunction->m_center.x = intersection.x;
|
|
Toshihiro Shimizu |
890ddd |
currJunction->m_center.y = intersection.y;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
*/ }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (true || currJunction->m_nodes.size() <= 12 || currJunction->isConvex()) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint junctionPoint(currJunction->m_center);
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it != currJunction->m_protoStrokes.end(); it++) {
|
|
Shinya Kitaoka |
120a6e |
assert((*it)->m_startJunction == currJunction ||
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_endJunction == currJunction);
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_startJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
TPointD deltaPoint = (*it)->m_points.front() - junctionPoint;
|
|
Shinya Kitaoka |
120a6e |
double deltaThick = (*it)->m_points.front().thick - junctionPoint.thick;
|
|
Shinya Kitaoka |
120a6e |
if (norm2(deltaPoint) > 0.2) {
|
|
Shinya Kitaoka |
120a6e |
if (norm2(deltaPoint) > 2) {
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_front(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.7 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.7 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_front(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.4 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.4 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_front(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.0 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.0 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_endJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
TPointD deltaPoint = (*it)->m_points.back() - junctionPoint;
|
|
Shinya Kitaoka |
120a6e |
double deltaThick = (*it)->m_points.back().thick - junctionPoint.thick;
|
|
Shinya Kitaoka |
120a6e |
if (norm2(deltaPoint) > 0.2) {
|
|
Shinya Kitaoka |
120a6e |
if (norm2(deltaPoint) > 2) {
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.7 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.7 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.4 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.4 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(junctionPoint + 0.0 * deltaPoint,
|
|
Shinya Kitaoka |
120a6e |
junctionPoint.thick + 0.0 * deltaThick));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Shinya Kitaoka |
120a6e |
ProtoRegion region(currJunction->isConvex());
|
|
Shinya Kitaoka |
120a6e |
region.m_center = currJunction->m_center;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::deque<node *="">::iterator it_nodes;</node>
|
|
Shinya Kitaoka |
120a6e |
for (it_nodes = currJunction->m_nodes.begin();
|
|
Shinya Kitaoka |
120a6e |
it_nodes != currJunction->m_nodes.end(); it_nodes++)
|
|
Shinya Kitaoka |
120a6e |
region.m_points.push_back(
|
|
Shinya Kitaoka |
120a6e |
TThickPoint(convert((*it_nodes)->m_pixel->m_pos), 0.0));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
region.m_points.push_back(TThickPoint(
|
|
Shinya Kitaoka |
120a6e |
convert((*currJunction->m_nodes.begin())->m_pixel->m_pos), 0.0));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_protoRegions.push_back(region);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (it = currJunction->m_protoStrokes.begin();
|
|
Shinya Kitaoka |
120a6e |
it != currJunction->m_protoStrokes.end(); it++) {
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_startJunction == currJunction &&
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_endJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_points.size() < 10) (*it)->m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_startJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_startJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if ((*it)->m_endJunction == currJunction) {
|
|
Shinya Kitaoka |
120a6e |
(*it)->m_endJunction = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
currJunction->m_protoStrokes.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// handleLinks();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::createStrokes() {
|
|
Shinya Kitaoka |
120a6e |
std::list<protostroke>::iterator it_centerlines = m_protoStrokes.begin();</protostroke>
|
|
Shinya Kitaoka |
120a6e |
for (; it_centerlines != m_protoStrokes.end(); it_centerlines++) {
|
|
Shinya Kitaoka |
120a6e |
if (!it_centerlines->m_points.empty()) {
|
|
Shinya Kitaoka |
120a6e |
joinProtoStrokes(&(*it_centerlines));
|
|
Shinya Kitaoka |
120a6e |
if (it_centerlines->m_points.size() <= 1) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
std::deque<tthickpoint>::iterator it;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_configuration.m_smoothness > 0) // gmt: prima era true
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// gmt, 30-3-2006:
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
it = it_centerlines->m_points.begin()+1;
|
|
Shinya Kitaoka |
120a6e |
for(;;)
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if( it >=
|
|
Shinya Kitaoka |
120a6e |
it_centerlines->m_points.end()-(m_configuration.m_smoothness+1)) break;
|
|
Shinya Kitaoka |
120a6e |
for(int j=0; j
|
|
Shinya Kitaoka |
120a6e |
it = it_centerlines->m_points.erase(it);
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
*/
|
|
Shinya Kitaoka |
120a6e |
// gmt. credo che l'idea sia di lasciare un punto e
|
|
Shinya Kitaoka |
120a6e |
// toglierne m_configuration.m_smoothness e cosi' via fino alla fine
|
|
Shinya Kitaoka |
120a6e |
// n.b. ho modificato il comportamento sugli eventuali ultimi punti
|
|
Shinya Kitaoka |
120a6e |
// (
|
|
Shinya Kitaoka |
120a6e |
// vengono tolti
|
|
Shinya Kitaoka |
120a6e |
std::deque<tthickpoint> &points = it_centerlines->m_points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
it = points.begin();
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (it == points.end()) break;
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
int maxD = std::distance(it, points.end());
|
|
Shinya Kitaoka |
120a6e |
int d = tmin(maxD, m_configuration.m_smoothness);
|
|
Shinya Kitaoka |
120a6e |
if (d == 0) break;
|
|
Shinya Kitaoka |
120a6e |
it = points.erase(it, it + d);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
it = it_centerlines->m_points.begin();
|
|
Shinya Kitaoka |
120a6e |
points.push_back(*it);
|
|
Shinya Kitaoka |
120a6e |
assert(it->thick >= THICKNESS_LIMIT);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint old = *it;
|
|
Shinya Kitaoka |
120a6e |
for (it++; it != it_centerlines->m_points.end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
assert(it->thick >= THICKNESS_LIMIT);
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point(0.5 * (*it + old), 0.5 * (it->thick + old.thick));
|
|
Shinya Kitaoka |
120a6e |
points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
old = *it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
points.push_back(it_centerlines->m_points.back());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int n = points.size();
|
|
Shinya Kitaoka |
120a6e |
if (n > 5) {
|
|
Shinya Kitaoka |
120a6e |
double *rr = new double[n];
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < n; i++) rr[i] = points[i].thick;
|
|
Shinya Kitaoka |
120a6e |
for (i = 2; i < n - 2; i++)
|
|
Shinya Kitaoka |
120a6e |
points[i].thick = 0.8 * (1 / 5.0) * (/*rr[i-4]+rr[i-3]*/ +rr[i - 2] +
|
|
Shinya Kitaoka |
120a6e |
rr[i - 1] + rr[i] + rr[i + 1] +
|
|
Shinya Kitaoka |
120a6e |
rr[i + 2] /*+rr[i+3]+rr[i+4]*/);
|
|
Shinya Kitaoka |
120a6e |
points[0].thick = points[1].thick =
|
|
Shinya Kitaoka |
120a6e |
points[2].thick; //=points[3].thick;//=points[4].thick;
|
|
Shinya Kitaoka |
120a6e |
points[n - 1].thick = points[n - 2].thick =
|
|
Shinya Kitaoka |
120a6e |
points[n - 3].thick; //=points[n-4].thick;//=points[n-5].thick;
|
|
Shinya Kitaoka |
120a6e |
delete[] rr;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke =
|
|
Shinya Kitaoka |
120a6e |
TStroke::interpolate(points, m_configuration.m_interpolationError);
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(m_configuration.m_strokeStyleId); // FirstUserStyle+2);
|
|
Shinya Kitaoka |
120a6e |
m_vimage->addStroke(stroke);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::createRegions() {
|
|
Shinya Kitaoka |
120a6e |
std::list<protoregion>::iterator it_regions;</protoregion>
|
|
Shinya Kitaoka |
120a6e |
for (it_regions = m_protoRegions.begin(); it_regions != m_protoRegions.end();
|
|
Shinya Kitaoka |
120a6e |
it_regions++) {
|
|
Shinya Kitaoka |
120a6e |
assert(it_regions->m_points.size() > 4);
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke = TStroke::interpolate(it_regions->m_points, 0.1);
|
|
Shinya Kitaoka |
120a6e |
stroke->setSelfLoop();
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(m_configuration.m_strokeStyleId);
|
|
Shinya Kitaoka |
120a6e |
m_vimage->addStroke(stroke);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
if(it_regions->m_isConvex)
|
|
Shinya Kitaoka |
120a6e |
m_vimage->fill(it_regions->m_center, TPalette::DefaultStrokeStyle);
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
TPointD internalPoint;
|
|
Shinya Kitaoka |
120a6e |
internalPoint = rotate90(it_regions->m_points[1] -
|
|
Toshihiro Shimizu |
890ddd |
it_regions->m_points[0]);
|
|
Shinya Kitaoka |
120a6e |
assert(norm2(internalPoint) != 0);
|
|
Shinya Kitaoka |
120a6e |
normalize(internalPoint);
|
|
Shinya Kitaoka |
120a6e |
internalPoint = internalPoint*0.001 + 0.5*(it_regions->m_points[1] +
|
|
Toshihiro Shimizu |
890ddd |
it_regions->m_points[0]);
|
|
Shinya Kitaoka |
120a6e |
m_vimage->fill(internalPoint, TPalette::DefaultStrokeStyle);
|
|
Shinya Kitaoka |
120a6e |
}*/
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::vectorize() {
|
|
Shinya Kitaoka |
120a6e |
int j = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)m_nodes.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[j];
|
|
Shinya Kitaoka |
120a6e |
if (node->m_pixel == 0 || node->m_visited) continue;
|
|
Shinya Kitaoka |
120a6e |
traceLine(node->m_pixel);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
handleJunctions();
|
|
Shinya Kitaoka |
120a6e |
createStrokes();
|
|
Shinya Kitaoka |
120a6e |
createRegions();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
void printTime(TStopWatch &sw, string name) {
|
|
Shinya Kitaoka |
120a6e |
ostrstream ss;
|
|
Shinya Kitaoka |
120a6e |
ss << name << " : ";
|
|
Shinya Kitaoka |
120a6e |
sw.print(ss);
|
|
Shinya Kitaoka |
120a6e |
ss << '\n' << '\0';
|
|
Shinya Kitaoka |
120a6e |
string s = ss.str();
|
|
Shinya Kitaoka |
120a6e |
ss.freeze(false);
|
|
Shinya Kitaoka |
120a6e |
TSystem::outputDebug(s);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
void CenterLineVectorizer::outputInks() {
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < m_dataRaster->getLx() * m_dataRaster->getLy(); i++) {
|
|
Shinya Kitaoka |
120a6e |
DataPixel *pix = m_dataRaster->pixels() + i;
|
|
Shinya Kitaoka |
120a6e |
if (pix->m_ink)
|
|
Shinya Kitaoka |
120a6e |
getOutPix(pix) = TPixel32::Black;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
getOutPix(pix) = TPixel32::White;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP centerlineVectorize(const TImageP &image,
|
|
Shinya Kitaoka |
120a6e |
const VectorizerConfiguration &c,
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette) {
|
|
Shinya Kitaoka |
120a6e |
CenterLineVectorizer vectorizer(c, palette);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri = image;
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP vi = image;
|
|
Shinya Kitaoka |
120a6e |
if (ri)
|
|
Shinya Kitaoka |
120a6e |
vectorizer.makeDataRaster(ri->getRaster());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
vectorizer.makeDataRaster(vi->getRaster());
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)vectorizer.m_dataRasterArray.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_dataRaster = vectorizer.m_dataRasterArray[i].second;
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_configuration.m_strokeStyleId =
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_dataRasterArray[i].first;
|
|
Shinya Kitaoka |
120a6e |
vectorizer.init();
|
|
Shinya Kitaoka |
120a6e |
vectorizer.vectorize();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
renormalizeImage(vectorizer.m_vimage.getPointer());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return vectorizer.m_vimage;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class OutlineVectorizer : public CenterLineVectorizer {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
list<vector<tthickpoint>> m_protoOutlines;</vector<tthickpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void traceOutline(Node *initialNode);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
OutlineVectorizer(const VectorizerConfiguration &configuration,
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette)
|
|
Shinya Kitaoka |
120a6e |
: CenterLineVectorizer(configuration, palette) {}
|
|
Shinya Kitaoka |
120a6e |
~OutlineVectorizer();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void createOutlineStrokes();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
OutlineVectorizer(const OutlineVectorizer &);
|
|
Shinya Kitaoka |
120a6e |
OutlineVectorizer &operator=(const OutlineVectorizer &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
OutlineVectorizer::~OutlineVectorizer() { m_protoOutlines.clear(); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OutlineVectorizer::traceOutline(Node *initialNode) {
|
|
Shinya Kitaoka |
120a6e |
Node *startNode = initialNode;
|
|
Shinya Kitaoka |
120a6e |
Node *node;
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
if (!startNode) break;
|
|
Shinya Kitaoka |
120a6e |
node = findOtherSide(startNode);
|
|
Shinya Kitaoka |
120a6e |
if (!node) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double startDist2 = computeDistance2(startNode, node);
|
|
Shinya Kitaoka |
120a6e |
if (startDist2 > 0.1) break;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
startNode = startNode->m_next;
|
|
Shinya Kitaoka |
120a6e |
// assert(startNode != initialNode);
|
|
Shinya Kitaoka |
120a6e |
} while (startNode != initialNode);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!startNode) return;
|
|
Shinya Kitaoka |
120a6e |
node = startNode;
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
node = node->m_next;
|
|
Shinya Kitaoka |
120a6e |
if (!node) break;
|
|
Shinya Kitaoka |
120a6e |
node->m_visited = true;
|
|
Shinya Kitaoka |
120a6e |
points.push_back(TThickPoint(convert(node->m_pixel->m_pos), 0));
|
|
Shinya Kitaoka |
120a6e |
} while (node != startNode);
|
|
Shinya Kitaoka |
120a6e |
m_protoOutlines.push_back(points);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void OutlineVectorizer::createOutlineStrokes() {
|
|
Shinya Kitaoka |
120a6e |
m_vimage->enableRegionComputing(true, false);
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)m_nodes.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[j];
|
|
Shinya Kitaoka |
120a6e |
if (node->m_pixel == 0 || node->m_visited) continue;
|
|
Shinya Kitaoka |
120a6e |
traceOutline(node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DEBUG
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < (int)m_nodes.size(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Node *node = m_nodes[j];
|
|
Shinya Kitaoka |
120a6e |
// assert(node->m_visited || !node->m_pixel);
|
|
Shinya Kitaoka |
120a6e |
if (node->m_pixel == 0 || node->m_flag) continue;
|
|
Shinya Kitaoka |
120a6e |
outputNodes(node);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::list<std::vector<tthickpoint>>::iterator it_outlines =</std::vector<tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
m_protoOutlines.begin();
|
|
Shinya Kitaoka |
120a6e |
for (; it_outlines != m_protoOutlines.end(); it_outlines++) {
|
|
Shinya Kitaoka |
120a6e |
if (it_outlines->size() > 3) {
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint> points;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
std::vector<tthickpoint>::iterator it;</tthickpoint>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (it_outlines->size() > 10) {
|
|
Shinya Kitaoka |
120a6e |
it = it_outlines->begin() + 1;
|
|
Shinya Kitaoka |
120a6e |
for (;;) {
|
|
Shinya Kitaoka |
120a6e |
if (it >= it_outlines->end() - (m_configuration.m_smoothness + 1))
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < m_configuration.m_smoothness; j++)
|
|
Shinya Kitaoka |
120a6e |
it = it_outlines->erase(it);
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
points.push_back(it_outlines->front());
|
|
Shinya Kitaoka |
120a6e |
it = it_outlines->begin();
|
|
Shinya Kitaoka |
120a6e |
TThickPoint old = *it;
|
|
Shinya Kitaoka |
120a6e |
++it;
|
|
Shinya Kitaoka |
120a6e |
for (; it != it_outlines->end(); ++it) {
|
|
Shinya Kitaoka |
120a6e |
TThickPoint point((1 / 2.0) * (*it + old));
|
|
Shinya Kitaoka |
120a6e |
points.push_back(point);
|
|
Shinya Kitaoka |
120a6e |
old = *it;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
points.push_back(it_outlines->back());
|
|
Shinya Kitaoka |
120a6e |
points.push_back(it_outlines->front());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
/*TPointD internalPoint;
|
|
Shinya Kitaoka |
120a6e |
internalPoint = rotate90(points[1] - points[0]);
|
|
Shinya Kitaoka |
120a6e |
assert(norm2(internalPoint) != 0);
|
|
Shinya Kitaoka |
120a6e |
normalize(internalPoint);
|
|
Shinya Kitaoka |
120a6e |
internalPoint = internalPoint*0.001 + points[0];
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD externalPoint;
|
|
Shinya Kitaoka |
120a6e |
externalPoint = rotate270(points[1] - points[0]);
|
|
Shinya Kitaoka |
120a6e |
assert(norm2(externalPoint) != 0);
|
|
Shinya Kitaoka |
120a6e |
normalize(externalPoint);
|
|
Shinya Kitaoka |
120a6e |
externalPoint = externalPoint*0.001 + points[0];*/
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke =
|
|
Shinya Kitaoka |
120a6e |
TStroke::interpolate(points, m_configuration.m_interpolationError);
|
|
Shinya Kitaoka |
120a6e |
stroke->setStyle(m_configuration.m_strokeStyleId);
|
|
Shinya Kitaoka |
120a6e |
stroke->setSelfLoop();
|
|
Shinya Kitaoka |
120a6e |
m_vimage->addStroke(stroke);
|
|
Shinya Kitaoka |
120a6e |
// TStroke *stroke = TStroke::interpolate(points,
|
|
Shinya Kitaoka |
38fd86 |
// m_configuration.interpolationError);
|
|
Shinya Kitaoka |
120a6e |
// stroke->setStyle(strokeStyleId);
|
|
Shinya Kitaoka |
120a6e |
// m_vimage->addStroke(stroke);//,
|
|
Shinya Kitaoka |
38fd86 |
// TPalette::DefaultStrokeStyle, TPalette::DefaultFillStyle);
|
|
Shinya Kitaoka |
120a6e |
// internalPoints.push_back(internalPoint);
|
|
Shinya Kitaoka |
120a6e |
// m_vimage->fill(externalPoint, TPalette::DefaultFillStyle);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// m_vimage->autoFill(m_configuration.m_strokeStyleId);
|
|
Shinya Kitaoka |
120a6e |
// for (UINT i=0; i
|
|
Shinya Kitaoka |
120a6e |
// m_vimage->fill(internalPoints[i],fillStyleId);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP outlineVectorize(const TImageP &image,
|
|
Shinya Kitaoka |
120a6e |
const VectorizerConfiguration &configuration,
|
|
Shinya Kitaoka |
120a6e |
TPalette *palette) {
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP out;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
OutlineVectorizer vectorizer(configuration, palette);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri = image;
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP vi = image;
|
|
Shinya Kitaoka |
120a6e |
if (ri)
|
|
Shinya Kitaoka |
120a6e |
vectorizer.makeDataRaster(ri->getRaster());
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
vectorizer.makeDataRaster(vi->getRaster());
|
|
Shinya Kitaoka |
120a6e |
int layersCount = vectorizer.m_dataRasterArray.size();
|
|
Shinya Kitaoka |
120a6e |
if (layersCount > 1) {
|
|
Shinya Kitaoka |
120a6e |
out = new TVectorImage();
|
|
Shinya Kitaoka |
120a6e |
out->setPalette(palette);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)layersCount; i++) {
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_dataRaster = vectorizer.m_dataRasterArray[i].second;
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_configuration.m_strokeStyleId =
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_dataRasterArray[i].first;
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_protoOutlines.clear();
|
|
Shinya Kitaoka |
120a6e |
vectorizer.init();
|
|
Shinya Kitaoka |
120a6e |
vectorizer.createOutlineStrokes();
|
|
Shinya Kitaoka |
120a6e |
renormalizeImage(vectorizer.m_vimage.getPointer());
|
|
Shinya Kitaoka |
120a6e |
vectorizer.m_vimage->setPalette(palette);
|
|
Shinya Kitaoka |
120a6e |
if (layersCount > 1) out->mergeImage(vectorizer.m_vimage, TAffine());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (i != (int)layersCount - 1) vectorizer.m_vimage = new TVectorImage();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return (layersCount == 1) ? vectorizer.m_vimage : out;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|
|
Shinya Kitaoka |
120a6e |
void applyFillColors(TRegion *r, const TRasterP &ras, TPalette *palette,
|
|
Shinya Kitaoka |
120a6e |
const TPoint &offset, bool leaveUnpainted) {
|
|
Shinya Kitaoka |
120a6e |
TPointD pd;
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P rt = (TRasterCM32P)ras;
|
|
Shinya Kitaoka |
120a6e |
TRaster32P rr = (TRaster32P)ras;
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P rgr = (TRasterGR8P)ras;
|
|
Shinya Kitaoka |
120a6e |
assert(rt || rr || rgr);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (/*r->getStyle()==0 && */ r->getInternalPoint(pd)) {
|
|
Shinya Kitaoka |
120a6e |
TPoint p = convert(pd) + offset;
|
|
Shinya Kitaoka |
120a6e |
if (ras->getBounds().contains(p)) {
|
|
Shinya Kitaoka |
120a6e |
int styleId = 0;
|
|
Shinya Kitaoka |
120a6e |
if (rt) {
|
|
Shinya Kitaoka |
120a6e |
TPixelCM32 col = rt->pixels(p.y)[p.x];
|
|
Shinya Kitaoka |
120a6e |
int tone = col.getTone();
|
|
Shinya Kitaoka |
120a6e |
if (tone < 100) {
|
|
Shinya Kitaoka |
120a6e |
styleId = col.getInk();
|
|
Shinya Kitaoka |
120a6e |
if (styleId == 0 && !leaveUnpainted) styleId = col.getPaint();
|
|
Shinya Kitaoka |
120a6e |
} else if (!leaveUnpainted || col.getPaint() == 0) {
|
|
Shinya Kitaoka |
120a6e |
styleId = col.getPaint();
|
|
Shinya Kitaoka |
120a6e |
if (styleId == 0) styleId = col.getInk();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 color;
|
|
Shinya Kitaoka |
120a6e |
if (rr)
|
|
Shinya Kitaoka |
120a6e |
color = rr->pixels(p.y)[p.x];
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
int val = rgr->pixels(p.y)[p.x].value;
|
|
Shinya Kitaoka |
120a6e |
color = (val < 80) ? TPixel32::Black : TPixel32::White;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
styleId = palette->getClosestStyle(color);
|
|
Shinya Kitaoka |
120a6e |
if (palette->getStyle(styleId)->getMainColor() != color)
|
|
Shinya Kitaoka |
120a6e |
styleId = palette->addStyle(color);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
r->fill(pd, styleId);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)r->getSubregionCount(); i++)
|
|
Shinya Kitaoka |
120a6e |
applyFillColors(r->getSubregion(i), ras, palette, offset, leaveUnpainted);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void applyFillColors(TVectorImageP vi, const TImageP &img, TPalette *palette,
|
|
Shinya Kitaoka |
120a6e |
bool leaveUnpainted) {
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti = (TToonzImageP)img;
|
|
Shinya Kitaoka |
120a6e |
TRasterImageP ri = (TRasterImageP)img;
|
|
Shinya Kitaoka |
120a6e |
TRectD vb = vi->getBBox();
|
|
Shinya Kitaoka |
120a6e |
TRectD tb = img->getBBox();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (ti)
|
|
Shinya Kitaoka |
120a6e |
ras = ti->getRaster();
|
|
Shinya Kitaoka |
120a6e |
else if (ri)
|
|
Shinya Kitaoka |
120a6e |
ras = ri->getRaster();
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
vi->findRegions();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < (int)vi->getRegionCount(); i++)
|
|
Shinya Kitaoka |
120a6e |
applyFillColors(vi->getRegion(i), ras, palette,
|
|
Shinya Kitaoka |
120a6e |
convert(tb.getP00() - vb.getP00()), leaveUnpainted);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=========================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vectorize(const TImageP &img, const VectorizerConfiguration &c,
|
|
Shinya Kitaoka |
120a6e |
TPalette *plt) {
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = c.m_outline ? outlineVectorize(img, c, plt)
|
|
Shinya Kitaoka |
120a6e |
: centerlineVectorize(img, c, plt);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
applyFillColors(vi, img, plt, c.m_leaveUnpainted);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// else if (c.m_outline)
|
|
Shinya Kitaoka |
120a6e |
// vi->autoFill(c.m_strokeStyleId);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD center;
|
|
Shinya Kitaoka |
120a6e |
if (TToonzImageP ti = img)
|
|
Shinya Kitaoka |
120a6e |
center = ti->getRaster()->getCenterD();
|
|
Shinya Kitaoka |
120a6e |
else if (TRasterImageP ri = img)
|
|
Shinya Kitaoka |
120a6e |
center = ri->getRaster()->getCenterD();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TAffine aff = TTranslation(-center);
|
|
Shinya Kitaoka |
120a6e |
vi->transform(aff);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return vi;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------
|