void CreateCurveLine(Metroline line, EdgeGeometry edge) {
     var c = new Curve();
     Point start = FindCurveStart(metroGraphData, metroOrdering, line);
     Point currentEnd = start;
     var hubSegsOfLine = HubSegsOfLine(metroGraphData, metroOrdering, line);
     foreach (var seg in hubSegsOfLine) {
         if (seg == null) continue;
         c.AddSegment(new LineSegment(currentEnd, seg.Start));
         c.AddSegment(seg);
         currentEnd = seg.End;
     }
     c.AddSegment(new LineSegment(currentEnd, FindCurveEnd(metroGraphData, metroOrdering, line)));
     edge.Curve = c;
     if (CreateUnderlyingPolylines)
         edge.SmoothedPolyline = BuildUnderlyingPolyline(start, currentEnd, hubSegsOfLine);
 }
        /// <summary>
        /// Create in the specified curve, a rectangle with smoothed corners
        /// </summary>
        /// <param name="c"></param>
        /// <param name="width">the rectangle width</param>
        /// <param name="height">the rectangle height</param>
        /// <param name="radiusInXDirection">the length of the x axis of the corner smoothing ellipse</param>
        /// <param name="radiusInYDirection">the length of the y axis of the corner smoothing ellipse</param>
        /// <param name="center">the rectangle center</param>
        /// <returns></returns>
        static internal void CreateRectangleWithRoundedCorners(Curve c, double width, double height, double radiusInXDirection, double radiusInYDirection, Point center)
        {
            if (radiusInXDirection == 0 || radiusInYDirection == 0)
            {
                CreateRectangle(c, width, height, center);
                return;
            }
            double w = width / 2;
            if (radiusInXDirection > w/2)
                radiusInXDirection = w/2;
            double h = height / 2;
            if (radiusInYDirection > h/2)
                radiusInYDirection = h/2;
            double x = center.X;
            double y = center.Y;
            double ox = w - radiusInXDirection;
            double oy = h - radiusInYDirection;
            double top = y + h;
            double bottom = y - h;
            double left = x - w;
            double right = x + w;
            //ellipse's axises
            Point a = new Point(radiusInXDirection, 0);
            Point b = new Point(0, radiusInYDirection);

            c.IncreaseSegmentCapacity(8);

            if (ox > 0)
                c.AddSegment(new LineSegment(new Point(x - ox, bottom), new Point(x + ox, bottom)));
            c.AddSegment(new Ellipse(1.5 * Math.PI, 2 * Math.PI, a, b, x + ox, y - oy));
            if (oy > 0)
                c.AddSegment(new LineSegment(new Point(right, y - oy), new Point(right, y + oy)));
            c.AddSegment(new Ellipse(0, 0.5 * Math.PI, a, b, x + ox, y + oy));
            if (ox > 0)
                c.AddSegment(new LineSegment(new Point(x + ox, top), new Point(x - ox, top)));
            c.AddSegment(new Ellipse(0.5 * Math.PI, Math.PI, a, b, x - ox, y + oy));
            if (oy > 0)
                c.AddSegment(new LineSegment(new Point(left, y + oy), new Point(left, y - oy)));
            c.AddSegment(new Ellipse(Math.PI, 1.5 * Math.PI, a, b, x - ox, y - oy));
        }
         ICurve TrimEntryCurve(Tuple<double, double> span) {
            var start = span.Item1;
            var end = span.Item2;
            if (start < end) {
                return this.EntryCurve.Trim(start, end);
            }
            
            // For the classes that implement it, wrap the Trim.
            if ((this.EntryCurve is Polyline) || (this.EntryCurve is Curve) || (this.EntryCurve is RoundedRect)) {
                return this.EntryCurve.TrimWithWrap(start, end);
            }

            // Ellipse does not (yet) support TrimWithWrap but for our purposes we can deal with it as a Curve.
            if (this.EntryCurve is Ellipse) {
                var c = new Curve();
                c.AddSegment(this.EntryCurve.Trim(start, this.EntryCurve.ParEnd));
                c.AddSegment(this.EntryCurve.Trim(this.EntryCurve.ParStart, end));
                return c;
            }

            // For the remaining implementations of ICurve, this is what Trim does if start is greater than end, unless it throws.
            return this.EntryCurve.Trim(end, start);
        }
 private Curve ReadCurve()
 {
     var c = new Curve();
     Match m;
     while ((m = ParseNextOrDone(RectFileStrings.ParseSegment, RectFileStrings.EndCurve)).Success)
     {
         c.AddSegment(LoadLineSegment(m));
     }
     return c;
 }
        //   static int calls;
        // bool debug { get { return calls == 5;} }

        Curve Poly() {
            Curve c = new Curve();
            for (Site s = this.headSite; s.Next != null; s = s.Next)
                c.AddSegment(new CubicBezierSegment(s.Point, 2 * s.Point / 3 + s.Next.Point / 3, s.Point / 3 + 2 * s.Next.Point / 3, s.Next.Point));
            return c;
        }
 void ProceedWithLines(Curve curve, CurveStream curveStream, ref Point currentPoint) {
     do {
         curve.AddSegment(new LineSegment(currentPoint, currentPoint = GetNextPointFromCurveData(curveStream)));
     } while (curveStream.PickNextCurveStreamElement() is DoubleStreamElement);
 }
        /// <summary>
        /// Routes a self edge inside the given "howMuchToStickOut" parameter
        /// </summary>
        /// <param name="boundaryCurve"></param>
        /// <param name="howMuchToStickOut"></param>
        /// <returns></returns>
        static internal ICurve RouteSelfEdgeAtSide(ICurve boundaryCurve, double howMuchToStickOut)
        {
            //we just need to find the box of the corresponding node
            var w = boundaryCurve.BoundingBox.Width;
            var h = boundaryCurve.BoundingBox.Height;
            var center = boundaryCurve.BoundingBox.Center;

            var p0 = new Point(center.X, center.Y - h / 4);
            var p1 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y - h / 4);
            var p2 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y);
            var p3 = new Point(center.X - w / 2 - howMuchToStickOut, center.Y + h / 4);
            var p4 = new Point(center.X, center.Y + h / 4);

            var curve = new Curve();
            curve.AddSegment(new CubicBezierSegment(p0, p1, p1, p2));
            curve.AddSegment(new CubicBezierSegment(p2, p3, p3, p4));
            return curve;
        }
 static ICurve CreatObstaceOnLabel(Label label) {
     var c = new Curve();
     double obstacleBottom = label.Center.Y - label.Height/4;
     c.AddSegment(new LineSegment(new Point(label.BoundingBox.Left, obstacleBottom),
                                  new Point(label.BoundingBox.Right, obstacleBottom)));
     Curve.ContinueWithLineSegment(c, label.BoundingBox.RightTop);
     Curve.ContinueWithLineSegment(c, label.BoundingBox.LeftTop);
     Curve.CloseCurve(c);
     return c;
 }
        static Curve TrimCurve(Curve curve, double u, double v) {
            Debug.Assert(u >= curve.ParStart && u <= curve.ParEnd);
            Debug.Assert(v >= curve.ParStart && v <= curve.ParEnd);
            if (u < v)
                return curve.Trim(u, v) as Curve;

            var c = new Curve();
            c.AddSegment(curve.Trim(u, curve.ParEnd) as Curve);
            c.AddSegment(curve.Trim(curve.ParStart, v) as Curve);
            return c;
        }
 /// <summary>
 /// Convert points to line curve
 /// </summary>
 internal static Curve CreateLineCurve(List<Point> route) {
     ValidateArg.IsNotNull(route, "route");
     var curve = new Curve(route.Count);
     for (int i = 0; i + 1 < route.Count; i++) curve.AddSegment(new LineSegment(route[i], route[i + 1]));
     return curve;
 }
        private void AddSmoothedCorner(Site a, Site b, Site c, Curve curve) {
            double k = 0.5;
            CubicBezierSegment seg;
            do {
                seg = Curve.CreateBezierSeg(k, k, a, b, c);
                //if (Routing.db)
                //    LayoutAlgorithmSettings .Show(seg, CreatePolyTest());
                b.PreviousBezierSegmentFitCoefficient = k;
                k /= 2;
            } while (BezierSegIntersectsBoundary(seg));

            k *= 2; //that was the last k
            if (k < 0.5) {//one time try a smoother seg
                k = 0.5 * (k + k * 2);
                CubicBezierSegment nseg = Curve.CreateBezierSeg(k, k, a, b, c);
                if (!BezierSegIntersectsBoundary(nseg)) {
                    b.PreviousBezierSegmentFitCoefficient = b.NextBezierSegmentFitCoefficient = k;
                    seg = nseg;
                }
            }

            if (curve.Segments.Count > 0 && !ApproximateComparer.Close(curve.End, seg.Start))
                curve.AddSegment(new LineSegment(curve.End, seg.Start));
            curve.AddSegment(seg);
        }
 ///<summary>
 ///adds a line segment to the curve
 ///</summary>
 ///<param name="curve"></param>
 ///<param name="pointA"></param>
 ///<param name="pointB"></param>
 ///<returns></returns>
 public static Curve AddLineSegment(Curve curve, Point pointA, Point pointB) {
     ValidateArg.IsNotNull(curve, "curve");
     return curve.AddSegment(new LineSegment(pointA, pointB));
 }
        /// <summary>
        /// Returns the trimmed curve, wrapping around the end if start is greater than end.
        /// </summary>
        /// <param name="start">The starting parameter</param>
        /// <param name="end">The ending parameter</param>
        /// <returns>The trimmed curve</returns>
        public ICurve TrimWithWrap(double start, double end) {
            Debug.Assert(start >= ParStart && start <= ParEnd);
            Debug.Assert(end >= ParStart && end <= ParEnd);
            if (start < end)
                return Trim(start, end) as Curve;

            Debug.Assert(ApproximateComparer.Close(Start, End), "Curve must be closed to wrap");
            var c = new Curve();
            c.AddSegment(Trim(start, ParEnd) as Curve);
            c.AddSegment(Trim(ParStart, end) as Curve);
            return c;
        }
        ///// <summary>
        ///// //sort intersections by the a parameter
        ///// </summary>
        ///// <param name="dictionary"></param>
        ///// <param name="coeff"></param>
        ///// <param name="side1"></param>
        //internal static void AddRealIntersectionsToDictionaryForClosedCurve(SortedDictionary<double, IntersectionInfo> dictionary, ICurve coeff, Curve side1) {
        //    StopIntersect si = new StopIntersect((new XExaminer(dictionary, coeff, side1)).IntersectionExaminerForClosedCurveWithIntersectionLifting);
        //    Curve.GetAllIntersections(coeff, side1, si, true);
        //}

        //internal static void AddRealIntersectionsWithTreeToDictionaryForClosedCurves(SortedDictionary<double, IntersectionInfo> dictionary, ICurve coeff, ParallelogramNode bound) {
        //    if( Parallelogram.Intersect( coeff.ParallelogramNodeOverICurve.Parallelogram, bound.Parallelogram)){
        //        ParallelogramBinaryTreeNode treeNode = bound as ParallelogramBinaryTreeNode;
        //        if (treeNode != null) {
        //            AddRealIntersectionsWithTreeToDictionaryForClosedCurves(dictionary, coeff, treeNode.LeftSon);
        //            AddRealIntersectionsWithTreeToDictionaryForClosedCurves(dictionary, coeff, treeNode.RightSon);
        //        } else 
        //            AddRealIntersectionsToDictionaryForClosedCurve(dictionary, coeff, (Curve)((ParallelogramNodeOverICurve)bound).Seg);
        //    }
        //}

        #region ICurve Members

        /// <summary>
        /// clones the curve. 
        /// </summary>
        /// <returns>the cloned curve</returns>
        public ICurve Clone() {
            var c = new Curve(Segments.Count);
            foreach (ICurve seg in Segments)
                c.AddSegment(seg.Clone());
            return c;
        }
        /// <summary>
        /// Returns the trim curve
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public ICurve Trim(double start, double end) {
            AdjustStartEndEndParametersToDomain(ref start, ref end);

            int sseg;
            double spar;

            GetSegmentAndParameter(start, out spar, out sseg);

            int eseg;
            double epar;

            GetSegmentAndParameter(end, out epar, out eseg);

            if (sseg == eseg)
                return Segments[sseg].Trim(spar, epar);

            var c = new Curve(eseg-sseg+1);

            if (spar < Segments[sseg].ParEnd)
                c = c.AddSegment(Segments[sseg].Trim(spar, Segments[sseg].ParEnd));

            for (int i = sseg + 1; i < eseg; i++)
                c = c.AddSegment(Segments[i]);

            if (Segments[eseg].ParStart < epar)
                c = c.AddSegment(Segments[eseg].Trim(Segments[eseg].ParStart, epar));

            return c;
        }
 /// <summary>
 /// this[Reverse[t]]=this[ParEnd+ParStart-t]
 /// </summary>
 /// <returns></returns>
 public ICurve Reverse() {
     var ret = new Curve(segs.Count);
     for (int i = segs.Count - 1; i >= 0; i--)
         ret.AddSegment(segs[i].Reverse());
     return ret;
 }
 Curve CreateSmoothedPolyline() {
     RemoveVerticesWithNoTurns();
     Curve curve = new Curve();
     Site a = headSite;//the corner start
     Site b; //the corner origin
     Site c;//the corner other end
     if (Curve.FindCorner(a, out b, out c)) {
         CreateFilletCurve(curve, ref a, ref b, ref c);
         curve = ExtendCurveToEndpoints(curve);
     } else
         curve.AddSegment(new LineSegment(EdgePathPoint(0), EdgePathPoint(edgePath.Count)));
     return curve;
 }
Esempio n. 18
0
        public void ClosestParameterWithinBounds() {
#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                DisplayGeometryGraph.SetShowFunctions();
            }
#endif
            var ellipse = CurveFactory.CreateEllipse(8, 10, new Point());
            var point = new Point(20, 1);
            var t = ellipse.ClosestParameter(point);
            var low = t - 1;
            var high = t + 1;
            var t1 = ellipse.ClosestParameterWithinBounds(point, low, high);
#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(100, 0.1, "black", ellipse),
                        new DebugCurve(100, 0.01, "brown", new LineSegment(ellipse[t], point)),
                        new DebugCurve(100, 0.01, "green", new LineSegment(ellipse[t1], point)));
            }
#endif
            var dist = point - ellipse[t];
            var dist1 = point - ellipse[t1];
            Assert.IsTrue(ApproximateComparer.Close(dist.Length, dist1.Length) && ApproximateComparer.Close(t, t1));
#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(ellipse), new DebugCurve("red", new LineSegment(point, ellipse[t])));
            }
#endif

            var curve = new Curve();
            curve.AddSegment(new LineSegment(new Point(-10, -10), new Point(10, -10)));
            curve.AddSegment(new Ellipse(0, Math.PI / 2, new Point(0, -10), new Point(10, 0), new Point(10, 0)));
            Curve.ContinueWithLineSegment(curve, new Point(20, 10));
            curve.AddSegment(new CubicBezierSegment(curve.End, new Point(20, 20), new Point(15, 25), new Point(10, 25)));
            Curve.ContinueWithLineSegment(curve, new Point(-10, 25));
            Point p = new Point(11, 0);
            t = curve.ClosestParameter(p);

#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(curve), new DebugCurve("red", new LineSegment(p, curve[t])));
            }
#endif
            t1 = curve.ClosestParameterWithinBounds(p, 1 + Math.PI / 4, 2);
#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(curve), new DebugCurve("red", new LineSegment(p, curve[t1])));
            }
#endif
            Assert.IsTrue(t1 < t);
            p = new Point(30, 30);
            t = curve.ClosestParameter(p);
            t1 = curve.ClosestParameterWithinBounds(p, t - 0.5, t + 0.5);
            Assert.IsTrue(t > 1 + Math.PI / 2 + 1 && t < 1 + Math.PI / 2 + 2);
            Assert.IsTrue(ApproximateComparer.Close(t, t1));

            var poly = new Polyline(new Point(0, 0), new Point(10, 0), new Point(20, 10));
            p = new Point(9, 9);
            const double l = 0.7;
            const double h = 1.3;
            t = poly.ClosestParameterWithinBounds(p, l, h);
#if GDI_DEBUG_VIEWER
            if (!MsaglTestBase.DontShowTheDebugViewer()) {
                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(poly), new DebugCurve("red", new LineSegment(p, poly[t])));
            }
#endif
            var d = (p - poly[t]).Length;

            Assert.IsTrue(d <= (p - poly[l]).Length + ApproximateComparer.Tolerance && d < (p - poly[h]).Length + ApproximateComparer.Tolerance && d < (p - poly[(l + h) / 2]).Length + ApproximateComparer.Tolerance);
        }
 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;
 }
        internal static ICurve FitArcsIntoCorners(double radius, Point[] polyline) {
            IEnumerable<Ellipse> ellipses = GetFittedArcSegs(radius, polyline);
            var curve = new Curve(polyline.Length);
            Ellipse prevEllipse = null;
            foreach (Ellipse ellipse in ellipses) {
                bool ellipseIsAlmostCurve = EllipseIsAlmostLineSegment(ellipse);

                if (prevEllipse != null) {
                    if (ellipseIsAlmostCurve)
                        Curve.ContinueWithLineSegment(curve, CornerPoint(ellipse));
                    else {
                        Curve.ContinueWithLineSegment(curve, ellipse.Start);
                        curve.AddSegment(ellipse);
                    }
                } else {
                    if (ellipseIsAlmostCurve)
                        Curve.AddLineSegment(curve, polyline[0], CornerPoint(ellipse));
                    else {
                        Curve.AddLineSegment(curve, polyline[0], ellipse.Start);
                        curve.AddSegment(ellipse);
                    }
                }

                prevEllipse = ellipse;
            }

            if (curve.Segments.Count > 0)
                Curve.ContinueWithLineSegment(curve, polyline[polyline.Length - 1]);
            else
                Curve.AddLineSegment(curve, polyline[0], polyline[polyline.Length - 1]);

            return curve;
        }
 /// <summary>
 /// create a triangle inside the box formed by width and height.
 /// </summary>
 /// <param name="width"></param>
 /// <param name="height"></param>
 /// <param name="center"></param>
 /// <returns></returns>
 static public ICurve CreateInteriorTriangle(double width, double height, Point center) {
     double w = width / 2;
     double h = height / 2;
     double x = center.X;
     double y = center.Y;
     Curve c = new Curve(3);
     Point[] p = new Point[] { new Point(x - w, y - h), new Point(x + w, y - h), new Point(x, y + h) };
     c.AddSegment(new LineSegment(p[0], p[1]));
     c.AddSegment(new LineSegment(p[1], p[2]));
     c.AddSegment(new LineSegment(p[2], p[0]));
     return c;
 }
 static void AddBezieSegsToEdgeFromPosData(Edge edge, List<P2> list) {
     var curve = new Curve();
     for (int i = 0; i + 3 < list.Count; i += 3)
         curve.AddSegment(new CubicBezierSegment(list[i], list[i + 1], list[i + 2], list[i + 3]));
     InitGeomEdge(edge);
     edge.GeometryEdge.Curve = curve;
 }
 private ICurve BoundingBoxCurve(ref Rectangle rectangle)
 {
     Curve c = new Curve();
     c.AddSegment(new LineSegment(rectangle.LeftTop, rectangle.LeftBottom));
     Curve.ContinueWithLineSegment(c, rectangle.RightBottom);
     Curve.ContinueWithLineSegment(c, rectangle.RightTop);
     Curve.CloseCurve(c);
     return c;
 }
 void AddCurveSegment(CurveStream curveStream, char c, Curve curve, ref Point currentPoint) {
     switch (c) {
         case 'M': //moveto
             currentPoint = GetNextPointFromCurveData(curveStream);
             break;
         case 'm': //relative moveto
             throw new NotImplementedException();
         case 'Z':
         case 'z': //closepath
             if (curve.Segments.Count == 0)
                 Error("the curve is too short");
             curve.AddSegment(new LineSegment(currentPoint, currentPoint = curve.Start));
             break;
         case 'L': //lineto
             ProceedWithLines(curve, curveStream, ref currentPoint);
             break;
         case 'l': //lineto relative
             throw new NotImplementedException();
         case 'H': //lineto horizontal
             throw new NotImplementedException();
         case 'h': //lineto horizontal relative
             throw new NotImplementedException();
         case 'V': //lineto vertical
             throw new NotImplementedException();
         case 'v': //lineto vertical relative
             throw new NotImplementedException();
         case 'C': //cubic Bezier
             ProceedWithCubicBeziers(curve, curveStream, ref currentPoint);
             break;
         case 'c': //cubic Bezier relative
             throw new NotImplementedException();
         case 'S': //cubic Bezier shorthand
             throw new NotImplementedException();
         case 's': //cubic Bezier relative shorthand
             throw new NotImplementedException();
         case 'Q': //quadratic Bezier
             throw new NotImplementedException();
         case 'q': //quadratic Bezier relative
             throw new NotImplementedException();
         case 'T': //quadratic Bezier shorthand
             throw new NotImplementedException();
         case 't': //quadratic Bezier relative shorthand
             throw new NotImplementedException();
         case 'A': //elleptical arc
             ReadEllepticalArc(curve, curveStream, ref currentPoint);
             break;
         case 'a': //eleptical arc relative
             throw new NotImplementedException();
         default:
             Error("unknown character " + c);
             break;
     }
 }
 void ReadEllepticalArc(Curve curve, CurveStream curveStream, ref Point currentPoint) {
     curve.AddSegment(ReadEllepticalArc(curveStream, ref currentPoint));
 }
 internal static Shape CurveFromPoints(Point[] points)
 {
     var curve = new Curve();
     for (int ii = 0; ii < points.Length - 1; ++ii)
     {
         curve.AddSegment(new LineSegment(points[ii], points[ii + 1]));
     }
     curve.AddSegment(new LineSegment(points[points.Length - 1], points[0]));
     return new Shape(curve);
 }