private void VertexToEdge(ref List <AEL> Edges, List <Point> Vertex, out int ymin, out int ymax) { AEL temp; ymin = Vertex[0].Y; ymax = Vertex[0].Y; Vertex.Add(Vertex[0]); Vertex.Add(Vertex[1]); Vertex.Insert(0, Vertex[Vertex.Count - 3]); for (int i = 1; i <= Vertex.Count - 3; i++) { temp = new AEL(); temp.yUpper = Math.Max(Vertex[i].Y, Vertex[i + 1].Y); temp.yLower = Math.Min(Vertex[i].Y, Vertex[i + 1].Y); if (Vertex[i].Y > Vertex[i + 1].Y) { temp.xIntersect = Vertex[i + 1].X; } else { temp.xIntersect = Vertex[i].X; } if (temp.yLower == temp.yUpper) { temp.reciSlope = 0; } else { temp.reciSlope = (Vertex[i].X - Vertex[i + 1].X) * 1.0 / (Vertex[i].Y - Vertex[i + 1].Y) * 1.0; } //Trường hợp điểm giao nhau không phải là cực trị if (Vertex[i + 1].Y < Vertex[i].Y && Vertex[i].Y < Vertex[i - 1].Y) { temp.yUpper--; } else if (Vertex[i + 2].Y > Vertex[i + 1].Y && Vertex[i + 1].Y > Vertex[i].Y) { temp.yUpper--; } Edges.Add(temp); ymin = Math.Min(ymin, Vertex[i + 1].Y); ymax = Math.Max(ymax, Vertex[i + 1].Y); } Vertex.RemoveAt(0); Vertex.RemoveAt(Vertex.Count - 1); Vertex.RemoveAt(Vertex.Count - 1); }
public double ScanFill(Shape shape, Color fillColor) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); TimeSpan ts; shape.fillType = FillType.SCANLINE; int yMin, yMax; if (shape.type == ShapeType.CIRCLE || shape.type == ShapeType.ELLIPSE) { List <Point> fillVertex = new List <Point>(); fillVertex.AddRange(shape.vertexs); yMin = fillVertex[0].Y; yMax = yMin; foreach (var v in fillVertex) { if (v.Y > yMax) { yMax = v.Y; } if (v.Y < yMin) { yMin = v.Y; } } for (int y = yMin; y <= yMax; y++) { List <Point> line = new List <Point>(); line.AddRange(fillVertex.Where(v => v.Y == y)); line = line.OrderBy(v => v.X).ToList(); int xmin = -1, xmax = -1; for (int i = 0; i < line.Count - 1; i++) { if (Math.Abs(line[i].X - line[i + 1].X) > 1) { xmin = line[i].X; xmax = line[i + 1].X; break; } } if (xmax < 0) { continue; } gl.Color(fillColor.R / 255.0, fillColor.G / 255.0, fillColor.B / 255.0); gl.Begin(OpenGL.GL_LINES); gl.Vertex(xmin, y); gl.Vertex(xmax, y); gl.End(); } gl.Flush(); shape.Draw(gl); stopWatch.Stop(); ts = stopWatch.Elapsed; return(ts.TotalMilliseconds); } List <List <AEL> > edgeTable = new List <List <AEL> >(); List <AEL> begList = new List <AEL>(); List <AEL> edges = new List <AEL>(); VertexToEdge(ref edges, shape.vertexs, out yMin, out yMax); //Tạo Edge Table for (int y = yMin; y <= yMax; y++) { List <AEL> subList = new List <AEL>(); edgeTable.Add(subList); } for (int i = 0; i < edges.Count; i++) { if (edges[i].yLower != edges[i].yUpper) { int id = edges[i].yLower - yMin; edgeTable[id].Add(edges[i]); } } for (int y = yMin; y <= yMax; y++) { begList.AddRange(edgeTable[y - yMin]); //Sắp xếp các giao điểm theo x begList = begList.OrderBy(v => v.xIntersect).ToList(); //Tô màu cho dòng hiện tại if (y != yMin && y != yMax) { gl.Color(fillColor.R / 255.0, fillColor.G / 255.0, fillColor.B / 255.0); gl.Begin(OpenGL.GL_LINES); for (int i = 0; i < begList.Count; i += 2) { if (i + 1 < begList.Count) { gl.Vertex(begList[i].xIntersect, y); gl.Vertex(begList[i + 1].xIntersect, y); } } gl.End(); } gl.Flush(); //Xoá các cạnh đã ở dưới scan line int j = 0; while (j < begList.Count) { if (begList[j].yUpper == y) { begList.RemoveAt(j); } else { j++; } } for (int i = 0; i < begList.Count; i++) { AEL t = new AEL(); t.reciSlope = begList[i].reciSlope; t.yLower = begList[i].yLower; t.yUpper = begList[i].yUpper; t.xIntersect = begList[i].xIntersect + begList[i].reciSlope; begList[i] = t; } } shape.Draw(gl); stopWatch.Stop(); ts = stopWatch.Elapsed; return(ts.TotalMilliseconds); }