69 return fValue != fValue;
74 return fabsf(fValue) == std::numeric_limits<float>::infinity();
84 DrawPoint(pImage,
int(point.
x + 0.5f),
int(point.
y + 0.5f), r, g, b);
89 const int width = pImage->
width;
90 const int height = pImage->
height;
91 const int nPixels = width * height;
93 if (x < 0 || x >= width || y < 0 || y >= height)
98 pImage->
pixels[y * width + x] = (r + (g << 1) + b) >> 2;
102 const int offset = 3 * (y * width + x);
103 pImage->
pixels[offset] = r;
104 pImage->
pixels[offset + 1] = g;
105 pImage->
pixels[offset + 2] = b;
109 const int offset = y * width + x;
110 pImage->
pixels[offset] = r;
111 pImage->
pixels[offset + nPixels] = g;
112 pImage->
pixels[offset + (nPixels << 1)] = b;
123 const int width = pImage->
width;
124 const int height = pImage->
height;
125 const int nPixels = width * height;
127 if (x < 0 || x >= width || y < 0 || y >= height)
132 const float o = (float) pImage->
pixels[y * width + x];
133 const float n = (
float) ((r + (g << 1) + b + 1) >> 2);
135 pImage->
pixels[y * width + x] = (int) ((1.0f - blend) * o + blend * n);
139 const int offset = 3 * (y * width + x);
140 int ro = pImage->
pixels[offset];
141 int go = pImage->
pixels[offset + 1];
142 int bo = pImage->
pixels[offset + 2];
144 r = (int) ((1.0f - blend) * (float) ro + blend * (
float) r);
145 g = (int) ((1.0f - blend) * (float) go + blend * (
float) g);
146 b = (int) ((1.0f - blend) * (float) bo + blend * (
float) b);
148 pImage->
pixels[offset] = r;
149 pImage->
pixels[offset + 1] = g;
150 pImage->
pixels[offset + 2] = b;
154 const int offset = y * width + x;
156 int ro = pImage->
pixels[offset];
157 int go = pImage->
pixels[offset + nPixels];
158 int bo = pImage->
pixels[offset + (nPixels << 1)];
160 r = (int) ((1.0f - blend) * (float) ro + blend * (
float) r);
161 g = (int) ((1.0f - blend) * (float) go + blend * (
float) g);
162 b = (int) ((1.0f - blend) * (float) bo + blend * (
float) b);
164 pImage->
pixels[offset] = r;
165 pImage->
pixels[offset + nPixels] = g;
166 pImage->
pixels[offset + (nPixels << 1)] = b;
172 const int nPoints = points.
GetSize();
174 for (
int i = 0; i < nPoints; i++)
183 for (
int y = region.
min_y; y <= region.
max_y; y++)
184 for (
int x = region.
min_x; x <= region.
max_x; x++)
194 DrawLine(pImage, p1, p2, r, g, b, thickness);
195 DrawLine(pImage, p2, p3, r, g, b, thickness);
196 DrawLine(pImage, p3, p4, r, g, b, thickness);
197 DrawLine(pImage, p4, p1, r, g, b, thickness);
209 const float dx = p1.
x - p2.
x;
210 const float dy = p1.
y - p2.
y;
214 if (fabsf(dx) < 0.01f && fabsf(dy) < 0.01f)
218 else if (fabsf(dy) < fabsf(dx))
220 const float slope = dy / dx;
221 const int max_x = int(p2.
x + 0.5f);
222 float y = p1.
y + 0.5f;
226 for (
int x =
int(p1.
x + 0.5f); x <= max_x; x++, y += slope)
231 for (
int x =
int(p1.
x + 0.5f); x >= max_x; x--, y -= slope)
237 const float slope = dx / dy;
238 const int max_y = int(p2.
y + 0.5f);
239 float x = p1.
x + 0.5f;
243 for (
int y =
int(p1.
y + 0.5f); y <= max_y; y++, x += slope)
248 for (
int y =
int(p1.
y + 0.5f); y >= max_y; y--, x -= slope)
255 const float radius = 0.5f * thickness;
257 if (fabsf(dx) < 0.01f && fabsf(dy) < 0.01f)
261 else if (fabsf(dy) < fabsf(dx))
263 const float slope = dy / dx;
264 const int max_x = int(p2.
x + 0.5f);
265 float y = p1.
y + 0.5f;
269 for (
int x =
int(p1.
x + 0.5f); x <= max_x; x++, y += slope)
274 for (
int x =
int(p1.
x + 0.5f); x >= max_x; x--, y -= slope)
280 const float slope = dx / dy;
281 const int max_y = int(p2.
y + 0.5f);
282 float x = p1.
x + 0.5f;
286 for (
int y =
int(p1.
y + 0.5f); y <= max_y; y++, x += slope)
291 for (
int y =
int(p1.
y + 0.5f); y >= max_y; y--, x -= slope)
305 const int min_x = int(mx - radius);
306 const int min_y = int(my - radius);
307 const int max_x = int(mx + radius);
308 const int max_y = int(my + radius);
311 const float r2 = radius * radius;
315 for (i = min_y; i <= max_y; i++)
317 const float d = r2 - (my - (float)i) * (my - (float)i);
321 const float x = sqrtf((
float)d);
323 int sx = (int)ceil(mx - x);
324 int ex = (int)floor(mx + x);
326 float sb = (float)sx - (mx - x);
327 float eb = (mx + x) - (
float)ex;
331 for (
int j = sx+1; j <= ex-1; j++)
342 for (i = min_y; i <= max_y; i++)
344 const float d = r2 - (my - (float)i) * (my - (float)i);
348 const float x = sqrtf(d);
350 int sx = (int)ceil(mx - x);
351 int ex = (int)floor(mx + x);
353 float sb = (float)sx - (mx - x);
354 float eb = (mx + x) - (
float)ex;
364 for (i = min_x; i <= max_x; i++)
366 const float d = r2 - (mx - (float)i) * (mx - (float)i);
370 const float y = sqrtf(d);
372 int sy = (int)ceil(my - y);
373 int ey = (int)floor(my + y);
375 float sb = (float)sy - (my - y);
376 float eb = (my + y) - (
float)ey;
388 const float radius = 0.5f * (float)thickness;
390 for (i = min_x; i <= max_x; i++)
392 const float d = r2 - (mx - i) * (mx - i);
396 const float y = sqrtf(d);
397 DrawCircleAA(pImage,
float(i), floor(my + y), radius, r, g, b, -1);
398 DrawCircleAA(pImage,
float(i), floor(my - y), radius, r, g, b, -1);
402 for (i = min_y; i <= max_y; i++)
404 const float d = r2 - (my - i) * (my - i);
408 const float x = sqrtf(d);
409 DrawCircleAA(pImage, floor(mx + x),
float(i), radius, r, g, b, -1);
410 DrawCircleAA(pImage, floor(mx - x),
float(i), radius, r, g, b, -1);
421 DrawCircleAA(pImage, mx, my, radius, r, g, b, thickness);
427 const int radius_int =
my_round(radius);
432 const int min_x = mx_int - radius_int;
433 const int min_y = my_int - radius_int;
434 const int max_x = mx_int + radius_int;
435 const int max_y = my_int + radius_int;
437 const int r2 = radius_int * radius_int;
443 for (i = min_y; i <= max_y; i++)
445 const int d = r2 - (my_int - i) * (my_int - i);
449 const int x = int(sqrtf(
float(d)) + 0.5f);
451 const int sx = mx_int - x;
452 const int ex = mx_int + x;
454 for (
int j = sx; j <= ex; j++)
459 for (i = min_x; i <= max_x; i++)
461 const int d = r2 - (mx_int - i) * (mx_int - i);
465 const int y = int(sqrtf(
float(d)) + 0.5f);
478 for (i = min_y; i <= max_y; i++)
480 const int d = r2 - (my_int - i) * (my_int - i);
484 const int x = int(sqrtf(
float(d)) + 0.5f);
491 for (i = min_x; i <= max_x; i++)
493 const int d = r2 - (mx_int - i) * (mx_int - i);
497 const int y = int(sqrtf(
float(d)) + 0.5f);
506 const float fThicknessRadius = 0.5f * thickness;
510 for (i = min_x; i <= max_x; i++)
512 const int d = r2 - (mx_int - i) * (mx_int - i);
516 const int y = int(sqrtf(
float(d)) + 0.5f);
523 for (i = min_y; i <= max_y; i++)
525 const int d = r2 - (my_int - i) * (my_int - i);
529 const int x = int(sqrtf(
float(d)) + 0.5f);
541 DrawCircle(pImage, center.
x, center.
y, radius, r, g, b, thickness, antiAlias);
553 if (fabsf(nx) > fabsf(ny))
555 const float m = -ny / nx;
556 const float cc = -c / nx;
558 for (
int y = 0; y < pImage->
height; y++)
560 Vec2d p = { floor(m * y + cc + 0.5f), float(y) };
566 const float m = -nx / ny;
567 const float cc = -c / ny;
569 for (
int x = 0; x < pImage->
width; x++)
571 Vec2d p = { float(x), floor(m * x + cc + 0.5f) };
578 const float radius = 0.5f * thickness;
580 if (fabsf(nx) > fabsf(ny))
582 const float m = -ny / nx;
583 const float cc = -c / nx;
585 for (
int y = 0; y < pImage->
height; y++)
587 Vec2d p = { floor(m * y + cc + 0.5f), float(y) };
593 const float m = -nx / ny;
594 const float cc = -c / ny;
596 for (
int x = 0; x < pImage->
width; x++)
598 Vec2d p = { float(x), floor(m * x + cc + 0.5f) };
607 DrawLineNormal(pImage, cosf(theta), sinf(theta), -r, color_r, color_g, color_b, thickness);
617 const int x = int(point.
x + 0.5f);
618 const int y = int(point.
y + 0.5f);
620 const int l = length / 2;
622 for (
int i = -l; i <= l; i++)
643 float x_intersection;
646 float inverse_gradient;
661 Edge *q = ppEdgeList;
666 if (pEdge->x_intersection < p->x_intersection)
673 pEdge->next = q->next;
682 static void MakeEdgeRecord(
const Vec2dInt &lower,
const Vec2dInt &upper,
int yComp, Edge *pEdge, Edge **ppEdgeList,
int height)
684 pEdge->inverse_gradient = float(upper.x - lower.x) / float(upper.y - lower.y);
685 pEdge->x_intersection = float(lower.x);
688 pEdge->max_y = upper.y - 1;
690 pEdge->max_y = upper.y;
692 if (lower.y >= 0 && lower.y < height)
705 static int NextY(
int nIndex,
const Vec2dInt *pPoints,
int nVertices)
708 int j = nIndex + 1 > nVertices - 1 ? 0 : nIndex + 1;
710 while (pPoints[nIndex].y == pPoints[j].y)
712 if (j + 1 > nVertices - 1)
729 static void BuildEdgeList(
const Vec2dInt *pPoints,
int nPoints, Edge **ppResultEdges,
int height)
731 int nPreviousY = pPoints[nPoints - 2].y;
732 Vec2dInt v1 = { pPoints[nPoints - 1].x, pPoints[nPoints - 1].y };
734 for (
int i = 0; i < nPoints; i++)
736 Vec2dInt v2 = pPoints[i];
740 Edge *pEdge =
new Edge();
769 Edge *p = ppEdges[y]->next;
786 const int width = pImage->
width;
787 const int height = pImage->
height;
788 const int nPixels = width * height;
790 if (y < 0 || y >= height)
795 Edge *p1 = pActiveEdge->next;
797 while (p1 && p1->next)
799 const Edge *p2 = p1->next;
801 const int x1 =
MY_MIN(
MY_MAX(
int(p1->x_intersection + 0.5f), 0), pImage->
width - 1);
802 const int x2 =
MY_MAX(
MY_MIN(
int(p2->x_intersection + 0.5f), pImage->
width - 1), 0);
806 for (
int x = x1, offset = 3 * x1; x <= x2; x++, offset += 3)
809 pixels[offset + 1] = g;
810 pixels[offset + 2] = b;
815 memset(pixels + x1, r, x2 - x1 + 1);
816 memset(pixels + x1 + nPixels, g, x2 - x1 + 1);
817 memset(pixels + x1 + (nPixels << 1), b, x2 - x1 + 1);
826 if (y < 0 || y >= pImage->
height)
829 unsigned char *pixels = pImage->
pixels + y * pImage->
width;
831 Edge *p1 = pActiveEdge->next;
833 while (p1 && p1->next)
835 const Edge *p2 = p1->next;
837 const int x1 =
MY_MIN(
MY_MAX(
int(p1->x_intersection + 0.5f), 0), pImage->
width - 1);
838 const int x2 =
MY_MAX(
MY_MIN(
int(p2->x_intersection + 0.5f), pImage->
width - 1), 0);
840 memset(pixels + x1, g, x2 - x1 + 1);
849 Edge *p = pEdge->next;
850 pEdge->next = p->next;
858 Edge *q = pActiveEdge;
859 Edge *p = pActiveEdge->next;
870 p->x_intersection += p->inverse_gradient;
880 Edge *p = pActiveEdge->next;
881 pActiveEdge->next = 0;
902 const int height = pImage->
height;
907 Edge **ppEdges =
new Edge*[height];
908 for (i = 0; i < height; i++)
909 ppEdges[i] =
new Edge();
912 Vec2dInt *pPointsInt =
new Vec2dInt[nPoints];
913 for (i = 0; i < nPoints; i++)
915 pPointsInt[i].x = int(pPoints[i].x + 0.5f);
916 pPointsInt[i].y = int(pPoints[i].y + 0.5f);
919 if (pPoints[0].x == pPoints[nPoints - 1].x && pPoints[0].y == pPoints[nPoints - 1].y)
926 delete [] pPointsInt;
928 Edge *pActiveEdge =
new Edge();
931 for (i = 0; i < height; i++)
935 if (pActiveEdge->next)
938 FillScan(pImage, i, pActiveEdge, (r + (g << 1) + b + 2) >> 2);
940 FillScan(pImage, i, pActiveEdge, r, g, b);
948 for (i = 0; i < height; i++)
958 printf(
"error: at least three points must be provided for PrimitivesDrawer::DrawPolygon\n");
968 for (
int i = 0; i < nPoints - 1; i++)
969 DrawLine(pImage, pPoints[i], pPoints[i + 1], r, g, b, thickness);
971 if (pPoints[0].x != pPoints[nPoints - 1].x || pPoints[0].y != pPoints[nPoints - 1].y)
972 DrawLine(pImage, pPoints[nPoints - 1], pPoints[0], r, g, b, thickness);
978 const int nPoints = points.
GetSize();
982 for (
int i = 0; i < nPoints; i++)
985 DrawPolygon(pImage, pPoints, nPoints, r, g, b, thickness);
992 const float mx = ellipse.
center.
x;
993 const float my = ellipse.
center.
y;
995 const int min_x = int(mx - ellipse.
radius_x + 0.5f);
996 const int min_y = int(my - ellipse.
radius_y + 0.5f);
997 const int max_x = int(mx + ellipse.
radius_x + 0.5f);
998 const int max_y = int(my + ellipse.
radius_y + 0.5f);
1000 const int rx = int(ellipse.
radius_x + 0.5f);
1001 const int ry = int(ellipse.
radius_y + 0.5f);
1007 const float a2divb2 = a2 / b2;
1008 const float b2diva2 = b2 / a2;
1010 const float ca = cosf(ellipse.
angle);
1011 const float sa = sinf(ellipse.
angle);
1013 if (thickness == -1)
1015 printf(
"error: filling of ellipses has not been implemented yet in PrimitivesDrawer::DrawEllipse\n");
1021 for (i = -ry; i <= ry; i++)
1023 const float y = float(i);
1024 const float d = a2 - a2divb2 * y * y;
1028 const float x = sqrtf(d);
1030 const float xr = ca * x - sa * y;
1031 const float yr = sa * x + ca * y;
1038 for (i = -rx; i <= rx; i++)
1040 const float x = float(i);
1041 const float d = b2 - b2diva2 * x * x;
1045 const float y = sqrtf(d);
1047 const float xr = ca * x - sa * y;
1048 const float yr = sa * x + ca * y;
1057 const float thickness_radius = 0.5f * thickness;
1059 for (i = -ry; i <= ry; i++)
1061 const float y = float(i);
1062 const float d = a2 - a2divb2 * y * y;
1066 const float x = sqrtf(d);
1068 const float xr = ca * x - sa * y;
1069 const float yr = sa * x + ca * y;
1076 for (i = -rx; i <= rx; i++)
1078 const float x = float(i);
1079 const float d = b2 - b2diva2 * x * x;
1083 const float y = sqrtf(d);
1085 const float xr = ca * x - sa * y;
1086 const float yr = sa * x + ca * y;
1098 Vec2d cornerPoints[4];
1101 DrawPolygon(pImage, cornerPoints, 4, r, g, b, thickness);
static void BuildActiveList(int y, Edge *pActiveEdge, Edge **ppEdges)
void DrawPolygon(CByteImage *pImage, const Vec2d *pPoints, int nPoints, int r, int g, int b, int thickness=1)
Draws a polygon into a CByteImage.
Data structure for the representation of a 2D vector.
void DrawPoints(CByteImage *pImage, const CVec2dArray &points, int r=255, int g=255, int b=255)
Draws a list of points of type CVec2dArray into a CByteImage.
Data structure for the representation of a 2D straight line.
Vec2d normalVector
The normalized normal vector of the straight line.
void DrawRegion(CByteImage *pImage, const MyRegion ®ion, int r=255, int g=255, int b=255, int thickness=1)
Draws a rectangle into a CByteImage.
void DrawCross(CByteImage *pImage, const Vec2d &point, int length, int r, int g, int b)
Draws a small cross into a CByteImage.
void DrawLineNormal(CByteImage *pImage, float nx, float ny, float c, int r, int g, int b, int thickness=1)
Draws a line into a CByteImage, given its parameters in normal form.
float radius_x
The radius in horizontal direction of the ellipse (horizontal refers to when angle = 0)...
void DrawPoint(CByteImage *pImage, const Vec2d &point, int r=255, int g=255, int b=255)
Draws a point into a CByteImage.
float radius
The radius of the circle.
static int NextY(int nIndex, const Vec2dInt *pPoints, int nVertices)
float radius_y
The radius in vertical direction of the ellipse (vertical refers to when angle = 0).
void DrawCircleAA(CByteImage *pImage, float mx, float my, float radius, int r, int g, int b, int thickness)
void DrawLinePolar(CByteImage *pImage, float theta, float r, int color_r, int color_g, int color_b, int thickness=1)
Draws a straight line into a CByteImage, given its parameters in polar form.
void DrawEllipse(CByteImage *pImage, const Ellipse2d &ellipse, int r=255, int g=255, int b=255, int thickness=1)
Draws an ellipse into a CByteImage.
static void DeleteAfter(Edge *pEdge)
static void FillScan(CByteImage *pImage, int y, Edge *pActiveEdge, int r, int g, int b)
static void BuildEdgeList(const Vec2dInt *pPoints, int nPoints, Edge **ppResultEdges, int height)
ImageType type
The type of the image.
int width
The width of the image in pixels.
static bool is_infinite(const float fValue)
int height
The height of the image in pixels.
void DrawPointBlended(CByteImage *pImage, const Vec2d &point, int r=255, int g=255, int b=255, float blend=1.0f)
Draws a point into a CByteImage, with blending.
Data structure for the representation of a 2D rectangle.
static void ResortActiveList(Edge *pActiveEdge)
void DrawRectangle(CByteImage *pImage, const Rectangle2d &rectangle, int r, int g, int b, int thickness=1)
Draws a rectangle into a CByteImage.
Vec2d center
The center of the circle.
Vec2d center
The center of the ellipse.
static void UpdateActiveList(int y, Edge *pActiveEdge)
static void InsertEdge(Edge *ppEdgeList, Edge *pEdge)
float c
The negative scalar product of normalVector and point.
unsigned char * pixels
The pointer to the the pixels.
Data structure for the representation of a 2D ellipse.
void DrawLine(CByteImage *pImage, const PointPair2d &line, int r=255, int g=255, int b=255, int thickness=1)
Draws a line segment into a CByteImage, given its two end points.
static void FillPolygon(CByteImage *pImage, const Vec2d *pPoints, int nPoints, int r, int g, int b)
Data structure for the representation of a 2D circle.
float angle
The rotiation angle of the ellipse, given in radians.
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
static void MakeEdgeRecord(const Vec2dInt &lower, const Vec2dInt &upper, int yComp, Edge *pEdge, Edge **ppEdgeList, int height)
static bool is_indeterminate(const float fValue)
void SetVec(Vec2d &vec, float x, float y)
void ComputeRectangleCornerPoints(const Rectangle2d &rectangle, Vec2d resultCornerPoints[4])
void DrawCircle(CByteImage *pImage, float mx, float my, float radius, int r=255, int g=255, int b=255, int thickness=1, bool bAntiAlias=false)
Draws a circle into a CByteImage.