Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/rasterbrush.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <vector></vector>
Toshihiro Shimizu 890ddd
#include <tcurves.h></tcurves.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=====================================================================================
Toshihiro Shimizu 890ddd
// forward declaration
Toshihiro Shimizu 890ddd
void lightPixel(const TRasterCM32P &ras, const TPoint &pix, double distance, int styleId, bool checkAntialiasedPixel);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ConeSubVolume
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const static double m_values[21];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ConeSubVolume()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//calcola il sottovolume di un cono di raggio e volume unitario in base
Toshihiro Shimizu 890ddd
	static double compute(double cover)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double x = (10 * tcrop(cover, -1.0, 1.0)) + 10;
Toshihiro Shimizu 890ddd
		assert(0 <= x && x <= 20);
Toshihiro Shimizu 890ddd
		int i = tfloor(x);
Toshihiro Shimizu 890ddd
		if (i == 20)
Toshihiro Shimizu 890ddd
			return m_values[i];
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			//Interpolazione lineare.
Toshihiro Shimizu 890ddd
			return (-(x - (i + 1)) * m_values[i]) - (-(x - i) * m_values[i + 1]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double ConeSubVolume::m_values[] = {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	1.0, 0.99778, 0.987779, 0.967282, 0.934874,
Toshihiro Shimizu 890ddd
	0.889929, 0.832457, 0.763067, 0.683002, 0.594266,
Toshihiro Shimizu 890ddd
	0.5, 0.405734, 0.316998, 0.236933, 0.167543,
Toshihiro Shimizu 890ddd
	0.110071, 0.0651259, 0.0327182, 0.0122208, 0.00221986,
Toshihiro Shimizu 890ddd
	0.0};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Permette di disegnare un disco pieno
Toshihiro Shimizu 890ddd
class Disk
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD m_centre;
Toshihiro Shimizu 890ddd
	double m_radius;
Toshihiro Shimizu 890ddd
	bool m_doAntialias;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Traccia una linea tra due punti per riempire il disco
Toshihiro Shimizu 890ddd
	void fill(const TRasterCM32P &ras, const TPoint &p1, const TPoint &p2, int styleId) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (p1.y == p2.y) {
Toshihiro Shimizu 890ddd
			int xMax, xMin;
Toshihiro Shimizu 890ddd
			if (p1.x > p2.x) {
Toshihiro Shimizu 890ddd
				xMax = p1.x;
Toshihiro Shimizu 890ddd
				xMin = p2.x;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				xMin = p1.x;
Toshihiro Shimizu 890ddd
				xMax = p2.x;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			TPixelCM32 color(styleId, 0, 0);
Toshihiro Shimizu 890ddd
			for (int i = xMin; i <= xMax; i++)
Toshihiro Shimizu 890ddd
				ras->pixels(p1.y)[i] = color;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			int yMax, yMin;
Toshihiro Shimizu 890ddd
			if (p1.y > p2.y) {
Toshihiro Shimizu 890ddd
				yMax = p1.y;
Toshihiro Shimizu 890ddd
				yMin = p2.y;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				yMin = p1.y;
Toshihiro Shimizu 890ddd
				yMax = p2.y;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			TPixelCM32 color(styleId, 0, 0);
Toshihiro Shimizu 890ddd
			for (int i = yMin; i <= yMax; i++)
Toshihiro Shimizu 890ddd
				ras->pixels(i)[p1.x] = color;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Calcola la distanza di un pixel dal centro "reale"
Toshihiro Shimizu 890ddd
	inline double distancePointToCentre(const TPoint &point) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double d = sqrt((point.x - m_centre.x) * (point.x - m_centre.x) + (point.y - m_centre.y) * (point.y - m_centre.y));
Toshihiro Shimizu 890ddd
		return d;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Calcola la distanza tra un punto della cironferenza ideale ed il pixel che la approssima
Toshihiro Shimizu 890ddd
	//Inoltre calcola la distanza dei pixel vicini per gestire l'antialias
Toshihiro Shimizu 890ddd
	void computeDistances(double distances[3], const TPoint &point, const TPoint ¢re, bool upperPoint) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TPoint p = point - centre;
Toshihiro Shimizu 890ddd
		if (upperPoint) {
Toshihiro Shimizu 890ddd
			double d = distancePointToCentre(point);
Toshihiro Shimizu 890ddd
			distances[0] = d - m_radius;
Toshihiro Shimizu 890ddd
			d = distancePointToCentre(TPoint(point.x, point.y + 1));
Toshihiro Shimizu 890ddd
			distances[1] = d - m_radius;
Toshihiro Shimizu 890ddd
			d = distancePointToCentre(TPoint(point.x, point.y - 1));
Toshihiro Shimizu 890ddd
			distances[2] = d - m_radius;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			double d = distancePointToCentre(point);
Toshihiro Shimizu 890ddd
			distances[0] = d - m_radius;
Toshihiro Shimizu 890ddd
			d = distancePointToCentre(TPoint(point.x + 1, point.y));
Toshihiro Shimizu 890ddd
			distances[1] = d - m_radius;
Toshihiro Shimizu 890ddd
			d = distancePointToCentre(TPoint(point.x - 1, point.y));
Toshihiro Shimizu 890ddd
			distances[2] = d - m_radius;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Illumina otto pixel simmetrici per ottenere la circonferenza del disco.
Toshihiro Shimizu 890ddd
	//Per ogni pixel illumina anche i vicini per gestire l'antialias.
Toshihiro Shimizu 890ddd
	void makeAntiAliasedDiskBorder(const TRasterCM32P &ras,
Toshihiro Shimizu 890ddd
								   const TPoint ¢re,
Toshihiro Shimizu 890ddd
								   const TPoint &point,
Toshihiro Shimizu 890ddd
								   double distancesAntialias[3],
Toshihiro Shimizu 890ddd
								   int styleId,
Toshihiro Shimizu 890ddd
								   int maxPointToFill) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		computeDistances(distancesAntialias, point + centre, centre, true);
Toshihiro Shimizu 890ddd
		lightPixel(ras, point + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(point.x, point.y + 1) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(point.x, point.y - 1) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeDistances(distancesAntialias, TPoint(point.y, point.x) + centre, centre, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(point.y, point.x) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(point.y + 1, point.x) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(point.y - 1, point.x) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeDistances(distancesAntialias, TPoint(-point.x, -point.y) + centre, centre, true);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.x, -point.y) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.x, -point.y - 1) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.x, -point.y + 1) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		computeDistances(distancesAntialias, TPoint(-point.y + centre.x, point.x + centre.y), centre, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.y, point.x) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.y - 1, point.x) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
		lightPixel(ras, TPoint(-point.y + 1, point.x) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((point.x + centre.x) != (centre.x)) {
Toshihiro Shimizu 890ddd
			computeDistances(distancesAntialias, TPoint(point.y, -point.x) + centre, centre, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.y, -point.x) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.y + 1, -point.x) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.y - 1, -point.x) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			computeDistances(distancesAntialias, TPoint(point.x, -point.y) + centre, centre, true);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.x, -point.y) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.x, -point.y - 1) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.x, -point.y + 1) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			computeDistances(distancesAntialias, TPoint(-point.y, -point.x) + centre, centre, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.y, -point.x) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.y - 1, -point.x) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.y + 1, -point.x) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			computeDistances(distancesAntialias, TPoint(-point.x, point.y) + centre, centre, true);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.x, point.y) + centre, distancesAntialias[0], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.x, point.y + 1) + centre, distancesAntialias[1], styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.x, point.y - 1) + centre, distancesAntialias[2], styleId, false);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (maxPointToFill <= point.y - 2) {
Toshihiro Shimizu 890ddd
			fill(ras, TPoint(point.x, maxPointToFill) + centre, TPoint(point.x, point.y - 2) + centre, styleId);
Toshihiro Shimizu 890ddd
			fill(ras, TPoint(maxPointToFill, point.x) + centre, TPoint(point.y - 2, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
			fill(ras, TPoint(point.x, -maxPointToFill) + centre, TPoint(point.x, -point.y + 2) + centre, styleId);
Toshihiro Shimizu 890ddd
			fill(ras, TPoint(-maxPointToFill, -point.x) + centre, TPoint(-point.y + 2, -point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (point.x != 0) {
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(maxPointToFill, -point.x) + centre, TPoint(point.y - 2, -point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(-point.x, -maxPointToFill) + centre, TPoint(-point.x, -point.y + 2) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(-maxPointToFill, point.x) + centre, TPoint(-point.y + 2, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(-point.x, maxPointToFill) + centre, TPoint(-point.x, point.y - 2) + centre, styleId);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void makeNoAntiAliasedDiskBorder(const TRasterCM32P &ras,
Toshihiro Shimizu 890ddd
									 const TPoint ¢re,
Toshihiro Shimizu 890ddd
									 const TPoint &point,
Toshihiro Shimizu 890ddd
									 int styleId,
Toshihiro Shimizu 890ddd
									 int maxPointToFill) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (((int)(m_radius * 2)) % 2 == 0) {
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.x - 1, point.y) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.y - 1, -point.x + 1) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.x, -point.y + 1) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.y, point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			lightPixel(ras, point + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(point.y, -point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.x, -point.y) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			lightPixel(ras, TPoint(-point.y, point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((point.x + centre.x) != (centre.x)) {
Toshihiro Shimizu 890ddd
			if (((int)(m_radius * 2)) % 2 == 0) {
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(point.y - 1, point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(point.x - 1, -point.y + 1) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(-point.y, -point.x + 1) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(-point.x, point.y) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(point.y, point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(point.x, -point.y) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(-point.y, -point.x) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
				lightPixel(ras, TPoint(-point.x, point.y) + centre, -1, styleId, false);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (maxPointToFill <= point.y - 1) {
Toshihiro Shimizu 890ddd
			if (((int)(m_radius * 2)) % 2 == 0) {
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(point.x - 1, 0) + centre, TPoint(point.x - 1, point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(0, -point.x + 1) + centre, TPoint(point.y - 1, -point.x + 1) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(-point.x, 0) + centre, TPoint(-point.x, -point.y + 1) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(0, point.x) + centre, TPoint(-point.y, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
				if (point.x != 0) {
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(0, point.x) + centre, TPoint(point.y - 1, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(point.x - 1, 0) + centre, TPoint(point.x - 1, -point.y + 1) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(0, -point.x + 1) + centre, TPoint(-point.y, -point.x + 1) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(-point.x, 0) + centre, TPoint(-point.x, point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(point.x, 0) + centre, TPoint(point.x, point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(0, -point.x) + centre, TPoint(point.y, -point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(-point.x, 0) + centre, TPoint(-point.x, -point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
				fill(ras, TPoint(0, point.x) + centre, TPoint(-point.y, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (point.x != 0) {
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(0, point.x) + centre, TPoint(point.y, point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(point.x, -0) + centre, TPoint(point.x, -point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(0, -point.x) + centre, TPoint(-point.y, -point.x) + centre, styleId);
Toshihiro Shimizu 890ddd
					fill(ras, TPoint(-point.x, 0) + centre, TPoint(-point.x, point.y) + centre, styleId);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Disk()
Toshihiro Shimizu 890ddd
		: m_centre(0.0, 0.0), m_radius(1.0), m_doAntialias(true)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Disk(const TThickPoint &p, bool doAntialias)
Toshihiro Shimizu 890ddd
		: m_doAntialias(doAntialias)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_doAntialias) {
Toshihiro Shimizu 890ddd
			m_centre = TPointD(p.x, p.y);
Toshihiro Shimizu 890ddd
			m_radius = p.thick * 0.5;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			m_centre = TPointD(tround(p.x), tround(p.y));
Toshihiro Shimizu 890ddd
			m_radius = tround(p.thick) * 0.5;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Disegna un disco
Toshihiro Shimizu 890ddd
	void draw(const TRasterCM32P &ras, int styleId) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double distances[3];
Toshihiro Shimizu 890ddd
		int maxPointToFill = 0;
Toshihiro Shimizu 890ddd
		TPoint centre = convert(m_centre);
Toshihiro Shimizu 890ddd
		TPoint point;
Toshihiro Shimizu 890ddd
		if (m_doAntialias) {
Toshihiro Shimizu 890ddd
			TPoint point(0, tround(m_radius));
Toshihiro Shimizu 890ddd
			int d = 1 - tround(m_radius), dE = 3, dSE = -2 * tround(m_radius) + 5;
Toshihiro Shimizu 890ddd
			makeAntiAliasedDiskBorder(ras, centre, point, distances, styleId, maxPointToFill);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			while (point.y > point.x) {
Toshihiro Shimizu 890ddd
				if (d < 0) {
Toshihiro Shimizu 890ddd
					d += dE;
Toshihiro Shimizu 890ddd
					dE += 2;
Toshihiro Shimizu 890ddd
					dSE += 2;
Toshihiro Shimizu 890ddd
					point.x++;
Toshihiro Shimizu 890ddd
					maxPointToFill++;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					d += dSE;
Toshihiro Shimizu 890ddd
					dE += 2;
Toshihiro Shimizu 890ddd
					dSE += 4;
Toshihiro Shimizu 890ddd
					point.x++;
Toshihiro Shimizu 890ddd
					point.y--;
Toshihiro Shimizu 890ddd
					maxPointToFill++;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				makeAntiAliasedDiskBorder(ras, centre, point, distances, styleId, maxPointToFill);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TPoint point(0, tround(m_radius - 0.5));
Toshihiro Shimizu 890ddd
			int d = 3 - 2 * (int)m_radius;
Toshihiro Shimizu 890ddd
			while (point.y > point.x) {
Toshihiro Shimizu 890ddd
				makeNoAntiAliasedDiskBorder(ras, centre, point, styleId, maxPointToFill);
Toshihiro Shimizu 890ddd
				if (d < 0)
Toshihiro Shimizu 890ddd
					d = d + 4 * point.x + 6;
Toshihiro Shimizu 890ddd
				else {
Toshihiro Shimizu 890ddd
					d = d + 4 * (point.x - point.y) + 10;
Toshihiro Shimizu 890ddd
					point.y--;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				maxPointToFill++;
Toshihiro Shimizu 890ddd
				point.x++;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (point.x == point.y)
Toshihiro Shimizu 890ddd
				makeNoAntiAliasedDiskBorder(ras, centre, point, styleId, maxPointToFill);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD getCentre() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_centre;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double getRadius() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return m_radius;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setCentre(const TPointD ¢re)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_centre = centre;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setCentre(double x, double y)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_centre.x = x;
Toshihiro Shimizu 890ddd
		m_centre.y = y;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setRadius(double radius)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_radius = radius;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Calcola la distanza di una curva al parametro "t" dalla retta che unisce i punti nei parametri "tPrevious" e "tNext"
Toshihiro Shimizu 890ddd
double findChordalDeviation(const TQuadratic &quadratic, double t, double tPrevious, double tNext)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD pPrevious = quadratic.getPoint(tPrevious);
Toshihiro Shimizu 890ddd
	TPointD pNext = quadratic.getPoint(tNext);
Toshihiro Shimizu 890ddd
	TPointD p = quadratic.getPoint(t);
Toshihiro Shimizu 890ddd
	TPointD P(p - pPrevious), Q(pNext - pPrevious);
Toshihiro Shimizu 890ddd
	double PQ = P * Q;
Toshihiro Shimizu 890ddd
	double QQ = Q * Q;
Toshihiro Shimizu 890ddd
	return norm(P - (PQ / QQ) * Q);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Accende un pixel calcolandone l'intensita'
Toshihiro Shimizu 890ddd
/*-- 筆先のアンチエイリアス部分の描画 --*/
Toshihiro Shimizu 890ddd
void lightPixel(const TRasterCM32P &ras, const TPoint &pix, double distance, int styleId, bool checkAntialiasedPixel)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPixelCM32 pixel = ras->pixels(pix.y)[pix.x];
Toshihiro Shimizu 890ddd
	double volumeParziale = ConeSubVolume::compute(distance);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- 現在のToneに乗算していく -*/
Toshihiro Shimizu 890ddd
	int newTone = tround((double)pixel.getTone() * (1.0 - volumeParziale));
Toshihiro Shimizu 890ddd
	assert(newTone >= 0 && newTone <= 255);
Toshihiro Shimizu 890ddd
	ras->pixels(pix.y)[pix.x] = TPixelCM32(styleId, pixel.getPaint(), newTone);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool isDiskNecessaryNecessary(const TQuadratic &quadratic, double tCurrent, double lastT, double nextT, bool &idLastDiskDrown)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPoint currentPoint = convert(quadratic.getPoint(tCurrent));
Toshihiro Shimizu 890ddd
	TPoint lastPoint = convert(quadratic.getPoint(lastT));
Toshihiro Shimizu 890ddd
	TPoint nextPoint = convert(quadratic.getPoint(nextT));
Toshihiro Shimizu 890ddd
	TPoint lastDiff = currentPoint - lastPoint;
Toshihiro Shimizu 890ddd
	TPoint nextDiff = currentPoint - nextPoint;
Toshihiro Shimizu 890ddd
	TPoint otherDiff = lastPoint - nextPoint;
Toshihiro Shimizu 890ddd
	bool isLastNear = lastDiff.x == 0 || lastDiff.y == 0;
Toshihiro Shimizu 890ddd
	bool isNextNear = nextDiff.x == 0 || nextDiff.y == 0;
Toshihiro Shimizu 890ddd
	bool isOtheNear = otherDiff.x == 0 || otherDiff.y == 0;
Toshihiro Shimizu 890ddd
	if (isLastNear && isNextNear && !isOtheNear && idLastDiskDrown) {
Toshihiro Shimizu 890ddd
		idLastDiskDrown = false;
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Disegna una porzione di del tratto (un piccolo arco)
Toshihiro Shimizu 890ddd
void makeLittleArch(const TRasterCM32P &ras, const Disk &disk1, const Disk &disk2,
Toshihiro Shimizu 890ddd
					const Disk &disk3, int styleId, bool doAntialias)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD center1 = disk1.getCentre();
Toshihiro Shimizu 890ddd
	TPointD center2 = disk2.getCentre();
Toshihiro Shimizu 890ddd
	TPointD center3 = disk3.getCentre();
Toshihiro Shimizu 890ddd
	TQuadratic quadratic(center1, center2, center3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	disk1.draw(ras, styleId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double length = quadratic.getLength();
Toshihiro Shimizu 890ddd
	if (length < 2)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	double t = 0, step = 1 / (length * 1.5), t2 = quadratic.getT(center2);
Toshihiro Shimizu 890ddd
	bool idLastDiskDrown = true;
Toshihiro Shimizu 890ddd
	for (t = step; t < 1; t += step) {
Toshihiro Shimizu 890ddd
		TPointD center = quadratic.getPoint(t);
Toshihiro Shimizu 890ddd
		double radius = disk1.getRadius() + (disk3.getRadius() - disk1.getRadius()) * t;
Toshihiro Shimizu 890ddd
		Disk disk(TThickPoint(center, radius * 2), doAntialias);
Toshihiro Shimizu 890ddd
		bool drawDisk = true;
Toshihiro Shimizu 890ddd
		if (!doAntialias)
Toshihiro Shimizu 890ddd
			drawDisk = isDiskNecessaryNecessary(quadratic, t, t - step, t + step > 1 ? 1 : t + step, idLastDiskDrown);
Toshihiro Shimizu 890ddd
		if (t != 1 && drawDisk) {
Toshihiro Shimizu 890ddd
			disk.draw(ras, styleId);
Toshihiro Shimizu 890ddd
			idLastDiskDrown = true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	disk3.draw(ras, styleId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Disegna un piccolo segmento, invece di un archetto.
Toshihiro Shimizu 890ddd
void makeLittleSegment(const TRasterCM32P &ras, const Disk &disk1, const Disk &disk2,
Toshihiro Shimizu 890ddd
					   int styleId, bool doAntialias)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TPointD center1 = disk1.getCentre();
Toshihiro Shimizu 890ddd
	TPointD center2 = disk2.getCentre();
Toshihiro Shimizu 890ddd
	TPointD middle = (center1 + center2) * 0.5;
Toshihiro Shimizu 890ddd
	double raius = (disk1.getRadius() + disk2.getRadius()) * 0.5;
Toshihiro Shimizu 890ddd
	Disk disk(TThickPoint(middle, raius * 2), doAntialias);
Toshihiro Shimizu 890ddd
	makeLittleArch(ras, disk1, disk, disk2, styleId, doAntialias);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Preso un vettore di punti, disegna una pennelata che li approssima in un raster trasparente
Toshihiro Shimizu 890ddd
void rasterBrush(const TRasterCM32P &rasBuffer, const vector<tthickpoint> &points, int styleId, bool doAntialias)</tthickpoint>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i, n = points.size();
Toshihiro Shimizu 890ddd
	if (n == 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	else if (n == 1) {
Toshihiro Shimizu 890ddd
		Disk disk(points[0], doAntialias);
Toshihiro Shimizu 890ddd
		disk.draw(rasBuffer, styleId);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else if (n == 2) {
Toshihiro Shimizu 890ddd
		makeLittleSegment(rasBuffer, Disk(points[0], doAntialias), Disk(points[1], doAntialias), styleId, doAntialias);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else if (n == 4) {
Toshihiro Shimizu 890ddd
		makeLittleArch(rasBuffer,
Toshihiro Shimizu 890ddd
					   Disk(points[0], doAntialias),
Toshihiro Shimizu 890ddd
					   Disk(points[1], doAntialias),
Toshihiro Shimizu 890ddd
					   Disk(points[2], doAntialias),
Toshihiro Shimizu 890ddd
					   styleId, doAntialias);
Toshihiro Shimizu 890ddd
		makeLittleSegment(rasBuffer, Disk(points[2], doAntialias), Disk(points[3], doAntialias), styleId, doAntialias);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (i = 0; i + 2 < n; i += 2)
Toshihiro Shimizu 890ddd
			makeLittleArch(rasBuffer,
Toshihiro Shimizu 890ddd
						   Disk(points[i], doAntialias),
Toshihiro Shimizu 890ddd
						   Disk(points[i + 1], doAntialias),
Toshihiro Shimizu 890ddd
						   Disk(points[i + 2], doAntialias),
Toshihiro Shimizu 890ddd
						   styleId, doAntialias);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}