예제 #1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="line1Start"></param>
 /// <param name="line1End"></param>
 /// <param name="line2Start"></param>
 /// <param name="line2End"></param>
 /// <returns></returns>
 public static double AngleLineSegments(
     Point2 line1Start, Point2 line1End,
     Point2 line2Start, Point2 line2End)
 {
     double angle1 = Math.Atan2(line1Start.Y - line1End.Y, line1Start.X - line1End.X);
     double angle2 = Math.Atan2(line2Start.Y - line2End.Y, line2Start.X - line2End.X);
     double result = (angle2 - angle1) * 180.0 / Math.PI;
     if (result < 0)
         result += 360.0;
     return result;
 }
예제 #2
0
파일: Point2.cs 프로젝트: hacklex/Core2D
 /// <summary>
 /// 
 /// </summary>
 /// <param name="centerPoint"></param>
 /// <param name="angleInDegrees"></param>
 /// <returns></returns>
 public Point2 RotateAt(
     Point2 centerPoint,
     double angleInDegrees)
 {
     double angleInRadians = angleInDegrees * (Math.PI / 180.0);
     double cosTheta = Math.Cos(angleInRadians);
     double sinTheta = Math.Sin(angleInRadians);
     return new Point2
     {
         X = (cosTheta * (this.X - centerPoint.X) - sinTheta * (this.Y - centerPoint.Y) + centerPoint.X),
         Y = (sinTheta * (this.X - centerPoint.X) + cosTheta * (this.Y - centerPoint.Y) + centerPoint.Y)
     };
 }
예제 #3
0
파일: Point2.cs 프로젝트: hacklex/Core2D
 /// <summary>
 /// 
 /// </summary>
 /// <param name="point"></param>
 /// <returns></returns>
 public double Distance(Point2 point)
 {
     double dx = this.X - point.X;
     double dy = this.Y - point.Y;
     return Math.Sqrt(dx * dx + dy * dy);
 }
예제 #4
0
파일: Rect2.cs 프로젝트: monocraft/Core2D
 /// <summary>
 /// 
 /// </summary>
 /// <param name="tl"></param>
 /// <param name="br"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 Create(
     Point2 tl, Point2 br,
     double dx = 0.0, double dy = 0.0)
 {
     return Rect2.Create(tl.X, tl.Y, br.X, br.Y, dx, dy);
 }
예제 #5
0
        /// <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;
        }
예제 #6
0
        /// <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;
        }
예제 #7
0
        /// <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
        /// <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);
        }
예제 #9
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
            });
        }
예제 #10
0
파일: Rect2.cs 프로젝트: monocraft/Core2D
 /// <summary>
 ///
 /// </summary>
 /// <param name="tl"></param>
 /// <param name="br"></param>
 /// <param name="dx"></param>
 /// <param name="dy"></param>
 /// <returns></returns>
 public static Rect2 Create(
     Point2 tl, Point2 br,
     double dx = 0.0, double dy = 0.0)
 {
     return(Rect2.Create(tl.X, tl.Y, br.X, br.Y, dx, dy));
 }