public void classifySelf() { // we do need to compute the interior angle double pX, pY, qX, qY; pX = neighboor1.X - this.X; pY = neighboor1.Y - this.Y; qX = neighboor2.X - this.X; qY = neighboor2.Y - this.Y; double angle = PolygonVertex.Angle(pX, pY, qX, qY); if (PolygonVertex.CrossProductSign(pX, pY, qX, qY)) { // it is exterior angle angle = 2 * Math.PI - angle; } if (neighboor1 < this && neighboor2 < this) { // start or split? type = (angle < Math.PI) ? PolygonVertexType.start : PolygonVertexType.split; } else if (neighboor1 > this && neighboor2 > this) { // end or merge? type = (angle < Math.PI) ? PolygonVertexType.end : PolygonVertexType.merge; } else { type = PolygonVertexType.regular; } }
private static bool intersect(PolygonVertex a, PolygonVertex b, PolygonVertex c, PolygonVertex d) { return(intersect_1(a.X, b.X, c.X, d.X) && intersect_1(a.Y, b.Y, c.Y, d.Y) && area(a, b, c) * area(a, b, d) <= 0 && area(c, d, a) * area(c, d, b) <= 0); }
private void HandleRegularVertex(PolygonVertex v) { if (v.neighboor2.Y < v.Y) { // interior of P lies to the right of v (counterclockwise ordering) PolygonEdge d = edges.findEdgeEndingIn(v); PolygonEdge e = edges.findEdgeStartingIn(v); PolygonVertex dh = helpers[d]; if (dh.type == PolygonVertexType.merge) { insertDiagonal(dh, v); } T.Remove(d); T.Add(e); helpers[e] = v; } else { // interior of P lies to the left of v // search in T to find the edge ej directly left of v Dictionary <PolygonEdge, PointF> interSections = getIntersections(T, v); // take intersections to the left of vertex & select the leftmost _edge_ from them PolygonEdge ej = interSections.Where(kvp => kvp.Value.X < v.X).OrderBy(kvp => kvp.Value.X).Last().Key; if (helpers[ej].type == PolygonVertexType.merge) { insertDiagonal(helpers[ej], v); } helpers[ej] = v; } }
private void HandleStartVertex(PolygonVertex v) { PolygonEdge e = edges.findEdgeStartingIn(v); T.Add(e); helpers[e] = v; }
private List <PolygonVertex> findMonotones(PolygonEdge diagonal) { PolygonVertex start, end; List <PolygonVertex> vert = new List <PolygonVertex>(); if (diagonal.edge1.index < diagonal.edge2.index) { start = diagonal.edge1; end = diagonal.edge2; } else { start = diagonal.edge2; end = diagonal.edge1; } PolygonVertex fixedStart = vertices.Find(v => v == start); PolygonVertex fixedEnd = vertices.Find(v => v == end); while (start != end) { vert.Add(start); start = start.neighboor2; } vert.Add(end); fixedStart.neighboor2 = fixedEnd; fixedEnd.neighboor1 = fixedStart; vertices = vertices.Except(vert.Except(new[] { diagonal.edge1, diagonal.edge2 })).ToList(); return(vert); }
private bool sameChain(Dictionary <PolygonVertex, int> chains, PolygonVertex a, PolygonVertex b) { if (a.neighboor1 == b || a.neighboor2 == b) { return(true); } return(chains[a] == chains[b]); }
public void insertDiagonal(PolygonVertex a, PolygonVertex b, Pen pen = null) { if (pen == null) { pen = Pens.Red; } graphics.DrawLine(pen, a.X, polygonBox.Height - a.Y, b.X, polygonBox.Height - b.Y); addedDiagonals.Add(new PolygonEdge(a, b)); }
private void HandleEndVertex(PolygonVertex v) { PolygonEdge d = edges.findEdgeEndingIn(v); PolygonVertex dh = helpers[d]; if (dh.type == PolygonVertexType.merge) { insertDiagonal(v, dh); } T.Remove(d); }
private void HandleSplitVertex(PolygonVertex v) { // search in T to find the edge ej directly left of v Dictionary <PolygonEdge, PointF> interSections = getIntersections(T, v); // take intersections to the left of vertex & select the leftmost _edge_ from them PolygonEdge ej = interSections.Where(kvp => kvp.Value.X < v.X).OrderBy(kvp => kvp.Value.X).Last().Key; PolygonEdge e = edges.findEdgeStartingIn(v); insertDiagonal(v, helpers[ej]); helpers[ej] = v; T.Add(e); helpers[e] = v; }
public bool checkCrossing(PolygonVertex newVertex) { PolygonVertex lastPoint = vertices[vertices.Count - 1]; for (int i = 0; i < vertices.Count - 2; i++) { if (intersect(vertices[i], vertices[i + 1], newVertex, lastPoint)) { return(true); } } return(false); }
public void addVertex(PolygonVertex pv) { if (vertices.Count > 2 && checkCrossing(pv)) { MessageBox.Show("Добавленная вершина создаст в прямоугольнике самопересечение!", "Ошибка"); return; } ; pv.index = vertices.Count; vertices.Add(pv); graphics.FillEllipse(Brushes.Black, pv.X - 5, (polygonBox.Height - pv.Y - 5), 10, 10); if (vertices.Count > 1) { PolygonVertex prevVertex = vertices[vertices.Count - 2]; pv.neighboor1 = prevVertex; prevVertex.neighboor2 = pv; edges.Add(new PolygonEdge(prevVertex, pv)); graphics.DrawLine(Pens.Black, pv.X, polygonBox.Height - pv.Y, prevVertex.X, polygonBox.Height - prevVertex.Y); } }
private void HandleMergeVertex(PolygonVertex v) { PolygonEdge d = edges.findEdgeEndingIn(v); PolygonVertex dh = helpers[d]; if (dh.type == PolygonVertexType.merge) { insertDiagonal(v, dh); } T.Remove(d); // search in T to find the edge ej directly left of v Dictionary <PolygonEdge, PointF> interSections = getIntersections(T, v); // take intersections to the left of vertex & select the leftmost _edge_ from them PolygonEdge ej = interSections.Where(kvp => kvp.Value.X < v.X).OrderBy(kvp => kvp.Value.X).Last().Key; if (helpers[ej].type == PolygonVertexType.merge) { insertDiagonal(v, helpers[ej]); } helpers[ej] = v; }
public static PolygonEdge findEdgeStartingIn(this List <PolygonEdge> edges, PolygonVertex v) { return(edges.Find(e => e.edge1 == v)); }
public PolygonEdge(PolygonVertex e1, PolygonVertex e2) { edge1 = e1; edge2 = e2; }
private bool orientation(PolygonVertex a, PolygonVertex b, PolygonVertex c) { int v = (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X); return(v > 0); }
private static float area(PolygonVertex a, PolygonVertex b, PolygonVertex c) { return((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)); }
private Dictionary <PolygonEdge, PointF> getIntersections(HashSet <PolygonEdge> where, PolygonVertex v) { var ints = new Dictionary <PolygonEdge, PointF>(); foreach (PolygonEdge e in where) { var line = e.toLine(); ints[e] = intersectionPoint(line, v.Y); } return(ints); }
private void triangulateMonotonePolygon(List <PolygonVertex> polygon) { List <PolygonVertex> V = polygon.OrderByDescending(v => v.Y).ToList(); Dictionary <PolygonVertex, int> chains = new Dictionary <PolygonVertex, int>(); PolygonVertex chainStart = V[0], chainEnd = V.Last(), lc = chainStart.neighboor2, rc = chainStart.neighboor1; while (lc != chainEnd) { chains[lc] = -1; // left chain lc = lc.neighboor2; } while (rc != chainEnd) { chains[rc] = 1; // right chain rc = rc.neighboor1; } Stack <PolygonVertex> S = new Stack <PolygonVertex>(); S.Push(V[0]); S.Push(V[1]); for (int j = 2; j < V.Count - 1; j++) { if (!sameChain(chains, V[j], S.Peek())) { while (S.Count > 0) { if (S.Count != 1) { insertDiagonal(V[j], S.Peek(), new Pen(Color.SeaGreen, 1f)); } S.Pop(); } S.Push(V[j - 1]); S.Push(V[j]); } else { PolygonVertex last = S.Pop(); while (S.Count > 0 && ( (orientation(S.Peek(), last, V[j]) && chains[last] == -1) || (!orientation(S.Peek(), last, V[j]) && chains[last] == 1))) { last = S.Pop(); insertDiagonal(V[j], last, new Pen(Color.Yellow, 1f)); } S.Push(last); S.Push(V[j]); } } S.Pop(); // except the first while (S.Count > 0) { if (S.Count != 1) { insertDiagonal(V[V.Count - 1], S.Peek(), Pens.Violet); // diag from u_j to all vert on the stack } S.Pop(); // and the last one } }