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