/// <summary> /// Creates a curve by using the underlying polyline /// </summary> /// <returns></returns> public Curve CreateCurve() { Curve curve = new Curve(); Site a = HeadSite; //the corner start Site b; //the corner origin Site c; //the corner other end while (Curve.FindCorner(a, out b, out c)) { CubicBezierSegment bezierSeg = CreateBezierSegOnSite(b); if (curve.Segments.Count == 0) { if (!ApproximateComparer.Close(a.Point, bezierSeg.Start)) { Curve.AddLineSegment(curve, a.Point, bezierSeg.Start); } } else if (!ApproximateComparer.Close(curve.End, bezierSeg.Start)) { Curve.ContinueWithLineSegment(curve, bezierSeg.Start); } curve.AddSegment(bezierSeg); a = b; } System.Diagnostics.Debug.Assert(a.Next.Next == null); if (curve.Segments.Count == 0) { if (!ApproximateComparer.Close(a.Point, a.Next.Point)) { Curve.AddLineSegment(curve, a.Point, a.Next.Point); } else { double w = 5; curve.Segments.Add(new CubicBezierSegment(a.Point, a.Point + new Point(w, w), a.Point + new Point(-w, w), b.Point)); } } else if (!ApproximateComparer.Close(curve.End, a.Next.Point)) { Curve.ContinueWithLineSegment(curve, a.Next.Point); } return(curve); }
internal static Polyline CreateConvexHullAsClosedPolyline(IEnumerable <Point> points) { var convexHull = new Polyline(CalculateConvexHull(points)) { Closed = true }; #if TEST_MSAGL foreach (var point in points) { if (Curve.PointRelativeToCurveLocation(point, convexHull) == PointLocation.Outside) { var hullPoint = convexHull[convexHull.ClosestParameter(point)]; // This can be too restrictive if very close points are put into the hull. It is probably // better to clean up in the caller before doing this, but this assert can also be relaxed. Debug.Assert(ApproximateComparer.Close(point, hullPoint, ApproximateComparer.IntersectionEpsilon * 20), String.Format("not CloseIntersections: initial point {0}, hull point {1}", point, hullPoint)); } } #endif // TEST_MSAGL return(convexHull); }
/// <summary> /// computes orientation of three vectors with a common source /// (compare polar angles of v1 and v2 with respect to v0) /// </summary> /// <returns> /// -1 if the orientation is v0 v1 v2 /// 1 if the orientation is v0 v2 v1 /// 0 if v1 and v2 are collinear and codirectinal /// </returns> static public int GetOrientationOf3Vectors(Point vector0, Point vector1, Point vector2) { const double multiplier = 1000; //TODO, need to fix it? vector0 *= multiplier; vector1 *= multiplier; vector2 *= multiplier; double xp2 = Point.CrossProduct(vector0, vector2); double dotp2 = vector0 * vector2; double xp1 = Point.CrossProduct(vector0, vector1); double dotp1 = vector0 * vector1; // v1 is collinear with v0 if (ApproximateComparer.Close(xp1, 0.0) && ApproximateComparer.GreaterOrEqual(dotp1, 0.0)) { if (ApproximateComparer.Close(xp2, 0.0) && ApproximateComparer.GreaterOrEqual(dotp2, 0.0)) { return(0); } return(1); } // v2 is collinear with v0 if (ApproximateComparer.Close(xp2, 0.0) && ApproximateComparer.GreaterOrEqual(dotp2, 0.0)) { return(-1); } if (ApproximateComparer.Close(xp1, 0.0) || ApproximateComparer.Close(xp2, 0.0) || xp1 * xp2 > 0.0) { // both on same side of v0, compare to each other return(ApproximateComparer.Compare(Point.CrossProduct(vector2, vector1), 0.0)); } // vectors "less than" zero degrees are actually large, near 2 pi return(-ApproximateComparer.Compare(Math.Sign(xp1), 0.0)); }