/// <summary> /// Returns the projection of this UV as a point from a specified line. /// </summary> /// <param name="line">The line.</param> /// <returns>UV.</returns> public UV Projection(UVLine line) { double u = (line.End - line.Start).DotProduct(this - line.Start); u /= line.GetLength(); return(line.FindPoint(u)); }
/// <summary> /// Return ths distance of the UV as a point from a line. /// </summary> /// <param name="line">The line.</param> /// <returns>System.Double.</returns> public double DistanceTo(UVLine line) { double area = (line.Start - line.End).CrossProductValue(line.Start - this); area = Math.Abs(area); return(area / line.GetLength()); }
/// <summary> /// Returns a parameter at the intersection point with another line if found. This function takes the length of this line if it is available for performance optimization. /// </summary> /// <param name="line">The line.</param> /// <param name="length">The length of this line.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Nullable<System.Double>.</returns> public double?Intersection(UVLine line, double length, double tolerance = .000001f) { UV lineVector = this.End - this.Start; double area1 = lineVector.CrossProductValue(line.Start - this.Start); double area2 = lineVector.CrossProductValue(line.End - this.Start); if (area1 * area2 > tolerance) { lineVector = null; return(null); } lineVector = line.End - line.Start; area1 = lineVector.CrossProductValue(this.Start - line.Start); area2 = lineVector.CrossProductValue(this.End - line.Start); if (area1 * area2 > tolerance) { lineVector = null; return(null); } double a1 = (line.Start - this.Start).CrossProductValue(line.End - this.Start); if (a1 == 0) { return(Math.Min(line.Start.DistanceTo(this.Start), line.End.DistanceTo(this.Start))); } lineVector = null; double u = length * Math.Abs(a1) / (Math.Abs(area1) + Math.Abs(area2)); return(u); }
/// <summary> /// Returns a parameter at the intersection point with another line if found. /// </summary> /// <param name="l">The l.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Nullable<System.Double>.</returns> public double?Intersection(UVLine l, double tolerance = OSMDocument.AbsoluteTolerance) { UV lineVector = this.End - this.Start; double area1 = lineVector.CrossProductValue(l.Start - this.Start); double area2 = lineVector.CrossProductValue(l.End - this.Start); if (area1 * area2 > tolerance) { lineVector = null; return(null); } lineVector = l.End - l.Start; area1 = lineVector.CrossProductValue(this.Start - l.Start); area2 = lineVector.CrossProductValue(this.End - l.Start); if (area1 * area2 > tolerance) { lineVector = null; return(null); } //double lengthL = l.GetLength(); double a1 = (l.Start - this.Start).CrossProductValue(l.End - this.Start); if (a1 == 0) { return(Math.Min(l.Start.DistanceTo(this.Start), l.End.DistanceTo(this.Start))); } lineVector = null; double u = this.GetLength() * Math.Abs(a1) / (Math.Abs(area1) + Math.Abs(area2)); return(u); }
/// <summary> /// Finds the closest point on the polygon from a given point /// </summary> /// <param name="points">The points that represent a polygon.</param> /// <param name="p">The point from which the closest point should be found.</param> /// <param name="closed">if set to <c>true</c> the polygon is closed.</param> /// <returns>UV.</returns> public static UV ClosestPoint(UV[] points, UV p, bool closed) { UV[] vecs = new UV[points.Length]; double[] vecLengths = new double[points.Length]; for (int i = 0; i < points.Length; i++) { vecs[i] = points[i] - p; vecLengths[i] = vecs[i].GetLengthSquared(); } double minDistSquared = double.PositiveInfinity; int index = 0; for (int i = 0; i < points.Length - 1; i++) { double area = vecs[i].CrossProductValue(vecs[i + 1]); area *= area; double d1 = UV.GetLengthSquared(points[i], points[i + 1]); double distSquared = area / d1; if (distSquared < vecLengths[i] - d1 || distSquared < vecLengths[i + 1] - d1) { distSquared = Math.Min(vecLengths[i + 1], vecLengths[i]); } if (minDistSquared > distSquared) { minDistSquared = distSquared; index = i; } } if (closed) { double area = vecs[points.Length - 1].CrossProductValue(vecs[0]); area *= area; double d1 = UV.GetLengthSquared(points[points.Length - 1], points[0]); double distSquared = area / d1; if (distSquared < vecLengths[0] - d1 || distSquared < vecLengths[points.Length - 1] - d1) { distSquared = Math.Min(vecLengths[0], vecLengths[points.Length - 1]); } if (minDistSquared > distSquared) { minDistSquared = distSquared; index = points.Length - 1; } } int j = index + 1; if (j == points.Length) { j = 0; } UVLine line = new UVLine(points[index], points[j]); return(p.GetClosestPoint(line)); }
/// <summary> /// Gets the reflection of this UV as a vector from a line. /// </summary> /// <param name="line">The line.</param> /// <returns>UV.</returns> public UV GetReflection(UVLine line) { var vector = line.GetDirection(); vector.Unitize(); double dotPro = this.DotProduct(vector); UV horizontal_Component = vector * dotPro; UV normal_Component = this - horizontal_Component; var result = horizontal_Component - normal_Component; return(result); }
/// <summary> /// Gets the closest point of this UV as a point from a line. /// </summary> /// <param name="line">The line.</param> /// <returns>UV.</returns> public UV GetClosestPoint(UVLine line) { double length = line.GetLength(); double u = (line.End - line.Start).DotProduct(this - line.Start); u /= length; if (u < 0) { return(line.Start); } if (u > length) { return(line.End); } return(line.FindPoint(u)); }
/// <summary> /// Gets the distance squared of this UV as a point from a line. /// </summary> /// <param name="line">The line.</param> /// <returns>System.Double.</returns> public double GetDistanceSquared(UVLine line) { UV vs = this - line.Start; double vs2 = vs.GetLengthSquared(); UV ve = this - line.End; double ve2 = ve.GetLengthSquared(); double area = vs.CrossProductValue(ve); area *= area; double d = UV.GetLengthSquared(line.Start, line.End); double distSquared = area / d; if (distSquared < vs2 - d || distSquared < ve2 - d) { distSquared = Math.Min(vs2, ve2); } return(distSquared); }
public override bool Equals(object obj) { UVLine l = obj as UVLine; if (l == null) { return(false); } else { if ((l.Start == this.Start && l.End == this.End) || (l.End == this.Start && l.Start == this.End)) { return(true); } } return(false); }
/// <summary> /// Gets the closest point of this UV as a point from a line. /// </summary> /// <param name="line">The line.</param> /// <param name="isEndPoint">if set to <c>true</c> the closest point is the end point of the line.</param> /// <returns>UV.</returns> public UV GetClosestPoint(UVLine line, ref bool isEndPoint) { double length = line.GetLength(); double u = (line.End - line.Start).DotProduct(this - line.Start); u /= length; if (u < 0) { isEndPoint = true; return(line.Start); } if (u > length) { isEndPoint = true; return(line.End); } isEndPoint = false; return(line.FindPoint(u)); }
/// <summary> /// Initializes a new instance of the <see cref="PLine"/> class. /// </summary> /// <param name="line">A line to start with.</param> /// <param name="numberOfFractionalDigits">The number of fractional digits used as the tolerance of equality.</param> /// <exception cref="ArgumentException">Line length is zero</exception> public PLine(UVLine line, int numberOfFractionalDigits = 5, double tolerance = OSMDocument.AbsoluteTolerance) { if (line.End == line.Start) { throw new ArgumentException("Line length is zero"); } this._end = line.End; this._start = line.Start; this._pntList = new List <UV>() { this._start, this._end, }; this._comparer = new UVComparer(numberOfFractionalDigits, tolerance); this._pntSet = new HashSet <UV>(this._comparer) { this._end, this._start }; this.Closed = false; }
/// <summary> /// Returns the closest distance of this UV as a point from a line . /// </summary> /// <param name="line">The line.</param> /// <returns>System.Double.</returns> public double ClosestDistance(UVLine line) { UV p = new UV(); double length = line.GetLength(); double u = (line.End - line.Start).DotProduct(this - line.Start); u /= length; if (u < 0) { p = line.Start; } else if (u > length) { p = line.End; } else { p = this.GetClosestPoint(line); } return(p.DistanceTo(this)); }
/// <summary> /// Determines if this line intersects with another line. /// </summary> /// <param name="l">The l.</param> /// <param name="tolerance">The tolerance.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> public bool Intersects(UVLine l, double tolerance = OSMDocument.AbsoluteTolerance) { UV lineVector = this.End - this.Start; double area1 = lineVector.CrossProductValue(l.Start - this.Start); double area2 = lineVector.CrossProductValue(l.End - this.Start); if (area1 * area2 > tolerance) { lineVector = null; return(false); } lineVector = l.End - l.Start; area1 = lineVector.CrossProductValue(this.Start - l.Start); area2 = lineVector.CrossProductValue(this.End - l.Start); if (area1 * area2 > tolerance) { lineVector = null; return(false); } return(true); }
/// <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); }
private bool addSegment(UVLine line) { try { if (this.Closed) { return(false); } else { if (this._pntSet.Contains(line.Start) && this._pntSet.Contains(line.End)) { if (this._comparer.Equals(this._start, line.Start) && this._comparer.Equals(this._end, line.End)) { this.Closed = true; return(true); } else if (this._comparer.Equals(this._start, line.End) && this._comparer.Equals(this._end, line.Start)) { this.Closed = true; return(true); } else { /* * StringBuilder sb = new StringBuilder(); * sb.AppendLine("POINTS:"); * foreach (var item in this._pntList) * { * sb.AppendLine(item.ToString()); * } * sb.AppendLine("\nAdded Line:"); * sb.AppendLine(line.Start.ToString()); * sb.AppendLine(line.End.ToString()); * MessageBox.Show(sb.ToString()); * sb.Clear(); * sb = null; * throw new ArgumentException("Self intersection"); */ } } if (this._comparer.Equals(this._start, line.Start)) { this.addStart(line.End); return(true); } if (this._comparer.Equals(this._start, line.End)) { this.addStart(line.Start); return(true); } if (this._comparer.Equals(this._end, line.End)) { this.addEnd(line.Start); return(true); } if (this._comparer.Equals(this._end, line.Start)) { this.addEnd(line.End); return(true); } } return(false); } catch (Exception e) { MessageBox.Show(e.Report()); } return(false); }