扫描线填充
Java
import javax.swing.*;import java.awt.*;import java.util.ArrayList;import java.util.Collections;public class FillTest extends JFrame { private ArrayList<Edge> edgeTable = new ArrayList<>(); private int getYmin() { int yMin = edgeTable.get(0).y1; for (Edge edge : edgeTable) { if (edge.y1 < yMin) yMin = edge.y1; } return yMin; } private int getYmax() { int yMax = edgeTable.get(0).y1; for (Edge edge : edgeTable) { if (edge.y1 > yMax) yMax = edge.y1; } return yMax; } private boolean isActive(Edge edge, int currentY) { return edge.y1 < currentY && currentY <= edge.y2 || edge.y1 >= currentY && currentY > edge.y2; } private void updateActiveEdges(ArrayList<Edge> activeEdges, int y) { for (Edge edge : edgeTable) { if (isActive(edge, y)) { if (!activeEdges.contains(edge)) { activeEdges.add(edge); } } else { activeEdges.remove(edge); } } } private void findIntersections(ArrayList<Integer> intersections, ArrayList<Edge> activeEdges, int currentY) { intersections.clear(); for (Edge edge : activeEdges) { int x = edge.x1 + ((currentY - edge.y1) * (edge.dx)) / (edge.dy); intersections.add(x); } } public void fill() { ArrayList<Edge> activeEdges = new ArrayList(10); ArrayList<Integer> intersections = new ArrayList(20); Graphics g = getGraphics(); g.setColor(Color.red); // x1,y1,x2,y2 edgeTable.add(new Edge(100, 100, 100, 600)); edgeTable.add(new Edge(100, 600,500,400)); edgeTable.add(new Edge(500,400, 100, 100)); int yMin = getYmin(); int yMax = getYmax(); for (int y = yMin; y < yMax; y++) { updateActiveEdges(activeEdges, y); findIntersections(intersections, activeEdges, y); Collections.sort(intersections); for (int i = 0; i < intersections.size(); i += 2) { int x1 = intersections.get(i); if (i + 1 >= intersections.size()){ break; } int x2 = intersections.get(i + 1); g.drawLine(x1, y, x2, y); } } } public static void main(String[] args) { FillTest s = new FillTest(); s.setSize(800, 800); s.setVisible(true); s.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); s.fill(); }}class Edge { int x1, y1, x2, y2, dx, dy; Edge(int x1, int y1, int x2, int y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.dx = x2 - x1; this.dy = y2 - y1; }}
C++
ScanlineFilling.h
#include <iostream>#include <vector>class ScanlineFilling{ public: class Edge { public: int x1, y1, x2, y2, dx, dy; Edge(int x1, int y1, int x2, int y2); }; private: std::vector<Edge> edgeTable; int getYmin(); int getYmax(); bool isActive(Edge edge, int currentY); void updateActiveEdges(std::vector<Edge>& activeEdges, int y); void findIntersections(std::vector<int>& intersections, std::vector <Edge> activeEdges, int currentY); public: // 多边形填充 void fill(int** matrix, int x, int y, int** position, int len, int fillValue);};
ScanlineFilling.cpp
#include "ScanlineFilling.h"#include <iostream>#include <vector>#include <algorithm>using namespace std;ScanlineFilling::Edge::Edge(int x1, int y1, int x2, int y2) { this->x1 = x1; this->y1 = y1; this->x2 = x2; this->y2 = y2; this->dx = x2 - x1; this->dy = y2 - y1;}int ScanlineFilling::getYmin() { int yMin = edgeTable.front().y1; for (Edge edge : edgeTable) { if (edge.y1 < yMin) yMin = edge.y1; } return yMin;}int ScanlineFilling::getYmax() { int yMax = edgeTable.front().y1; for (Edge edge : edgeTable) { if (edge.y1 > yMax) yMax = edge.y1; } return yMax;}bool ScanlineFilling::isActive(Edge edge, int currentY) { return edge.y1 < currentY && currentY <= edge.y2 || edge.y1 >= currentY && currentY > edge.y2;}void ScanlineFilling::updateActiveEdges(std::vector<Edge>& activeEdges, int y) { for (Edge edge : edgeTable) { if (isActive(edge, y)) { activeEdges.push_back(edge); } }}void ScanlineFilling::findIntersections(std::vector<int>& intersections, std::vector<Edge> activeEdges, int currentY) { for (Edge edge : activeEdges) { int x = edge.x1 + ((currentY - edge.y1) * (edge.dx)) / (edge.dy); intersections.push_back(x); }}//参数:要填充的二维数组,数组的行列,多边形的坐标[x,y],多边形坐标的个数(从起点到终点的个数,其中起点==终点),填充的值void ScanlineFilling::fill(int** matrix, int x, int y, int** position, int len,int fillValue) { vector<Edge> activeEdges; vector<int> intersections; int firstX, firstY; edgeTable.clear(); // 获取面的点 for (int i = 0; i < len; i++) { if (i == 0) { firstX = position[i][0]; firstY = position[i][1]; continue; } edgeTable.push_back(*(new Edge(firstX, firstY, position[i][0], position[i][1]))); firstX = position[i][0]; firstY = position[i][1]; } int yMin = getYmin(); int yMax = getYmax(); for (int y = yMin; y < yMax; y++) { activeEdges.clear(); intersections.clear(); updateActiveEdges(activeEdges, y); findIntersections(intersections, activeEdges, y); // 升序 sort(intersections.begin(),intersections.end()); for (int i = 0; i < intersections.size(); i += 2) { int x1 = intersections[i]; if ((i + 1) >= intersections.size()) { break; } int x2 = intersections[i + 1]; for (int k = x1; k < x2; k++) { matrix[k][y] = fillValue; } } }}