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
}