/// <summary>
 /// Create a rounded rectangle geometry
 /// </summary>
 /// <param name="bounds">rounded rectangle will fit these bounds</param>
 /// <param name="radiusX">horizontal radius of the corner ellipse segments</param>
 /// <param name="radiusY">vertical radius of the corner ellipse segments</param>
 public RoundedRect(Rectangle bounds, double radiusX, double radiusY) {
     RadiusX = radiusX;
     RadiusY = radiusY;
     curve = new Curve(8);
     CurveFactory.CreateRectangleWithRoundedCorners(curve,
         bounds.Width, bounds.Height, radiusX, radiusY, bounds.Center);
 }
 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 void VerifyPolylines()
 {
     // Is this still needed?
     foreach (DEdge e in Edges.Concat(m_CrossEdges))
     {
         var edge = e.GeometryEdge;
         if (edge.UnderlyingPolyline != null)
             continue;
         if (edge.Curve == null)
             continue;
         Curve c = edge.Curve as Curve;
         if (c == null)
         {
             c = new Curve();
             c.Segments.Add(edge.Curve);
         }
         edge.UnderlyingPolyline = Microsoft.Msagl.Core.Geometry.SmoothedPolyline.FromPoints(new[] { edge.Source.Center }.Concat(PolylineFromCurve(c)).Concat(new[] { edge.Target.Center }));
     }
 }
 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;
 }
 private static MsaglPolyline PolylineFromCurve(Curve curve)
 {
     var ret = new MsaglPolyline();
     ret.AddPoint(curve.Start);
     foreach (var ls in curve.Segments)
         ret.AddPoint(ls.End);
     ret.Closed = curve.Start == curve.End;
     return ret;
 }
 internal ICurve CreateBoundary() {
     double w = Width/2;
     double h = Height/2;
     Curve curve = new Curve();
     Curve.AddLineSegment(curve, Center.X - w, Center.Y - h, Center.X - w, Center.Y + h);
     Curve.ContinueWithLineSegment(curve, Center.X + w, Center.Y + h);
     Curve.ContinueWithLineSegment(curve, Center.X + w, Center.Y - h);
     Curve.CloseCurve(curve);
     return curve;
 }
        /// <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;
        }
 static void FillContexForCurve(StreamGeometryContext context,Curve c) {
     foreach(ICurve seg in c.Segments) {
         var bezSeg = seg as CubicBezierSegment;
         if(bezSeg != null) {
             context.BezierTo(Common.WpfPoint(bezSeg.B(1)),
                              Common.WpfPoint(bezSeg.B(2)),Common.WpfPoint(bezSeg.B(3)),true,false);
         } else {
             var ls = seg as LineSegment;
             if(ls != null)
                 context.LineTo(Common.WpfPoint(ls.End),true,false);
             else {
                 var ellipse = seg as Ellipse;
                 if(ellipse != null) {
                     //       context.LineTo(Common.WpfPoint(ellipse.End),true,false);
                     double sweepAngle = EllipseSweepAngle(ellipse);
                     bool largeArc = Math.Abs(sweepAngle) >= Math.PI;
                     Rectangle box = ellipse.FullBox();
                     context.ArcTo(Common.WpfPoint(ellipse.End),
                                   new Size(box.Width / 2,box.Height / 2),
                                   sweepAngle,
                                   largeArc,
                                   sweepAngle < 0
                                       ? SweepDirection.Counterclockwise
                                       : SweepDirection.Clockwise,
                                   true,true);
                 } else
                     throw new NotImplementedException();
             }
         }
     }
 }
 void WriteCurveGeometry(Curve curve)
 {
     WriteAttribute("d", CurveString(curve));
 }
 /// <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 curve resembling a house within the rectangle formed by width and height at center
 /// (if the rectangle is a square, the house has the shape of home plate in baseball).
 /// </summary>
 /// <param name="width">the bounding rectangle width</param>
 /// <param name="height">the bounding rectangle height</param>
 /// <param name="center">the bounding rectangle center</param>
 /// <returns></returns>
 static public ICurve CreateInteriorHouse(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(4);
     Curve.AddLineSegment(c, x - w, y - h, x + w, y - h);
     Curve.ContinueWithLineSegment(c, x + w, y);
     Curve.ContinueWithLineSegment(c, x, y + h);
     Curve.ContinueWithLineSegment(c, x - w, y);
     Curve.CloseCurve(c);
     return c;
 }
 static ICurve MakeShapeCurve(Point center, int width, int height) {
     var r = new Rectangle(center) {Width = width, Height = height};
     var c = new Curve();
     Curve.AddLineSegment(c, r.LeftBottom, r.LeftTop);
     Curve.ContinueWithLineSegment(c, r.RightTop);
     Curve.ContinueWithLineSegment(c, r.RightBottom);
     Curve.CloseCurve(c);
     return c;
 }
Exemple #15
0
 internal static void CreateGraphicsPathFromCurve(PathFigure pathFigure, Curve curve)
 {
     foreach (var seg in curve.Segments)
     {
         var bezSeg = seg as CubicBezierSegment;
         if (bezSeg != null)
             pathFigure.Segments.Add(new BezierSegment
             {
                 Point1 = WinPoint(bezSeg.B(1)),
                 Point2 = WinPoint(bezSeg.B(2)),
                 Point3 = WinPoint(bezSeg.B(3))
             });
         else
         {
             var ls = seg as MsaglLineSegment;
             if (ls != null)
                 pathFigure.Segments.Add(new WinLineSegment() { Point = WinPoint(ls.End) });
             else
             {
                 var ellipse = seg as Ellipse;
                 if (ellipse != null)
                     pathFigure.Segments.Add(
                         new ArcSegment()
                         {
                             Size = new WinSize(ellipse.AxisA.Length, ellipse.AxisB.Length),
                             SweepDirection = SweepDirection.Clockwise,
                             Point = WinPoint(ellipse.End)
                         });
                 else
                     throw new InvalidOperationException();
             }
         }
     }
 }
Exemple #16
0
 static void AddCurve(PathFigure pathFigure, Point c, Curve curve)
 {
     foreach (ICurve seg in curve.Segments) {
         var ls = seg as LineSegment;
         if (ls != null)
             pathFigure.Segments.Add(new System.Windows.Media.LineSegment(CommonX.WpfPoint(ls.End - c), true));
         else {
             var ellipse = seg as Ellipse;
             pathFigure.Segments.Add(new ArcSegment(CommonX.WpfPoint(ellipse.End - c),
                                                    new Size(ellipse.AxisA.Length, ellipse.AxisB.Length),
                                                    Point.Angle(new Point(1, 0), ellipse.AxisA),
                                                    ellipse.ParEnd - ellipse.ParEnd >= Math.PI,
                                                    !ellipse.OrientedCounterclockwise()
                                                        ? SweepDirection.Counterclockwise
                                                        : SweepDirection.Clockwise, true));
         }
     }
 }
        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);
        }
 private void CreateFilletCurve(Curve curve, ref Site a, ref Site b, ref Site c) {
     do {
         AddSmoothedCorner(a, b, c, curve);
         a = b;
         b = c;
         if (b.Next != null)
             c = b.Next;
         else
             break;
     } while (true);
 }
 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;
 }
 /// <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;
 }
        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>
 /// testing, don't use
 /// </summary>
 /// <param name="width"></param>
 /// <param name="height"></param>
 /// <returns></returns>
 public static ICurve CreateTestShape(double width, double height ) {
     int mult = 1;
     double w = width *3;
     double h = height *3;
     Curve curve = new Curve(9);
     Curve.AddLineSegment(curve,  - w,  - h,  0,  -h/2);
     Curve.ContinueWithLineSegment(curve, w / 2, -0.75 * h);
     Curve.ContinueWithLineSegment(curve, w, -h);
     Curve.ContinueWithLineSegment(curve, 0.75 * w, -h / 2);
     Curve.ContinueWithLineSegment(curve, w / 2, 0);
     Curve.ContinueWithLineSegment(curve,  w,  h);
    
     Curve.ContinueWithLineSegment(curve, 0, h / 2);
     Curve.ContinueWithLineSegment(curve, -w, mult * h);
     Curve.ContinueWithLineSegment(curve, -w / 3, 0);
     Curve.CloseCurve(curve);
     return curve;
 }
        void WriteCurve(Curve curve, Node node)
        {
            WriteStartElement("path");
            WriteFillAndStroke(node.Attr);
            WriteCurveGeometry(curve);
            WriteEndElement();

        }
 Curve CreatePolyTest() {
     Curve c = new Curve();
     IEnumerator<Point> e = new PointNodesList(this.headSite);
     e.MoveNext();
     Point p = e.Current;
     while (e.MoveNext()) {
         Curve.AddLineSegment(c, p, e.Current);
         p = e.Current;
     }
     return c;
 }
 void WriteCurveInSvgStyle(Curve curve) {
     WriteStartElement(GeometryToken.Curve);
     WriteAttribute( GeometryToken.CurveData, CurveString(curve));   
     WriteEndElement();
 }
        //   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;
        }
 private void WriteCurve(Shape shape, Curve curve)
 {
     this.outputFileWriter.WriteLine(RectFileStrings.BeginCurve);
     if (null != shape)
     {
         // If a path, this is null
         this.outputFileWriter.WriteLine(RectFileStrings.WriteId, shapeToIdMap[shape]);
     }
     foreach (var seg in curve.Segments)
     {
         this.outputFileWriter.WriteLine(RectFileStrings.WriteSegment, seg.Start.X, seg.Start.Y, seg.End.X, seg.End.Y);
     }
     this.outputFileWriter.WriteLine(RectFileStrings.EndCurve);
 }
Exemple #28
0
 internal static void CreateGraphicsPathFromCurve(PathFigure pathFigure, Curve curve)
 {
     foreach (ICurve seg in curve.Segments)
     {
         if (seg is CubicBezierSegment)
         {
             var bezSeg = seg as CubicBezierSegment;
             pathFigure.Segments.Add(new BezierSegment
             {
                 Point1 = WinPoint(bezSeg.B(1)),
                 Point2 = WinPoint(bezSeg.B(2)),
                 Point3 = WinPoint(bezSeg.B(3))
             });
         }
         else if (seg is Ellipse)
         {
             var ellipse = seg as Ellipse;
             pathFigure.Segments.Add(new ArcSegment()
             {
                 Size = new WinSize(ellipse.AxisA.Length, ellipse.AxisB.Length),
                 SweepDirection = ellipse.OrientedCounterclockwise() ? SweepDirection.Clockwise : SweepDirection.Counterclockwise,
                 Point = WinPoint(ellipse.End)
             });
         }
         else
             pathFigure.Segments.Add(new WinLineSegment() { Point = WinPoint(seg.End) });
     }
 }
 /// <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;
 }
 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;
 }