测试
#include <glut.h>
#include <iostream>
#include <vector>
#include <algorithm>
struct Point {
int x, y;
Point(int _x, int _y) : x(_x), y(_y) {}
};
void midPointLine(int x1, int y1, int x2, int y2, std::vector<Point>& points) {
int dx = std::abs(x2 - x1);
int dy = std::abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
while (true) {
points.emplace_back(x1, y1);
if (x1 == x2 && y1 == y2) break;
int e2 = 2 * err;
if (e2 > -dy) { err -= dy; x1 += sx; }
if (e2 < dx) { err += dx; y1 += sy; }
}
}
void drawLine(int x1, int y1, int x2, int y2, std::vector<Point>& points) {
midPointLine(x1, y1, x2, y2, points);
}
void fillPolygon(const std::vector<Point>& polygon, std::vector<Point>& filledPoints) {
int minY = polygon[0].y, maxY = polygon[0].y;
for (const auto& p : polygon) {
minY = std::min(minY, p.y);
maxY = std::max(maxY, p.y);
}
for (int y = minY; y <= maxY; y++) {
std::vector<int> intersections;
for (size_t i = 0; i < polygon.size(); i++) {
const auto& p1 = polygon[i];
const auto& p2 = polygon[(i + 1) % polygon.size()];
if ((p1.y <= y && p2.y > y) || (p2.y <= y && p1.y > y)) {
int x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y);
intersections.push_back(x);
}
}
std::sort(intersections.begin(), intersections.end());
for (size_t i = 0; i < intersections.size(); i += 2) {
for (int x = intersections[i]; x < intersections[i + 1]; x++) {
filledPoints.emplace_back(x, y);
}
}
}
}
std::vector<Point> threeDotsVertices[] = {
{{60, 360}, {80, 390}, {100, 350}},
{{70, 290}, {95, 320}, {110, 280}},
{{85, 220}, {110, 250}, {125, 210}}
};
std::vector<Point> leftStrokeVertices = {
{180, 420}, {210, 430},
{185, 380}, {155, 370}
};
std::vector<Point> upperHorizontalVertices = {
{220, 420}, {360, 420},
{360, 400}, {220, 400}
};
std::vector<Point> lowerHorizontalVertices = {
{210, 330}, {370, 330},
{370, 310}, {210, 310}
};
std::vector<Point> verticalLineVertices = {
{290, 450}, {310, 450},
{310, 310}, {290, 310}
};
std::vector<Point> mouthOuterVertices = {
{220, 270}, {360, 270},
{340, 190}, {240, 190}
};
std::vector<Point> mouthInnerVertices = {
{250, 250}, {330, 250},
{315, 205}, {265, 205}
};
void drawOutlines(std::vector<Point>& outlinePoints) {
for (const auto& poly : threeDotsVertices) {
for (size_t i = 0; i < poly.size(); i++) {
drawLine(poly[i].x, poly[i].y, poly[(i + 1) % poly.size()].x, poly[(i + 1) % poly.size()].y, outlinePoints);
}
}
auto drawPolyOutline = [&](const std::vector<Point>& poly) {
for (size_t i = 0; i < poly.size(); i++) {
drawLine(poly[i].x, poly[i].y, poly[(i + 1) % poly.size()].x, poly[(i + 1) % poly.size()].y, outlinePoints);
}
};
drawPolyOutline(leftStrokeVertices);
drawPolyOutline(upperHorizontalVertices);
drawPolyOutline(lowerHorizontalVertices);
drawPolyOutline(verticalLineVertices);
drawPolyOutline(mouthOuterVertices);
drawPolyOutline(mouthInnerVertices);
}
void fillAllParts(std::vector<Point>& filledPoints) {
for (const auto& poly : threeDotsVertices) {
fillPolygon(poly, filledPoints);
}
auto fillPoly = [&](const std::vector<Point>& poly) {
fillPolygon(poly, filledPoints);
};
fillPoly(leftStrokeVertices);
fillPoly(upperHorizontalVertices);
fillPoly(lowerHorizontalVertices);
fillPoly(verticalLineVertices);
fillPoly(mouthOuterVertices);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
std::vector<Point> outlinePoints;
drawOutlines(outlinePoints);
glBegin(GL_POINTS);
for (const auto& p : outlinePoints) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(0.0, 0.0, 1.0);
std::vector<Point> filledPoints;
fillAllParts(filledPoints);
glBegin(GL_POINTS);
for (const auto& p : filledPoints) {
glVertex2i(p.x, p.y);
}
glEnd();
glColor3f(1.0, 0.0, 0.0);
std::vector<Point> innerMouthFill;
fillPolygon(mouthInnerVertices, innerMouthFill);
glBegin(GL_POINTS);
for (const auto& p : innerMouthFill) {
glVertex2i(p.x, p.y);
}
glEnd();
glFlush();
}
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
gluOrtho2D(0, 500, 0, 500);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("Hollow and Filled Hao");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}