|
Shinya Kitaoka |
6a4e01 |
#include <memory></memory>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
40cabe |
#include <cstring></cstring>
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=======================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class HalfCord {
|
|
Shinya Kitaoka |
120a6e |
std::unique_ptr<int[]> m_array;</int[]>
|
|
Shinya Kitaoka |
120a6e |
int m_radius;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
HalfCord(int radius) : m_radius(radius), m_array(new int[radius + 1]) {
|
|
Shinya Kitaoka |
120a6e |
assert(radius >= 0);
|
|
Shinya Kitaoka |
120a6e |
memset(m_array.get(), 0, (m_radius + 1) * sizeof(int));
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
float dCircle = 1.25f - m_radius; // inizializza decision variable
|
|
Shinya Kitaoka |
120a6e |
int y = m_radius; // inizializzazione indice scanline
|
|
Shinya Kitaoka |
120a6e |
int x = 0; // inizializzazione indice colonna
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
m_array[y] = std::max(x, m_array[y]);
|
|
Shinya Kitaoka |
120a6e |
m_array[x] = y;
|
|
Shinya Kitaoka |
120a6e |
if (dCircle <= 0) {
|
|
Shinya Kitaoka |
120a6e |
dCircle = dCircle + 2 * x + 3;
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
y--;
|
|
Shinya Kitaoka |
120a6e |
dCircle = dCircle + 2 * (x - y) + 5;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
x++;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} while (y >= x);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
inline int getCord(int x) {
|
|
Shinya Kitaoka |
120a6e |
assert(0 <= x && x <= m_radius);
|
|
Shinya Kitaoka |
120a6e |
return m_array[x];
|
|
Shinya Kitaoka |
120a6e |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
// not implemented
|
|
Shinya Kitaoka |
120a6e |
HalfCord(const HalfCord &);
|
|
Shinya Kitaoka |
120a6e |
HalfCord &operator=(const HalfCord &);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=======================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::brush(TRaster32P ras, const TPoint &aa, const TPoint &bb, int radius,
|
|
Shinya Kitaoka |
120a6e |
const TPixel32 &col) {
|
|
Shinya Kitaoka |
120a6e |
TPoint a = aa;
|
|
Shinya Kitaoka |
120a6e |
TPoint b = bb;
|
|
Shinya Kitaoka |
120a6e |
if (a.y > b.y) tswap(a, b); // a e' piu' in basso di b
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int lx = ras->getLx();
|
|
Shinya Kitaoka |
120a6e |
int ly = ras->getLy();
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- radius = 0
|
|
Shinya Kitaoka |
120a6e |
if (radius == 0) {
|
|
Shinya Kitaoka |
120a6e |
// k = +1/-1 se il rettangolo e' inclinato positivamente
|
|
Shinya Kitaoka |
120a6e |
// (0<=m)/negativamente (m<0)
|
|
Shinya Kitaoka |
120a6e |
// (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle
|
|
Shinya Kitaoka |
120a6e |
// coordinate "di schermo")
|
|
Shinya Kitaoka |
120a6e |
int k = 1;
|
|
Shinya Kitaoka |
120a6e |
int dy = b.y - a.y;
|
|
Shinya Kitaoka |
120a6e |
int dx = b.x - a.x;
|
|
Shinya Kitaoka |
120a6e |
if (dx < 0) {
|
|
Shinya Kitaoka |
120a6e |
dx = -dx;
|
|
Shinya Kitaoka |
120a6e |
k = -1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(dx >= 0);
|
|
Shinya Kitaoka |
120a6e |
assert(dy >= 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double m; // m sara' definita solo per dx!=0)
|
|
Shinya Kitaoka |
120a6e |
if (dx > 0) {
|
|
Shinya Kitaoka |
120a6e |
m = dy / (double)dx;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// double length = sqrt(dx*dx + dy*dy);
|
|
Shinya Kitaoka |
120a6e |
const int alpha = dy, beta = -dx;
|
|
Shinya Kitaoka |
120a6e |
const int incE = alpha;
|
|
Shinya Kitaoka |
120a6e |
const int incNE = alpha + beta;
|
|
Shinya Kitaoka |
120a6e |
const int incN = beta;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// N.B. le coordinate sono relative ad un sist. di rif. con l'origine in a
|
|
Shinya Kitaoka |
120a6e |
// l'eq. della retta e' alpha * x + beta * y = 0
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int yMin = std::max(a.y, 0) - a.y; // clipping y + cambio riferimento
|
|
Shinya Kitaoka |
120a6e |
int yMax = std::min(b.y, ly - 1) - a.y; // (trasporto dell'origine in a)
|
|
Shinya Kitaoka |
120a6e |
if (dx > 0 && m <= 1) {
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm
|
|
Shinya Kitaoka |
120a6e |
TPoint segm;
|
|
Shinya Kitaoka |
120a6e |
if (dy == 0) // segmento orizzontale: inizializza segm
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
segm.x = 0;
|
|
Shinya Kitaoka |
120a6e |
segm.y = yMin;
|
|
Shinya Kitaoka |
120a6e |
} else // 0
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
segm.x = tceil((yMin - 0.5) / m);
|
|
Shinya Kitaoka |
120a6e |
segm.y = yMin;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int dSegm = tfloor(alpha * (segm.x + 1) + beta * (segm.y + 0.5));
|
|
Shinya Kitaoka |
120a6e |
while (segm.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int count =
|
|
Shinya Kitaoka |
120a6e |
0; // i trati orizzontali di segm vengono disegnati in "blocco"
|
|
Shinya Kitaoka |
120a6e |
while (dSegm < 0 && segm.x <= dx) // Est: segm.x<=dx evita il ciclo
|
|
Shinya Kitaoka |
120a6e |
{ // infinito quando m=0 (incE=0)
|
|
Shinya Kitaoka |
120a6e |
dSegm = dSegm + incE;
|
|
Shinya Kitaoka |
120a6e |
segm.x++;
|
|
Shinya Kitaoka |
120a6e |
count++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// NordEst
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(
|
|
Shinya Kitaoka |
120a6e |
{a.x + segm.x - count, a.x, 0}); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(
|
|
Shinya Kitaoka |
120a6e |
{a.x + segm.x, b.x, lx - 1}); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max({a.x - segm.x, a.x - dx,
|
|
Shinya Kitaoka |
120a6e |
0}); // clipping x + riflessione + ritorno
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min({a.x - segm.x + count, a.x,
|
|
Shinya Kitaoka |
120a6e |
lx - 1}); // alle coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segm.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dSegm = dSegm + incNE;
|
|
Shinya Kitaoka |
120a6e |
segm.x++;
|
|
Shinya Kitaoka |
120a6e |
segm.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else // m>1 oppure segmento verticale
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm
|
|
Shinya Kitaoka |
120a6e |
TPoint segm;
|
|
Shinya Kitaoka |
120a6e |
if (dx == 0) // segmento verticale: inizializza segm
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
segm.x = 0;
|
|
Shinya Kitaoka |
120a6e |
segm.y = yMin;
|
|
Shinya Kitaoka |
120a6e |
} else // m>1 : inizializza segm
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
segm.x = tround(yMin / m);
|
|
Shinya Kitaoka |
120a6e |
segm.y = yMin;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int dSegm = tfloor(alpha * (segm.x + 0.5) + beta * (segm.y + 1));
|
|
Shinya Kitaoka |
120a6e |
while (segm.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x + segm.x, 0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + segm.x, lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin =
|
|
Shinya Kitaoka |
120a6e |
std::max(a.x - segm.x, 0); // clipping x + riflessione + ritorno
|
|
Shinya Kitaoka |
120a6e |
xMax =
|
|
Shinya Kitaoka |
120a6e |
std::min(a.x - segm.x, lx - 1); // alle coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segm.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dSegm <= 0) // NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegm = dSegm + incNE;
|
|
Shinya Kitaoka |
120a6e |
segm.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // Nord
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegm = dSegm + incN;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segm.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
HalfCord halfCord(radius);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int x, y;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- punti iniziali coincidenti: disegna un cerchio
|
|
Shinya Kitaoka |
120a6e |
if (a == b) {
|
|
Shinya Kitaoka |
120a6e |
int yMin = std::max(a.y - radius, 0); // clipping y
|
|
Shinya Kitaoka |
120a6e |
int yMax = std::min(a.y + radius, ly - 1); // clipping y
|
|
Shinya Kitaoka |
120a6e |
for (y = yMin; y <= yMax; y++) {
|
|
Shinya Kitaoka |
120a6e |
int deltay = abs(y - a.y);
|
|
Shinya Kitaoka |
120a6e |
int xMin = std::max(a.x - halfCord.getCord(deltay), 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
int xMax =
|
|
Shinya Kitaoka |
120a6e |
std::min(a.x + halfCord.getCord(deltay), lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- rettangolo orizzontale (a.y = b.y, a.x != b.x)
|
|
Shinya Kitaoka |
120a6e |
if (a.y == b.y) {
|
|
Shinya Kitaoka |
120a6e |
int yMin = std::max((a.y - radius), 0); // clipping y
|
|
Shinya Kitaoka |
120a6e |
int yMax = std::min((a.y + radius), ly - 1); // clipping y
|
|
Shinya Kitaoka |
120a6e |
int xLeft = std::min(a.x, b.x);
|
|
Shinya Kitaoka |
120a6e |
int xRight = std::max(a.x, b.x);
|
|
Shinya Kitaoka |
120a6e |
for (y = yMin; y <= yMax; y++) {
|
|
Shinya Kitaoka |
120a6e |
int deltay = abs(y - a.y);
|
|
Shinya Kitaoka |
120a6e |
int xMin = std::max(xLeft - halfCord.getCord(deltay), 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
int xMax =
|
|
Shinya Kitaoka |
120a6e |
std::min(xRight + halfCord.getCord(deltay), lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- rettangolo verticale (a.x = b.x, a.y != b.y)
|
|
Shinya Kitaoka |
120a6e |
if (a.x == b.x) {
|
|
Shinya Kitaoka |
120a6e |
int xMin = std::max(a.x - radius, 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
int xMax = std::min(a.x + radius, lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
for (x = xMin; x <= xMax; x++) {
|
|
Shinya Kitaoka |
120a6e |
int deltax = abs(x - a.x);
|
|
Shinya Kitaoka |
120a6e |
int yMin = std::max(a.y - halfCord.getCord(deltax), 0); // clipping y
|
|
Shinya Kitaoka |
120a6e |
int yMax =
|
|
Shinya Kitaoka |
120a6e |
std::min(b.y + halfCord.getCord(deltax), ly - 1); // clipping y
|
|
Shinya Kitaoka |
120a6e |
if (yMin <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(yMin) + x;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = ras->pixels(yMax) + x;
|
|
Shinya Kitaoka |
120a6e |
int wrap = ras->getWrap();
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) {
|
|
Shinya Kitaoka |
120a6e |
*p = col;
|
|
Shinya Kitaoka |
120a6e |
p += wrap;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- rettangolo inclinato
|
|
Shinya Kitaoka |
120a6e |
// k = +1/-1 se il rettangolo e' inclinato positivamente/negativamente
|
|
Shinya Kitaoka |
120a6e |
int k = 1;
|
|
Shinya Kitaoka |
120a6e |
int dx = b.x - a.x;
|
|
Shinya Kitaoka |
120a6e |
if (dx < 0) {
|
|
Shinya Kitaoka |
120a6e |
dx = -dx;
|
|
Shinya Kitaoka |
120a6e |
k = -1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
int dy = b.y - a.y;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
assert(dx > 0);
|
|
Shinya Kitaoka |
120a6e |
assert(dy > 0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
double length = sqrt((double)(dx * dx + dy * dy));
|
|
Shinya Kitaoka |
120a6e |
const double m = dy / (double)dx;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// punto di tangenza superiore nel sistema di riferimento del cerchio
|
|
Shinya Kitaoka |
120a6e |
TPointD up(-radius * dy / length, radius * dx / length);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// semi-ampiezza orizzontale delle "calotte" circolari
|
|
Shinya Kitaoka |
120a6e |
int halfAmplCap = tfloor(-up.x);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// A meno di intersezioni relative tra le diverse zone:
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// le scanline della "calotta" circolare superiore sono
|
|
Shinya Kitaoka |
120a6e |
// (b.y+cutExt,b.y+radius]
|
|
Shinya Kitaoka |
120a6e |
// le scanline del trapezoide circolare superiore sono [b.y-cutIn,b.y+cutExt]
|
|
Shinya Kitaoka |
120a6e |
// le scanline del parallelogramma sono (a.y+cutIn,b.y-cutIn)
|
|
Shinya Kitaoka |
120a6e |
// le scanline del trapezoide circolare inferiore sono [a.y-cutExt,a.y+cutIn]
|
|
Shinya Kitaoka |
120a6e |
// le scanline della "calotta" circolare inferiore sono
|
|
Shinya Kitaoka |
120a6e |
// [a.y-radius,a.y-cutExt)
|
|
Shinya Kitaoka |
120a6e |
int cutExt, cutIn;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// vertici del parallelogramma
|
|
Shinya Kitaoka |
120a6e |
TPointD rightUp;
|
|
Shinya Kitaoka |
120a6e |
TPointD rightDown;
|
|
Shinya Kitaoka |
120a6e |
TPointD leftUp;
|
|
Shinya Kitaoka |
120a6e |
TPointD leftDown;
|
|
Shinya Kitaoka |
120a6e |
double mParall; // coeff. angolare parallelogramma
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// NOTA BENE: halfAmplCap=0 <=> (radius=0 (caso a parte) , 1)
|
|
Shinya Kitaoka |
120a6e |
if (radius > 1) {
|
|
Shinya Kitaoka |
120a6e |
for (cutExt = radius;
|
|
Shinya Kitaoka |
120a6e |
cutExt >= 0 && halfCord.getCord(cutExt) <= halfAmplCap; cutExt--)
|
|
Shinya Kitaoka |
120a6e |
;
|
|
Shinya Kitaoka |
120a6e |
cutIn = cutExt; // vedi else successivo
|
|
Shinya Kitaoka |
120a6e |
rightUp.x = dx + halfCord.getCord(cutIn);
|
|
Shinya Kitaoka |
120a6e |
rightUp.y = dy - cutIn;
|
|
Shinya Kitaoka |
120a6e |
rightDown.x = halfCord.getCord(cutIn);
|
|
Shinya Kitaoka |
120a6e |
rightDown.y = -cutIn;
|
|
Shinya Kitaoka |
120a6e |
leftUp.x = dx - halfCord.getCord(cutIn);
|
|
Shinya Kitaoka |
120a6e |
leftUp.y = dy + cutIn;
|
|
Shinya Kitaoka |
120a6e |
leftDown.x = -halfCord.getCord(cutIn);
|
|
Shinya Kitaoka |
120a6e |
leftDown.y = cutIn;
|
|
Shinya Kitaoka |
120a6e |
mParall = dy / (double)dx;
|
|
Shinya Kitaoka |
120a6e |
} else // N.B. cutExt != cutIn solo quando radius=1
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
cutExt = radius; // radius=1 => halfAmplCap=0 (non ci sono mai le
|
|
Shinya Kitaoka |
120a6e |
// "calotte" circolari)
|
|
Shinya Kitaoka |
120a6e |
cutIn = 0; // anche per radius=1 il limite "interno" dei trapezoidi
|
|
Shinya Kitaoka |
120a6e |
// circolari e' < radius
|
|
Shinya Kitaoka |
120a6e |
rightUp.x = dx - up.x;
|
|
Shinya Kitaoka |
120a6e |
rightUp.y = dy - up.y;
|
|
Shinya Kitaoka |
120a6e |
rightDown.x = -up.x;
|
|
Shinya Kitaoka |
120a6e |
rightDown.y = -up.y;
|
|
Shinya Kitaoka |
120a6e |
leftUp.x = dx + up.x;
|
|
Shinya Kitaoka |
120a6e |
leftUp.y = dy + up.y;
|
|
Shinya Kitaoka |
120a6e |
leftDown.x = up.x;
|
|
Shinya Kitaoka |
120a6e |
leftDown.y = up.y;
|
|
Shinya Kitaoka |
120a6e |
mParall = m;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie "calotte" circolari
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie "calotta" circolare inferiore
|
|
Shinya Kitaoka |
120a6e |
int yMin = std::max(a.y - radius, 0); // clipping y
|
|
Shinya Kitaoka |
120a6e |
int yMax = std::min(a.y - cutExt - 1, ly - 1); // clipping y
|
|
Shinya Kitaoka |
120a6e |
for (y = yMin; y <= yMax; y++) {
|
|
Shinya Kitaoka |
120a6e |
int r = halfCord.getCord(a.y - y);
|
|
Shinya Kitaoka |
120a6e |
int xMin = std::max(a.x - r, 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
int xMax = std::min(a.x + r, lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie "calotta" circolare superiore
|
|
Shinya Kitaoka |
120a6e |
yMin = std::max(b.y + cutExt + 1, 0); // clipping y
|
|
Shinya Kitaoka |
120a6e |
yMax = std::min(b.y + radius, ly - 1); // clipping y
|
|
Shinya Kitaoka |
120a6e |
for (y = yMin; y <= yMax; y++) {
|
|
Shinya Kitaoka |
120a6e |
int r = halfCord.getCord(y - b.y);
|
|
Shinya Kitaoka |
120a6e |
int xMin = std::max(b.x - r, 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
int xMax = std::min(b.x + r, lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie trapezoidi
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle
|
|
Shinya Kitaoka |
120a6e |
// coordinate "di schermo")
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// limite destro assoluto delle scanline trapezoide:
|
|
Shinya Kitaoka |
120a6e |
int xSegmMax = tround(dx - up.x); // coordinata x del punto di tangenza
|
|
Shinya Kitaoka |
120a6e |
// inferiore sul cerchio superiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// limite sinistro assoluto delle scanline:
|
|
Shinya Kitaoka |
120a6e |
int xSegmMin = tround(up.x); // coordinata x del punto di tangenza superiore
|
|
Shinya Kitaoka |
120a6e |
// sul cerchio inferiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie trapezoide inferiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul
|
|
Shinya Kitaoka |
120a6e |
// centro
|
|
Shinya Kitaoka |
120a6e |
// del cerchio inferiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
yMin = std::max(a.y - cutExt, 0) - a.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
yMax = std::min({a.y + cutIn, b.y - cutIn - 1, ly - 1}) - a.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// l'eq. della retta e' alpha * x + beta * y + gammaRight = 0
|
|
Shinya Kitaoka |
120a6e |
const int alpha = dy, beta = -dx;
|
|
Shinya Kitaoka |
120a6e |
const double gammaRight = rightDown.y * dx - rightDown.x * dy;
|
|
Shinya Kitaoka |
120a6e |
const int incE = alpha;
|
|
Shinya Kitaoka |
120a6e |
const int incNE = alpha + beta;
|
|
Shinya Kitaoka |
120a6e |
const int incN = beta;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m <= 1) {
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate solo
|
|
Shinya Kitaoka |
120a6e |
// sul NordEst. L'ultima scanline non viene disegnata
|
|
Shinya Kitaoka |
120a6e |
TPoint segmRight(
|
|
Shinya Kitaoka |
120a6e |
tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmRight = tfloor(alpha * (segmRight.x + 1) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmRight.y + 0.5) + gammaRight);
|
|
Shinya Kitaoka |
120a6e |
while (segmRight.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
if (dSegmRight < 0) // Est
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + std::min(segmRight.x, xSegmMax),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - std::min(segmRight.x, xSegmMax),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
segmRight.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else // m>1
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate sempre
|
|
Shinya Kitaoka |
120a6e |
TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x),
|
|
Shinya Kitaoka |
120a6e |
yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmRight.y + 1) + gammaRight);
|
|
Shinya Kitaoka |
120a6e |
while (segmRight.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - segmRight.x,
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle coordinate
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dSegmRight <= 0) // NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // Nord
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incN;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segmRight.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- riempie trapezoide superiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul
|
|
Shinya Kitaoka |
120a6e |
// centro
|
|
Shinya Kitaoka |
120a6e |
// del cerchio superiore
|
|
Shinya Kitaoka |
120a6e |
yMin = std::max({b.y - cutIn, a.y + cutIn + 1, 0}) - b.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
yMax = std::min(b.y + cutExt, ly - 1) - b.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// l'eq. della retta e' alpha * x + beta * y + gammaLeft = 0
|
|
Shinya Kitaoka |
120a6e |
const double gammaLeft = leftDown.y * dx - leftDown.x * dy;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m <= 1) {
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate solo
|
|
Shinya Kitaoka |
120a6e |
// sul NordEst. L'ultima scanline non viene disegnata
|
|
Shinya Kitaoka |
120a6e |
TPoint segmLeft(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x),
|
|
Shinya Kitaoka |
120a6e |
yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmLeft.y + 0.5) + gammaLeft);
|
|
Shinya Kitaoka |
120a6e |
while (segmLeft.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(b.x + std::max(segmLeft.x, xSegmMin - dx),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(b.x - std::max(segmLeft.x, xSegmMin - dx),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
while (dSegmLeft < 0) {
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else // m>1
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate sempre
|
|
Shinya Kitaoka |
120a6e |
TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmLeft.y + 1) + gammaLeft);
|
|
Shinya Kitaoka |
120a6e |
while (segmLeft.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(b.x + segmLeft.x, 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(b.x - segmLeft.x, lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dSegmLeft <= 0) // NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // Nord
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incN;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segmLeft.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ----- parallelogramma (in alternativa a "parallelogrammoide circolare")
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul
|
|
Shinya Kitaoka |
120a6e |
// centro
|
|
Shinya Kitaoka |
120a6e |
// del cerchio inferiore
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// retta destra di equaz. alpha * x + beta * y + gammaRight = 0
|
|
Shinya Kitaoka |
120a6e |
// retta sinistra di equaz. alpha * x + beta * y + gammaLeft = 0
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
yMin = std::max(a.y + cutIn + 1, 0) - a.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
yMax = std::min(b.y - cutIn - 1, ly - 1) - a.y; // clipping y
|
|
Shinya Kitaoka |
120a6e |
if (m <= 1) {
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate solo
|
|
Shinya Kitaoka |
120a6e |
// sul NordEst. L'ultima scanline non viene disegnata
|
|
Shinya Kitaoka |
120a6e |
TPoint segmRight(
|
|
Shinya Kitaoka |
120a6e |
tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin);
|
|
Shinya Kitaoka |
120a6e |
TPoint segmLeft =
|
|
Shinya Kitaoka |
120a6e |
TPoint(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmRight = tfloor(alpha * (segmRight.x + 1) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmRight.y + 0.5) + gammaRight);
|
|
Shinya Kitaoka |
120a6e |
int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmLeft.y + 0.5) + gammaLeft);
|
|
Shinya Kitaoka |
120a6e |
while (segmRight.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
if (dSegmRight < 0) // segmRight a Est
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // segmRight a NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin =
|
|
Shinya Kitaoka |
120a6e |
std::max(a.x + std::max(segmLeft.x, xSegmMin), 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + std::min(segmRight.x, xSegmMax),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - std::min(segmRight.x, xSegmMax),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x - std::max(segmLeft.x, xSegmMin),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
segmRight.y++;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (dSegmLeft < 0) // segmLeft a Est
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// segmLeft a NordEst
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.y++;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else // m>1
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
// midpoint algorithm; le scanline vengono disegnate sempre
|
|
Shinya Kitaoka |
120a6e |
TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x),
|
|
Shinya Kitaoka |
120a6e |
yMin);
|
|
Shinya Kitaoka |
120a6e |
TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin);
|
|
Shinya Kitaoka |
120a6e |
int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmRight.y + 1) + gammaRight);
|
|
Shinya Kitaoka |
120a6e |
int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) +
|
|
Shinya Kitaoka |
120a6e |
beta * (segmLeft.y + 1) + gammaLeft);
|
|
Shinya Kitaoka |
120a6e |
while (segmRight.y <= yMax) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x + segmLeft.x, 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - segmRight.x, 0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x - segmLeft.x, lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dSegmRight <= 0) // segmRight a NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmRight.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // segmRight a Nord
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmRight = dSegmRight + incN;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
segmRight.y++;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (dSegmLeft <= 0) // segmLeft a NordEst
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incNE;
|
|
Shinya Kitaoka |
120a6e |
segmLeft.x++;
|
|
Shinya Kitaoka |
120a6e |
} else // segmLeft a Nord
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
dSegmLeft = dSegmLeft + incN;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// ---- parallelogrammoide circolare (in alternativa a parallelogramma)
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// N.B. coordinate di schermo (riflessione per k<0 )
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
yMin = std::max(b.y - cutIn, 0);
|
|
Shinya Kitaoka |
120a6e |
yMax = std::min(a.y + cutIn, ly - 1);
|
|
Shinya Kitaoka |
120a6e |
for (y = yMin; y <= yMax; y++) {
|
|
Shinya Kitaoka |
120a6e |
int xMin, xMax;
|
|
Shinya Kitaoka |
120a6e |
if (k > 0) {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(a.x - halfCord.getCord(abs(y - a.y)), 0); // clipping x
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(b.x + halfCord.getCord(abs(b.y - y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // clipping x
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
xMin = std::max(b.x - halfCord.getCord(abs(b.y - y)),
|
|
Shinya Kitaoka |
120a6e |
0); // clipping x + ritorno alle
|
|
Shinya Kitaoka |
120a6e |
xMax = std::min(a.x + halfCord.getCord(abs(y - a.y)),
|
|
Shinya Kitaoka |
120a6e |
lx - 1); // coordinate "di schermo"
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *p = ras->pixels(y) + xMin;
|
|
Shinya Kitaoka |
120a6e |
TPixel32 *q = p + (xMax - xMin);
|
|
Shinya Kitaoka |
120a6e |
while (p <= q) *p++ = col;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|