예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool TryToConnectPoint3(XArc arc, double x, double y)
        {
            var result = ShapeBounds.HitTest(_editor.Project.CurrentContainer, new Vector2(x, y), _editor.Project.Options.HitTreshold);

            if (result != null && result is XPoint)
            {
                arc.Point3 = result as XPoint;
                return(true);
            }
            return(false);
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static Rect2 GetArcBounds(XArc arc, double dx, double dy)
        {
            double x1 = arc.Point1.X + dx;
            double y1 = arc.Point1.Y + dy;
            double x2 = arc.Point2.X + dx;
            double y2 = arc.Point2.Y + dy;

            double x0 = (x1 + x2) / 2.0;
            double y0 = (y1 + y2) / 2.0;

            double r      = Math.Sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
            double x      = x0 - r;
            double y      = y0 - r;
            double width  = 2.0 * r;
            double height = 2.0 * r;

            return(new Rect2(x, y, width, height));
        }
예제 #3
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static Rect2 GetArcBounds(XArc arc, double dx, double dy)
        {
            double x1 = arc.Point1.X + dx;
            double y1 = arc.Point1.Y + dy;
            double x2 = arc.Point2.X + dx;
            double y2 = arc.Point2.Y + dy;

            double x0 = (x1 + x2) / 2.0;
            double y0 = (y1 + y2) / 2.0;

            double r = Math.Sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
            double x = x0 - r;
            double y = y0 - r;
            double width = 2.0 * r;
            double height = 2.0 * r;

            return new Rect2(x, y, width, height);
        }
예제 #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object gfx, XArc arc, double dx, double dy, ImmutableArray <ShapeProperty> db, Record r)
        {
            var a = GdiArc.FromXArc(arc, dx, dy);

            if (a.Width <= 0.0 || a.Height <= 0.0)
            {
                return;
            }

            var _gfx = gfx as Graphics;

            Brush brush = ToSolidBrush(arc.Style.Fill);
            Pen   pen   = ToPen(arc.Style, _scaleToPage);

            if (arc.IsFilled)
            {
                var path = new GraphicsPath();
                path.AddArc(
                    _scaleToPage(a.X),
                    _scaleToPage(a.Y),
                    _scaleToPage(a.Width),
                    _scaleToPage(a.Height),
                    (float)a.StartAngle,
                    (float)a.SweepAngle);
                _gfx.FillPath(brush, path);
            }

            if (arc.IsStroked)
            {
                _gfx.DrawArc(
                    pen,
                    _scaleToPage(a.X),
                    _scaleToPage(a.Y),
                    _scaleToPage(a.Width),
                    _scaleToPage(a.Height),
                    (float)a.StartAngle,
                    (float)a.SweepAngle);
            }

            brush.Dispose();
            pen.Dispose();
        }
예제 #5
0
        /// <summary>
        /// Creates a new instance of the XArc class.
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="point2"></param>
        /// <param name="point3"></param>
        /// <param name="point4"></param>
        /// <param name="isStroked"></param>
        /// <param name="isFilled"></param>
        /// <returns></returns>
        public XArc Arc(
            XPoint point1,
            XPoint point2,
            XPoint point3,
            XPoint point4,
            bool isStroked = true,
            bool isFilled  = false)
        {
            var arc = XArc.Create(
                point1,
                point2,
                point3,
                point4,
                Context.Editor.Project.CurrentStyleLibrary.CurrentStyle,
                Context.Editor.Project.Options.PointShape,
                isStroked,
                isFilled);

            Context.Editor.AddWithHistory(arc);
            return(arc);
        }
예제 #6
0
        /// <summary>
        /// Creates a new instance of the XArc class.
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="x3"></param>
        /// <param name="y3"></param>
        /// <param name="x4"></param>
        /// <param name="y4"></param>
        /// <param name="isStroked"></param>
        /// <param name="isFilled"></param>
        /// <returns></returns>
        public XArc Arc(
            double x1      = 30, double y1 = 30,
            double x2      = 60, double y2 = 60,
            double x3      = 30, double y3 = 45,
            double x4      = 60, double y4 = 45,
            bool isStroked = true,
            bool isFilled  = false)
        {
            var arc = XArc.Create(
                x1, y1,
                x2, y2,
                x3, y3,
                x4, y4,
                Context.Editor.Project.CurrentStyleLibrary.CurrentStyle,
                Context.Editor.Project.Options.PointShape,
                isStroked,
                isFilled);

            Context.Editor.AddWithHistory(arc);
            return(arc);
        }
예제 #7
0
파일: WpfArc.cs 프로젝트: hacklex/Core2D
        /// <summary>
        /// 
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static WpfArc FromXArc(XArc arc, double dx, double dy)
        {
            var p1 = Point2.Create(arc.Point1.X + dx, arc.Point1.Y + dy);
            var p2 = Point2.Create(arc.Point2.X + dx, arc.Point2.Y + dy);
            var p3 = Point2.Create(arc.Point3.X + dx, arc.Point3.Y + dy);
            var p4 = Point2.Create(arc.Point4.X + dx, arc.Point4.Y + dy);
            var rect = Rect2.Create(p1, p2);
            var center = Point2.Create(rect.X + rect.Width / 2.0, rect.Y + rect.Height / 2.0);
            double offsetX = center.X - rect.X;
            double offsetY = center.Y - rect.Y;

            double minLenght = Math.Max(offsetX, offsetY);

            double length1 = center.Distance(p3);
            double p3x = p3.X + (p3.X - center.X) / length1 * minLenght;
            double p3y = p3.Y + (p3.Y - center.Y) / length1 * minLenght;

            double length2 = center.Distance(p4);
            double p4x = p4.X + (p4.X - center.X) / length2 * minLenght;
            double p4y = p4.Y + (p4.Y - center.Y) / length2 * minLenght;

            p3.X = p3x;
            p3.Y = p3y;
            p4.X = p4x;
            p4.Y = p4y;

            var p3i = MathHelpers.FindEllipseSegmentIntersections(rect, center, p3, true);
            var p4i = MathHelpers.FindEllipseSegmentIntersections(rect, center, p4, true);
            Point2 start;
            Point2 end;

            if (p3i.Count == 1)
                start = p3i.FirstOrDefault();
            else
                start = Point2.Create(p3.X, p3.Y);

            if (p4i.Count == 1)
                end = p4i.FirstOrDefault();
            else
                end = Point2.Create(p4.X, p4.Y);

            double angle = MathHelpers.AngleLineSegments(center, start, center, end);
            bool isLargeArc = angle > 180.0;

            double helperLenght = 60.0;

            double lengthStart = center.Distance(start);
            double p3hx = start.X + (start.X - center.X) / lengthStart * helperLenght;
            double p3hy = start.Y + (start.Y - center.Y) / lengthStart * helperLenght;

            double lengthEnd = center.Distance(end);
            double p4hx = end.X + (end.X - center.X) / lengthEnd * helperLenght;
            double p4hy = end.Y + (end.Y - center.Y) / lengthEnd * helperLenght;

            p3.X = p3hx;
            p3.Y = p3hy;
            p4.X = p4hx;
            p4.Y = p4hy;

            return new WpfArc()
            {
                P1 = p1,
                P2 = p2,
                P3 = p3,
                P4 = p4,
                Rect = rect,
                Center = center,
                Start = start,
                End = end,
                Radius = Size2.Create(offsetX, offsetY),
                IsLargeArc = isLargeArc,
                Angle = angle
            };
        }
예제 #8
0
파일: GdiArc.cs 프로젝트: hacklex/Core2D
 /// <summary>
 /// 
 /// </summary>
 /// <param name="arc"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static GdiArc FromXArc(XArc arc, double dx, double dy)
 {
     return FromXArc(arc.Point1, arc.Point2, arc.Point3, arc.Point4, dx, dy);
 }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public override void LeftDown(double x, double y)
        {
            double sx = _editor.Project.Options.SnapToGrid ? Editor.Snap(x, _editor.Project.Options.SnapX) : x;
            double sy = _editor.Project.Options.SnapToGrid ? Editor.Snap(y, _editor.Project.Options.SnapY) : y;

            switch (_currentState)
            {
            case State.None:
            {
                _connectedP3 = false;
                _connectedP4 = false;
                _shape       = XArc.Create(
                    sx, sy,
                    _editor.Project.CurrentStyleLibrary.CurrentStyle,
                    _editor.Project.Options.PointShape,
                    _editor.Project.Options.DefaultIsStroked,
                    _editor.Project.Options.DefaultIsFilled);
                if (_editor.Project.Options.TryToConnect)
                {
                    TryToConnectPoint1(_shape, sx, sy);
                }
                _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                ToStateOne();
                Move(_shape);
                _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                _currentState           = State.One;
                _editor.CancelAvailable = true;
            }
            break;

            case State.One:
            {
                if (_shape != null)
                {
                    _shape.Point2.X = sx;
                    _shape.Point2.Y = sy;
                    _shape.Point3.X = sx;
                    _shape.Point3.Y = sy;
                    if (_editor.Project.Options.TryToConnect)
                    {
                        TryToConnectPoint2(_shape, sx, sy);
                    }
                    _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                    ToStateTwo();
                    Move(_shape);
                    _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                    _currentState = State.Two;
                }
            }
            break;

            case State.Two:
            {
                if (_shape != null)
                {
                    _shape.Point3.X = sx;
                    _shape.Point3.Y = sy;
                    _shape.Point4.X = sx;
                    _shape.Point4.Y = sy;
                    if (_editor.Project.Options.TryToConnect)
                    {
                        _connectedP3 = TryToConnectPoint3(_shape, sx, sy);
                    }
                    _editor.Project.CurrentContainer.WorkingLayer.Shapes = _editor.Project.CurrentContainer.WorkingLayer.Shapes.Add(_shape);
                    _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                    ToStateThree();
                    Move(_shape);
                    _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                    _currentState = State.Three;
                }
            }
            break;

            case State.Three:
            {
                if (_shape != null)
                {
                    _shape.Point4.X = sx;
                    _shape.Point4.Y = sy;
                    if (_editor.Project.Options.TryToConnect)
                    {
                        _connectedP4 = TryToConnectPoint4(_shape, sx, sy);
                    }
                    _editor.Project.CurrentContainer.WorkingLayer.Shapes = _editor.Project.CurrentContainer.WorkingLayer.Shapes.Remove(_shape);
                    Remove();
                    Finalize(_shape);
                    _editor.AddWithHistory(_shape);
                    _currentState           = State.None;
                    _editor.CancelAvailable = false;
                }
            }
            break;
            }
        }
예제 #10
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object gfx, XArc arc, double dx, double dy, ImmutableArray<ShapeProperty> db, Record r)
        {
            var a = GdiArc.FromXArc(arc, dx, dy);
            if (a.Width <= 0.0 || a.Height <= 0.0)
                return;

            var _gfx = gfx as Graphics;

            Brush brush = ToSolidBrush(arc.Style.Fill);
            Pen pen = ToPen(arc.Style, _scaleToPage);

            if (arc.IsFilled)
            {
                var path = new GraphicsPath();
                path.AddArc(
                    _scaleToPage(a.X),
                    _scaleToPage(a.Y),
                    _scaleToPage(a.Width),
                    _scaleToPage(a.Height),
                    (float)a.StartAngle,
                    (float)a.SweepAngle);
                _gfx.FillPath(brush, path);
            }

            if (arc.IsStroked)
            {
                _gfx.DrawArc(
                    pen,
                    _scaleToPage(a.X),
                    _scaleToPage(a.Y),
                    _scaleToPage(a.Width),
                    _scaleToPage(a.Height),
                    (float)a.StartAngle,
                    (float)a.SweepAngle);
            }

            brush.Dispose();
            pen.Dispose();
        }
예제 #11
0
파일: GdiArc.cs 프로젝트: monocraft/Core2D
 /// <summary>
 ///
 /// </summary>
 /// <param name="arc"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static GdiArc FromXArc(XArc arc, double dx, double dy)
 {
     return(FromXArc(arc.Point1, arc.Point2, arc.Point3, arc.Point4, dx, dy));
 }
예제 #12
0
        public void Draw(object ds, XArc arc, double dx, double dy, ImmutableArray<Property> db, Record r)
        {
            var a = WpfArc.FromXArc(arc, dx, dy);

            var _ds = ds as CanvasDrawingSession;

            double thickness = arc.Style.Thickness / _state.Zoom;
            var brush = ToColor(arc.Style.Fill);
            var pen = ToColor(arc.Style.Stroke);
            var ss = CreateStrokeStyle(arc.Style);

            CanvasGeometry g;
            using (var builder = new CanvasPathBuilder(_ds))
            {
                builder.BeginFigure((float)a.Start.X, (float)a.Start.Y);
                builder.AddArc(
                    new N.Vector2(
                        (float)a.End.X,
                        (float)a.End.Y),
                    (float)a.Radius.Width,
                    (float)a.Radius.Height,
                    0f,
                    CanvasSweepDirection.Clockwise,
                    a.IsLargeArc ? CanvasArcSize.Large : CanvasArcSize.Small);
                builder.EndFigure(CanvasFigureLoop.Open);
                g = CanvasGeometry.CreatePath(builder);
            }

            if (arc.IsFilled)
            {
                _ds.FillGeometry(g, brush);
            }

            if (arc.IsStroked)
            {
                _ds.DrawGeometry(g, pen, (float)thickness, ss);
            }

            g.Dispose();
            ss.Dispose();
        }
예제 #13
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object dc, XArc arc, double dx, double dy, ImmutableArray<ShapeProperty> db, Record r)
        {
            if (!arc.IsFilled && !arc.IsStroked)
                return;

            var _dc = dc as DrawingContext;

            Brush brush = ToSolidBrush(arc.Style.Fill);
            Pen pen = ToPen(arc.Style, _scaleToPage);

            var sg = new StreamGeometry();
            using (var sgc = sg.Open())
            {
                var a = WpfArc.FromXArc(arc, dx, dy);

                sgc.BeginFigure(
                    new Point(a.Start.X, a.Start.Y),
                    arc.IsFilled);

                sgc.ArcTo(
                    new Point(a.End.X, a.End.Y),
                    new Size(a.Radius.Width, a.Radius.Height),
                    0.0,
                    a.IsLargeArc,
                    SweepDirection.Clockwise);

                sgc.EndFigure(false);
            }

            _dc.DrawGeometry(
                arc.IsFilled ? brush : null,
                arc.IsStroked ? pen : null,
                sg);

            // TODO: sg.Dispose();
            // TODO: brush.Dispose();
            // TODO: pen.Dispose();
        }
예제 #14
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="arc"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <returns></returns>
 public bool TryToConnectPoint4(XArc arc, double x, double y)
 {
     var result = ShapeBounds.HitTest(_editor.Project.CurrentContainer, new Vector2(x, y), _editor.Project.Options.HitTreshold);
     if (result != null && result is XPoint)
     {
         arc.Point4 = result as XPoint;
         return true;
     }
     return false;
 }
예제 #15
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object dc, XArc arc, double dx, double dy, ImmutableArray<Property> db, Record r)
        {
            var _dc = dc as DrawingContext;

            var style = arc.Style;
            if (style == null)
                return;

            double thickness = style.Thickness / _state.Zoom;
            double half = thickness / 2.0;

            Tuple<Brush, Pen> cache = null;
            Brush fill;
            Pen stroke;
            if (_enableStyleCache
                && _styleCache.TryGetValue(style, out cache))
            {
                fill = cache.Item1;
                stroke = cache.Item2;
            }
            else
            {
                fill = CreateBrush(style.Fill);
                stroke = CreatePen(style, thickness);
                if (_enableStyleCache)
                    _styleCache.Add(style, Tuple.Create(fill, stroke));
            }

            var a = WpfArc.FromXArc(arc, dx, dy);

            PathGeometry pg = null;
            if (_enableArcCache
                && _arcCache.TryGetValue(arc, out pg))
            {
                var pf = pg.Figures[0];
                pf.StartPoint = new Point(a.Start.X, a.Start.Y);
                pf.IsFilled = arc.IsFilled;
                var segment = pf.Segments[0] as ArcSegment;
                segment.Point = new Point(a.End.X, a.End.Y);
                segment.Size = new Size(a.Radius.Width, a.Radius.Height);
                segment.IsLargeArc = a.IsLargeArc;
                segment.IsStroked = arc.IsStroked;
            }
            else
            {
                var pf = new PathFigure()
                {
                    StartPoint = new Point(a.Start.X, a.Start.Y),
                    IsFilled = arc.IsFilled
                };

                var segment = new ArcSegment(
                    new Point(a.End.X, a.End.Y),
                    new Size(a.Radius.Width, a.Radius.Height),
                    0.0,
                    a.IsLargeArc, SweepDirection.Clockwise,
                    arc.IsStroked);

                //segment.Freeze();
                pf.Segments.Add(segment);
                //pf.Freeze();
                pg = new PathGeometry();
                pg.Figures.Add(pf);
                //pg.Freeze();

                if (_enableArcCache)
                    _arcCache.Add(arc, pg);
            }

            DrawPathGeometryInternal(_dc, half, fill, stroke, arc.IsStroked, arc.IsFilled, pg);
        }
예제 #16
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 public override void LeftDown(double x, double y)
 {
     double sx = _editor.Project.Options.SnapToGrid ? Editor.Snap(x, _editor.Project.Options.SnapX) : x;
     double sy = _editor.Project.Options.SnapToGrid ? Editor.Snap(y, _editor.Project.Options.SnapY) : y;
     switch (_currentState)
     {
         case State.None:
             {
                 _connectedP3 = false;
                 _connectedP4 = false;
                 _shape = XArc.Create(
                     sx, sy,
                     _editor.Project.CurrentStyleLibrary.CurrentStyle,
                     _editor.Project.Options.PointShape,
                     _editor.Project.Options.DefaultIsStroked,
                     _editor.Project.Options.DefaultIsFilled);
                 if (_editor.Project.Options.TryToConnect)
                 {
                     TryToConnectPoint1(_shape, sx, sy);
                 }
                 _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                 ToStateOne();
                 Move(_shape);
                 _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                 _currentState = State.One;
                 _editor.CancelAvailable = true;
             }
             break;
         case State.One:
             {
                 if (_shape != null)
                 {
                     _shape.Point2.X = sx;
                     _shape.Point2.Y = sy;
                     _shape.Point3.X = sx;
                     _shape.Point3.Y = sy;
                     if (_editor.Project.Options.TryToConnect)
                     {
                         TryToConnectPoint2(_shape, sx, sy);
                     }
                     _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                     ToStateTwo();
                     Move(_shape);
                     _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                     _currentState = State.Two;
                 }
             }
             break;
         case State.Two:
             {
                 if (_shape != null)
                 {
                     _shape.Point3.X = sx;
                     _shape.Point3.Y = sy;
                     _shape.Point4.X = sx;
                     _shape.Point4.Y = sy;
                     if (_editor.Project.Options.TryToConnect)
                     {
                         _connectedP3 = TryToConnectPoint3(_shape, sx, sy);
                     }
                     _editor.Project.CurrentContainer.WorkingLayer.Shapes = _editor.Project.CurrentContainer.WorkingLayer.Shapes.Add(_shape);
                     _editor.Project.CurrentContainer.WorkingLayer.Invalidate();
                     ToStateThree();
                     Move(_shape);
                     _editor.Project.CurrentContainer.HelperLayer.Invalidate();
                     _currentState = State.Three;
                 }
             }
             break;
         case State.Three:
             {
                 if (_shape != null)
                 {
                     _shape.Point4.X = sx;
                     _shape.Point4.Y = sy;
                     if (_editor.Project.Options.TryToConnect)
                     {
                         _connectedP4 = TryToConnectPoint4(_shape, sx, sy);
                     }
                     _editor.Project.CurrentContainer.WorkingLayer.Shapes = _editor.Project.CurrentContainer.WorkingLayer.Shapes.Remove(_shape);
                     Remove();
                     Finalize(_shape);
                     _editor.AddWithHistory(_shape);
                     _currentState = State.None;
                     _editor.CancelAvailable = false;
                 }
             }
             break;
     }
 }
예제 #17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="arc"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static WpfArc FromXArc(XArc arc, double dx, double dy)
        {
            var    p1      = Point2.Create(arc.Point1.X + dx, arc.Point1.Y + dy);
            var    p2      = Point2.Create(arc.Point2.X + dx, arc.Point2.Y + dy);
            var    p3      = Point2.Create(arc.Point3.X + dx, arc.Point3.Y + dy);
            var    p4      = Point2.Create(arc.Point4.X + dx, arc.Point4.Y + dy);
            var    rect    = Rect2.Create(p1, p2);
            var    center  = Point2.Create(rect.X + rect.Width / 2.0, rect.Y + rect.Height / 2.0);
            double offsetX = center.X - rect.X;
            double offsetY = center.Y - rect.Y;

            double minLenght = Math.Max(offsetX, offsetY);

            double length1 = center.Distance(p3);
            double p3x     = p3.X + (p3.X - center.X) / length1 * minLenght;
            double p3y     = p3.Y + (p3.Y - center.Y) / length1 * minLenght;

            double length2 = center.Distance(p4);
            double p4x     = p4.X + (p4.X - center.X) / length2 * minLenght;
            double p4y     = p4.Y + (p4.Y - center.Y) / length2 * minLenght;

            p3.X = p3x;
            p3.Y = p3y;
            p4.X = p4x;
            p4.Y = p4y;

            var    p3i = MathHelpers.FindEllipseSegmentIntersections(rect, center, p3, true);
            var    p4i = MathHelpers.FindEllipseSegmentIntersections(rect, center, p4, true);
            Point2 start;
            Point2 end;

            if (p3i.Count == 1)
            {
                start = p3i.FirstOrDefault();
            }
            else
            {
                start = Point2.Create(p3.X, p3.Y);
            }

            if (p4i.Count == 1)
            {
                end = p4i.FirstOrDefault();
            }
            else
            {
                end = Point2.Create(p4.X, p4.Y);
            }

            double angle      = MathHelpers.AngleLineSegments(center, start, center, end);
            bool   isLargeArc = angle > 180.0;

            double helperLenght = 60.0;

            double lengthStart = center.Distance(start);
            double p3hx        = start.X + (start.X - center.X) / lengthStart * helperLenght;
            double p3hy        = start.Y + (start.Y - center.Y) / lengthStart * helperLenght;

            double lengthEnd = center.Distance(end);
            double p4hx      = end.X + (end.X - center.X) / lengthEnd * helperLenght;
            double p4hy      = end.Y + (end.Y - center.Y) / lengthEnd * helperLenght;

            p3.X = p3hx;
            p3.Y = p3hy;
            p4.X = p4hx;
            p4.Y = p4hy;

            return(new WpfArc()
            {
                P1 = p1,
                P2 = p2,
                P3 = p3,
                P4 = p4,
                Rect = rect,
                Center = center,
                Start = start,
                End = end,
                Radius = Size2.Create(offsetX, offsetY),
                IsLargeArc = isLargeArc,
                Angle = angle
            });
        }