public override List <Point> Points() { var len = vertices.Count; controlPolygonPoints = new List <Point>(); for (var i = 0; i < len - 1; i++) { var line = new BresenhamLine(vertices[i], vertices[i + 1], f); controlPolygonPoints.AddRange(line.Points()); } curvePoints = GetCurvePoints(); var result = new List <Point>(); // 手动将两个list合并成一个新的list foreach (var p in vertices) { result.Add(p); } foreach (var p in controlPolygonPoints) { result.Add(p); } foreach (var p in curvePoints) { result.Add(p); } return(result); }
// 多边形一条边的两个端点分别为a与b // 扫描线高度为y // 通过type参数,告诉调用者是以何种形式相交的 // type == 1,过上端点 // type == -1,过下端点 // type == 0,无交点 // type == 2,有交点,但不是端点 // 返回交点的横坐标 private int ScanLineIntersect(int y, Point a, Point b, ref int type) { // 因为我们的多边形在构造时,就把相同坐标的点给去除了 // 所以进来的这两个点坐标肯定不同 // 水平线不必处理,就当成无交点即可 if (a.Y == b.Y || y > Math.Max(a.Y, b.Y) || y < Math.Min(a.Y, b.Y)) { type = 0; return(0); } Point up = b, down = a; if (a.Y > b.Y) { up = a; down = b; } // 交于上端点 if (y == up.Y) { type = 1; return(up.X); } // 交于下端点 if (y == down.Y) { type = -1; return(down.X); } // 不交于端点,交于线段中间的某个点 type = 2; var dy = up.Y - down.Y; var dx = up.X - down.X; var x = 0; if (dx == 0) { x = up.X; } else { // 我们在绘多边形时,用的是Bresenham算法 // 而我们这里直接拿算术求交,求出的交点可能和Bresenham画出的线与扫描线的交点不同 // x = Convert.ToInt32((double)(y - down.Y) * dx / dy + down.X); // 这样会导致填充时,靠近直线有些像素就填充不起来,效果不好 // 因此我们不如直接把直线上的点给算出来,再直接找交点 var l = new BresenhamLine(a, b, f); x = EdgeIntersectWithY(l, y).X; } return(x); }
// 返回多边形的一条边与一条水平线的交点 private Point EdgeIntersectWithY(BresenhamLine l, int y) { foreach (var p in l.points) { if (p.Y == y) { return(p); } } return(new Point(-1, -1)); }
// 以p点为中心开始扩展,填充 public override List <Point> Points() { List <Point> l = new List <Point>(); var len = vertices.Count; for (var i = 0; i < len; i++) { var p = new BresenhamLine(vertices[i], vertices[(i + 1) % len], f); l.AddRange(p.Points()); } return(l); }