Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef T_CENTERLINE_VECTORIZER_PRIVATE
Toshihiro Shimizu 890ddd
#define T_CENTERLINE_VECTORIZER_PRIVATE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tcenterlinevectorizer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trastercm.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tgeometry.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <vector></vector>
Toshihiro Shimizu 890ddd
#include <list></list>
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <functional></functional>
Toshihiro Shimizu 890ddd
#include <algorithm></algorithm>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <math.h></math.h>
Toshihiro Shimizu 890ddd
#include <assert.h></assert.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------
Toshihiro Shimizu 890ddd
//    Preliminary geometric helpers
Toshihiro Shimizu 890ddd
//--------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline TPointD planeProjection(const T3DPointD &p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return TPointD(p.x, p.y);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns distance of \p P from line of direction \p v that touches \p B
Toshihiro Shimizu 890ddd
inline double tdistance2(const T3DPointD &P, const T3DPointD &v, const T3DPointD &B)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double t = P * v - B * v;
Toshihiro Shimizu 890ddd
	T3DPointD Q = B + t * v - P;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return Q * Q;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline double tdistance(TPointD P, TPointD v, TPointD B)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return fabs(cross(P - B, normalize(v)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline double tdistance(T3DPointD P, T3DPointD v, T3DPointD B)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double vv = norm2(v);
Toshihiro Shimizu 890ddd
	if (vv < 0.01)
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double t = (P * v - B * v) / vv;
Toshihiro Shimizu 890ddd
	T3DPointD Q = B + t * v - P;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return norm(Q);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline double planeDistance(const T3DPointD &P, const T3DPointD &Q)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return sqrt((P.x - Q.x) * (P.x - Q.x) + (P.y - Q.y) * (P.y - Q.y));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline double crossZ(const T3DPointD &p, const T3DPointD &q)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return p.x * q.y - p.y * q.x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// a, b assumed normalized
Toshihiro Shimizu 890ddd
inline bool angleLess(const TPointD &a, const TPointD &b)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return a.y >= 0 ? b.y >= 0 ? a.x > b.x : 1 : b.y < 0 ? a.x < b.x : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// a, b, ref assumed normalized
Toshihiro Shimizu 890ddd
inline bool angleLess(const TPointD &a, const TPointD &b, const TPointD &ref)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return angleLess(a, ref) ? angleLess(b, ref) ? angleLess(a, b) : 0 : angleLess(b, ref) ? 1 : angleLess(a, b);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
//    STL auxiliaries
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Container append (needs reverse iterators)
Toshihiro Shimizu 890ddd
// NOTE: Merge could be used... but it requires operator< and we don't...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! warning: must be I == T::Reverse_iterator; explicited because on Mac it was not compiling!
Toshihiro Shimizu 890ddd
template <class class="" i="" t,=""></class>
Toshihiro Shimizu 890ddd
void append(T &cont1, T &cont2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	I i, j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cont1.resize(cont1.size() + cont2.size());
Toshihiro Shimizu 890ddd
	for (i = cont2.rbegin(), j = cont1.rbegin(); i != cont2.rend(); ++i, ++j)
Toshihiro Shimizu 890ddd
		*j = *i;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************
Toshihiro Shimizu 890ddd
//       Traversable Graphs
Toshihiro Shimizu 890ddd
//*********************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef unsigned int UINT;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  \brief    Graph class used by the centerline vectorization process.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \details  Introducing a directed graph structure that allows local access: main feature is that a graph edge
Toshihiro Shimizu 890ddd
            physically belongs to the node that emitted it, by storing it in a 'link vector' inside the node.
Toshihiro Shimizu 890ddd
            No full-scale edge search method is therefore needed to find node neighbours.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
            No specific iterator class is needed, just use unsigned ints to perform random access to nodes and
Toshihiro Shimizu 890ddd
            links vectors.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename arctype="" nodecontenttype,="" typename=""></typename>
Toshihiro Shimizu 890ddd
class Graph
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	class Link
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		UINT m_next;   //!< Index of the node pointed by this link.
Toshihiro Shimizu 890ddd
		ArcType m_arc; //!< Edge data associated to this link.
Toshihiro Shimizu 890ddd
		int m_access;  //!< Whether access to a node is allowed
Toshihiro Shimizu 890ddd
					   //!  through this link.
Toshihiro Shimizu 890ddd
	public:
Toshihiro Shimizu 890ddd
		Link() : m_access(1) {}
Toshihiro Shimizu 890ddd
		Link(UINT _next) : m_next(_next), m_access(1) {}
Toshihiro Shimizu 890ddd
		Link(UINT _next, ArcType _arc)
Toshihiro Shimizu 890ddd
			: m_next(_next), m_arc(_arc), m_access(1) {}
Toshihiro Shimizu 890ddd
		~Link() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ArcType &operator*() { return m_arc; }
Toshihiro Shimizu 890ddd
		const ArcType &operator*() const { return m_arc; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ArcType *operator->() { return &m_arc; }
Toshihiro Shimizu 890ddd
		const ArcType *operator->() const { return &m_arc; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		UINT getNext() const { return m_next; }
Toshihiro Shimizu 890ddd
		void setNext(UINT _next) { m_next = _next; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int getAccess() const { return m_access; }
Toshihiro Shimizu 890ddd
		void setAccess(int acc) { m_access = acc; }
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	class Node
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		friend class Graph; // Grant Graph access to m_links
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<link> m_links; //!< Links to neighbouring nodes.
Toshihiro Shimizu 890ddd
		NodeContentType m_content; //!< The node's content.
Toshihiro Shimizu 890ddd
		int m_attributes;		   //!< Node attributes.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	public:
Toshihiro Shimizu 890ddd
		Node() : m_attributes(0) {}
Toshihiro Shimizu 890ddd
		Node(const NodeContentType &_cont) : m_content(_cont), m_attributes(0) {}
Toshihiro Shimizu 890ddd
		~Node() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Link &link(UINT i) { return m_links[i]; }
Toshihiro Shimizu 890ddd
		const Link &getLink(UINT i) const { return m_links[i]; }
Toshihiro Shimizu 890ddd
		UINT getLinksCount() const { return m_links.size(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		NodeContentType &operator*() { return m_content; }
Toshihiro Shimizu 890ddd
		const NodeContentType &operator*() const { return m_content; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		NodeContentType *operator->() { return &m_content; }
Toshihiro Shimizu 890ddd
		const NodeContentType *operator->() const { return &m_content; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Attributes
Toshihiro Shimizu 890ddd
		int hasAttribute(int attr) const { return m_attributes & attr; }
Toshihiro Shimizu 890ddd
		void setAttribute(int attr) { m_attributes |= attr; }
Toshihiro Shimizu 890ddd
		void clearAttribute(int attr) { m_attributes &= ~attr; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Others
Toshihiro Shimizu 890ddd
		int degree() const { return int(m_links.size()); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*!
Toshihiro Shimizu 890ddd
      \warning    If more links can be set between the same nodes, the
Toshihiro Shimizu 890ddd
                  returned link index will be ambiguous.
Toshihiro Shimizu 890ddd
    */
Toshihiro Shimizu 890ddd
		UINT linkOfNode(UINT next) const
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			UINT i = 0;
Toshihiro Shimizu 890ddd
			for (; i < m_links.size() && m_links[i].getNext() != next; ++i)
Toshihiro Shimizu 890ddd
				;
Toshihiro Shimizu 890ddd
			return i;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	std::vector<node> m_nodes; //!< Nodes container.</node>
Toshihiro Shimizu 890ddd
	UINT m_linksCount;		   //!< Links counter.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Graph() : m_linksCount(0) {}
Toshihiro Shimizu 890ddd
	virtual ~Graph() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Node &node(UINT i) { return m_nodes[i]; }
Toshihiro Shimizu 890ddd
	const Node &getNode(UINT i) const { return m_nodes[i]; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT getNodesCount() const { return m_nodes.size(); }
Toshihiro Shimizu 890ddd
	UINT getLinksCount() const { return m_linksCount; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Nodes/Links insertions
Toshihiro Shimizu 890ddd
	UINT newNode()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_nodes.push_back(Node());
Toshihiro Shimizu 890ddd
		return m_nodes.size() - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT newNode(const NodeContentType &content)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_nodes.push_back(Node(content));
Toshihiro Shimizu 890ddd
		return m_nodes.size() - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT newLink(UINT first, UINT last)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(first < m_nodes.size() && last < m_nodes.size());
Toshihiro Shimizu 890ddd
		m_nodes[first].m_links.push_back(Link(last));
Toshihiro Shimizu 890ddd
		++m_linksCount;
Toshihiro Shimizu 890ddd
		return m_nodes[first].m_links.size() - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT newLink(UINT first, UINT last, const ArcType &arc)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(first < m_nodes.size() && last < m_nodes.size());
Toshihiro Shimizu 890ddd
		m_nodes[first].m_links.push_back(Link(last, arc));
Toshihiro Shimizu 890ddd
		++m_linksCount;
Toshihiro Shimizu 890ddd
		return m_nodes[first].m_links.size() - 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void insert(UINT inserted, UINT afterNode, UINT onLink)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		newLink(inserted, getNode(afterNode).getLink(onLink).getNext());
Toshihiro Shimizu 890ddd
		node(afterNode).link(onLink).setNext(inserted);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************
Toshihiro Shimizu 890ddd
//*    Polygonization classes    *
Toshihiro Shimizu 890ddd
//********************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Of course we don't want RawBorders to be entirely copied whenever STL
Toshihiro Shimizu 890ddd
// requires to resize a BorderFamily...
Toshihiro Shimizu 890ddd
class RawBorder;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<rawborder *=""> BorderFamily;</rawborder>
Toshihiro Shimizu 890ddd
typedef std::vector<borderfamily> BorderList;</borderfamily>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
//    Output Polygon Classes
Toshihiro Shimizu 890ddd
//--------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ContourEdge;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// NOTE: The following class is mainly used in the later 'straight skeleton computation'
Toshihiro Shimizu 890ddd
//       - for polygonization purposes, consider it like a TPointD class.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ContourNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	enum Attributes //! Node attributes
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		HEAD = 0x1,		  //!< Node is the 'first' of a nodes ring.
Toshihiro Shimizu 890ddd
		ELIMINATED = 0x4, //!< Node was eliminated by the SS process.
Toshihiro Shimizu 890ddd
		SK_NODE_DROPPED = 0x8,
Toshihiro Shimizu 890ddd
		AMBIGUOUS_LEFT = 0x10,  //!< Node represents an ambiguous \a left turn in
Toshihiro Shimizu 890ddd
								//!  the original image.
Toshihiro Shimizu 890ddd
		AMBIGUOUS_RIGHT = 0x20, //!< Node represents an ambiguous \a right turn in
Toshihiro Shimizu 890ddd
								//!  the original image.
Toshihiro Shimizu 890ddd
		JR_RESERVED = 0x40,		//!< Reserved for joints recovery.
Toshihiro Shimizu 890ddd
		LINEAR_ADDED = 0x80		//!< Node was added by the linear skeleton technique.
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	// Node kinematics infos
Toshihiro Shimizu 890ddd
	T3DPointD m_position,	 //!< Node's position.
Toshihiro Shimizu 890ddd
		m_direction,		  //!< Node's direction.
Toshihiro Shimizu 890ddd
		m_AngularMomentum,	//!< Angular momentum with the next node's edge.
Toshihiro Shimizu 890ddd
		m_AuxiliaryMomentum1, // Used only when this vertex is convex
Toshihiro Shimizu 890ddd
		m_AuxiliaryMomentum2; // Used only when this vertex is convex
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Further node properties
Toshihiro Shimizu 890ddd
	bool m_concave;							   //!< Whether the node represents a concave angle.
Toshihiro Shimizu 890ddd
	unsigned int m_attributes,				   //!< Bitwise signatures of this node
Toshihiro Shimizu 890ddd
		m_updateTime,						   //!< \a Algoritmic time in which the node was updated.
Toshihiro Shimizu 890ddd
		m_ancestor,							   //!< Index of the original node from which this one evolved.
Toshihiro Shimizu 890ddd
		m_ancestorContour;					   //!< Contour index of the original node from which this one evolved.
Toshihiro Shimizu 890ddd
	std::vector<contouredge *=""> m_notOpposites; //!< List of edges \a not to be used as possible opposites.</contouredge>
Toshihiro Shimizu 890ddd
	int m_outputNode;						   //!< Skeleton node produced by this ContourNode.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Connective data
Toshihiro Shimizu 890ddd
	ContourEdge *m_edge; //!< Edge departing from this, keeping adjacent black
Toshihiro Shimizu 890ddd
						 //!  region on the right
Toshihiro Shimizu 890ddd
	// Node neighbours
Toshihiro Shimizu 890ddd
	ContourNode *m_next; //!< Next node on the contour.
Toshihiro Shimizu 890ddd
	ContourNode *m_prev; //!< Previous node on the contour.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ContourNode() : m_attributes(0) {}
Toshihiro Shimizu 890ddd
	ContourNode(double x, double y) : m_position(x, y, 0), m_attributes(0) {}
Toshihiro Shimizu 890ddd
	ContourNode(const TPointD &P) : m_position(P.x, P.y, 0), m_attributes(0) {}
Toshihiro Shimizu 890ddd
	ContourNode(double x, double y, unsigned short attrib)
Toshihiro Shimizu 890ddd
		: m_position(x, y, 0), m_attributes(attrib) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int hasAttribute(int attr) const { return m_attributes & attr; }
Toshihiro Shimizu 890ddd
	void setAttribute(int attr) { m_attributes |= attr; }
Toshihiro Shimizu 890ddd
	void clearAttribute(int attr) { m_attributes &= ~attr; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	// Private Node Methods
Toshihiro Shimizu 890ddd
	inline void buildNodeInfos(bool forceConvex = false);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<contournode> Contour;</contournode>
Toshihiro Shimizu 890ddd
typedef std::vector<contour> ContourFamily;</contour>
Toshihiro Shimizu 890ddd
typedef std::vector<contourfamily> Contours;</contourfamily>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------
Toshihiro Shimizu 890ddd
//    Straight Skeleton Classes
Toshihiro Shimizu 890ddd
//-----------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class SkeletonArc
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double m_slope;
Toshihiro Shimizu 890ddd
	unsigned int m_leftGeneratingNode,
Toshihiro Shimizu 890ddd
		m_leftContour,
Toshihiro Shimizu 890ddd
		m_rightGeneratingNode,
Toshihiro Shimizu 890ddd
		m_rightContour;
Toshihiro Shimizu 890ddd
	int m_attributes;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE:  Typically an arc is generated by a couple of *edges* of the original
Toshihiro Shimizu 890ddd
	//        contours; but we store instead the *nodes* which address those edges.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	SkeletonArc() : m_attributes(0) {}
Toshihiro Shimizu 890ddd
	SkeletonArc(ContourNode *node)
Toshihiro Shimizu 890ddd
		: m_slope(node->m_direction.z),
Toshihiro Shimizu 890ddd
		  m_leftGeneratingNode(node->m_ancestor),
Toshihiro Shimizu 890ddd
		  m_leftContour(node->m_ancestorContour),
Toshihiro Shimizu 890ddd
		  m_rightGeneratingNode(node->m_prev->m_ancestor),
Toshihiro Shimizu 890ddd
		  m_rightContour(node->m_prev->m_ancestorContour),
Toshihiro Shimizu 890ddd
		  m_attributes(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enum { ROAD = 0x1 };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double getSlope() const { return m_slope; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned int getLeftGenerator() const { return m_leftGeneratingNode; }
Toshihiro Shimizu 890ddd
	unsigned int getRightGenerator() const { return m_rightGeneratingNode; }
Toshihiro Shimizu 890ddd
	unsigned int getLeftContour() const { return m_leftContour; }
Toshihiro Shimizu 890ddd
	unsigned int getRightContour() const { return m_rightContour; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enum { SS_OUTLINE = 0x10,
Toshihiro Shimizu 890ddd
		   SS_OUTLINE_REVERSED = 0x20 };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int hasAttribute(int attr) const { return m_attributes & attr; }
Toshihiro Shimizu 890ddd
	void setAttribute(int attr) { m_attributes |= attr; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void turn()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_slope = -m_slope;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::swap(m_leftGeneratingNode, m_rightGeneratingNode);
Toshihiro Shimizu 890ddd
		std::swap(m_leftContour, m_rightContour);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef Graph<t3dpointd, skeletonarc=""> SkeletonGraph;</t3dpointd,>
Toshihiro Shimizu 890ddd
typedef std::vector<skeletongraph *=""> SkeletonList;</skeletongraph>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------
Toshihiro Shimizu 890ddd
//    Joints and Sequences definition
Toshihiro Shimizu 890ddd
//----------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Sequence
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UINT m_head;
Toshihiro Shimizu 890ddd
	UINT m_headLink;
Toshihiro Shimizu 890ddd
	UINT m_tail;
Toshihiro Shimizu 890ddd
	UINT m_tailLink;
Toshihiro Shimizu 890ddd
	SkeletonGraph *m_graphHolder;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Stroke color-sensible data
Toshihiro Shimizu 890ddd
	int m_color;
Toshihiro Shimizu 890ddd
	int m_strokeIndex;
Toshihiro Shimizu 890ddd
	int m_strokeHeight;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Sequence() : m_graphHolder(0) {}
Toshihiro Shimizu 890ddd
	~Sequence() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Impose a property dependant only on the extremity we consider first
Toshihiro Shimizu 890ddd
	// - so that the same sequence is not considered twice when head and tail
Toshihiro Shimizu 890ddd
	// are exchanged
Toshihiro Shimizu 890ddd
	bool isForward() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (m_head < m_tail) ||
Toshihiro Shimizu 890ddd
			   (m_head == m_tail && m_headLink < m_tailLink);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Advances a couple (old, current) of sequence nodes
Toshihiro Shimizu 890ddd
	void advance(UINT &old, UINT ¤t) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		UINT temp = current;
Toshihiro Shimizu 890ddd
		current = m_graphHolder->getNode(current).getLink(0).getNext() == old ? m_graphHolder->getNode(current).getLink(1).getNext() : m_graphHolder->getNode(current).getLink(0).getNext();
Toshihiro Shimizu 890ddd
		old = temp;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Advances a couple (current, link) of a sequence node plus its link direction
Toshihiro Shimizu 890ddd
	void next(UINT ¤t, UINT &link) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		UINT temp = current;
Toshihiro Shimizu 890ddd
		current = m_graphHolder->getNode(current).getLink(link).getNext();
Toshihiro Shimizu 890ddd
		link = m_graphHolder->getNode(current).getLink(0).getNext() == temp ? 1 : 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class JointSequenceGraph : public Graph<uint, sequence=""></uint,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	JointSequenceGraph() {}
Toshihiro Shimizu 890ddd
	~JointSequenceGraph() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	enum { REACHED = 0x1,
Toshihiro Shimizu 890ddd
		   ELIMINATED = 0x2 };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Extracts JSG tail link of input node-link
Toshihiro Shimizu 890ddd
	inline UINT tailLinkOf(UINT node, UINT link)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		UINT i, next = getNode(node).getLink(link).getNext();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; getNode(next).getLink(i)->m_tail != getNode(node).getLink(link)->m_head ||
Toshihiro Shimizu 890ddd
					getNode(next).getLink(i)->m_tailLink != getNode(node).getLink(link)->m_headLink;
Toshihiro Shimizu 890ddd
			 ++i)
Toshihiro Shimizu 890ddd
			;
Toshihiro Shimizu 890ddd
		return i;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<jointsequencegraph> JointSequenceGraphList;</jointsequencegraph>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::vector<sequence> SequenceList;</sequence>
Toshihiro Shimizu 890ddd
typedef std::vector<t3dpointd> PointList;</t3dpointd>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------
Toshihiro Shimizu 890ddd
//    Globals
Toshihiro Shimizu 890ddd
//----------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!\b FOR \b INTERNAL \b USE \b ONLY!
Toshihiro Shimizu 890ddd
//!EXPLANATION: Some variables are used widely used and shared by all the "tcenterline*.cpp"
Toshihiro Shimizu 890ddd
//sources. Instead than passing each variable repeatedly, it is easier to define a Global
Toshihiro Shimizu 890ddd
//class passed to each file, which gets immediatly pointed in an anonymous namespace.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class VectorizerCoreGlobals
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	const CenterlineConfiguration *currConfig;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	JointSequenceGraphList organizedGraphs;
Toshihiro Shimizu 890ddd
	SequenceList singleSequences;
Toshihiro Shimizu 890ddd
	PointList singlePoints;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	VectorizerCoreGlobals() {}
Toshihiro Shimizu 890ddd
	~VectorizerCoreGlobals() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
//SkeletonGraph nodes global signatures - used for various purposes
Toshihiro Shimizu 890ddd
enum { ORGANIZEGRAPHS_SIGN = 0x10,
Toshihiro Shimizu 890ddd
	   SAMPLECOLOR_SIGN = 0x20,
Toshihiro Shimizu 890ddd
	   COLORORDERING_SIGN = 0x40 };
Toshihiro Shimizu 890ddd
const int infinity = 1000000; //just a great enough number
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================
Toshihiro Shimizu 890ddd
//    Function prototypes
Toshihiro Shimizu 890ddd
//===============================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void polygonize(const TRasterP &ras, Contours &polygons, VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
SkeletonList *skeletonize(Contours &contours, VectorizerCore *thisVectorizer,
Toshihiro Shimizu 890ddd
						  VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void organizeGraphs(SkeletonList *skeleton, VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void junctionRecovery(Contours *polygons, VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void conversionToStrokes(std::vector<tstroke *=""> &strokes, VectorizerCoreGlobals &g);</tstroke>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void calculateSequenceColors(const TRasterP &ras, VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void applyStrokeColors(std::vector<tstroke *=""> &strokes, const TRasterP &ras, TPalette *palette,</tstroke>
Toshihiro Shimizu 890ddd
					   VectorizerCoreGlobals &g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif // T_CENTERLINE_VECTORIZER_PRIVATE