コード例 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="container"></param>
        private void DrawBackgroundInternal(Graphics gfx, Container container)
        {
            Brush brush = ToSolidBrush(container.Background);
            var   rect  = Rect2.Create(0, 0, container.Width, container.Height);

            gfx.FillRectangle(
                brush,
                _scaleToPage(rect.X),
                _scaleToPage(rect.Y),
                _scaleToPage(rect.Width),
                _scaleToPage(rect.Height));
            brush.Dispose();
        }
コード例 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="container"></param>
        /// <param name="rect"></param>
        /// <param name="treshold"></param>
        /// <returns></returns>
        public static ImmutableHashSet <BaseShape> HitTest(Container container, Rect2 rect, double treshold)
        {
            var builder = ImmutableHashSet.CreateBuilder <BaseShape>();

            var selection = new Vector2[]
            {
                new Vector2(rect.X, rect.Y),
                new Vector2(rect.X + rect.Width, rect.Y),
                new Vector2(rect.X + rect.Width, rect.Y + rect.Height),
                new Vector2(rect.X, rect.Y + rect.Height)
            };

            HitTest(container.CurrentLayer.Shapes.Reverse(), rect, selection, builder, treshold, 0, 0);

            return(builder.ToImmutableHashSet());
        }
コード例 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="shapes"></param>
        /// <param name="rect"></param>
        /// <param name="selection"></param>
        /// <param name="builder"></param>
        /// <param name="treshold"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        private static bool HitTest(
            IEnumerable <BaseShape> shapes,
            Rect2 rect,
            Vector2[] selection,
            ImmutableHashSet <BaseShape> .Builder builder,
            double treshold,
            double dx,
            double dy)
        {
            foreach (var shape in shapes)
            {
                var result = HitTest(shape, rect, selection, builder, treshold, dx, dy);
                if (result == true)
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #4
0
ファイル: GdiArc.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        ///
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="p4"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public static GdiArc FromXArc(XPoint p1, XPoint p2, XPoint p3, XPoint p4, double dx, double dy)
        {
            double x1         = p1.X + dx;
            double y1         = p1.Y + dy;
            double x2         = p2.X + dx;
            double y2         = p2.Y + dy;
            double x3         = p3.X + dx;
            double y3         = p3.Y + dy;
            double x4         = p4.X + dx;
            double y4         = p4.Y + dy;
            var    rect       = Rect2.Create(x1, y1, x2, y2, dx, dy);
            double cx         = rect.X + rect.Width / 2.0;
            double cy         = rect.Y + rect.Height / 2.0;
            double radiusX    = cx - rect.X;
            double radiusY    = cy - rect.Y;
            double startAngle = Math.Atan2(y3 - cy, x3 - cx);
            double endAngle   = Math.Atan2(y4 - cy, x4 - cx);
            double sweepAngle = (endAngle - startAngle) * 180.0 / Math.PI;

            if (sweepAngle < 0)
            {
                sweepAngle += 360;
            }

            startAngle *= 180.0 / Math.PI;
            endAngle   *= 180.0 / Math.PI;

            return(new GdiArc
            {
                X = rect.X,
                Y = rect.Y,
                Width = rect.Width,
                Height = rect.Height,
                RadiusX = radiusX,
                RadiusY = radiusY,
                StartAngle = startAngle,
                EndAngle = endAngle,
                SweepAngle = sweepAngle
            });
        }
コード例 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="stroke"></param>
        /// <param name="rect"></param>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        /// <param name="cellWidth"></param>
        /// <param name="cellHeight"></param>
        /// <param name="isStroked"></param>
        private void DrawGridInternal(
            Graphics gfx,
            Pen stroke,
            ref Rect2 rect,
            double offsetX, double offsetY,
            double cellWidth, double cellHeight,
            bool isStroked)
        {
            double ox = rect.X;
            double oy = rect.Y;
            double sx = ox + offsetX;
            double sy = oy + offsetY;
            double ex = ox + rect.Width;
            double ey = oy + rect.Height;

            for (double x = sx; x < ex; x += cellWidth)
            {
                var p0 = new PointF(
                    _scaleToPage(x),
                    _scaleToPage(oy));
                var p1 = new PointF(
                    _scaleToPage(x),
                    _scaleToPage(ey));
                DrawLineInternal(gfx, stroke, isStroked, ref p0, ref p1);
            }

            for (double y = sy; y < ey; y += cellHeight)
            {
                var p0 = new PointF(
                    _scaleToPage(ox),
                    _scaleToPage(y));
                var p1 = new PointF(
                    _scaleToPage(ex),
                    _scaleToPage(y));
                DrawLineInternal(gfx, stroke, isStroked, ref p0, ref p1);
            }
        }
コード例 #6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="rectangle"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 GetRectangleBounds(XRectangle rectangle, double dx, double dy)
 {
     return(Rect2.Create(rectangle.TopLeft, rectangle.BottomRight, dx, dy));
 }
コード例 #7
0
ファイル: MathHelpers.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        ///
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="onlySegment"></param>
        /// <returns></returns>
        public static IList <Point2> FindEllipseSegmentIntersections(
            Rect2 rect,
            Point2 p1, Point2 p2,
            bool onlySegment)
        {
            if ((rect.Width == 0) || (rect.Height == 0) || ((p1.X == p2.X) && (p1.Y == p2.Y)))
            {
                return new Point2[] { }
            }
            ;

            if (rect.Width < 0)
            {
                rect.X = rect.Right;

                rect.Width = -rect.Width;
            }

            if (rect.Height < 0)
            {
                rect.Y      = rect.Bottom;
                rect.Height = -rect.Height;
            }

            double cx = rect.Left + rect.Width / 2.0;
            double cy = rect.Top + rect.Height / 2.0;

            rect.X -= cx;
            rect.Y -= cy;

            p1.X -= cx;
            p1.Y -= cy;
            p2.X -= cx;
            p2.Y -= cy;

            double a = rect.Width / 2.0;
            double b = rect.Height / 2.0;

            double A = (p2.X - p1.X) * (p2.X - p1.X) / a / a + (p2.Y - p1.Y) * (p2.Y - p1.Y) / b / b;
            double B = 2 * p1.X * (p2.X - p1.X) / a / a + 2 * p1.Y * (p2.Y - p1.Y) / b / b;
            double C = p1.X * p1.X / a / a + p1.Y * p1.Y / b / b - 1;

            var solutions = new List <double>();

            double discriminant = B * B - 4 * A * C;

            if (discriminant == 0)
            {
                solutions.Add(-B / 2 / A);
            }
            else if (discriminant > 0)
            {
                solutions.Add((-B + Math.Sqrt(discriminant)) / 2 / A);
                solutions.Add((-B - Math.Sqrt(discriminant)) / 2 / A);
            }

            var points = new List <Point2>();

            foreach (var t in solutions)
            {
                if (!onlySegment || ((t >= 0f) && (t <= 1f)))
                {
                    double x = p1.X + (p2.X - p1.X) * t + cx;
                    double y = p1.Y + (p2.Y - p1.Y) * t + cy;
                    points.Add(Point2.Create(x, y));
                }
            }

            return(points);
        }
コード例 #8
0
ファイル: EmfRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="brush"></param>
        /// <param name="pen"></param>
        /// <param name="isStroked"></param>
        /// <param name="isFilled"></param>
        /// <param name="rect"></param>
        private static void DrawRectangleInternal(
            Graphics gfx,
            Brush brush,
            Pen pen,
            bool isStroked,
            bool isFilled,
            ref Rect2 rect)
        {
            if (isFilled)
            {
                gfx.FillRectangle(
                    brush,
                    (float)rect.X,
                    (float)rect.Y,
                    (float)rect.Width,
                    (float)rect.Height);
            }

            if (isStroked)
            {
                gfx.DrawRectangle(
                    pen,
                    (float)rect.X,
                    (float)rect.Y,
                    (float)rect.Width,
                    (float)rect.Height);
            }
        }
コード例 #9
0
ファイル: Win2dRenderer.cs プロジェクト: monocraft/Test2d
        private static void DrawEllipseInternal(
            CanvasDrawingSession ds,
            Color brush,
            Color pen,
            CanvasStrokeStyle ss,
            bool isStroked,
            bool isFilled,
            ref Rect2 rect,
            double strokeWidth)
        {
            double radiusX = rect.Width / 2.0;
            double radiusY = rect.Height / 2.0;
            double x = rect.X + radiusX;
            double y = rect.Y + radiusY;

            if (isFilled)
            {
                ds.FillEllipse(
                    (float)x,
                    (float)y,
                    (float)radiusX,
                    (float)radiusY,
                    brush);
            }

            if (isStroked)
            {
                ds.DrawEllipse(
                    (float)x,
                    (float)y,
                    (float)radiusX,
                    (float)radiusY,
                    pen,
                    (float)strokeWidth,
                    ss);
            }
        }
コード例 #10
0
ファイル: Win2dRenderer.cs プロジェクト: monocraft/Test2d
        private void DrawGridInternal(
            CanvasDrawingSession ds,
            Color stroke,
            CanvasStrokeStyle ss,
            ref Rect2 rect,
            double offsetX, double offsetY,
            double cellWidth, double cellHeight,
            bool isStroked,
            double strokeWidth)
        {
            double ox = rect.X;
            double oy = rect.Y;
            double sx = ox + offsetX;
            double sy = oy + offsetY;
            double ex = ox + rect.Width;
            double ey = oy + rect.Height;

            for (double x = sx; x < ex; x += cellWidth)
            {
                var p0 = new N.Vector2((float)x, (float)oy);
                var p1 = new N.Vector2((float)x, (float)ey);
                DrawLineInternal(ds, stroke, ss, isStroked, ref p0, ref p1, strokeWidth);
            }

            for (double y = sy; y < ey; y += cellHeight)
            {
                var p0 = new N.Vector2((float)ox, (float)y);
                var p1 = new N.Vector2((float)ex, (float)y);
                DrawLineInternal(ds, stroke, ss, isStroked, ref p0, ref p1, strokeWidth);
            }
        }
コード例 #11
0
ファイル: MathHelpers.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// Check if line intersects with rectangle using Liang-Barsky line clipping algorithm.
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns>True if line intersects with rectangle.</returns>
        public static bool LineIntersectsWithRect(Rect2 rect, Point2 p0, Point2 p1)
        {
            double left = rect.Left;
            double right = rect.Right;
            double bottom = rect.Bottom;
            double top = rect.Top;
            double x0 = p0.X;
            double y0 = p0.Y;
            double x1 = p1.X;
            double y1 = p1.Y;

            double t0 = 0.0;
            double t1 = 1.0;
            double dx = x1 - x0;
            double dy = y1 - y0;
            double p = 0.0, q = 0.0, r;

            for (int edge = 0; edge < 4; edge++)
            {
                if (edge == 0)
                {
                    p = -dx;
                    q = -(left - x0);
                }
                if (edge == 1)
                {
                    p = dx;
                    q = (right - x0);
                }
                if (edge == 2)
                {
                    p = dy;
                    q = (bottom - y0);
                }
                if (edge == 3)
                {
                    p = -dy;
                    q = -(top - y0);
                }

                r = q / p;

                if (p == 0.0 && q < 0.0)
                {
                    return false;
                }

                if (p < 0.0)
                {
                    if (r > t1)
                    {
                        return false;
                    }
                    else if (r > t0)
                    {
                        t0 = r;
                    }
                }
                else if (p > 0.0)
                {
                    if (r < t0)
                    {
                        return false;
                    }
                    else if (r < t1)
                    {
                        t1 = r;
                    }
                }
            }

            // to calulate clipped line position
            // x0clip = x0 + t0 * dx;
            // y0clip = y0 + t0 * dy;
            // x1clip = x0 + t1 * dx;
            // y1clip = y0 + t1 * dy;

            return true;
        }
コード例 #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="shape"></param>
        /// <param name="rect"></param>
        /// <param name="selection"></param>
        /// <param name="builder"></param>
        /// <param name="treshold"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        private static bool HitTest(
            BaseShape shape,
            Rect2 rect,
            Vector2[] selection,
            ImmutableHashSet <BaseShape> .Builder builder,
            double treshold,
            double dx,
            double dy)
        {
            if (shape is XPoint)
            {
                if (GetPointBounds(shape as XPoint, treshold, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XLine)
            {
                var line = shape as XLine;
                if (GetPointBounds(line.Start, treshold, dx, dy).IntersectsWith(rect) ||
                    GetPointBounds(line.End, treshold, dx, dy).IntersectsWith(rect) ||
                    MathHelpers.LineIntersectsWithRect(rect, new Point2(line.Start.X, line.Start.Y), new Point2(line.End.X, line.End.Y)))
                {
                    if (builder != null)
                    {
                        builder.Add(line);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XEllipse)
            {
                if (GetEllipseBounds(shape as XEllipse, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XRectangle)
            {
                if (GetRectangleBounds(shape as XRectangle, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XArc)
            {
                if (GetArcBounds(shape as XArc, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XBezier)
            {
                if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(shape as XBezier, dx, dy)))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XQBezier)
            {
                if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(shape as XQBezier, dx, dy)))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XText)
            {
                if (GetTextBounds(shape as XText, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XImage)
            {
                if (GetImageBounds(shape as XImage, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (shape is XPath)
            {
                if ((shape as XPath).Geometry != null)
                {
                    var points = (shape as XPath).GetAllPoints();
                    if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(points, dx, dy)))
                    {
                        if (builder != null)
                        {
                            builder.Add(shape);
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                }
                return(false);
            }
            else if (shape is XGroup)
            {
                if (HitTest((shape as XGroup).Shapes.Reverse(), rect, selection, null, treshold, dx, dy) == true)
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
                return(false);
            }

            return(false);
        }
コード例 #13
0
ファイル: PerspexRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="brush"></param>
        /// <param name="pen"></param>
        /// <param name="isStroked"></param>
        /// <param name="isFilled"></param>
        /// <param name="rect"></param>
        private static void DrawRectangleInternal(
            IDrawingContext dc,
            Brush brush,
            Pen pen,
            bool isStroked,
            bool isFilled,
            ref Rect2 rect)
        {
            if (!isStroked && !isFilled)
                return;

            var r = new Rect(rect.X, rect.Y, rect.Width, rect.Height);

            if (isFilled)
            {
                dc.FillRectangle(brush, r);
            }

            if (isStroked)
            {
                dc.DrawRectangle(pen, r);
            }
        }
コード例 #14
0
ファイル: PerspexRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="line"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object dc, XLine line, double dx, double dy, ImmutableArray<ShapeProperty> db, Record r)
        {
            var _dc = dc as IDrawingContext;

            Brush fillLine = ToSolidBrush(line.Style.Fill);
            Pen strokeLine = ToPen(line.Style, _scaleToPage);

            Brush fillStartArrow = ToSolidBrush(line.Style.StartArrowStyle.Fill);
            Pen strokeStartArrow = ToPen(line.Style.StartArrowStyle, _scaleToPage);

            Brush fillEndArrow = ToSolidBrush(line.Style.EndArrowStyle.Fill);
            Pen strokeEndArrow = ToPen(line.Style.EndArrowStyle, _scaleToPage);

            double _x1 = line.Start.X + dx;
            double _y1 = line.Start.Y + dy;
            double _x2 = line.End.X + dx;
            double _y2 = line.End.Y + dy;

            XLine.SetMaxLength(line, ref _x1, ref _y1, ref _x2, ref _y2);

            float x1 = _scaleToPage(_x1);
            float y1 = _scaleToPage(_y1);
            float x2 = _scaleToPage(_x2);
            float y2 = _scaleToPage(_y2);

            var sas = line.Style.StartArrowStyle;
            var eas = line.Style.EndArrowStyle;
            double a1 = Math.Atan2(y1 - y2, x1 - x2);
            double a2 = Math.Atan2(y2 - y1, x2 - x1);

            var t1 = MatrixHelper.Rotation(a1, new Vector(x1, y1));
            var t2 = MatrixHelper.Rotation(a2, new Vector(x2, y2));

            Point pt1 = default(Point);
            Point pt2 = default(Point);

            double radiusX1 = sas.RadiusX;
            double radiusY1 = sas.RadiusY;
            double sizeX1 = 2.0 * radiusX1;
            double sizeY1 = 2.0 * radiusY1;

            switch (sas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt1 = new Point(x1, y1);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        pt1 = MatrixHelper.TransformPoint(t1, new Point(x1 - (float)sizeX1, y1));
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        var d = _dc.PushTransform(t1);
                        DrawRectangleInternal(_dc, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                        d.Dispose();
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        pt1 = MatrixHelper.TransformPoint(t1, new Point(x1 - (float)sizeX1, y1));
                        var d = _dc.PushTransform(t1);
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        DrawEllipseInternal(_dc, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                        d.Dispose();
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        var pts = new Point[]
                        {
                            new Point(x1, y1),
                            new Point(x1 - (float)sizeX1, y1 + (float)sizeY1),
                            new Point(x1, y1),
                            new Point(x1 - (float)sizeX1, y1 - (float)sizeY1),
                            new Point(x1, y1)
                        };
                        pt1 = MatrixHelper.TransformPoint(t1, pts[0]);
                        var p11 = MatrixHelper.TransformPoint(t1, pts[1]);
                        var p21 = MatrixHelper.TransformPoint(t1, pts[2]);
                        var p12 = MatrixHelper.TransformPoint(t1, pts[3]);
                        var p22 = MatrixHelper.TransformPoint(t1, pts[4]);
                        DrawLineInternal(_dc, strokeStartArrow, sas.IsStroked, ref p11, ref p21);
                        DrawLineInternal(_dc, strokeStartArrow, sas.IsStroked, ref p12, ref p22);
                    }
                    break;
            }

            double radiusX2 = eas.RadiusX;
            double radiusY2 = eas.RadiusY;
            double sizeX2 = 2.0 * radiusX2;
            double sizeY2 = 2.0 * radiusY2;

            switch (eas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt2 = new Point(x2, y2);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        pt2 = MatrixHelper.TransformPoint(t2, new Point(x2 - (float)sizeX2, y2));
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        var d = _dc.PushTransform(t2);
                        DrawRectangleInternal(_dc, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                        d.Dispose();
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        pt2 = MatrixHelper.TransformPoint(t2, new Point(x2 - (float)sizeX2, y2));
                        var d = _dc.PushTransform(t2);
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        DrawEllipseInternal(_dc, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                        d.Dispose();
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        var pts = new Point[]
                        {
                            new Point(x2, y2),
                            new Point(x2 - (float)sizeX2, y2 + (float)sizeY2),
                            new Point(x2, y2),
                            new Point(x2 - (float)sizeX2, y2 - (float)sizeY2),
                            new Point(x2, y2)
                        };
                        pt2 = MatrixHelper.TransformPoint(t2, pts[0]);
                        var p11 = MatrixHelper.TransformPoint(t2, pts[1]);
                        var p21 = MatrixHelper.TransformPoint(t2, pts[2]);
                        var p12 = MatrixHelper.TransformPoint(t2, pts[3]);
                        var p22 = MatrixHelper.TransformPoint(t2, pts[4]);
                        DrawLineInternal(_dc, strokeEndArrow, eas.IsStroked, ref p11, ref p21);
                        DrawLineInternal(_dc, strokeEndArrow, eas.IsStroked, ref p12, ref p22);
                    }
                    break;
            }

            _dc.DrawLine(strokeLine, pt1, pt2);

            // TODO: fillLine.Dispose();
            // TODO: strokeLine.Dispose();

            // TODO: fillStartArrow.Dispose();
            // TODO: strokeStartArrow.Dispose();

            // TODO: fillEndArrow.Dispose();
            // TODO: strokeEndArrow.Dispose();
        }
コード例 #15
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="tl"></param>
 /// <param name="br"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 private static Rect2 CreateRect(XPoint tl, XPoint br, double dx, double dy)
 {
     return(Rect2.Create(tl, br, dx, dy));
 }
コード例 #16
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="text"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 GetTextBounds(XText text, double dx, double dy)
 {
     return(Rect2.Create(text.TopLeft, text.BottomRight, dx, dy));
 }
コード例 #17
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="ellipse"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 GetEllipseBounds(XEllipse ellipse, double dx, double dy)
 {
     return(Rect2.Create(ellipse.TopLeft, ellipse.BottomRight, dx, dy));
 }
コード例 #18
0
ファイル: PerspexRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dc"></param>
        /// <param name="brush"></param>
        /// <param name="pen"></param>
        /// <param name="isStroked"></param>
        /// <param name="isFilled"></param>
        /// <param name="rect"></param>
        private static void DrawEllipseInternal(
            IDrawingContext dc,
            Brush brush,
            Pen pen,
            bool isStroked,
            bool isFilled,
            ref Rect2 rect)
        {
            if (!isFilled && !isStroked)
                return;

            var r = new Rect(rect.X, rect.Y, rect.Width, rect.Height);
            var g = new EllipseGeometry(r);

            dc.DrawGeometry(
                isFilled ? brush : null,
                isStroked ? pen : null,
                g);

            // TODO: g.Dispose();
        }
コード例 #19
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="line"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object gfx, XLine line, double dx, double dy, ImmutableArray <ShapeProperty> db, Record r)
        {
            var _gfx = gfx as Graphics;

            Brush fillLine   = ToSolidBrush(line.Style.Fill);
            Pen   strokeLine = ToPen(line.Style, _scaleToPage);

            Brush fillStartArrow   = ToSolidBrush(line.Style.StartArrowStyle.Fill);
            Pen   strokeStartArrow = ToPen(line.Style.StartArrowStyle, _scaleToPage);

            Brush fillEndArrow   = ToSolidBrush(line.Style.EndArrowStyle.Fill);
            Pen   strokeEndArrow = ToPen(line.Style.EndArrowStyle, _scaleToPage);

            double _x1 = line.Start.X + dx;
            double _y1 = line.Start.Y + dy;
            double _x2 = line.End.X + dx;
            double _y2 = line.End.Y + dy;

            XLine.SetMaxLength(line, ref _x1, ref _y1, ref _x2, ref _y2);

            float x1 = _scaleToPage(_x1);
            float y1 = _scaleToPage(_y1);
            float x2 = _scaleToPage(_x2);
            float y2 = _scaleToPage(_y2);

            var   sas = line.Style.StartArrowStyle;
            var   eas = line.Style.EndArrowStyle;
            float a1  = (float)(Math.Atan2(y1 - y2, x1 - x2) * 180.0 / Math.PI);
            float a2  = (float)(Math.Atan2(y2 - y1, x2 - x1) * 180.0 / Math.PI);

            var t1 = new Matrix();
            var c1 = new PointF(x1, y1);

            t1.RotateAt(a1, c1);

            var t2 = new Matrix();
            var c2 = new PointF(x2, y2);

            t2.RotateAt(a2, c2);

            PointF pt1;
            PointF pt2;

            double radiusX1 = sas.RadiusX;
            double radiusY1 = sas.RadiusY;
            double sizeX1   = 2.0 * radiusX1;
            double sizeY1   = 2.0 * radiusY1;

            switch (sas.ArrowType)
            {
            default:
            case ArrowType.None:
            {
                pt1 = new PointF(x1, y1);
            }
            break;

            case ArrowType.Rectangle:
            {
                var pts = new PointF[] { new PointF(x1 - (float)sizeX1, y1) };
                t1.TransformPoints(pts);
                pt1 = pts[0];
                var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                var gs   = _gfx.Save();
                _gfx.MultiplyTransform(t1);
                DrawRectangleInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                _gfx.Restore(gs);
            }
            break;

            case ArrowType.Ellipse:
            {
                var pts = new PointF[] { new PointF(x1 - (float)sizeX1, y1) };
                t1.TransformPoints(pts);
                pt1 = pts[0];
                var gs = _gfx.Save();
                _gfx.MultiplyTransform(t1);
                var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                DrawEllipseInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                _gfx.Restore(gs);
            }
            break;

            case ArrowType.Arrow:
            {
                var pts = new PointF[]
                {
                    new PointF(x1, y1),
                    new PointF(x1 - (float)sizeX1, y1 + (float)sizeY1),
                    new PointF(x1, y1),
                    new PointF(x1 - (float)sizeX1, y1 - (float)sizeY1),
                    new PointF(x1, y1)
                };
                t1.TransformPoints(pts);
                pt1 = pts[0];
                var p11 = pts[1];
                var p21 = pts[2];
                var p12 = pts[3];
                var p22 = pts[4];
                DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p11, ref p21);
                DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p12, ref p22);
            }
            break;
            }

            double radiusX2 = eas.RadiusX;
            double radiusY2 = eas.RadiusY;
            double sizeX2   = 2.0 * radiusX2;
            double sizeY2   = 2.0 * radiusY2;

            switch (eas.ArrowType)
            {
            default:
            case ArrowType.None:
            {
                pt2 = new PointF(x2, y2);
            }
            break;

            case ArrowType.Rectangle:
            {
                var pts = new PointF[] { new PointF(x2 - (float)sizeX2, y2) };
                t2.TransformPoints(pts);
                pt2 = pts[0];
                var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                var gs   = _gfx.Save();
                _gfx.MultiplyTransform(t2);
                DrawRectangleInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                _gfx.Restore(gs);
            }
            break;

            case ArrowType.Ellipse:
            {
                var pts = new PointF[] { new PointF(x2 - (float)sizeX2, y2) };
                t2.TransformPoints(pts);
                pt2 = pts[0];
                var gs = _gfx.Save();
                _gfx.MultiplyTransform(t2);
                var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                DrawEllipseInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                _gfx.Restore(gs);
            }
            break;

            case ArrowType.Arrow:
            {
                var pts = new PointF[]
                {
                    new PointF(x2, y2),
                    new PointF(x2 - (float)sizeX2, y2 + (float)sizeY2),
                    new PointF(x2, y2),
                    new PointF(x2 - (float)sizeX2, y2 - (float)sizeY2),
                    new PointF(x2, y2)
                };
                t2.TransformPoints(pts);
                pt2 = pts[0];
                var p11 = pts[1];
                var p21 = pts[2];
                var p12 = pts[3];
                var p22 = pts[4];
                DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p11, ref p21);
                DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p12, ref p22);
            }
            break;
            }

            _gfx.DrawLine(strokeLine, pt1, pt2);

            fillLine.Dispose();
            strokeLine.Dispose();

            fillStartArrow.Dispose();
            strokeStartArrow.Dispose();

            fillEndArrow.Dispose();
            strokeEndArrow.Dispose();
        }
コード例 #20
0
ファイル: PerspexRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="style"></param>
        /// <param name="rect"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private Point GetTextOrigin(ShapeStyle style, ref Rect2 rect, ref Size size)
        {
            double ox, oy;

            switch (style.TextStyle.TextHAlignment)
            {
                case TextHAlignment.Left:
                    ox = rect.X;
                    break;
                case TextHAlignment.Right:
                    ox = rect.Right - size.Width;
                    break;
                case TextHAlignment.Center:
                default:
                    ox = (rect.Left + rect.Width / 2.0) - (size.Width / 2.0);
                    break;
            }

            switch (style.TextStyle.TextVAlignment)
            {
                case TextVAlignment.Top:
                    oy = rect.Y;
                    break;
                case TextVAlignment.Bottom:
                    oy = rect.Bottom - size.Height;
                    break;
                case TextVAlignment.Center:
                default:
                    oy = (rect.Bottom - rect.Height / 2f) - (size.Height / 2f);
                    break;
            }

            return new Point(ox, oy);
        }
コード例 #21
0
ファイル: Rect2.cs プロジェクト: gitter-badger/Test2d
 /// <summary>
 /// 
 /// </summary>
 /// <param name="rect"></param>
 /// <returns></returns>
 public bool IntersectsWith(Rect2 rect)
 {
     return (rect.Left <= Right)
         && (rect.Right >= Left)
         && (rect.Top <= Bottom)
         && (rect.Bottom >= Top);
 }
コード例 #22
0
ファイル: MathHelpers.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="onlySegment"></param>
        /// <returns></returns>
        public static IList<Point2> FindEllipseSegmentIntersections(
            Rect2 rect,
            Point2 p1, Point2 p2,
            bool onlySegment)
        {
            if ((rect.Width == 0) || (rect.Height == 0) || ((p1.X == p2.X) && (p1.Y == p2.Y)))
                return new Point2[] { };

            if (rect.Width < 0)
            {
                rect.X = rect.Right;
                rect.Width = -rect.Width;
            }

            if (rect.Height < 0)
            {
                rect.Y = rect.Bottom;
                rect.Height = -rect.Height;
            }

            double cx = rect.Left + rect.Width / 2.0;
            double cy = rect.Top + rect.Height / 2.0;

            rect.X -= cx;
            rect.Y -= cy;

            p1.X -= cx;
            p1.Y -= cy;
            p2.X -= cx;
            p2.Y -= cy;

            double a = rect.Width / 2.0;
            double b = rect.Height / 2.0;

            double A = (p2.X - p1.X) * (p2.X - p1.X) / a / a + (p2.Y - p1.Y) * (p2.Y - p1.Y) / b / b;
            double B = 2 * p1.X * (p2.X - p1.X) / a / a + 2 * p1.Y * (p2.Y - p1.Y) / b / b;
            double C = p1.X * p1.X / a / a + p1.Y * p1.Y / b / b - 1;

            var solutions = new List<double>();

            double discriminant = B * B - 4 * A * C;
            if (discriminant == 0)
            {
                solutions.Add(-B / 2 / A);
            }
            else if (discriminant > 0)
            {
                solutions.Add((-B + Math.Sqrt(discriminant)) / 2 / A);
                solutions.Add((-B - Math.Sqrt(discriminant)) / 2 / A);
            }

            var points = new List<Point2>();

            foreach (var t in solutions)
            {
                if (!onlySegment || ((t >= 0f) && (t <= 1f)))
                {
                    double x = p1.X + (p2.X - p1.X) * t + cx;
                    double y = p1.Y + (p2.Y - p1.Y) * t + cy;
                    points.Add(Point2.Create(x, y));
                }
            }

            return points;
        }
コード例 #23
0
ファイル: WpfArc.cs プロジェクト: gitter-badger/Test2d
        /// <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
            });
        }
コード例 #24
0
ファイル: Win2dRenderer.cs プロジェクト: monocraft/Test2d
        public void Draw(object ds, XLine line, double dx, double dy, ImmutableArray<ShapeProperty> db, Record r)
        {
            // TODO: Finish draw line implementation.
            var _ds = ds as CanvasDrawingSession;

            double thicknessLine = line.Style.Thickness / _state.Zoom;
            double thicknessStartArrow = line.Style.StartArrowStyle.Thickness / _state.Zoom;
            double thicknessEndArrow = line.Style.EndArrowStyle.Thickness / _state.Zoom;

            var fillLine = ToColor(line.Style.Fill);
            var strokeLine = ToColor(line.Style.Stroke);

            var fillStartArrow = ToColor(line.Style.StartArrowStyle.Fill);
            var strokeStartArrow = ToColor(line.Style.StartArrowStyle.Stroke);

            var fillEndArrow = ToColor(line.Style.EndArrowStyle.Fill);
            var strokeEndArrow = ToColor(line.Style.EndArrowStyle.Stroke);

            var ssLine = CreateStrokeStyle(line.Style);
            var ssStartArrow = CreateStrokeStyle(line.Style.StartArrowStyle);
            var ssEndArrow = CreateStrokeStyle(line.Style.EndArrowStyle);

            double _x1 = line.Start.X + dx;
            double _y1 = line.Start.Y + dy;
            double _x2 = line.End.X + dx;
            double _y2 = line.End.Y + dy;

            XLine.SetMaxLength(line, ref _x1, ref _y1, ref _x2, ref _y2);

            float x1 = (float)_x1;
            float y1 = (float)_y1;
            float x2 = (float)_x2;
            float y2 = (float)_y2;

            var sas = line.Style.StartArrowStyle;
            var eas = line.Style.EndArrowStyle;
            float a1 = (float)Math.Atan2(y1 - y2, x1 - x2);
            float a2 = (float)Math.Atan2(y2 - y1, x2 - x1);

            var t1 = N.Matrix3x2.CreateRotation(a1, new N.Vector2(x1, y1));
            var t2 = N.Matrix3x2.CreateRotation(a2, new N.Vector2(x2, y2));

            N.Vector2 pt1;
            N.Vector2 pt2;

            double radiusX1 = sas.RadiusX;
            double radiusY1 = sas.RadiusY;
            double sizeX1 = 2.0 * radiusX1;
            double sizeY1 = 2.0 * radiusY1;

            switch (sas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt1 = new N.Vector2(x1, y1);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        pt1 = N.Vector2.Transform(new N.Vector2(x1 - (float)sizeX1, y1), t1);
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        var old = _ds.Transform;
                        _ds.Transform = t1;
                        DrawRectangleInternal(_ds, fillStartArrow, strokeStartArrow, ssStartArrow, sas.IsStroked, sas.IsFilled, ref rect, thicknessStartArrow);
                        _ds.Transform = old;
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        pt1 = N.Vector2.Transform(new N.Vector2(x1 - (float)sizeX1, y1), t1);
                        var old = _ds.Transform;
                        _ds.Transform = t1;
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        DrawEllipseInternal(_ds, fillStartArrow, strokeStartArrow, ssStartArrow, sas.IsStroked, sas.IsFilled, ref rect, thicknessStartArrow);
                        _ds.Transform = old;
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        pt1 = N.Vector2.Transform(new N.Vector2(x1, y1), t1);
                        var p11 = N.Vector2.Transform(new N.Vector2(x1 - (float)sizeX1, y1 + (float)sizeY1), t1);
                        var p21 = N.Vector2.Transform(new N.Vector2(x1, y1), t1);
                        var p12 = N.Vector2.Transform(new N.Vector2(x1 - (float)sizeX1, y1 - (float)sizeY1), t1);
                        var p22 = N.Vector2.Transform(new N.Vector2(x1, y1), t1);
                        DrawLineInternal(_ds, strokeStartArrow, ssStartArrow, sas.IsStroked, ref p11, ref p21, thicknessStartArrow);
                        DrawLineInternal(_ds, strokeStartArrow, ssStartArrow, sas.IsStroked, ref p12, ref p22, thicknessStartArrow);
                    }
                    break;
            }

            double radiusX2 = eas.RadiusX;
            double radiusY2 = eas.RadiusY;
            double sizeX2 = 2.0 * radiusX2;
            double sizeY2 = 2.0 * radiusY2;

            switch (eas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt2 = new N.Vector2(x2, y2);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        pt2 = N.Vector2.Transform(new N.Vector2(x2 - (float)sizeX2, y2), t2);
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        var old = _ds.Transform;
                        _ds.Transform = t1;
                        DrawRectangleInternal(_ds, fillEndArrow, strokeEndArrow, ssEndArrow, eas.IsStroked, eas.IsFilled, ref rect, thicknessEndArrow);
                        _ds.Transform = old;
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        pt2 = N.Vector2.Transform(new N.Vector2(x2 - (float)sizeX2, y2), t2);
                        var old = _ds.Transform;
                        _ds.Transform = t1;
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        DrawEllipseInternal(_ds, fillEndArrow, strokeEndArrow, ssEndArrow, eas.IsStroked, eas.IsFilled, ref rect, thicknessEndArrow);
                        _ds.Transform = old;
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        pt2 = N.Vector2.Transform(new N.Vector2(x2, y2), t2);
                        var p11 = N.Vector2.Transform(new N.Vector2(x2 - (float)sizeX2, y2 + (float)sizeY2), t2);
                        var p21 = N.Vector2.Transform(new N.Vector2(x2, y2), t2);
                        var p12 = N.Vector2.Transform(new N.Vector2(x2 - (float)sizeX2, y2 - (float)sizeY2), t2);
                        var p22 = N.Vector2.Transform(new N.Vector2(x2, y2), t2);
                        DrawLineInternal(_ds, strokeEndArrow, ssEndArrow, eas.IsStroked, ref p11, ref p21, thicknessEndArrow);
                        DrawLineInternal(_ds, strokeEndArrow, ssEndArrow, eas.IsStroked, ref p12, ref p22, thicknessEndArrow);
                    }
                    break;
            }

            DrawLineInternal(_ds, strokeLine, ssLine, line.IsStroked, ref pt1, ref pt2, thicknessLine);

            ssEndArrow.Dispose();
            ssStartArrow.Dispose();
            ssLine.Dispose();
        }
コード例 #25
0
ファイル: ShapeBounds.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        /// <param name="rect"></param>
        /// <param name="treshold"></param>
        /// <returns></returns>
        public static ImmutableHashSet<BaseShape> HitTest(Container container, Rect2 rect, double treshold)
        {
            var builder = ImmutableHashSet.CreateBuilder<BaseShape>();

            var selection = new Vector2[]
            {
                new Vector2(rect.X, rect.Y),
                new Vector2(rect.X + rect.Width, rect.Y),
                new Vector2(rect.X + rect.Width, rect.Y + rect.Height),
                new Vector2(rect.X, rect.Y + rect.Height)
            };

            HitTest(container.CurrentLayer.Shapes.Reverse(), rect, selection, builder, treshold, 0, 0);

            return builder.ToImmutableHashSet();
        }
コード例 #26
0
ファイル: Win2dRenderer.cs プロジェクト: monocraft/Test2d
        private static void DrawRectangleInternal(
            CanvasDrawingSession ds,
            Color brush,
            Color pen,
            CanvasStrokeStyle ss,
            bool isStroked,
            bool isFilled,
            ref Rect2 rect,
            double strokeWidth)
        {
            if (isFilled)
            {
                ds.FillRectangle(
                    (float)rect.X,
                    (float)rect.Y,
                    (float)rect.Width,
                    (float)rect.Height,
                    brush);
            }

            if (isStroked)
            {
                ds.DrawRectangle(
                    (float)rect.X,
                    (float)rect.Y,
                    (float)rect.Width,
                    (float)rect.Height,
                    pen,
                    (float)strokeWidth,
                    ss);
            }
        }
コード例 #27
0
ファイル: ShapeBounds.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="shape"></param>
        /// <param name="rect"></param>
        /// <param name="selection"></param>
        /// <param name="builder"></param>
        /// <param name="treshold"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        private static bool HitTest(
            BaseShape shape,
            Rect2 rect,
            Vector2[] selection,
            ImmutableHashSet<BaseShape>.Builder builder,
            double treshold,
            double dx,
            double dy)
        {
            if (shape is XPoint)
            {
                if (GetPointBounds(shape as XPoint, treshold, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XLine)
            {
                var line = shape as XLine;
                if (GetPointBounds(line.Start, treshold, dx, dy).IntersectsWith(rect)
                    || GetPointBounds(line.End, treshold, dx, dy).IntersectsWith(rect)
                    || MathHelpers.LineIntersectsWithRect(rect, new Point2(line.Start.X, line.Start.Y), new Point2(line.End.X, line.End.Y)))
                {
                    if (builder != null)
                    {
                        builder.Add(line);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XEllipse)
            {
                if (GetEllipseBounds(shape as XEllipse, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XRectangle)
            {
                if (GetRectangleBounds(shape as XRectangle, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XArc)
            {
                if (GetArcBounds(shape as XArc, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XBezier)
            {
                if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(shape as XBezier, dx, dy)))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XQBezier)
            {
                if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(shape as XQBezier, dx, dy)))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XText)
            {
                if (GetTextBounds(shape as XText, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XImage)
            {
                if (GetImageBounds(shape as XImage, dx, dy).IntersectsWith(rect))
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }
            else if (shape is XPath)
            {
                if ((shape as XPath).Geometry != null)
                {
                    var points = (shape as XPath).GetAllPoints();
                    if (ConvexHullBounds.Overlap(selection, ConvexHullBounds.GetVertices(points, dx, dy)))
                    {
                        if (builder != null)
                        {
                            builder.Add(shape);
                            return false;
                        }
                        else
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
            else if (shape is XGroup)
            {
                if (HitTest((shape as XGroup).Shapes.Reverse(), rect, selection, null, treshold, dx, dy) == true)
                {
                    if (builder != null)
                    {
                        builder.Add(shape);
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            }

            return false;
        }
コード例 #28
0
ファイル: MathHelpers.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// Check if line intersects with rectangle using Liang-Barsky line clipping algorithm.
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns>True if line intersects with rectangle.</returns>
        public static bool LineIntersectsWithRect(Rect2 rect, Point2 p0, Point2 p1)
        {
            double left   = rect.Left;
            double right  = rect.Right;
            double bottom = rect.Bottom;
            double top    = rect.Top;
            double x0     = p0.X;
            double y0     = p0.Y;
            double x1     = p1.X;
            double y1     = p1.Y;

            double t0 = 0.0;
            double t1 = 1.0;
            double dx = x1 - x0;
            double dy = y1 - y0;
            double p = 0.0, q = 0.0, r;

            for (int edge = 0; edge < 4; edge++)
            {
                if (edge == 0)
                {
                    p = -dx;
                    q = -(left - x0);
                }
                if (edge == 1)
                {
                    p = dx;
                    q = (right - x0);
                }
                if (edge == 2)
                {
                    p = dy;
                    q = (bottom - y0);
                }
                if (edge == 3)
                {
                    p = -dy;
                    q = -(top - y0);
                }

                r = q / p;

                if (p == 0.0 && q < 0.0)
                {
                    return(false);
                }

                if (p < 0.0)
                {
                    if (r > t1)
                    {
                        return(false);
                    }
                    else if (r > t0)
                    {
                        t0 = r;
                    }
                }
                else if (p > 0.0)
                {
                    if (r < t0)
                    {
                        return(false);
                    }
                    else if (r < t1)
                    {
                        t1 = r;
                    }
                }
            }

            // to calulate clipped line position
            // x0clip = x0 + t0 * dx;
            // y0clip = y0 + t0 * dy;
            // x1clip = x0 + t1 * dx;
            // y1clip = y0 + t1 * dy;

            return(true);
        }
コード例 #29
0
ファイル: ShapeBounds.cs プロジェクト: gitter-badger/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="shapes"></param>
        /// <param name="rect"></param>
        /// <param name="selection"></param>
        /// <param name="builder"></param>
        /// <param name="treshold"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        private static bool HitTest(
            IEnumerable<BaseShape> shapes,
            Rect2 rect,
            Vector2[] selection,
            ImmutableHashSet<BaseShape>.Builder builder,
            double treshold,
            double dx,
            double dy)
        {
            foreach (var shape in shapes)
            {
                var result = HitTest(shape, rect, selection, builder, treshold, dx, dy);
                if (result == true)
                {
                    return true;
                }
            }

            return false;
        }
コード例 #30
0
ファイル: EmfRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="line"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="db"></param>
        /// <param name="r"></param>
        public void Draw(object gfx, XLine line, double dx, double dy, ImmutableArray<ShapeProperty> db, Record r)
        {
            var _gfx = gfx as Graphics;

            Brush fillLine = ToSolidBrush(line.Style.Fill);
            Pen strokeLine = ToPen(line.Style, _scaleToPage);

            Brush fillStartArrow = ToSolidBrush(line.Style.StartArrowStyle.Fill);
            Pen strokeStartArrow = ToPen(line.Style.StartArrowStyle, _scaleToPage);

            Brush fillEndArrow = ToSolidBrush(line.Style.EndArrowStyle.Fill);
            Pen strokeEndArrow = ToPen(line.Style.EndArrowStyle, _scaleToPage);

            double _x1 = line.Start.X + dx;
            double _y1 = line.Start.Y + dy;
            double _x2 = line.End.X + dx;
            double _y2 = line.End.Y + dy;

            XLine.SetMaxLength(line, ref _x1, ref _y1, ref _x2, ref _y2);

            float x1 = _scaleToPage(_x1);
            float y1 = _scaleToPage(_y1);
            float x2 = _scaleToPage(_x2);
            float y2 = _scaleToPage(_y2);

            var sas = line.Style.StartArrowStyle;
            var eas = line.Style.EndArrowStyle;
            float a1 = (float)(Math.Atan2(y1 - y2, x1 - x2) * 180.0 / Math.PI);
            float a2 = (float)(Math.Atan2(y2 - y1, x2 - x1) * 180.0 / Math.PI);

            var t1 = new Matrix();
            var c1 = new PointF(x1, y1);
            t1.RotateAt(a1, c1);

            var t2 = new Matrix();
            var c2 = new PointF(x2, y2);
            t2.RotateAt(a2, c2);

            PointF pt1;
            PointF pt2;

            double radiusX1 = sas.RadiusX;
            double radiusY1 = sas.RadiusY;
            double sizeX1 = 2.0 * radiusX1;
            double sizeY1 = 2.0 * radiusY1;

            switch (sas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt1 = new PointF(x1, y1);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        var pts = new PointF[] { new PointF(x1 - (float)sizeX1, y1) };
                        t1.TransformPoints(pts);
                        pt1 = pts[0];
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        var gs = _gfx.Save();
                        _gfx.MultiplyTransform(t1);
                        DrawRectangleInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                        _gfx.Restore(gs);
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        var pts = new PointF[] { new PointF(x1 - (float)sizeX1, y1) };
                        t1.TransformPoints(pts);
                        pt1 = pts[0];
                        var gs = _gfx.Save();
                        _gfx.MultiplyTransform(t1);
                        var rect = new Rect2(x1 - sizeX1, y1 - radiusY1, sizeX1, sizeY1);
                        DrawEllipseInternal(_gfx, fillStartArrow, strokeStartArrow, sas.IsStroked, sas.IsFilled, ref rect);
                        _gfx.Restore(gs);
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        var pts = new PointF[]
                        {
                            new PointF(x1, y1),
                            new PointF(x1 - (float)sizeX1, y1 + (float)sizeY1),
                            new PointF(x1, y1),
                            new PointF(x1 - (float)sizeX1, y1 - (float)sizeY1),
                            new PointF(x1, y1)
                        };
                        t1.TransformPoints(pts);
                        pt1 = pts[0];
                        var p11 = pts[1];
                        var p21 = pts[2];
                        var p12 = pts[3];
                        var p22 = pts[4];
                        DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p11, ref p21);
                        DrawLineInternal(_gfx, strokeStartArrow, sas.IsStroked, ref p12, ref p22);
                    }
                    break;
            }

            double radiusX2 = eas.RadiusX;
            double radiusY2 = eas.RadiusY;
            double sizeX2 = 2.0 * radiusX2;
            double sizeY2 = 2.0 * radiusY2;

            switch (eas.ArrowType)
            {
                default:
                case ArrowType.None:
                    {
                        pt2 = new PointF(x2, y2);
                    }
                    break;
                case ArrowType.Rectangle:
                    {
                        var pts = new PointF[] { new PointF(x2 - (float)sizeX2, y2) };
                        t2.TransformPoints(pts);
                        pt2 = pts[0];
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        var gs = _gfx.Save();
                        _gfx.MultiplyTransform(t2);
                        DrawRectangleInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                        _gfx.Restore(gs);
                    }
                    break;
                case ArrowType.Ellipse:
                    {
                        var pts = new PointF[] { new PointF(x2 - (float)sizeX2, y2) };
                        t2.TransformPoints(pts);
                        pt2 = pts[0];
                        var gs = _gfx.Save();
                        _gfx.MultiplyTransform(t2);
                        var rect = new Rect2(x2 - sizeX2, y2 - radiusY2, sizeX2, sizeY2);
                        DrawEllipseInternal(_gfx, fillEndArrow, strokeEndArrow, eas.IsStroked, eas.IsFilled, ref rect);
                        _gfx.Restore(gs);
                    }
                    break;
                case ArrowType.Arrow:
                    {
                        var pts = new PointF[]
                        {
                            new PointF(x2, y2),
                            new PointF(x2 - (float)sizeX2, y2 + (float)sizeY2),
                            new PointF(x2, y2),
                            new PointF(x2 - (float)sizeX2, y2 - (float)sizeY2),
                            new PointF(x2, y2)
                        };
                        t2.TransformPoints(pts);
                        pt2 = pts[0];
                        var p11 = pts[1];
                        var p21 = pts[2];
                        var p12 = pts[3];
                        var p22 = pts[4];
                        DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p11, ref p21);
                        DrawLineInternal(_gfx, strokeEndArrow, eas.IsStroked, ref p12, ref p22);
                    }
                    break;
            }

            _gfx.DrawLine(strokeLine, pt1, pt2);

            fillLine.Dispose();
            strokeLine.Dispose();

            fillStartArrow.Dispose();
            strokeStartArrow.Dispose();

            fillEndArrow.Dispose();
            strokeEndArrow.Dispose();
        }
コード例 #31
0
ファイル: Rect2.cs プロジェクト: gitter-badger/Test2d
 /// <summary>
 ///
 /// </summary>
 /// <param name="tl"></param>
 /// <param name="br"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 Create(
     XPoint tl, XPoint br,
     double dx = 0.0, double dy = 0.0)
 {
     return(Rect2.Create(tl.X, tl.Y, br.X, br.Y, dx, dy));
 }
コード例 #32
0
ファイル: EmfRenderer.cs プロジェクト: monocraft/Test2d
        /// <summary>
        /// 
        /// </summary>
        /// <param name="gfx"></param>
        /// <param name="stroke"></param>
        /// <param name="rect"></param>
        /// <param name="offsetX"></param>
        /// <param name="offsetY"></param>
        /// <param name="cellWidth"></param>
        /// <param name="cellHeight"></param>
        /// <param name="isStroked"></param>
        private void DrawGridInternal(
            Graphics gfx,
            Pen stroke,
            ref Rect2 rect,
            double offsetX, double offsetY,
            double cellWidth, double cellHeight,
            bool isStroked)
        {
            double ox = rect.X;
            double oy = rect.Y;
            double sx = ox + offsetX;
            double sy = oy + offsetY;
            double ex = ox + rect.Width;
            double ey = oy + rect.Height;

            for (double x = sx; x < ex; x += cellWidth)
            {
                var p0 = new PointF(
                    _scaleToPage(x),
                    _scaleToPage(oy));
                var p1 = new PointF(
                    _scaleToPage(x),
                    _scaleToPage(ey));
                DrawLineInternal(gfx, stroke, isStroked, ref p0, ref p1);
            }

            for (double y = sy; y < ey; y += cellHeight)
            {
                var p0 = new PointF(
                    _scaleToPage(ox),
                    _scaleToPage(y));
                var p1 = new PointF(
                    _scaleToPage(ex),
                    _scaleToPage(y));
                DrawLineInternal(gfx, stroke, isStroked, ref p0, ref p1);
            }
        }
コード例 #33
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="image"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 GetImageBounds(XImage image, double dx, double dy)
 {
     return(Rect2.Create(image.TopLeft, image.BottomRight, dx, dy));
 }