/// <summary> /// Creates an arc defined by a start point, end point and a direction at the first point. /// </summary> /// <param name="ptStart">Start point arc.</param> /// <param name="ptEnd">End point arc.</param> /// <param name="dir">TangentAt direction at start.</param> /// <returns>An arc.</returns> public static Arc ByStartEndDirection(Point3 ptStart, Point3 ptEnd, Vector3 dir) { if (!ptStart.IsValid) { throw new Exception("The first point is not valid."); } if (!ptEnd.IsValid) { throw new Exception("The second point is not valid."); } if (!dir.IsValid) { throw new Exception("The tangent is not valid."); } Vector3 vec0 = dir.Unitize(); Vector3 vec1 = (ptEnd - ptStart).Unitize(); if (vec1.Length.Equals(0.0)) { throw new Exception("Start and End point of the arc are coincident. Enable to create an arc"); } if (vec0.IsParallelTo(vec1) != 0) { throw new Exception("Tangent is parallel with the endpoints. Enable to create an arc"); } Vector3 vec2 = (vec0 + vec1).Unitize(); Vector3 vec3 = vec2 * (0.5 * ptStart.DistanceTo(ptEnd) / Vector3.DotProduct(vec2, vec0)); return(new Arc(ptStart, ptStart + vec3, ptEnd)); }
/// <summary> /// Computes the point which is the closest point to the given point. /// </summary> /// <param name="pt">Point to test.</param> /// <returns>The point closest to the given point.</returns> public override Point3 ClosestPoint(Point3 pt) { // Brute force if (ControlPointLocations.Count <= 4) { double distance = double.MaxValue; Point3 closestPt = Point3.Unset; for (int i = 0; i < ControlPointLocations.Count - 1; i++) { Line tempLine = new Line(ControlPointLocations[i], ControlPointLocations[i + 1]); Point3 tempPt = tempLine.ClosestPoint(pt); double tempDistance = tempPt.DistanceTo(pt); if (!(tempDistance < distance)) { continue; } closestPt = tempPt; distance = tempDistance; } return(closestPt); } // Divide and conquer. List <Point3> leftSubCollection = new List <Point3>(); List <Point3> rightSubCollection = new List <Point3>(); List <Point3> conquer = new List <Point3>(ControlPointLocations); while (leftSubCollection.Count != 2 || rightSubCollection.Count != 2) { int mid = (int)((double)conquer.Count / 2); leftSubCollection = conquer.Take(mid + 1).ToList(); rightSubCollection = conquer.Skip(mid).ToList(); PolyLine leftPoly = new PolyLine(leftSubCollection); PolyLine rightPoly = new PolyLine(rightSubCollection); Point3 leftPt = leftPoly.PointAt(0.5); Point3 rightPt = rightPoly.PointAt(0.5); double leftDistance = leftPt.DistanceTo(pt); double rightDistance = rightPt.DistanceTo(pt); conquer = leftDistance > rightDistance ? new List <Point3>(rightSubCollection) : new List <Point3>(leftSubCollection); } Line line = new Line(conquer[0], conquer[1]); return(line.ClosestPoint(pt)); }
/// <summary> /// Initializes a line by start point and end point. /// </summary> /// <param name="startPoint">Start point.</param> /// <param name="endPoint">End point.</param> public Line(Point3 startPoint, Point3 endPoint) { if (startPoint == endPoint || !startPoint.IsValid || !endPoint.IsValid) { throw new Exception("Start or end point is not valid, or they are equal"); } StartPoint = startPoint; EndPoint = endPoint; Length = StartPoint.DistanceTo(EndPoint); Direction = (EndPoint - StartPoint).Unitize(); ToNurbs(); }