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