Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcenterlinevectP.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_numeric_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost container="" flat_map.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost algorithm="" minmax_element.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace boost_c = boost::container;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*************************
Toshihiro Shimizu 890ddd
//*    Colors handling    *
Toshihiro Shimizu 890ddd
//*************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Riassunto: Nel caso di normali raster, i tratti di penna sono colorati con
Toshihiro Shimizu 890ddd
//l'elemento della palette data maggiormente tendente al nero.
Toshihiro Shimizu 890ddd
//Per le Toonz colormap abilitiamo una gestione piu' complessa, che tiene
Toshihiro Shimizu 890ddd
//conto del colore dell'inchiostro specificato direttamente nell'immagine.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Nello specifico:
Toshihiro Shimizu 890ddd
//  a) I tratti di penna vengono rilevati in base al valore del campo *tone*
Toshihiro Shimizu 890ddd
//     di un TPixleCM32, non in base alla luminosita' del colore.
Toshihiro Shimizu 890ddd
//     (vv. Poligonizzazione)
Toshihiro Shimizu 890ddd
//  b) Sulle centerline grezze viene costruito un insieme di 'punti di assaggio'
Toshihiro Shimizu 890ddd
//     dell'immagine; gli id di inchiostro rilevati vengono assegnati
Toshihiro Shimizu 890ddd
//     direttamente alla stroke: se si verifica un cambio nell'id del colore,
Toshihiro Shimizu 890ddd
//     il punto di cambio del colore viene identificato e la centerline viene
Toshihiro Shimizu 890ddd
//     spezzata li'.
Toshihiro Shimizu 890ddd
//  c) Una volta identificati i colori delle stroke, le si ordina *prima*
Toshihiro Shimizu 890ddd
//     di inserirle nella vector image di output, in base al colore dell'immagine
Toshihiro Shimizu 890ddd
//     ai loro estremi (attualmente ordinamento solo parziale).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPixelCM32 pixel(const TRasterCM32 &ras, int x, int y)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Seems that raster access was not very much double-checked at the time
Toshihiro Shimizu 890ddd
	// I wrote this. Too bad. Enforcing it now.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return ras.pixels(tcrop(y, 0, ras.getLy() - 1))[tcrop(x, 0, ras.getLx() - 1)];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
T3DPointD firstInkChangePosition(
Toshihiro Shimizu 890ddd
	const TRasterCM32P &ras, const T3DPointD &start, const T3DPointD &end,
Toshihiro Shimizu 890ddd
	int threshold)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	double dist = norm(end - start);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int sampleMax = tceil(dist), sampleCount = sampleMax + 1;
Toshihiro Shimizu 890ddd
	double sampleMaxD = double(sampleMax);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get first ink color
Toshihiro Shimizu 890ddd
	int s, color = -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (s = 0; s != sampleCount; ++s) {
Toshihiro Shimizu 890ddd
		T3DPointD p = tcg::numeric_ops::lerp(start, end, s / sampleMaxD);
Toshihiro Shimizu 890ddd
		const TPixelCM32 &pix = pixel(*ras, p.x, p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (pix.getTone() < threshold) {
Toshihiro Shimizu 890ddd
			color = pix.getInk();
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Get second color
Toshihiro Shimizu 890ddd
	for (; s != sampleCount; ++s) {
Toshihiro Shimizu 890ddd
		T3DPointD p = tcg::numeric_ops::lerp(start, end, s / sampleMaxD);
Toshihiro Shimizu 890ddd
		const TPixelCM32 &pix = pixel(*ras, p.x, p.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (pix.getTone() < threshold && pix.getInk() != color)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Return middle position between s-1 and s
Toshihiro Shimizu 890ddd
	if (s < sampleCount)
Toshihiro Shimizu 890ddd
		return tcg::numeric_ops::lerp(start, end, (s - 0.5) / sampleMaxD);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TConsts::nap3d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Find color of input sequence. Will be copied to its equivalent stroke.
Toshihiro Shimizu 890ddd
//Currently in use only on colormaps
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Riassunto: Per saggiare il colore da assegnare alle strokes e' meglio controllare
Toshihiro Shimizu 890ddd
//le sequenze *prima* di convertirle in TStroke (visto che si perde parte dell'aderenza originale
Toshihiro Shimizu 890ddd
//al tratto). Si specifica un numero di 'punti di assaggio' della spezzata equidistanti tra loro,
Toshihiro Shimizu 890ddd
//su cui viene prelevato il valore dell'ink del pixel corrispondente. Se si identifica un cambio
Toshihiro Shimizu 890ddd
//di colore, viene lanciata la procedura di spezzamento della sequenza: si identifica il punto
Toshihiro Shimizu 890ddd
//di spezzamento, e la sequenza s viene bloccata li'; si costruisce una nuova sequenza newSeq e
Toshihiro Shimizu 890ddd
//viene rilanciata sampleColor(ras,newSeq,sOpposite). Le sequenze tra due punti di spezzamento
Toshihiro Shimizu 890ddd
//vengono inserite nel vector 'globals->singleSequences'.
Toshihiro Shimizu 890ddd
//Nel caso di sequenze circolari c'e' una piccola modifica: il primo punto di spezzamento
Toshihiro Shimizu 890ddd
//*ridefinisce solo* il nodo-raccordo di s, senza introdurre nuove sequenze.
Toshihiro Shimizu 890ddd
//La sequenza sOpposite, 'inversa' di s, rimane e diventa 'forward-oriented' previo aggiornamento
Toshihiro Shimizu 890ddd
//della coda.
Toshihiro Shimizu 890ddd
//Osservare che i nodi di spezzamento vengono inseriti con la signature 'SAMPLECOLOR_SIGN'.
Toshihiro Shimizu 890ddd
//NOTA: La struttura a grafo J-S 'superiore' non viene alterata qui dentro. Eventualm. da fare fuori.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void sampleColor(const TRasterCM32P &ras, int threshold, Sequence &seq, Sequence &seqOpposite,
Toshihiro Shimizu 890ddd
				 SequenceList &singleSequences)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	SkeletonGraph *currGraph = seq.m_graphHolder;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Calculate sequence parametrization
Toshihiro Shimizu 890ddd
	std::vector<unsigned int=""> nodes;</unsigned>
Toshihiro Shimizu 890ddd
	std::vector<double> params;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Meanwhile, ensure each point belong to ras. Otherwise, typically an error occured
Toshihiro Shimizu 890ddd
	// in the thinning process and it's better avoid sampling procedure. Only exception, when
Toshihiro Shimizu 890ddd
	// a point has x==ras->getLx() || y==ras->getLy(); that is accepted.
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		const T3DPointD &headPos = *currGraph->getNode(seq.m_head);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!ras->getBounds().contains(TPoint(headPos.x, headPos.y))) {
Toshihiro Shimizu 890ddd
			if (headPos.x < 0 || ras->getLx() < headPos.x ||
Toshihiro Shimizu 890ddd
				headPos.y < 0 || ras->getLy() < headPos.y)
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned int curr, currLink, next;
Toshihiro Shimizu 890ddd
	double meanThickness = currGraph->getNode(seq.m_head)->z;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	params.push_back(0);
Toshihiro Shimizu 890ddd
	nodes.push_back(seq.m_head);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (curr = seq.m_head, currLink = seq.m_headLink;
Toshihiro Shimizu 890ddd
		 curr != seq.m_tail || params.size() == 1;
Toshihiro Shimizu 890ddd
		 seq.next(curr, currLink)) {
Toshihiro Shimizu 890ddd
		next = currGraph->getNode(curr).getLink(currLink).getNext();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const T3DPointD &nextPos = *currGraph->getNode(next);
Toshihiro Shimizu 890ddd
		if (!ras->getBounds().contains(TPoint(nextPos.x, nextPos.y))) {
Toshihiro Shimizu 890ddd
			if (nextPos.x < 0 || ras->getLx() < nextPos.x ||
Toshihiro Shimizu 890ddd
				nextPos.y < 0 || ras->getLy() < nextPos.y)
Toshihiro Shimizu 890ddd
				return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		params.push_back(params.back() + tdistance(*currGraph->getNode(next), *currGraph->getNode(curr)));
Toshihiro Shimizu 890ddd
		nodes.push_back(next);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		meanThickness += currGraph->getNode(next)->z;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	meanThickness /= params.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Exclude 0-length sequences
Toshihiro Shimizu 890ddd
	if (params.back() < 0.01) {
Toshihiro Shimizu 890ddd
		seq.m_color = pixel(*ras, currGraph->getNode(seq.m_head)->x,
Toshihiro Shimizu 890ddd
							currGraph->getNode(seq.m_head)->y)
Toshihiro Shimizu 890ddd
						  .getInk();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare sampling procedure
Toshihiro Shimizu 890ddd
	int paramCount = params.size(),
Toshihiro Shimizu 890ddd
		paramMax = paramCount - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int sampleMax = tmax(params.back() / tmax(meanThickness, 1.0), 3.0), // Number of color samples depends on
Toshihiro Shimizu 890ddd
		sampleCount = sampleMax + 1;									 // the ratio params.back() / meanThickness
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<double> sampleParams(sampleCount); // Sampling lengths</double>
Toshihiro Shimizu 890ddd
	std::vector<tpoint> samplePoints(sampleCount); // Image points for color sampling</tpoint>
Toshihiro Shimizu 890ddd
	std::vector<int> sampleSegments(sampleCount);  // Sequence segment index for the above</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Sample colors
Toshihiro Shimizu 890ddd
	for (int s = 0, j = 0; s != sampleCount; ++s) {
Toshihiro Shimizu 890ddd
		double samplePar = params.back() * (s / double(sampleMax));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		while (j != paramMax && params[j + 1] < samplePar) // params[j] < samplePar <= params[j+1]
Toshihiro Shimizu 890ddd
			++j;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double t = (samplePar - params[j]) / (params[j + 1] - params[j]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		T3DPointD samplePoint(*currGraph->getNode(nodes[j]) * (1 - t) + *currGraph->getNode(nodes[j + 1]) * t);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sampleParams[s] = samplePar;
Toshihiro Shimizu 890ddd
		samplePoints[s] = TPoint(tmin(samplePoint.x, double(ras->getLx() - 1)),  // This deals with sample points at
Toshihiro Shimizu 890ddd
								 tmin(samplePoint.y, double(ras->getLy() - 1))); // the top/right raster border
Toshihiro Shimizu 890ddd
		sampleSegments[s] = j;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: Extremities of a sequence are considered unreliable: they typically happen
Toshihiro Shimizu 890ddd
	//       to be junction points shared between possibly different-colored strokes.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Find first and last extremity-free sampled points
Toshihiro Shimizu 890ddd
	T3DPointD first(*currGraph->getNode(seq.m_head));
Toshihiro Shimizu 890ddd
	T3DPointD last(*currGraph->getNode(seq.m_tail));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, k;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 1; params.back() * i / double(sampleMax) <= first.z && i < sampleCount; ++i)
Toshihiro Shimizu 890ddd
		;
Toshihiro Shimizu 890ddd
	for (k = sampleMax - 1; params.back() * (sampleMax - k) / double(sampleMax) <= last.z && k >= 0; --k)
Toshihiro Shimizu 890ddd
		;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Give s the first sampled ink color found
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize with a last-resort reasonable color - not just 0
Toshihiro Shimizu 890ddd
	seq.m_color = seqOpposite.m_color =
Toshihiro Shimizu 890ddd
		ras->pixels(samplePoints[0].y)[samplePoints[0].x].getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int l;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (l = i - 1; l >= 0; --l) {
Toshihiro Shimizu 890ddd
		if (ras->pixels(samplePoints[l].y)[samplePoints[l].x].getTone() < threshold) {
Toshihiro Shimizu 890ddd
			seq.m_color = seqOpposite.m_color =
Toshihiro Shimizu 890ddd
				ras->pixels(samplePoints[l].y)[samplePoints[l].x].getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Then, look for the first reliable ink
Toshihiro Shimizu 890ddd
	for (l = i; l <= k; ++l) {
Toshihiro Shimizu 890ddd
		if (ras->pixels(samplePoints[l].y)[samplePoints[l].x].getTone() < threshold) {
Toshihiro Shimizu 890ddd
			seq.m_color = seqOpposite.m_color =
Toshihiro Shimizu 890ddd
				ras->pixels(samplePoints[l].y)[samplePoints[l].x].getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (i >= k)
Toshihiro Shimizu 890ddd
		goto _getOut; // No admissible segment found for splitting
Toshihiro Shimizu 890ddd
					  // check.
Toshihiro Shimizu 890ddd
	// Find color changes between sampled colors
Toshihiro Shimizu 890ddd
	for (l = i; l < k; ++l) {
Toshihiro Shimizu 890ddd
		const TPixelCM32 &nextSample = ras->pixels(samplePoints[l + 1].y)[samplePoints[l + 1].x],
Toshihiro Shimizu 890ddd
						 &nextSample2 = ras->pixels(samplePoints[l + 2].y)[samplePoints[l + 2].x]; // l < k < sampleMax - so +2 is ok
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (nextSample.getTone() < threshold && nextSample.getInk() != seq.m_color && nextSample2.getTone() < threshold && nextSample2.getInk() == nextSample.getInk()) // Ignore single-sample color changes
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			// Found a color change - apply splitting procedure
Toshihiro Shimizu 890ddd
			// NOTE: The function RETURNS BEFORE THE FOR IS CONTINUED!
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			int nextColor = nextSample.getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Identify split segment
Toshihiro Shimizu 890ddd
			int u;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (u = sampleSegments[l]; u < sampleSegments[l + 1]; ++u) {
Toshihiro Shimizu 890ddd
				const TPixelCM32 &pix = pixel(*ras, currGraph->getNode(nodes[u + 1])->x,
Toshihiro Shimizu 890ddd
											  currGraph->getNode(nodes[u + 1])->y);
Toshihiro Shimizu 890ddd
				if (pix.getTone() < threshold && pix.getInk() != seq.m_color)
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Now u indicates the splitting segment. Search for splitting point by binary subdivision.
Toshihiro Shimizu 890ddd
			const T3DPointD &nodeStartPos = *currGraph->getNode(nodes[u]),
Toshihiro Shimizu 890ddd
							&nodeEndPos = *currGraph->getNode(nodes[u + 1]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			T3DPointD splitPoint = firstInkChangePosition(ras, nodeStartPos, nodeEndPos, threshold);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (splitPoint == TConsts::nap3d)
Toshihiro Shimizu 890ddd
				splitPoint = 0.5 * (nodeStartPos + nodeEndPos); // A color change was found, but could
Toshihiro Shimizu 890ddd
																// not be precisely located. Just take
Toshihiro Shimizu 890ddd
																// a reasonable representant.
Toshihiro Shimizu 890ddd
			// Insert a corresponding new node in basic graph structure.
Toshihiro Shimizu 890ddd
			unsigned int splitNode = currGraph->newNode(splitPoint);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			unsigned int nodesLink = currGraph->getNode(nodes[u]).linkOfNode(nodes[u + 1]);
Toshihiro Shimizu 890ddd
			currGraph->insert(splitNode, nodes[u], nodesLink);
Toshihiro Shimizu 890ddd
			*currGraph->node(splitNode).link(0) = *currGraph->getNode(nodes[u]).getLink(nodesLink);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			nodesLink = currGraph->getNode(nodes[u + 1]).linkOfNode(nodes[u]);
Toshihiro Shimizu 890ddd
			currGraph->insert(splitNode, nodes[u + 1], nodesLink);
Toshihiro Shimizu 890ddd
			*currGraph->node(splitNode).link(1) = *currGraph->getNode(nodes[u + 1]).getLink(nodesLink);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			currGraph->node(splitNode).setAttribute(SAMPLECOLOR_SIGN); // Sign all split-inserted nodes
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (seq.m_head == seq.m_tail && currGraph->getNode(seq.m_head).getLinksCount() == 2 && !currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN)) {
Toshihiro Shimizu 890ddd
				// Circular case: we update s to splitNode and relaunch this very procedure on it.
Toshihiro Shimizu 890ddd
				seq.m_head = seq.m_tail = splitNode;
Toshihiro Shimizu 890ddd
				sampleColor(ras, threshold, seq, seqOpposite, singleSequences);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				// Update upper (Joint-Sequence) graph data
Toshihiro Shimizu 890ddd
				Sequence newSeq;
Toshihiro Shimizu 890ddd
				newSeq.m_graphHolder = currGraph;
Toshihiro Shimizu 890ddd
				newSeq.m_head = splitNode;
Toshihiro Shimizu 890ddd
				newSeq.m_headLink = 0;
Toshihiro Shimizu 890ddd
				newSeq.m_tail = seq.m_tail;
Toshihiro Shimizu 890ddd
				newSeq.m_tailLink = seq.m_tailLink;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				seq.m_tail = splitNode;
Toshihiro Shimizu 890ddd
				seq.m_tailLink = 1; // (link from splitNode to nodes[u] inserted for second by 'insert')
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				seqOpposite.m_graphHolder = seq.m_graphHolder; // Inform that a split was found
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// NOTE: access on s terminates at newSeq's push_back, due to possible reallocation of globals->singleSequences
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if ((!(seq.m_head == newSeq.m_tail && currGraph->getNode(seq.m_head).getLinksCount() == 2)) && currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN))
Toshihiro Shimizu 890ddd
					singleSequences.push_back(seq);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				sampleColor(ras, threshold, newSeq, seqOpposite, singleSequences);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
_getOut:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Color changes not found (and therefore no newSeq got pushed back); if a split happened, update sOpposite.
Toshihiro Shimizu 890ddd
	if (currGraph->getNode(seq.m_head).hasAttribute(SAMPLECOLOR_SIGN)) {
Toshihiro Shimizu 890ddd
		seqOpposite.m_color = seq.m_color;
Toshihiro Shimizu 890ddd
		seqOpposite.m_head = seq.m_tail;
Toshihiro Shimizu 890ddd
		seqOpposite.m_headLink = seq.m_tailLink;
Toshihiro Shimizu 890ddd
		seqOpposite.m_tail = seq.m_head;
Toshihiro Shimizu 890ddd
		seqOpposite.m_tailLink = seq.m_headLink;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Take samples of image colors to associate each sequence to its corresponding
Toshihiro Shimizu 890ddd
//palette color. Currently working on colormaps.
Toshihiro Shimizu 890ddd
//void calculateSequenceColors(const TRasterP &ras)
Toshihiro Shimizu 890ddd
void calculateSequenceColors(const TRasterP &ras, VectorizerCoreGlobals &g)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int threshold = g.currConfig->m_threshold;
Toshihiro Shimizu 890ddd
	SequenceList &singleSequences = g.singleSequences;
Toshihiro Shimizu 890ddd
	JointSequenceGraphList &organizedGraphs = g.organizedGraphs;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterCM32P cm = ras;
Toshihiro Shimizu 890ddd
	unsigned int i, j, k;
Toshihiro Shimizu 890ddd
	int l;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (cm && g.currConfig->m_maxThickness > 0.0) {
Toshihiro Shimizu 890ddd
		//singleSequence is traversed back-to-front because new, possibly splitted sequences
Toshihiro Shimizu 890ddd
		//are inserted at back - and don't have to be re-sampled.
Toshihiro Shimizu 890ddd
		for (l = singleSequences.size() - 1; l >= 0; --l) {
Toshihiro Shimizu 890ddd
			Sequence rear;
Toshihiro Shimizu 890ddd
			sampleColor(ras, threshold, singleSequences[l], rear, singleSequences);
Toshihiro Shimizu 890ddd
			//If rear is built, a split occurred and the rear of this
Toshihiro Shimizu 890ddd
			//single sequence has to be pushed back.
Toshihiro Shimizu 890ddd
			if (rear.m_graphHolder)
Toshihiro Shimizu 890ddd
				singleSequences.push_back(rear);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < organizedGraphs.size(); ++i)
Toshihiro Shimizu 890ddd
			for (j = 0; j < organizedGraphs[i].getNodesCount(); ++j)
Toshihiro Shimizu 890ddd
				if (!organizedGraphs[i].getNode(j).hasAttribute(JointSequenceGraph::ELIMINATED)) //due to junction recovery
Toshihiro Shimizu 890ddd
					for (k = 0; k < organizedGraphs[i].getNode(j).getLinksCount(); ++k) {
Toshihiro Shimizu 890ddd
						Sequence &s = *organizedGraphs[i].node(j).link(k);
Toshihiro Shimizu 890ddd
						if (s.isForward() && !s.m_graphHolder->getNode(s.m_tail).hasAttribute(SAMPLECOLOR_SIGN)) {
Toshihiro Shimizu 890ddd
							unsigned int next = organizedGraphs[i].node(j).link(k).getNext();
Toshihiro Shimizu 890ddd
							unsigned int nextLink = organizedGraphs[i].tailLinkOf(j, k);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							Sequence &sOpposite = *organizedGraphs[i].node(next).link(nextLink);
Toshihiro Shimizu 890ddd
							sampleColor(cm, threshold, s, sOpposite, singleSequences);
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void applyStrokeIndices(VectorizerCoreGlobals *globals)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	unsigned int i, j, k, n;
Toshihiro Shimizu 890ddd
	unsigned int next, nextLink;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < globals->singleSequences.size(); ++i)
Toshihiro Shimizu 890ddd
		globals->singleSequences[i].m_strokeIndex = i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	n = i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = 0; i < globals->organizedGraphs.size(); ++i) {
Toshihiro Shimizu 890ddd
		JointSequenceGraph *currJSGraph = &globals->organizedGraphs[i];
Toshihiro Shimizu 890ddd
		for (j = 0; j < currJSGraph->getNodesCount(); ++j)
Toshihiro Shimizu 890ddd
			if (!currJSGraph->getNode(j).hasAttribute(JointSequenceGraph::ELIMINATED))
Toshihiro Shimizu 890ddd
				for (k = 0; k < currJSGraph->getNode(j).getLinksCount(); ++k) {
Toshihiro Shimizu 890ddd
					Sequence &s = *currJSGraph->node(j).link(k);
Toshihiro Shimizu 890ddd
					if (s.isForward()) {
Toshihiro Shimizu 890ddd
						s.m_strokeIndex = n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						if (!s.m_graphHolder->getNode(s.m_tail).hasAttribute(SAMPLECOLOR_SIGN)) {
Toshihiro Shimizu 890ddd
							next = currJSGraph->getNode(j).getLink(k).getNext();
Toshihiro Shimizu 890ddd
							nextLink = currJSGraph->tailLinkOf(j, k);
Toshihiro Shimizu 890ddd
							currJSGraph->node(next).link(nextLink)->m_strokeIndex = n;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						++n;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Riassunto: Dato un grafo superiore, possiamo associare ad ogni nodo il colore
Toshihiro Shimizu 890ddd
//del pixel associato a quel punto; se una sequenza e' nascosta, ha entrambi
Toshihiro Shimizu 890ddd
// i nodi agli estremi di colore diverso, viceversa per sequenze esposte.
Toshihiro Shimizu 890ddd
//Data una sequenza, a partire dai nodi superiori adiacenti possiamo stabilire un
Toshihiro Shimizu 890ddd
//insieme di sequenze che gli stanno sotto, ed uno di seq. che gli stanno sopra.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//NOTA: Questo problema e' un caso particolare di 'graph labeling', di cui non
Toshihiro Shimizu 890ddd
//ho ancora trovato soluzione. In rete qualcosa si trova...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//La seguente funzione fa qualcosa di piu' debole: ad ogni joint ed ogni Sequence
Toshihiro Shimizu 890ddd
//viene assegnata una altezza (intero). Dato un Joint, le sequenze che lo hanno
Toshihiro Shimizu 890ddd
//per estremo e che hanno lo stesso colore dell'immagine in quella posizione hanno
Toshihiro Shimizu 890ddd
//un'altezza +1 rispetto al giunto, e viceversa altezza -1. Partendo da
Toshihiro Shimizu 890ddd
//un giunto iniziale, quest'informazione viene propagata sul grafo; il problema
Toshihiro Shimizu 890ddd
//sta ritornando ai giunti gia' percorsi...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Find predominant ink color in a circle of given radius and center
Toshihiro Shimizu 890ddd
int getInkPredominance(const TRasterCM32P &ras, TPalette *palette, int x, int y, int radius, int threshold)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, j;
Toshihiro Shimizu 890ddd
	int mx, my, Mx, My;
Toshihiro Shimizu 890ddd
	std::vector<int> inksFound(palette->getStyleCount());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	radius = tmin(radius, 7); //Restrict radius for a minimum significative neighbour
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mx = tmax(x - radius, 0);
Toshihiro Shimizu 890ddd
	my = tmax(y - radius, 0);
Toshihiro Shimizu 890ddd
	Mx = tmin(x + radius, ras->getLx() - 1);
Toshihiro Shimizu 890ddd
	My = tmin(y + radius, ras->getLy() - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Check square grid around (x,y)
Toshihiro Shimizu 890ddd
	for (i = mx; i <= Mx; ++i)
Toshihiro Shimizu 890ddd
		for (j = my; j <= My; ++j)
Toshihiro Shimizu 890ddd
			if (sq(i) + sq(j) <= sq(radius) && ras->pixels(j)[i].getTone() < threshold) {
Toshihiro Shimizu 890ddd
				//Update color table
Toshihiro Shimizu 890ddd
				inksFound[ras->pixels(j)[i].getInk()] += 255 - ras->pixels(j)[i].getTone();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//return the most found ink
Toshihiro Shimizu 890ddd
	int maxCount = 0, mostFound = 0;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)inksFound.size(); ++i)
Toshihiro Shimizu 890ddd
		if (inksFound[i] > maxCount) {
Toshihiro Shimizu 890ddd
			maxCount = inksFound[i];
Toshihiro Shimizu 890ddd
			mostFound = i;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return mostFound;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  \brief    Find the predominant color in sequences adjacent to the
Toshihiro Shimizu 890ddd
            input graph node.
Toshihiro Shimizu 890ddd
  \return   The predominant branch color if found, \p -1 otherwise.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int getBranchPredominance(const TRasterCM32P &ras, TPalette *palette, JointSequenceGraph::Node &node)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static inline bool valueLess(
Toshihiro Shimizu 890ddd
			const std::pair<int, int=""> &a, const std::pair<int, int=""> &b)</int,></int,>
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			return (a.second < b.second);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	boost_c::flat_map<int, int=""> branchInksHistogram;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT l, lCount = node.getLinksCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (l = 0; l != lCount; ++l) {
Toshihiro Shimizu 890ddd
		int color = node.getLink(l)->m_color;
Toshihiro Shimizu 890ddd
		if (color >= 0 && color <= palette->getStyleCount())
Toshihiro Shimizu 890ddd
			++branchInksHistogram[color];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Return the most found ink, or -1 if a predominance color could not be found
Toshihiro Shimizu 890ddd
	if (branchInksHistogram.empty())
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typedef boost_c::flat_map<int, int="">::iterator histo_it;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const std::pair<histo_it, histo_it=""> &histoRange =</histo_it,>
Toshihiro Shimizu 890ddd
		boost::minmax_element(branchInksHistogram.begin(), branchInksHistogram.end(),
Toshihiro Shimizu 890ddd
							  locals::valueLess);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (histoRange.first->second == histoRange.second->second) ? -1 : histoRange.second->first;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//NOTA: Da implementare una versione in grado di ordinare *pienamente* la vector image.
Toshihiro Shimizu 890ddd
void sortJS(JointSequenceGraph *js, std::vector<std::pair<int, *="" tstroke="">> &toOrder,</std::pair<int,>
Toshihiro Shimizu 890ddd
			const TRasterCM32P &ras, TPalette *palette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	enum { SORTED = 0x10 };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<std::pair<unsigned int="" int,="">> nodesToDo;</std::pair<unsigned>
Toshihiro Shimizu 890ddd
	unsigned int currNodeIdx, nextNodeIdx;
Toshihiro Shimizu 890ddd
	int currColor, currHeight, nextColor, nextHeight;
Toshihiro Shimizu 890ddd
	T3DPointD pD;
Toshihiro Shimizu 890ddd
	TPoint p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SkeletonGraph *currGraph = js->getNode(0).getLink(0)->m_graphHolder;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unsigned int n, nCount = js->getNodesCount();
Toshihiro Shimizu 890ddd
	for (n = 0; n != nCount; ++n) {
Toshihiro Shimizu 890ddd
		// Get the first non-ELIMINATED and non-already treated JS node
Toshihiro Shimizu 890ddd
		if (!js->getNode(n).hasAttribute(JointSequenceGraph::ELIMINATED | SORTED)) {
Toshihiro Shimizu 890ddd
			nodesToDo.push_back(std::make_pair(n, 0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			while (!nodesToDo.empty()) {
Toshihiro Shimizu 890ddd
				currNodeIdx = nodesToDo.back().first;
Toshihiro Shimizu 890ddd
				currHeight = nodesToDo.back().second;
Toshihiro Shimizu 890ddd
				nodesToDo.pop_back();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				JointSequenceGraph::Node &currNode = js->node(currNodeIdx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Sign current node
Toshihiro Shimizu 890ddd
				currNode.setAttribute(SORTED);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Initialize this node infos
Toshihiro Shimizu 890ddd
				pD = *currGraph->getNode(currNode.getLink(0)->m_head);
Toshihiro Shimizu 890ddd
				p = TPoint(pD.x, pD.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (!ras->getBounds().contains(p))
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//currColor = getInkPredominance(ras, palette, p.x, p.y, (int) pD.z); //ras->pixels(p.y)[p.x].getInk();
Toshihiro Shimizu 890ddd
				currColor = getBranchPredominance(ras, palette, currNode);
Toshihiro Shimizu 890ddd
				if (currColor < 0)
Toshihiro Shimizu 890ddd
					currColor = ras->pixels(p.y)[p.x].getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				int l, lCount = currNode.getLinksCount();
Toshihiro Shimizu 890ddd
				for (l = 0; l != lCount; ++l) {
Toshihiro Shimizu 890ddd
					nextNodeIdx = currNode.getLink(l).getNext();
Toshihiro Shimizu 890ddd
					Sequence &s = *currNode.link(l);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// Check if outgoing sequence has current color (front) or not (back)
Toshihiro Shimizu 890ddd
					toOrder[s.m_strokeIndex].first = (s.m_color == currColor) ? currHeight : currHeight - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (!(currNode.getLink(l).getAccess() == SORTED)) {
Toshihiro Shimizu 890ddd
						// Deal with this unchecked branch
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						// If sequence was not split (due to color change)
Toshihiro Shimizu 890ddd
						if (!currGraph->getNode(s.m_tail).hasAttribute(SAMPLECOLOR_SIGN)) {
Toshihiro Shimizu 890ddd
							JointSequenceGraph::Node &nextNode = js->node(nextNodeIdx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							// Then check nextNode
Toshihiro Shimizu 890ddd
							pD = *currGraph->getNode(nextNode.getLink(0)->m_head);
Toshihiro Shimizu 890ddd
							p = TPoint(pD.x, pD.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							if (!ras->getBounds().contains(p))
Toshihiro Shimizu 890ddd
								continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							// If nextNode was not already inserted in ToDo vector, do it now.
Toshihiro Shimizu 890ddd
							if (!nextNode.hasAttribute(SORTED)) {
Toshihiro Shimizu 890ddd
								//nextColor = getInkPredominance(ras, palette, p.x, p.y, (int) pD.z);
Toshihiro Shimizu 890ddd
								nextColor = getBranchPredominance(ras, palette, nextNode);
Toshihiro Shimizu 890ddd
								if (nextColor < 0)
Toshihiro Shimizu 890ddd
									nextColor = ras->pixels(p.y)[p.x].getInk();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								nextHeight = (s.m_color == nextColor) ? toOrder[s.m_strokeIndex].first : toOrder[s.m_strokeIndex].first + 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
								nodesToDo.push_back(std::make_pair(nextNodeIdx, nextHeight));
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
							// Deny access to its inverse (already processed now)
Toshihiro Shimizu 890ddd
							nextNode.link(js->tailLinkOf(currNodeIdx, l)).setAccess(SORTED);
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline void orderColoredStrokes(JointSequenceGraphList &organizedGraphs, std::vector<tstroke *=""> &strokes,</tstroke>
Toshihiro Shimizu 890ddd
								const TRasterCM32P &ras, TPalette *palette)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Initialize ordering
Toshihiro Shimizu 890ddd
	std::vector<std::pair<int, *="" tstroke="">> strokesByHeight(</std::pair<int,>
Toshihiro Shimizu 890ddd
		strokes.size(), std::make_pair(-(std::numeric_limits<int>::max)(), (TStroke *)0));</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t s, sCount = strokes.size();
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s)
Toshihiro Shimizu 890ddd
		strokesByHeight[s].second = strokes[s];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	size_t og, ogCount = organizedGraphs.size();
Toshihiro Shimizu 890ddd
	for (og = 0; og != ogCount; ++og)
Toshihiro Shimizu 890ddd
		sortJS(&organizedGraphs[og], strokesByHeight, ras, palette);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, we have the order vector filled, apply sorting algorithm.
Toshihiro Shimizu 890ddd
	std::sort(strokesByHeight.begin(), strokesByHeight.end());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (s = 0; s != sCount; ++s)
Toshihiro Shimizu 890ddd
		strokes[s] = strokesByHeight[s].second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==========================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Take samples of image colors to associate each stroke to its corresponding
Toshihiro Shimizu 890ddd
//palette color. Currently working on colormaps, closest-to-black strokes
Toshihiro Shimizu 890ddd
//otherwise.
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
	JointSequenceGraphList &organizedGraphs = g.organizedGraphs;
Toshihiro Shimizu 890ddd
	SequenceList &singleSequences = g.singleSequences;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterCM32P cm = ras;
Toshihiro Shimizu 890ddd
	unsigned int i, j, k, n;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (cm && g.currConfig->m_maxThickness > 0.0) {
Toshihiro Shimizu 890ddd
		applyStrokeIndices(&g);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Treat single sequences before, like conversionToStrokes(..)
Toshihiro Shimizu 890ddd
		for (i = 0; i < singleSequences.size(); ++i)
Toshihiro Shimizu 890ddd
			strokes[i]->setStyle(singleSequences[i].m_color);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Then, treat remaining graph-strokes
Toshihiro Shimizu 890ddd
		n = i;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (i = 0; i < organizedGraphs.size(); ++i)
Toshihiro Shimizu 890ddd
			for (j = 0; j < organizedGraphs[i].getNodesCount(); ++j)
Toshihiro Shimizu 890ddd
				if (!organizedGraphs[i].getNode(j).hasAttribute(JointSequenceGraph::ELIMINATED)) //due to junction recovery
Toshihiro Shimizu 890ddd
					for (k = 0; k < organizedGraphs[i].getNode(j).getLinksCount(); ++k) {
Toshihiro Shimizu 890ddd
						Sequence &s = *organizedGraphs[i].node(j).link(k);
Toshihiro Shimizu 890ddd
						if (s.isForward()) {
Toshihiro Shimizu 890ddd
							//vi->getStroke(n)->setStyle(s.m_color);
Toshihiro Shimizu 890ddd
							strokes[n]->setStyle(s.m_color);
Toshihiro Shimizu 890ddd
							++n;
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Order vector image according to actual color-coverings at junctions.
Toshihiro Shimizu 890ddd
		orderColoredStrokes(organizedGraphs, strokes, cm, palette);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		//Choose closest-to-black palette color
Toshihiro Shimizu 890ddd
		int blackStyleId = palette->getClosestStyle(TPixel32::Black);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		unsigned int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < strokes.size(); ++i)
Toshihiro Shimizu 890ddd
			strokes[i]->setStyle(blackStyleId);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}