예제 #1
0
        public static double AngleBetween(XVector vector1, XVector vector2)
        {
            double y = vector1._x * vector2._y - vector2._x * vector1._y;
            double x = vector1._x * vector2._x + vector1._y * vector2._y;

            return(Math.Atan2(y, x) * 57.295779513082323);
        }
예제 #2
0
 public static bool Equals(XVector vector1, XVector vector2)
 {
     if (vector1.X.Equals(vector2.X))
     {
         return(vector1.Y.Equals(vector2.Y));
     }
     return(false);
 }
예제 #3
0
        public static XVector Parse(string source)
        {
            TokenizerHelper helper = new TokenizerHelper(source, CultureInfo.InvariantCulture);
            string          str    = helper.NextTokenRequired();
            XVector         vector = new XVector(Convert.ToDouble(str, CultureInfo.InvariantCulture), Convert.ToDouble(helper.NextTokenRequired(), CultureInfo.InvariantCulture));

            helper.LastTokenRequired();
            return(vector);
        }
예제 #4
0
 /// <summary>
 /// Moves a rectangle by the specified amount.
 /// </summary>
 public void Offset(XVector offsetVector)
 {
     if (IsEmpty)
     {
         throw new InvalidOperationException("CannotCallMethod"); //SR.Get(SRID.Rect_CannotCallMethod, new object[0]));
     }
     _x += offsetVector.X;
     _y += offsetVector.Y;
 }
예제 #5
0
 public static XVector Add(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1._x + vector2._x, vector1._y + vector2._y));
 }
예제 #6
0
 public static double Determinant(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._y - vector1._y * vector2._x);
 }
예제 #7
0
 public static double Multiply(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._x + vector1._y * vector2._y);
 }
예제 #8
0
 public static XVector Multiply(XVector vector, XMatrix matrix)
 {
     return(matrix.Transform(vector));
 }
예제 #9
0
 public static XVector Divide(XVector vector, double scalar)
 {
     return(vector * (1.0 / scalar));
 }
예제 #10
0
 public static XVector Multiply(double scalar, XVector vector)
 {
     return(new XVector(vector._x * scalar, vector._y * scalar));
 }
예제 #11
0
 public static XPoint Add(XVector vector, XPoint point)
 {
     return(new XPoint(point.X + vector._x, point.Y + vector._y));
 }
예제 #12
0
 /// <summary>
 /// Adds a point and a vector.
 /// </summary>
 public static XPoint Add(XPoint point, XVector vector)
 {
     return(new XPoint(point._x + vector.X, point._y + vector.Y));
 }
예제 #13
0
 public bool Equals(XVector value)
 {
     return(Equals(this, value));
 }
예제 #14
0
 /// <summary>
 /// Subtracts a vector from a point.
 /// </summary>
 public static XPoint Subtract(XPoint point, XVector vector)
 {
     return(new XPoint(point._x - vector.X, point._y - vector.Y));
 }
예제 #15
0
 public static double CrossProduct(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._y - vector1._y * vector2._x);
 }
예제 #16
0
 /// <summary>
 /// Initializes a new instance of the XRect class.
 /// </summary>
 public XRect(XPoint point, XVector vector)
     : this(point, point + vector)
 {
 }
예제 #17
0
 /// <summary>
 /// Returns a rectangle that is offset from the specified rectangle by using the specified vector.
 /// </summary>
 public static XRect Offset(XRect rect, XVector offsetVector)
 {
     rect.Offset(offsetVector.X, offsetVector.Y);
     return(rect);
 }
        /// <summary>
        /// Creates between 1 and 5 Béziers curves from parameters specified like in WPF.
        /// </summary>
        public static List <XPoint> BezierCurveFromArc(XPoint point1, XPoint point2, XSize size,
                                                       double rotationAngle, bool isLargeArc, bool clockwise, PathStart pathStart)
        {
            // See also http://www.charlespetzold.com/blog/blog.xml from January 2, 2008:
            // http://www.charlespetzold.com/blog/2008/01/Mathematics-of-ArcSegment.html
            double δx = size.Width;
            double δy = size.Height;

            Debug.Assert(δx * δy > 0);
            double factor             = δy / δx;
            bool   isCounterclockwise = !clockwise;

            // Adjust for different radii and rotation angle.
            XMatrix matrix = new XMatrix();

            matrix.RotateAppend(-rotationAngle);
            matrix.ScaleAppend(δy / δx, 1);
            XPoint pt1 = matrix.Transform(point1);
            XPoint pt2 = matrix.Transform(point2);

            // Get info about chord that connects both points.
            XPoint  midPoint  = new XPoint((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
            XVector vect      = pt2 - pt1;
            double  halfChord = vect.Length / 2;

            // Get vector from chord to center.
            XVector vectRotated;

            // (comparing two Booleans here!)
            if (isLargeArc == isCounterclockwise)
            {
                vectRotated = new XVector(-vect.Y, vect.X);
            }
            else
            {
                vectRotated = new XVector(vect.Y, -vect.X);
            }

            vectRotated.Normalize();

            // Distance from chord to center.
            double centerDistance = Math.Sqrt(δy * δy - halfChord * halfChord);

            if (double.IsNaN(centerDistance))
            {
                centerDistance = 0;
            }

            // Calculate center point.
            XPoint center = midPoint + centerDistance * vectRotated;

            // Get angles from center to the two points.
            double α = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X);
            double β = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X);

            // (another comparison of two Booleans!)
            if (isLargeArc == (Math.Abs(β - α) < Math.PI))
            {
                if (α < β)
                {
                    α += 2 * Math.PI;
                }
                else
                {
                    β += 2 * Math.PI;
                }
            }

            // Invert matrix for final point calculation.
            matrix.Invert();
            double sweepAngle = β - α;

            // Let the algorithm of GDI+ DrawArc to Bézier curves do the rest of the job
            return(BezierCurveFromArc(center.X - δx * factor, center.Y - δy, 2 * δx * factor, 2 * δy,
                                      α / Calc.Deg2Rad, sweepAngle / Calc.Deg2Rad, pathStart, ref matrix));
        }
예제 #19
0
 public static XVector Subtract(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1._x - vector2._x, vector1._y - vector2._y));
 }
예제 #20
0
        //+-------------------------------------------------------------------------------------------------
        //
        //  Function: ArcToBezier
        //
        //  Synopsis: Compute the Bezier approximation of an arc
        //
        //  Notes:    This utilitycomputes the Bezier approximation for an elliptical arc as it is defined
        //            in the SVG arc spec. The ellipse from which the arc is carved is axis-aligned in its
        //            own coordinates, and defined there by its x and y radii. The rotation angle defines
        //            how the ellipse's axes are rotated relative to our x axis. The start and end points
        //            define one of 4 possible arcs; the sweep and large-arc flags determine which one of
        //            these arcs will be chosen. See SVG spec for details.
        //
        //            Returning pieces = 0 indicates a line instead of an arc
        //                      pieces = -1 indicates that the arc degenerates to a point
        //
        //--------------------------------------------------------------------------------------------------
        public static PointCollection ArcToBezier(double xStart, double yStart, double xRadius, double yRadius, double rotationAngle,
                                                  bool isLargeArc, bool isClockwise, double xEnd, double yEnd, out int pieces)
        {
            double  cosArcAngle, sinArcAngle, xCenter, yCenter, r, bezDist;
            XVector vecToBez1, vecToBez2;
            XMatrix matToEllipse;

            double fuzz2        = FUZZ * FUZZ;
            bool   isZeroCenter = false;

            pieces = -1;

            // In the following, the line segment between between the arc's start and
            // end points is referred to as "the chord".

            // Transform 1: Shift the origin to the chord's midpoint
            double x = (xEnd - xStart) / 2;
            double y = (yEnd - yStart) / 2;

            double halfChord2 = x * x + y * y;     // (half chord length)^2

            // Degenerate case: single point
            if (halfChord2 < fuzz2)
            {
                // The chord degeneartes to a point, the arc will be ignored
                return(null);
            }

            // Degenerate case: straight line
            if (!AcceptRadius(halfChord2, fuzz2, ref xRadius) || !AcceptRadius(halfChord2, fuzz2, ref yRadius))
            {
                // We have a zero radius, add a straight line segment instead of an arc
                pieces = 0;
                return(null);
            }

            if (xRadius == 0 || yRadius == 0)
            {
                // We have a zero radius, add a straight line segment instead of an arc
                pieces = 0;
                return(null);
            }

            // Transform 2: Rotate to the ellipse's coordinate system
            rotationAngle = -rotationAngle * Calc.Deg2Rad;

            double cos = Math.Cos(rotationAngle);
            double sin = Math.Sin(rotationAngle);

            r = x * cos - y * sin;
            y = x * sin + y * cos;
            x = r;

            // Transform 3: Scale so that the ellipse will become a unit circle
            x /= xRadius;
            y /= yRadius;

            // We get to the center of that circle along a verctor perpendicular to the chord
            // from the origin, which is the chord's midpoint. By Pythagoras, the length of that
            // vector is sqrt(1 - (half chord)^2).

            halfChord2 = x * x + y * y;   // now in the circle coordinates

            if (halfChord2 > 1)
            {
                // The chord is longer than the circle's diameter; we scale the radii uniformly so
                // that the chord will be a diameter. The center will then be the chord's midpoint,
                // which is now the origin.
                r            = Math.Sqrt(halfChord2);
                xRadius     *= r;
                yRadius     *= r;
                xCenter      = yCenter = 0;
                isZeroCenter = true;

                // Adjust the unit-circle coordinates x and y
                x /= r;
                y /= r;
            }
            else
            {
                // The length of (-y,x) or (x,-y) is sqrt(rHalfChord2), and we want a vector
                // of length sqrt(1 - rHalfChord2), so we'll multiply it by:
                r = Math.Sqrt((1 - halfChord2) / halfChord2);
                //if (isLargeArc != (eSweepDirection == SweepDirection.Clockwise))
                if (isLargeArc != isClockwise)
                // Going to the center from the origin=chord-midpoint
                {
                    // in the direction of (-y, x)
                    xCenter = -r * y;
                    yCenter = r * x;
                }
                else
                {
                    // in the direction of (y, -x)
                    xCenter = r * y;
                    yCenter = -r * x;
                }
            }

            // Transformation 4: shift the origin to the center of the circle, which then becomes
            // the unit circle. Since the chord's midpoint is the origin, the start point is (-x, -y)
            // and the endpoint is (x, y).
            XPoint ptStart = new XPoint(-x - xCenter, -y - yCenter);
            XPoint ptEnd   = new XPoint(x - xCenter, y - yCenter);

            // Set up the matrix that will take us back to our coordinate system.  This matrix is
            // the inverse of the combination of transformation 1 thru 4.
            matToEllipse = new XMatrix(cos * xRadius, -sin * xRadius,
                                       sin * yRadius, cos * yRadius,
                                       (xEnd + xStart) / 2, (yEnd + yStart) / 2);

            if (!isZeroCenter)
            {
                // Prepend the translation that will take the origin to the circle's center
                matToEllipse.OffsetX += (matToEllipse.M11 * xCenter + matToEllipse.M21 * yCenter);
                matToEllipse.OffsetY += (matToEllipse.M12 * xCenter + matToEllipse.M22 * yCenter);
            }

            // Get the sine & cosine of the angle that will generate the arc pieces
            GetArcAngle(ptStart, ptEnd, isLargeArc, isClockwise, out cosArcAngle, out sinArcAngle, out pieces);

            // Get the vector to the first Bezier control point
            bezDist = GetBezierDistance(cosArcAngle, 1);

            //if (eSweepDirection == SweepDirection.Counterclockwise)
            if (!isClockwise)
            {
                bezDist = -bezDist;
            }

            vecToBez1 = new XVector(-bezDist * ptStart.Y, bezDist * ptStart.X);

            PointCollection result = new PointCollection();

            // Add the arc pieces, except for the last
            for (int idx = 1; idx < pieces; idx++)
            {
                // Get the arc piece's endpoint
                XPoint ptPieceEnd = new XPoint(ptStart.X * cosArcAngle - ptStart.Y * sinArcAngle, ptStart.X * sinArcAngle + ptStart.Y * cosArcAngle);
                vecToBez2 = new XVector(-bezDist * ptPieceEnd.Y, bezDist * ptPieceEnd.X);

                result.Add(matToEllipse.Transform(ptStart + vecToBez1));
                result.Add(matToEllipse.Transform(ptPieceEnd - vecToBez2));
                result.Add(matToEllipse.Transform(ptPieceEnd));

                // Move on to the next arc
                ptStart   = ptPieceEnd;
                vecToBez1 = vecToBez2;
            }

            // Last arc - we know the endpoint
            vecToBez2 = new XVector(-bezDist * ptEnd.Y, bezDist * ptEnd.X);

            result.Add(matToEllipse.Transform(ptStart + vecToBez1));
            result.Add(matToEllipse.Transform(ptEnd - vecToBez2));
            result.Add(new XPoint(xEnd, yEnd));

            return(result);
        }