[python] merge '6fcab395' and fix a bug in fill_polygon()

This commit is contained in:
Laury
2021-08-30 19:38:40 +02:00
18 changed files with 236 additions and 3 deletions

View File

@@ -3,8 +3,10 @@ SFLAGS += -Ikandinsky/include
kandinsky_src += $(addprefix kandinsky/src/,\
color.cpp \
context.cpp \
context_circle.cpp \
context_line.cpp \
context_pixel.cpp \
context_polygon.cpp \
context_rect.cpp \
context_text.cpp \
font.cpp \

View File

@@ -28,6 +28,10 @@ public:
// Line. Not anti-aliased.
void drawLine(KDPoint p1, KDPoint p2, KDColor c);
// Circle
void drawCircle(KDPoint c, KDCoordinate r, KDColor color);
void fillCircle(KDPoint c, KDCoordinate r, KDColor color);
// Rect
void fillRect(KDRect rect, KDColor color);
void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer);
@@ -36,6 +40,10 @@ public:
virtual void pushRect(KDRect, const KDColor * pixels) = 0;
virtual void pushRectUniform(KDRect rect, KDColor color) = 0;
virtual void pullRect(KDRect rect, KDColor * pixels) = 0;
//Polygon
static const int k_polygonMaxNumberOfPoints = 32;
void fillPolygon(KDCoordinate pointsX[], KDCoordinate pointsY[], int numberOfPoints, KDColor color);
protected:
KDContext(KDPoint origin, KDRect clippingRect);
private:

View File

@@ -0,0 +1,49 @@
#include <kandinsky/context.h>
#include <assert.h>
#include <math.h>
void KDContext::drawCircle(KDPoint c, KDCoordinate r, KDColor color) {
//The used algorithm is the Bresenham's arc tracing algorithm
KDCoordinate x, y, m;
x = 0;
y = r;
m = 5 - 4*r;
while(x <= y) {
setPixel(c.translatedBy(KDPoint(x,y)), color);
setPixel(c.translatedBy(KDPoint(y,x)), color);
setPixel(c.translatedBy(KDPoint(-x,y)), color);
setPixel(c.translatedBy(KDPoint(-y,x)), color);
setPixel(c.translatedBy(KDPoint(x,-y)), color);
setPixel(c.translatedBy(KDPoint(y,-x)), color);
setPixel(c.translatedBy(KDPoint(-x,-y)), color);
setPixel(c.translatedBy(KDPoint(-y,-x)), color);
if(m > 0) {
y = y - 1;
m = m - 8*y;
}
x = x + 1;
m = m + 8*x + 4;
}
}
void KDContext::fillCircle(KDPoint c, KDCoordinate r, KDColor color) {
KDCoordinate left = c.x()-r;
KDCoordinate right = c.x()+r;
if(left < 0) {
left = 0;
}
if(right > m_clippingRect.width()) {
right = m_clippingRect.width();
}
for(KDCoordinate x=left; x<=right; x++) {
KDCoordinate semiHeight = sqrt((r*r)-((c.x()-x)*(c.x()-x)));
fillRect(KDRect(x, c.y()-semiHeight, 1, semiHeight * 2 ), color);
}
}

View File

@@ -0,0 +1,67 @@
#include <kandinsky/context.h>
#include <assert.h>
#include <math.h>
void KDContext::fillPolygon(KDCoordinate pointsX[], KDCoordinate pointsY[], int numberOfPoints, KDColor color)
{
//The used algorithm is the scan-line algorithm
KDCoordinate top = KDCOORDINATE_MAX;
KDCoordinate bottom = KDCOORDINATE_MIN;
KDCoordinate right = m_clippingRect.width();
KDCoordinate left = 0;
for (int i = 0; i < numberOfPoints; i++) {
if (pointsY[i] < top) {
top = pointsY[i];
}
if (pointsY[i] > bottom) {
bottom = pointsY[i];
}
}
if (top < 0) {
top = 0;
}
if (bottom > m_clippingRect.height()) {
bottom = m_clippingRect.height();
}
for (int y=top; y<=bottom; y++) {
int switches=0;
KDCoordinate switchesX[KDContext::k_polygonMaxNumberOfPoints];
int lastPointIndex = numberOfPoints-1;
for (int i=0; i<numberOfPoints; i++) {
if (((pointsY[i]<=y && pointsY[lastPointIndex]>=y) || (pointsY[lastPointIndex]<= y && pointsY[i]>=y)) && pointsY[i] != pointsY[lastPointIndex]) {
switchesX[switches++] = (int) round(pointsX[i]+1.0*(y-pointsY[i])/(pointsY[lastPointIndex]-pointsY[i])*(pointsX[lastPointIndex]-pointsX[i]));
}
lastPointIndex=i;
}
//Sorting switches by a bubble sort
int i=0;
while (i<switches-1) {
if (switchesX[i]>switchesX[i+1]) {
KDCoordinate temp = switchesX[i];
switchesX[i]=switchesX[i+1];
switchesX[i+1]=temp;
if (i) i--;
}
else {
i++;
}
}
for (i=0; i<switches; i+=2) {
if (switchesX[i]>=right) {
break;
}
if (switchesX[i+1]>left) {
fillRect( KDRect( switchesX[ i ] , y, switchesX[ i+1 ] - switchesX[ i ], 1 ), color ) ;
}
}
}
}