/// <summary> /// Divide the polygon by the line segment between two vertices. /// </summary> /// <param name="a">the index of first vertex.</param> /// <param name="b">the index of second vertex.</param> public void DividedBy(int a, int b) { if (a < 0 || b < 0 || a > Parent.VertexCount || b > Parent.VertexCount) { throw (new ArgumentException()); } LineSegment2D lineSegment = new LineSegment2D(Parent.GetPoint(a), Parent.GetPoint(b)); DividedBy(lineSegment); }
public LineSegment2DCollection(LineSegment2D[] lineSegments, int capacity) { Capacity = capacity; CurrentCount = lineSegments.Length; if (Capacity < CurrentCount) { throw (new CollectionCapacityException()); } LineSegments = lineSegments; }
/// <summary> /// Whether the line segment inflects the edges of the polygon. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <returns>true if inflects.</returns> public bool InflectsEdge(LineSegment2D lineSegment) { for (int i = 0; i < this.VertexCount; i++) { if (lineSegment.Inflects(this.GetEdge(i))) { return(true); } } return(false); }
public void Union(LineSegment2DCollection lineSegment2DCollection) { Capacity += lineSegment2DCollection.Capacity; LineSegment2D[] lineSegments = new LineSegment2D[Capacity]; this.LineSegments.CopyTo(lineSegments, 0); lineSegment2DCollection.LineSegments.CopyTo(lineSegments, this.Count); this.LineSegments = lineSegments; CurrentCount += lineSegment2DCollection.Count; }
/// <summary> /// Divide the polygon by a line segment. /// </summary> /// <param name="lineSegment">the line segment.</param> public void DividedBy(LineSegment2D lineSegment) { Divisers.Add(lineSegment); int Count = SubDivision.Count; for (int i = 0; i < Count; i++) { Polygon2D poly = SubDivision[i]; SubDivision[i] = DividedBy(lineSegment, poly); } }
/// <summary> /// Divide the polygon to triangles. /// </summary> public void Triangulation() { for (int i = 0; i < SubDivision.Count; i++) { Polygon2D poly = SubDivision[i]; if (poly.PointCount > 3) { LineSegment2D lineSegment = new LineSegment2D(poly.GetPoint(0), poly.GetPoint(2)); SubDivision[i] = DividedBy(lineSegment, poly); } } }
/// <summary> /// If the point is on one of the edges of this polygon, it returns the index, otherwise it returns NoSuchPoint. /// </summary> /// <param name="point">the point.</param> /// <returns>the index</returns> public int OnEdge(Point2D point) { for (int i = 0; i < this.VertexCount; i++) { LineSegment2D line = this.GetEdge(i); if (line.Contains(point)) { return(i); } } return(NoSuchPoint); }
private LineSegment2D ChooseDiviser(LineSegment2D lineSegment) { for (int i = 0; i < CurrentPolygon.VertexCount; i++) { LineSegment2D Edge = CurrentPolygon.GetEdge(i); if (Edge == lineSegment || Edge.Intersects(lineSegment) || !Edge.LineIntersects(lineSegment)) { continue; } Point2D divPoint = lineSegment.ToLine().Intersects(Edge.ToLine()); if (lineSegment.Contains(divPoint)) { continue; } LineSegment2D divLine = new LineSegment2D(lineSegment.LastPoint, divPoint); if (divLine.Contains(lineSegment.FirstPoint)) { //divLine = new LineSegment2D(lineSegment.FirstPoint, divPoint); continue; } /*if (CurrentPolygon.InflectsEdge(divLine)) * { * int ssi = 0; * }*/ if (!CurrentPolygon.Contains(divLine)) { continue; } if (divPoint == this.LastPoint) { ///need trace here return(divLine); } if (this.isApart(divLine, this.CurrentPointIndex, this.LastPointIndex)) { return(divLine); } } return(null); }
/// <summary> /// Whether the line segment is inside the polygon. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <returns>true if contains.</returns> public bool Contains(LineSegment2D lineSegment) { /*for (int i = 0; i < this.VertexCount; i++) * { * if (lineSegment.Contains(this.GetEdge(i))) * { * return false; * } * }*/ if (this.InflectsEdge(lineSegment)) { return(false); } return(!lineSegment.Intersects(this) && this.Contains(lineSegment.MidPoint) && !this.isOnEdge(lineSegment.MidPoint)); }
private bool isApart(LineSegment2D lineSegment, int c, int d) { double a = CurrentPolygon.OnEdge(lineSegment.FirstPoint) - 0.5; double b = CurrentPolygon.OnEdge(lineSegment.LastPoint) - 0.5; if (a < 0) { a += CurrentPolygon.VertexCount; } if (b < 0) { b += CurrentPolygon.VertexCount; } return(isApart(a, b, c, d)); }
/// <summary> /// Whether the two line segments inflect each other. /// </summary> /// <param name="lineSegment">the target linesegment</param> /// <returns>true if inflect</returns> public bool Inflects(LineSegment2D lineSegment) { if (this.TrulyContains(lineSegment.FirstPoint) || this.TrulyContains(lineSegment.LastPoint)) { if (this.ToVector() * lineSegment.ToVector() < ZeroTolerance) { return(true); } } if (this.Contains(lineSegment) || lineSegment.Contains(this)) { return(true); } return(false); }
/// <summary> /// Whether ths line segment intersects a polygon. /// </summary> /// <param name="polygon">the polygon.</param> /// <returns>true if intersects.</returns> public bool Intersects(Polygon2D polygon) { bool bResult = false; for (int i = 0; i < polygon.VertexCount; i++) { LineSegment2D lineSegment = polygon.GetEdge(i); //bResult |= this.TrulyIntersects(polygon.GetEdge(i)); bResult |= (this.TrulyLineIntersects(lineSegment) && lineSegment.Intersects(this)); if (bResult) { return(true); } } return(bResult); }
public void Add(LineSegment2D lineSegment) { try { base.Add(); } catch (CollectionCapacityException e) { string emsg = e.Message; this.Capacity *= 2; LineSegment2D[] lineSegments = new LineSegment2D[Capacity]; this.LineSegments.CopyTo(lineSegments, 0); this.LineSegments = lineSegments; base.Add(); } LineSegments[CurrentCount - 1] = lineSegment; }
/// <summary> /// Get the intersect point of the two line segment. /// </summary> /// <param name="lineSegment">the ohter line segment.</param> /// <returns>the intersect point.</returns> public Point2D GetIntersectPoint(LineSegment2D lineSegment) { if (this.Intersects(lineSegment)) { try { Point2D point = this.ToLine().Intersects(lineSegment.ToLine()); return(point); } catch (ArgumentException e) { string emsg = e.Message; return(new Point2D(double.NaN, double.NaN)); } } else { return(new Point2D(double.NaN, double.NaN)); } }
/// <summary> /// Determines whether the specified object is equal to this line segment. /// </summary> /// <param name="obj">The object to compare with this line segment.</param> /// <returns><c>true</c> if the specified object is equal to this linesegment; otherwise, <c>false</c>.</returns> public override bool Equals(object obj) { if (obj == null) { return(false); } LineSegment2D lineSegment = (LineSegment2D)obj; if (lineSegment.FirstPoint == this.FirstPoint && lineSegment.LastPoint == this.LastPoint) { return(true); } else if (lineSegment.FirstPoint == this.LastPoint && lineSegment.LastPoint == this.FirstPoint) { return(true); } else { return(false); } }
/// <summary> /// Whether the line segment is the diagonal of this polygon. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <returns>true if is diagonal.</returns> public bool isDiagonal(LineSegment2D lineSegment) { if (!lineSegment.isRegular) { return(false); } if (this.isEdge(lineSegment)) { return(false); } if (!this.Contains(lineSegment)) { return(false); } for (int i = 0; i < this.VertexCount; i++) { if (lineSegment.TrulyContains(this.Vertices[i])) { return(false); } } for (int i = 0; i < this.VertexCount; i++) { if (lineSegment.FirstPoint == this.Vertices[i]) { for (int j = 0; j < this.VertexCount; j++) { if (lineSegment.LastPoint == this.Vertices[j]) { return(true); } } return(false); } } return(false); }
/// <summary> /// Whether the two extents intersect each other. /// (x1,y1)----------------------------- /// - Extent - /// ------------------------------(x2,y2) /// </summary> /// <param name="line">the other line.</param> /// <returns>true if intersect.</returns> private bool ExtentIntersects(LineSegment2D line) { double x1, y1; double x2, y2; double x3, y3; double x4, y4; x1 = Math.Min(this.FirstPoint.X, this.LastPoint.X); x2 = Math.Max(this.FirstPoint.X, this.LastPoint.X); y1 = Math.Min(this.FirstPoint.Y, this.LastPoint.Y); y2 = Math.Max(this.FirstPoint.Y, this.LastPoint.Y); x3 = Math.Min(line.FirstPoint.X, line.LastPoint.X); x4 = Math.Max(line.FirstPoint.X, line.LastPoint.X); y3 = Math.Min(line.FirstPoint.Y, line.LastPoint.Y); y4 = Math.Max(line.FirstPoint.Y, line.LastPoint.Y); if (x1 <= x4 && x2 >= x3 && y1 <= y4 && y2 >= y3) { return(true); } else { return(false); } }
/// <summary> /// Divide the polygon to triangles. /// </summary> public void Triangulation() { for (int i = 0; i < SubDivision.Count; i++) { Polygon2D poly = SubDivision[i]; if (poly.PointCount > 3) { LineSegment2D lineSegment = new LineSegment2D(poly.GetPoint(0), poly.GetPoint(2)); SubDivision[i] = DividedBy(lineSegment, poly); } } }
/// <summary> /// Divide the polygon by a line segment. /// </summary> /// <param name="lineSegment">the line segment.</param> public void DividedBy(LineSegment2D lineSegment) { Divisers.Add(lineSegment); int Count = SubDivision.Count; for (int i = 0; i < Count; i++) { Polygon2D poly = SubDivision[i]; SubDivision[i] = DividedBy(lineSegment, poly); } }
public void Add(LineSegment2D lineSegment) { try { base.Add(); } catch (CollectionCapacityException e) { string emsg = e.Message; this.Capacity *= 2; LineSegment2D[] lineSegments = new LineSegment2D[Capacity]; this.LineSegments.CopyTo(lineSegments, 0); this.LineSegments = lineSegments; base.Add(); } LineSegments[CurrentCount - 1] = lineSegment; }
/// <summary> /// Construct a minimum link path of a polygon. /// </summary> public void BuildPath() { this.LinkDivisers.Clear(); Point2D CurrentPoint = this.LastPoint; Point2D IntersectPoint = null; LineSegment2D CurrentLine = null; LineSegment2D IntersectLine = null; for (int i = this.Divisers.Count - 1; i >= 0; i--) { double position = -1.0; Polygon2D currentPolygon = this.SubDivision[i + 1]; CurrentLine = this.Divisers[i]; if (CurrentLine.Contains(CurrentPoint)) { this.LinkDivisers.Add(CurrentPoint); Vector2D vector = CurrentLine.ToVector().Normal().Normalize(); IntersectPoint = CurrentLine.MidPoint + vector; if (!this.SubDivision[i].Contains(IntersectPoint)) { vector = -vector; } double length = CurrentLine.Length; LineSegment2D testLine = null; do { IntersectPoint = CurrentLine.MidPoint + vector * length; length /= 2; testLine = new LineSegment2D(CurrentPoint, IntersectPoint); } while (!this.SubDivision[i].Contains(testLine)); continue; } for (int j = 0; j < currentPolygon.VertexCount; j++) { Point2D point = currentPolygon.GetPoint(j); if (CurrentPoint == point) { continue; } LineSegment2D lineSegment = new LineSegment2D(CurrentPoint, point); if (currentPolygon.Contains(lineSegment) || currentPolygon.isEdge(lineSegment)) { if (CurrentLine.LineIntersects(lineSegment)) { IntersectPoint = CurrentLine.ToLine().Intersects(lineSegment.ToLine()); if (position < 0) { position = CurrentLine.GetPosition(IntersectPoint); } else { position += CurrentLine.GetPosition(IntersectPoint); position /= 2; } } } } if (position < -0.5) { CurrentPoint = IntersectPoint + IntersectLine.ToVector().Normalize(); i++; continue; } this.LinkDivisers.Add(CurrentPoint); IntersectPoint = CurrentLine.GetPoint(position); IntersectLine = new LineSegment2D(CurrentPoint, IntersectPoint); double extend = IntersectLine.Length; do { extend /= 2; CurrentPoint = IntersectLine.Extend(extend); } while (!this.SubDivision[i].Contains(CurrentPoint)); //CurrentPoint = CurrentLine.GetPoint(position); } CurrentLine = new LineSegment2D(CurrentPoint, this.FirstPoint); if (this.Parent.Contains(CurrentLine)) { this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } else if (IntersectLine != null) { CurrentPoint = IntersectPoint + IntersectLine.ToVector().Normalize(); this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } else { Vector2D vector = CurrentLine.ToVector().Normal().Normalize(); IntersectPoint = CurrentLine.MidPoint + vector; if (!this.Parent.Contains(IntersectPoint)) { vector = -vector; } IntersectPoint = CurrentLine.MidPoint; double length = CurrentLine.Length; do { length /= 2; CurrentPoint = IntersectPoint + vector * length; } while (!this.Parent.Contains(CurrentPoint)); this.LinkDivisers.Add(this.LastPoint); this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } }
/// <summary> /// Whether the three points is on a line. /// </summary> /// <param name="a">the first point.</param> /// <param name="b">the second point.</param> /// <param name="c">the third point.</param> /// <returns>true if is on a line.</returns> static public bool isOnLine(Point2D a, Point2D b, Point2D c) { LineSegment2D line = new LineSegment2D(a, b); return(line.isOnLine(c)); }
public void FastTriangluation() { int from = 0; int to = 2; Polygon2DEditor polygonEditor = new Polygon2DEditor(this.FirstPolygons.Parent); polygonEditor.Clear(); polygonEditor = new Polygon2DEditor(this.SecondPolygons.Parent); polygonEditor.Clear(); this.InitLinkDistance(); for (int i = 0; i < FirstPolygons.SubDivision.Count; i++) { int vertexCount = FirstPolygons.SubDivision[i].VertexCount; Polygon2D firstPolygon = FirstPolygons.SubDivision[i]; Polygon2D secondPolygon = SecondPolygons.SubDivision[i]; if (vertexCount <= 3) { continue; } int dist = MAX_DIST; for (int j = 0; j < vertexCount; j++) { for (int k = j + 2; k < vertexCount; k++) { if (j == k || Math.Abs(j - k) == 1 || Math.Abs(j - k) == vertexCount - 1) { continue; } LineSegment2D testLine = new LineSegment2D(firstPolygon.GetPoint(j), firstPolygon.GetPoint(k)); if (firstPolygon.InflectsEdge(testLine)) { continue; } testLine = new LineSegment2D(secondPolygon.GetPoint(j), secondPolygon.GetPoint(k)); if (secondPolygon.InflectsEdge(testLine)) { continue; } LinkDistance link = this.linkDistance.Contains(this.FirstPolygons.GetParentIndex(j, i), this.FirstPolygons.GetParentIndex(k, i), 0); int d; if (link != null) { d = link.linkDistance; } else { FirstTarget = new Polygon2DLinkMaker(firstPolygon, j, k); SecondTarget = new Polygon2DLinkMaker(secondPolygon, j, k); FirstTarget.Divide(); SecondTarget.Divide(); d = Math.Max(FirstTarget.LinkDistance, SecondTarget.LinkDistance); link = new LinkDistance(this.FirstPolygons.GetParentIndex(j, i), this.FirstPolygons.GetParentIndex(k, i), 0, d); } if (dist > d) { dist = d; from = j; to = k; } else if (dist == d) { if (Math.Abs(vertexCount / 2 - Math.Abs(j - k)) > Math.Abs(vertexCount / 2 - Math.Abs(from - to))) { from = j; to = k; } } } } FirstTarget = new Polygon2DLinkMaker(firstPolygon, from, to); SecondTarget = new Polygon2DLinkMaker(secondPolygon, from, to); FirstTarget.Divide(); FirstTarget.BuildPath(); SecondTarget.Divide(); SecondTarget.BuildPath(); if (dist != Math.Max(FirstTarget.LinkDistance, SecondTarget.LinkDistance)) { dist = Math.Max(FirstTarget.LinkDistance, SecondTarget.LinkDistance); this.linkDistance.Set(this.FirstPolygons.GetParentIndex(from, i), this.FirstPolygons.GetParentIndex(to, i), 0, dist); } int Extra = dist - FirstTarget.LinkDistance; if (Extra > 0) { FirstTarget.LinkDivisers.Extend(Extra); } Extra = dist - SecondTarget.LinkDistance; if (Extra > 0) { SecondTarget.LinkDivisers.Extend(Extra); } FirstPolygons.DividedBy(FirstTarget.LinkDivisers, firstPolygon); SecondPolygons.DividedBy(SecondTarget.LinkDivisers, secondPolygon); } GetResult(); BuildGhostTriangle(); }
/// <summary> /// Whether the two line segment share terminal point with each other. /// </summary> /// <param name="lineSegment"></param> /// <returns></returns> public bool SharePointWith(LineSegment2D lineSegment) { if (lineSegment == this) { return false; } return lineSegment.FirstPoint == this.FirstPoint || lineSegment.FirstPoint == this.LastPoint || lineSegment.LastPoint == this.FirstPoint || lineSegment.LastPoint == this.LastPoint; }
private LineSegment2D Max(LineSegment2D a, LineSegment2D b, LineSegment2D c) { LineSegment2D lineSegment = a; if (lineSegment.Length < b.Length) { lineSegment = b; } if (lineSegment.Length < c.Length) { lineSegment = c; } return lineSegment; }
private void AddInnerPoints(Polygon2DAdorner polygon) { for (int j = 0; j < this.ghostPoint.Count; j++) { for (int i = 0; i < polygon.internalSegments.Count; i++) { int a = (int)(polygon.internalSegments[i].X); int b = (int)(polygon.internalSegments[i].Y); if (a == this.ghostPoint[j].FirstIndex && b == this.ghostPoint[j].LastIndex || a == this.ghostPoint[j].LastIndex && b == this.ghostPoint[j].FirstIndex) { Point2D point = null; LineSegment2D lineSegment = null; lineSegment = new LineSegment2D(polygon.polygon.GetPoint(a), polygon.polygon.GetPoint(b)); point = lineSegment.GetPoint(this.ghostPoint[j].LocalPosition); Polygon2DEditor polygonEditor = new Polygon2DEditor(polygon.polygon); polygonEditor.AddInnerPoint(point); break; } } } }
private void InitLinkDistance() { int Count = this.FirstPolygons.Parent.VertexCount; Polygon2D firstPolygon = FirstPolygons.Parent; Polygon2D secondPolygon = SecondPolygons.Parent; for (int i = 0; i < Count; i++) { for (int j = i + 2; j < Count; j++) { if (i == j || Math.Abs(i - j) == 1 || Math.Abs(i - j) == Count - 1) { continue; } LineSegment2D testLine = new LineSegment2D(firstPolygon.GetPoint(i), firstPolygon.GetPoint(j)); if (firstPolygon.InflectsEdge(testLine)) { continue; } testLine = new LineSegment2D(secondPolygon.GetPoint(i), secondPolygon.GetPoint(j)); if (secondPolygon.InflectsEdge(testLine)) { continue; } FirstTarget = new Polygon2DLinkMaker(firstPolygon, i, j); SecondTarget = new Polygon2DLinkMaker(secondPolygon, i, j); FirstTarget.Divide(); SecondTarget.Divide(); int linkDistance = Math.Max(FirstTarget.LinkDistance, SecondTarget.LinkDistance); if (this.linkDistance == null) { this.linkDistance = new LinkDistance(i, j, 0, linkDistance); } else { this.linkDistance.Add(new LinkDistance(i, j, 0, linkDistance)); } } } }
private bool isApart(LineSegment2D lineSegment, int c, int d) { double a = CurrentPolygon.OnEdge(lineSegment.FirstPoint) - 0.5; double b = CurrentPolygon.OnEdge(lineSegment.LastPoint) - 0.5; if (a < 0) { a += CurrentPolygon.VertexCount; } if (b < 0) { b += CurrentPolygon.VertexCount; } return isApart(a, b, c, d); }
private LineSegment2D ChooseDiviser(LineSegment2D lineSegment) { for (int i = 0; i < CurrentPolygon.VertexCount; i++) { LineSegment2D Edge = CurrentPolygon.GetEdge(i); if (Edge == lineSegment || Edge.Intersects(lineSegment) || !Edge.LineIntersects(lineSegment)) { continue; } Point2D divPoint = lineSegment.ToLine().Intersects(Edge.ToLine()); if (lineSegment.Contains(divPoint)) { continue; } LineSegment2D divLine = new LineSegment2D(lineSegment.LastPoint, divPoint); if (divLine.Contains(lineSegment.FirstPoint)) { //divLine = new LineSegment2D(lineSegment.FirstPoint, divPoint); continue; } /*if (CurrentPolygon.InflectsEdge(divLine)) { int ssi = 0; }*/ if (!CurrentPolygon.Contains(divLine)) { continue; } if (divPoint == this.LastPoint) { ///need trace here return divLine; } if (this.isApart(divLine, this.CurrentPointIndex, this.LastPointIndex)) { return divLine; } } return null; }
/// <summary> /// Divide the source polygon to compute link distance. /// </summary> public void Divide() { LineSegment2D entrance = this.LastDiviser; LineSegment2D path = new LineSegment2D(entrance.FirstPoint, this.LastPoint); if (this.CurrentPolygon.Contains(path)) { return; } path = new LineSegment2D(entrance.LastPoint, this.LastPoint); if (this.CurrentPolygon.Contains(path)) { return; } for (int i = 0; i < this.CurrentPolygon.VertexCount; i++) { if (this.CurrentPolygon.GetPoint(i) == entrance.FirstPoint) { continue; } LineSegment2D lineSegment = new LineSegment2D(entrance.FirstPoint, this.CurrentPolygon.GetPoint(i)); if(!this.CurrentPolygon.Contains(lineSegment) && !this.CurrentPolygon.isEdge(lineSegment)) { continue; } LineSegment2D lineDiviser = this.ChooseDiviser(lineSegment); if (lineDiviser == null) { continue; } Polygon2D testPoly = new Polygon2D(this.CurrentPolygon); if (!testPoly.isVertex(lineDiviser.LastPoint)) { testPoly.Add(lineDiviser.LastPoint, testPoly.OnEdge(lineDiviser.LastPoint)); } Polygon2D polygon = this.DividedBy(lineDiviser, testPoly); if (polygon.isVertex(this.LastPoint)) { testPoly = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } else { testPoly = polygon; polygon = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } if (entrance.FirstPoint == entrance.LastPoint) { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(testPoly); this.SubDivision.Add(polygon); } else { LineSegment2D testLine = new LineSegment2D(entrance.LastPoint, lineDiviser.FirstPoint); if (!testLine.isRegular) { entrance = new LineSegment2D(entrance.LastPoint, entrance.LastPoint); continue; } if (this.CurrentPolygon.Contains(testLine)) { testLine = this.ChooseDiviser(testLine); if (testLine != null && !testPoly.Contains(testLine)) { lineDiviser = testLine; testPoly = new Polygon2D(this.CurrentPolygon); if (!testPoly.isVertex(lineDiviser.LastPoint)) { testPoly.Add(lineDiviser.LastPoint, testPoly.OnEdge(lineDiviser.LastPoint)); } polygon = this.DividedBy(lineDiviser, testPoly); testPoly = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } else if (testLine == null) { continue; } } if (!polygon.isVertex(this.LastPoint)) { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(polygon); this.SubDivision.Add(testPoly); } else { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(testPoly); this.SubDivision.Add(polygon); } } this.Divisers.Add(lineDiviser); this.Divide(); return; } }
/// <summary> /// Divide a sub polygon by a line segment. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <param name="poly">the polygon to divide.</param> /// <returns>one of the sub polygon divided from the polygon.</returns> internal Polygon2D DividedBy(LineSegment2D lineSegment, Polygon2D poly) { if (poly.isDiagonal(lineSegment)) { int a = poly.HasVertex(lineSegment.FirstPoint); int b = poly.HasVertex(lineSegment.LastPoint); if (a > b) { int tmp = a; a = b; b = tmp; } Point2DCollection p2 = new Point2DCollection(b - a + 1); Point2DCollection p1 = new Point2DCollection(poly.VertexCount - p2.Size + 2); for (int i = 0; i < poly.VertexCount; i++) { if (i <= a || i >= b) { p1.Add(poly.GetPoint(i)); } if (i >= a && i <= b) { p2.Add(poly.GetPoint(i)); } } if (p1.Count > p2.Count) { SubDivision.Add(new Polygon2D(p1)); return new Polygon2D(p2); } else { SubDivision.Add(new Polygon2D(p2)); return new Polygon2D(p1); } } else if (lineSegment.Intersects(poly)) { Point2DCollection Points = new Point2DCollection(2); for (int i = 0; i < poly.VertexCount; i++) { LineSegment2D border = poly.GetEdge(i); Point2D p = lineSegment.GetIntersectPoint(border); if (p.isRegular) { Points.DistinctAdd(p); } } Debug.Assert(Points.Count == 2); if (poly.HasVertex(Points[0]) == Polygon2D.NoSuchPoint) { poly.Add(Points[0], poly.OnEdge(Points[0])); Parent.AddInner(Points[0]); this.InnerPoints.DistinctAdd(Points[0]); } if (poly.HasVertex(Points[1]) == Polygon2D.NoSuchPoint) { poly.Add(Points[1], poly.OnEdge(Points[1])); Parent.AddInner(Points[1]); this.InnerPoints.DistinctAdd(Points[1]); } LineSegment2D line = new LineSegment2D(Points[0], Points[1]); return DividedBy(line, poly); } else { return poly; } }
/// <summary> /// Whether the three points is on a line. /// </summary> /// <param name="a">the first point.</param> /// <param name="b">the second point.</param> /// <param name="c">the third point.</param> /// <returns>true if is on a line.</returns> public static bool isOnLine(Point2D a, Point2D b, Point2D c) { LineSegment2D line = new LineSegment2D(a, b); return line.isOnLine(c); }
/// <summary> /// Divide the polygon by the line segment between two vertices. /// </summary> /// <param name="a">the index of first vertex.</param> /// <param name="b">the index of second vertex.</param> public void DividedBy(int a, int b) { if (a < 0 || b < 0 || a > Parent.VertexCount || b > Parent.VertexCount) { throw (new ArgumentException()); } LineSegment2D lineSegment = new LineSegment2D(Parent.GetPoint(a), Parent.GetPoint(b)); DividedBy(lineSegment); }
/// <summary> /// Get the intersect point of the two line segment. /// </summary> /// <param name="lineSegment">the ohter line segment.</param> /// <returns>the intersect point.</returns> public Point2D GetIntersectPoint(LineSegment2D lineSegment) { if (this.Intersects(lineSegment)) { try { Point2D point = this.ToLine().Intersects(lineSegment.ToLine()); return point; } catch (ArgumentException e) { string emsg = e.Message; return new Point2D(double.NaN, double.NaN); } } else { return new Point2D(double.NaN, double.NaN); } }
/// <summary> /// Divide a sub polygon by a line segment. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <param name="poly">the polygon to divide.</param> /// <returns>one of the sub polygon divided from the polygon.</returns> internal Polygon2D DividedBy(LineSegment2D lineSegment, Polygon2D poly) { if (poly.isDiagonal(lineSegment)) { int a = poly.HasVertex(lineSegment.FirstPoint); int b = poly.HasVertex(lineSegment.LastPoint); if (a > b) { int tmp = a; a = b; b = tmp; } Point2DCollection p2 = new Point2DCollection(b - a + 1); Point2DCollection p1 = new Point2DCollection(poly.VertexCount - p2.Size + 2); for (int i = 0; i < poly.VertexCount; i++) { if (i <= a || i >= b) { p1.Add(poly.GetPoint(i)); } if (i >= a && i <= b) { p2.Add(poly.GetPoint(i)); } } if (p1.Count > p2.Count) { SubDivision.Add(new Polygon2D(p1)); return(new Polygon2D(p2)); } else { SubDivision.Add(new Polygon2D(p2)); return(new Polygon2D(p1)); } } else if (lineSegment.Intersects(poly)) { Point2DCollection Points = new Point2DCollection(2); for (int i = 0; i < poly.VertexCount; i++) { LineSegment2D border = poly.GetEdge(i); Point2D p = lineSegment.GetIntersectPoint(border); if (p.isRegular) { Points.DistinctAdd(p); } } Debug.Assert(Points.Count == 2); if (poly.HasVertex(Points[0]) == Polygon2D.NoSuchPoint) { poly.Add(Points[0], poly.OnEdge(Points[0])); Parent.AddInner(Points[0]); this.InnerPoints.DistinctAdd(Points[0]); } if (poly.HasVertex(Points[1]) == Polygon2D.NoSuchPoint) { poly.Add(Points[1], poly.OnEdge(Points[1])); Parent.AddInner(Points[1]); this.InnerPoints.DistinctAdd(Points[1]); } LineSegment2D line = new LineSegment2D(Points[0], Points[1]); return(DividedBy(line, poly)); } else { return(poly); } }
public void Triangulation() { if (!this.polygon.isRegular || !this.polygon.isSimple) { throw (new ApplicationException("Can not triangulate this polygon!")); } //this.triangles.Clear(); //this.lineSegments.Clear(); this.internalSegments.Clear(); this.ghostTriangles = new GhostTriangle2DCollection(); this.Clear(); int Count = this.polygon.VertexCount; int[] flag = new int[Count]; for (int i = 0; i < Count; i++) { flag[i] = i; } int a = 0; int b = 1; int c = 2; while (Count > 3) { LineSegment2D lineSegment = new LineSegment2D(this.polygon.GetPoint(flag[a]), this.polygon.GetPoint(flag[c])); if (this.polygon.Contains(lineSegment)) { Count--; this.Triangulation(flag[a], flag[b], flag[c]); for (int i = b; i < Count; i++) { flag[i] = flag[i + 1]; } a = a % Count; b = (a + 1) % Count; c = (b + 1) % Count; continue; } else { a = (a + 1) % Count; b = (b + 1) % Count; c = (c + 1) % Count; } } this.Triangulation(flag[a],flag[b],flag[c]); if (this.child != null) { this.child.Triangulation(); } }
private void Divide(Polygon2D poly) { for (int i = 0; i < poly.VertexCount; i++) //Find Convex Angle { if (poly.isConvexAngle(i)) { continue; } int index = i; double min_dist = 10000; for (int j = 0; j < poly.VertexCount; j++) //Divide Polygon { if (j == i) { continue; } LineSegment2D line = new LineSegment2D(poly.GetPoint(i), poly.GetPoint(j)); if (poly.isDiagonal(line)) { //double dist = line.Length; Vector2D v1 = line.ToVector(); LineSegment2D line1 = poly.GetEdge(i); line1.SwapPoints(); LineSegment2D line2 = poly.GetEdge((i + 1) % poly.VertexCount); Vector2D v2 = line1.ToVector(); Vector2D v3 = line2.ToVector(); double angle1 = Vector2D.Angle(v2, v1); double angle2 = Vector2D.Angle(v1, v3); //ѡȡ���ֽǶ�����ȵĵ����ָ�� if (angle1 < 0) { angle1 += Math.PI * 2; } if (angle2 < 0) { angle2 += Math.PI * 2; } double dist = Math.Max(angle1, angle2); if (!poly.isConvexAngle(j) && dist < Math.PI) { dist -= Math.PI; } if(dist < min_dist) { index = j; min_dist = dist; } } } if (index != i) { this.DividedBy(new LineSegment2D(poly.GetPoint(i), poly.GetPoint(index))); return; } } throw (new ArgumentException()); }
/// <summary> /// Whether the line segment is the diagonal of this polygon. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <returns>true if is diagonal.</returns> public bool isDiagonal(LineSegment2D lineSegment) { if (!lineSegment.isRegular) { return false; } if (this.isEdge(lineSegment)) { return false; } if (!this.Contains(lineSegment)) { return false; } for (int i = 0; i < this.VertexCount; i++) { if (lineSegment.TrulyContains(this.Vertices[i])) { return false; } } for (int i = 0; i < this.VertexCount; i++) { if (lineSegment.FirstPoint == this.Vertices[i]) { for (int j = 0; j < this.VertexCount; j++) { if (lineSegment.LastPoint == this.Vertices[j]) { return true; } } return false; } } return false; }
/// <summary> /// Whether the other line segment's line can truly intersects this line segment. /// </summary> /// <param name="line">the other line segment.</param> /// <returns>true if truly intersects.</returns> internal bool TrulyLineIntersects(LineSegment2D line) { /*Vector2D v1 = this.FirstPoint - line.FirstPoint; Vector2D v2 = line.LastPoint - line.FirstPoint; Vector2D v3 = this.LastPoint - line.FirstPoint; if (Vector2D.Determinant(v1, v2) * Vector2D.Determinant(v2, v3) >= ZeroTolerance) { double d = Vector2D.Determinant(v1, v2) * Vector2D.Determinant(v2, v3); return true; } else { return false; }*/ double x1 = this.FirstPoint.X - line.FirstPoint.X; double y1 = this.FirstPoint.Y - line.FirstPoint.Y; double x2 = line.LastPoint.X - line.FirstPoint.X; double y2 = line.LastPoint.Y - line.FirstPoint.Y; double x3 = this.LastPoint.X - line.FirstPoint.X; double y3 = this.LastPoint.Y - line.FirstPoint.Y; double d1 = x1 * y2 - x2 * y1; double d2 = x2 * y3 - x3 * y2; if (d1 * d2 >= ZeroTolerance) { return true; } else { return false; } }
/// <summary> /// Whether the line segment is a edge of this polygon. /// </summary> /// <param name="lineSegment">the line segment.</param> /// <returns>true if is edge.</returns> public bool isEdge(LineSegment2D lineSegment) { for (int i = 0; i < this.VertexCount; i++) { if (lineSegment == this.GetEdge(i)) { return true; } } return false; }
private GhostTriangle2D Split(Polygon2D first, Polygon2D second, GhostTriangle2D ghostTriangle) { Triangle2D triangle = ghostTriangle.ToTriangle(first); LineSegment2D splitLine = Max(triangle.AB, triangle.BC, triangle.AC); int a = first.GetPointIndex(splitLine.FirstPoint); int b = first.GetPointIndex(splitLine.LastPoint); Point2D p1 = splitLine.MidPoint; splitLine = new LineSegment2D(second.GetPoint(a), second.GetPoint(b)); Point2D p2 = splitLine.MidPoint; Polygon2DEditor polygonEditor = new Polygon2DEditor(first); polygonEditor.AddInnerPoint(p1); polygonEditor = new Polygon2DEditor(second); polygonEditor.AddInnerPoint(p2); return new GhostTriangle2D(a, b, first.PointCount - 1); }
public void Union(LineSegment2DCollection lineSegment2DCollection) { Capacity += lineSegment2DCollection.Capacity; LineSegment2D[] lineSegments = new LineSegment2D[Capacity]; this.LineSegments.CopyTo(lineSegments, 0); lineSegment2DCollection.LineSegments.CopyTo(lineSegments, this.Count); this.LineSegments = lineSegments; CurrentCount += lineSegment2DCollection.Count; }
/// <summary> /// Whether this line segment contains the other. /// </summary> /// <param name="lineSegment">the other line segment.</param> /// <returns>true if contains.</returns> public bool Contains(LineSegment2D lineSegment) { if (this.Contains(lineSegment.FirstPoint) && this.Contains(lineSegment.LastPoint)) { return true; } return false; }
public LineSegment2DCollection(LineSegment2D[] lineSegments) { Capacity = lineSegments.Length; LineSegments = lineSegments; CurrentCount = Capacity; }
/// <summary> /// Whether the two line segments inflect each other. /// </summary> /// <param name="lineSegment">the target linesegment</param> /// <returns>true if inflect</returns> public bool Inflects(LineSegment2D lineSegment) { if (this.TrulyContains(lineSegment.FirstPoint) || this.TrulyContains(lineSegment.LastPoint)) { if (this.ToVector() * lineSegment.ToVector() < ZeroTolerance) { return true; } } if (this.Contains(lineSegment) || lineSegment.Contains(this)) { return true; } return false; }
private void Triangulation(int a, int b, int c) { Debug.Assert(a != b && b != c && c != a); Triangle2D triangle = new Triangle2D(this.polygon.GetPoint(a), this.polygon.GetPoint(b), this.polygon.GetPoint(c)); GhostTriangle2D ghost = new GhostTriangle2D(a, b, c); this.triangles.Add(triangle); this.ghostTriangles.Add(ghost); if (lineSegments.Count < polygon.VertexCount - 3) { Vector2D internalSegment = new Vector2D(a, c); LineSegment2D lineSegment = new LineSegment2D(this.polygon.GetPoint(a), this.polygon.GetPoint(c)); this.lineSegments.Add(lineSegment); this.internalSegments.Add(internalSegment); } }
/// <summary> /// Whether the two line segment truly intersect each other. /// </summary> /// <param name="lineSegment">the other line segment.</param> /// <returns>true if truly intersect.</returns> public bool TrulyIntersects(LineSegment2D lineSegment) { if (!this.ExtentIntersects(lineSegment)) { return false; } return lineSegment.TrulyLineIntersects(this) && this.TrulyLineIntersects(lineSegment); }
/// <summary> /// Divide the source polygon to compute link distance. /// </summary> public void Divide() { LineSegment2D entrance = this.LastDiviser; LineSegment2D path = new LineSegment2D(entrance.FirstPoint, this.LastPoint); if (this.CurrentPolygon.Contains(path)) { return; } path = new LineSegment2D(entrance.LastPoint, this.LastPoint); if (this.CurrentPolygon.Contains(path)) { return; } for (int i = 0; i < this.CurrentPolygon.VertexCount; i++) { if (this.CurrentPolygon.GetPoint(i) == entrance.FirstPoint) { continue; } LineSegment2D lineSegment = new LineSegment2D(entrance.FirstPoint, this.CurrentPolygon.GetPoint(i)); if (!this.CurrentPolygon.Contains(lineSegment) && !this.CurrentPolygon.isEdge(lineSegment)) { continue; } LineSegment2D lineDiviser = this.ChooseDiviser(lineSegment); if (lineDiviser == null) { continue; } Polygon2D testPoly = new Polygon2D(this.CurrentPolygon); if (!testPoly.isVertex(lineDiviser.LastPoint)) { testPoly.Add(lineDiviser.LastPoint, testPoly.OnEdge(lineDiviser.LastPoint)); } Polygon2D polygon = this.DividedBy(lineDiviser, testPoly); if (polygon.isVertex(this.LastPoint)) { testPoly = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } else { testPoly = polygon; polygon = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } if (entrance.FirstPoint == entrance.LastPoint) { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(testPoly); this.SubDivision.Add(polygon); } else { LineSegment2D testLine = new LineSegment2D(entrance.LastPoint, lineDiviser.FirstPoint); if (!testLine.isRegular) { entrance = new LineSegment2D(entrance.LastPoint, entrance.LastPoint); continue; } if (this.CurrentPolygon.Contains(testLine)) { testLine = this.ChooseDiviser(testLine); if (testLine != null && !testPoly.Contains(testLine)) { lineDiviser = testLine; testPoly = new Polygon2D(this.CurrentPolygon); if (!testPoly.isVertex(lineDiviser.LastPoint)) { testPoly.Add(lineDiviser.LastPoint, testPoly.OnEdge(lineDiviser.LastPoint)); } polygon = this.DividedBy(lineDiviser, testPoly); testPoly = this.CurrentPolygon; this.SubDivision.Remove(this.SubDivision.Count - 1); } else if (testLine == null) { continue; } } if (!polygon.isVertex(this.LastPoint)) { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(polygon); this.SubDivision.Add(testPoly); } else { this.SubDivision.Remove(this.SubDivision.Count - 1); this.SubDivision.Add(testPoly); this.SubDivision.Add(polygon); } } this.Divisers.Add(lineDiviser); this.Divide(); return; } }
/// <summary> /// Whether the two extents intersect each other. /// (x1,y1)----------------------------- /// - Extent - /// ------------------------------(x2,y2) /// </summary> /// <param name="line">the other line.</param> /// <returns>true if intersect.</returns> private bool ExtentIntersects(LineSegment2D line) { double x1, y1; double x2, y2; double x3, y3; double x4, y4; x1 = Math.Min(this.FirstPoint.X, this.LastPoint.X); x2 = Math.Max(this.FirstPoint.X, this.LastPoint.X); y1 = Math.Min(this.FirstPoint.Y, this.LastPoint.Y); y2 = Math.Max(this.FirstPoint.Y, this.LastPoint.Y); x3 = Math.Min(line.FirstPoint.X, line.LastPoint.X); x4 = Math.Max(line.FirstPoint.X, line.LastPoint.X); y3 = Math.Min(line.FirstPoint.Y, line.LastPoint.Y); y4 = Math.Max(line.FirstPoint.Y, line.LastPoint.Y); if (x1 <= x4 && x2 >= x3 && y1 <= y4 && y2 >= y3) { return true; } else { return false; } }
/// <summary> /// Construct a minimum link path of a polygon. /// </summary> public void BuildPath() { this.LinkDivisers.Clear(); Point2D CurrentPoint = this.LastPoint; Point2D IntersectPoint = null; LineSegment2D CurrentLine = null; LineSegment2D IntersectLine = null; for (int i = this.Divisers.Count - 1; i >= 0; i--) { double position = -1.0; Polygon2D currentPolygon = this.SubDivision[i + 1]; CurrentLine = this.Divisers[i]; if (CurrentLine.Contains(CurrentPoint)) { this.LinkDivisers.Add(CurrentPoint); Vector2D vector = CurrentLine.ToVector().Normal().Normalize(); IntersectPoint = CurrentLine.MidPoint + vector; if (!this.SubDivision[i].Contains(IntersectPoint)) { vector = -vector; } double length = CurrentLine.Length; LineSegment2D testLine = null; do { IntersectPoint = CurrentLine.MidPoint + vector * length; length /= 2; testLine = new LineSegment2D(CurrentPoint, IntersectPoint); } while (!this.SubDivision[i].Contains(testLine)); continue; } for (int j = 0; j < currentPolygon.VertexCount; j++) { Point2D point = currentPolygon.GetPoint(j); if (CurrentPoint == point) { continue; } LineSegment2D lineSegment = new LineSegment2D(CurrentPoint, point); if (currentPolygon.Contains(lineSegment) || currentPolygon.isEdge(lineSegment)) { if (CurrentLine.LineIntersects(lineSegment)) { IntersectPoint = CurrentLine.ToLine().Intersects(lineSegment.ToLine()); if (position < 0) { position = CurrentLine.GetPosition(IntersectPoint); } else { position += CurrentLine.GetPosition(IntersectPoint); position /= 2; } } } } if (position < -0.5) { CurrentPoint = IntersectPoint + IntersectLine.ToVector().Normalize(); i++; continue; } this.LinkDivisers.Add(CurrentPoint); IntersectPoint = CurrentLine.GetPoint(position); IntersectLine = new LineSegment2D(CurrentPoint, IntersectPoint); double extend = IntersectLine.Length; do { extend /= 2; CurrentPoint = IntersectLine.Extend(extend); } while (!this.SubDivision[i].Contains(CurrentPoint)); //CurrentPoint = CurrentLine.GetPoint(position); } CurrentLine = new LineSegment2D(CurrentPoint, this.FirstPoint); if (this.Parent.Contains(CurrentLine)) { this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } else if (IntersectLine != null) { CurrentPoint = IntersectPoint + IntersectLine.ToVector().Normalize(); this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } else { Vector2D vector = CurrentLine.ToVector().Normal().Normalize(); IntersectPoint = CurrentLine.MidPoint + vector; if (!this.Parent.Contains(IntersectPoint)) { vector = -vector; } IntersectPoint = CurrentLine.MidPoint; double length = CurrentLine.Length; do { length /= 2; CurrentPoint = IntersectPoint + vector * length; }while (!this.Parent.Contains(CurrentPoint)); this.LinkDivisers.Add(this.LastPoint); this.LinkDivisers.Add(CurrentPoint); this.LinkDivisers.Add(this.FirstPoint); } }