/// <summary> /// Copies this instance deeply. /// </summary> /// <returns>PLine.</returns> public PLine Copy() { PLine pline = new PLine(new UVLine(this._pntList[0].Copy(), this._pntList[1].Copy())); for (int i = 2; i < this.PointCount; i++) { pline.addEnd(this._pntList[i].Copy()); } pline.Closed = this.Closed; return(pline); }
/// <summary> /// Extracts a list of polylines from an arbitrary collection of lines. NOTE: There might be different possibilities for this operation. /// </summary> /// <param name="lines">The lines.</param> /// <param name="fractionalDigits">The fractional digits used for hashing.</param> /// <param name="tolerance">The tolerance of point equality.</param> /// <returns>List<PLine>.</returns> public static List <PLine> ExtractPLines(ICollection <UVLine> lines, int fractionalDigits = 5, double tolerance = OSMDocument.AbsoluteTolerance) { Dictionary <UV, HashSet <UVLine> > pntToLine = new Dictionary <UV, HashSet <UVLine> >(new UVComparer(fractionalDigits, tolerance)); foreach (var item in lines) { if (item.GetLengthSquared() > 0) { if (pntToLine.ContainsKey(item.Start)) { pntToLine[item.Start].Add(item); } else { var set = new HashSet <UVLine>() { item }; pntToLine.Add(item.Start, set); } if (pntToLine.ContainsKey(item.End)) { pntToLine[item.End].Add(item); } else { var list = new HashSet <UVLine>() { item }; pntToLine.Add(item.End, list); } } else { MessageBox.Show("Line with zero length cannot be added to a polyLine!"); } } List <PLine> pLines = new List <PLine>(); while (pntToLine.Count != 0) { UVLine line = null; try { line = pntToLine.First().Value.First(); } catch (Exception e) { MessageBox.Show("Failed at 3\n" + e.Report()); } PLine pLine = new PLine(line, fractionalDigits); //lines.Remove(line); pntToLine[line.Start].Remove(line); if (pntToLine[line.Start].Count == 0) { pntToLine.Remove(line.Start); } pntToLine[line.End].Remove(line); if (pntToLine[line.End].Count == 0) { pntToLine.Remove(line.End); } bool iterate = true; while (iterate) { iterate = false; if (pntToLine.ContainsKey(pLine._start)) { UVLine line_ = null; try { line_ = pntToLine[pLine._start].First(); } catch (Exception e) { MessageBox.Show("Failed at 1\n" + e.Report()); } pLine.addSegment(line_); pntToLine[line_.Start].Remove(line_); if (pntToLine[line_.Start].Count == 0) { pntToLine.Remove(line_.Start); } pntToLine[line_.End].Remove(line_); if (pntToLine[line_.End].Count == 0) { pntToLine.Remove(line_.End); } //lines.Remove(line); if (pLine.Closed) { break; } iterate = true; } if (pntToLine.Count == 0) { break; } if (pntToLine.ContainsKey(pLine._end)) { UVLine line_ = null; try { line_ = pntToLine[pLine._end].First(); } catch (Exception e) { MessageBox.Show("Failed at 2\n" + e.Report()); try { line_ = pntToLine[pLine._end].First(); } catch (Exception) { } } pLine.addSegment(line_); pntToLine[line_.Start].Remove(line_); if (pntToLine[line_.Start].Count == 0) { pntToLine.Remove(line_.Start); } pntToLine[line_.End].Remove(line_); if (pntToLine[line_.End].Count == 0) { pntToLine.Remove(line_.End); } //lines.Remove(line); if (pLine.Closed) { break; } iterate = true; } } pLines.Add(pLine); } return(pLines); }
/// <summary> /// Finds the closest point on the polygon from a given point /// </summary> /// <param name="p">The point from which the closest point should be found.</param> /// <returns>UV.</returns> public UV ClosestPoint(UV p) { return(PLine.ClosestPoint(this.Points, p, this.Closed)); }
/// <summary> /// Splits this polyline to a list of polylines with equal lengths /// </summary> /// <param name="length">The length.</param> /// <param name="tolerance">The tolerance by default set to main documents absolute tolerance.</param> /// <returns>List<PLine>.</returns> public List <PLine> SplitToPLines(double length, double tolerance = OSMDocument.AbsoluteTolerance) { List <int> indexes = new List <int>() { 0 }; List <UV> pnts = new List <UV>(); double totalLength = 0; double u = length; for (int i = 0; i < this.PointCount; i++) { pnts.Add(this.Points[i]); //indexes.Add(pnts.Count - 1); int j = (i == this.PointCount - 1) ? 0 : i + 1; if (!this.Closed && j == 0) { break; } UV vector = this.Points[j] - this.Points[i]; double dist = vector.GetLength(); vector /= dist; while (u < totalLength + dist) { var p = this.Points[i] + (u - totalLength) * vector; if (!this._pntSet.Contains(p)) { pnts.Add(p); } indexes.Add(pnts.Count - 1); u += length; } totalLength += dist; } if (this.Closed) { if (this.Start != pnts[pnts.Count - 1]) { pnts.Add(this.Start); } indexes.Add(pnts.Count - 1); } else { if (this.End != pnts[pnts.Count - 1]) { pnts.Add(this.End); } indexes.Add(pnts.Count - 1); } List <PLine> plines = new List <PLine>(); if (indexes.Count == 2) { plines.Add(this); } for (int i = 0; i < indexes.Count - 1; i++) { var points = pnts.GetRange(indexes[i], indexes[i + 1] - indexes[i] + 1); if (points[0].DistanceTo(points[1]) < tolerance) { points.RemoveAt(1); } if (points.Count > 1) { if (points[points.Count - 1].DistanceTo(points[points.Count - 2]) < tolerance) { points.RemoveAt(points.Count - 2); } if (points.Count > 1) { PLine pline = new PLine(points, false); plines.Add(pline); } } } return(plines); }
/// <summary> /// Returns the distance squared to a this polygon /// </summary> /// <param name="p">The point to measure the distance squared from.</param> /// <returns>System.Double.</returns> public double DistanceSquaredTo(UV p) { return(PLine.DistanceSquaredTo(this.Points, p, this.Closed)); }