/// <summary>
        /// create a box of the given width and height at center.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="center"></param>
        /// <returns></returns>
        static internal void CreateRectangle(Curve c, double width, double height, Point center)
        {
            double w = width / 2;
            double h = height / 2;
            double x = center.X;
            double y = center.Y;

            Point[] p = new Point[] { new Point(x - w, y - h), new Point(x + w, y - h), new Point(x + w, y + h), new Point(x - w, y + h) };
            c.AddSegs(new LineSegment(p[0], p[1]), new LineSegment(p[1], p[2]), new LineSegment(p[2], p[3]), new LineSegment(p[3], p[0]));
        }
        /// <summary>
        /// Creates a curve resembling a diamond large enough to inscribe within it a rectangle of the
        /// given width and height at center.
        /// </summary>
        /// <param name="width">the width of the inscribed rectangle</param>
        /// <param name="height">the height of the inscribed rectangle</param>
        /// <param name="center">the diamond center</param>
        /// <returns></returns>
        static public ICurve CreateDiamond(double width, double height, Point center)
        {
            double w = width;
            double h = height;
            double x = center.X;
            double y = center.Y;
            Curve  c = new Curve();

            Point[] p = new Point[] { new Point(x, y - h), new Point(x + w, y), new Point(x, y + h), new Point(x - w, y) };
            c.AddSegs(new LineSegment(p[0], p[1]), new LineSegment(p[1], p[2]), new LineSegment(p[2], p[3]), new LineSegment(p[3], p[0]));
            return(c);
        }
        /// <summary>
        /// Following "Biarc approximation of NURBS curves", Les A. Piegl, and Wayne Tiller. The paper has a bug in V, where they write that v=p0+p4, it is p0-p4.
        /// Also I treat special cases differently.
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="ts"></param>
        /// <param name="p4"></param>
        /// <param name="te"></param>
        /// <returns></returns>
        internal static ICurve BiArc(Point p0, Point ts, Point p4, Point te) {
            Debug.Assert(ApproximateComparer.Close(ts.LengthSquared, 1));
            Debug.Assert(ApproximateComparer.Close(te.LengthSquared, 1));
            var v = p0 - p4;
            if (v.Length < ApproximateComparer.DistanceEpsilon)
                return null;

            var vtse = v * (ts - te);
            var tste = -ts * te;

            //solving a quadratic equation
            var a = 2 * (tste - 1);
            var b = 2 * vtse;
            var c = v * v;
            double al;
            if (Math.Abs(a) < ApproximateComparer.DistanceEpsilon) { //we have b*al+c=0
                if (Math.Abs(b) > ApproximateComparer.DistanceEpsilon) {
                    al = -c / b;
                }
                else {
                    return null;
                }
            }
            else {
                var d = b * b - 4 * a * c;
                Debug.Assert(d >= -ApproximateComparer.Tolerance);
                if (d < 0)
                    d = 0;
                d = Math.Sqrt(d);
                al = (-b + d) / (2 * a);
                if (al < 0)
                    al = (-b - d) / (2 * a);
            }

            var p1 = p0 + al * ts;
            var p3 = p4 + al * te;
            var p2 = 0.5 * (p1 + p3);
            var curve = new Curve();
            curve.AddSegs(ArcOn(p0, p1, p2), ArcOn(p2, p3, p4));

            //bad input for BiArc. we shouldn't allow such cases during bundle bases construction
            if (ts * (p4 - p0) <= 0 && ts * te <= 0) {
                //switch to Bezier
                var curve2 = StandardBezier(p0, ts, p4, te);
#if DEBUG && TEST_MSAGL
                /*List<DebugCurve> dc = new List<DebugCurve>();
                dc.Add(new DebugCurve(curve));
                dc.Add(new DebugCurve(0.3, "black", curve2));
                dc.Add(new DebugCurve(0.1, "red", new LineSegment(p0, p0 + 3 * ts)));
                dc.Add(new DebugCurve(0.1, "blue", new LineSegment(p4, p4 + 3 * te)));
                LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(dc);*/
#endif
                return curve2;
            }

            return curve;
        }
 /// <summary>
 /// Creates a curve resembling a diamond large enough to inscribe within it a rectangle of the 
 /// given width and height at center.
 /// </summary>
 /// <param name="width">the width of the inscribed rectangle</param>
 /// <param name="height">the height of the inscribed rectangle</param>
 /// <param name="center">the diamond center</param>
 /// <returns></returns>
 static public ICurve CreateDiamond(double width, double height, Point center) {
     double w = width;
     double h = height;
     double x = center.X;
     double y = center.Y;
     Curve c = new Curve();
     Point[] p = new Point[] { new Point(x, y - h), new Point(x + w, y), new Point(x, y + h), new Point(x - w, y) };
     c.AddSegs(new LineSegment(p[0], p[1]), new LineSegment(p[1], p[2]), new LineSegment(p[2], p[3]), new LineSegment(p[3], p[0]));
     return c;
 }
 /// <summary>
 /// create a box of the given width and height at center.
 /// </summary>
 /// <param name="c"></param>
 /// <param name="width"></param>
 /// <param name="height"></param>
 /// <param name="center"></param>
 /// <returns></returns>
 static internal void CreateRectangle(Curve c, double width, double height, Point center)
 {
     double w = width / 2;
     double h = height / 2;
     double x = center.X;
     double y = center.Y;
     Point[] p = new Point[] { new Point(x - w, y - h), new Point(x + w, y - h), new Point(x + w, y + h), new Point(x - w, y + h) };
     c.AddSegs(new LineSegment(p[0], p[1]), new LineSegment(p[1], p[2]), new LineSegment(p[2], p[3]), new LineSegment(p[3], p[0]));
 }
 private Curve ExtendCurveToEndpoints(Curve curve) {
     Point p = this.EdgePathPoint(0);
     if (!ApproximateComparer.Close(p, curve.Start)) {
         Curve nc = new Curve();
         nc.AddSegs(new LineSegment(p, curve.Start), curve);
         curve = nc;
     }
     p = this.EdgePathPoint(edgePath.Count);
     if (!ApproximateComparer.Close(p, curve.End))
         curve.AddSegment(new LineSegment(curve.End, p));
     return curve;
 }
        static ICurve GetTrimmedCurveForHookingUpAnywhere(ICurve curve, PolylinePoint lastPointInside, IntersectionInfo x0, IntersectionInfo x1) {
            var clockwise =
                Point.GetTriangleOrientation(x1.IntersectionPoint, x0.IntersectionPoint, lastPointInside.Point) ==
                TriangleOrientation.Clockwise;

            double rightX = x0.Par0;
            double leftX = x1.Par0;
            ICurve tr0, tr1;
            Curve ret;
            if (clockwise) {
                if (rightX < leftX)
                    return curve.Trim(rightX, leftX);

                tr0 = curve.Trim(rightX, curve.ParEnd);
                tr1 = curve.Trim(curve.ParStart, leftX);
                ret = new Curve();
                return ret.AddSegs(tr0, tr1);
            }

            if (leftX < rightX)
                return curve.Trim(leftX, rightX);
            tr0 = curve.Trim(leftX, curve.ParEnd);
            tr1 = curve.Trim(curve.ParStart, rightX);
            ret = new Curve();
            return ret.AddSegs(tr0, tr1);
        }