/// <summary>
 /// Initializes a new instance of the <see cref="XLinearGradientBrush"/> class.
 /// </summary>
 public XLinearGradientBrush(XPoint point1, XPoint point2, XColor color1, XColor color2) : base(color1, color2)
 {
     _point1 = point1;
     _point2 = point2;
 }
        /// <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));
        }
Esempio n. 3
0
 /// <summary>
 /// Returns the intersection of a rectangle and a point.
 /// </summary>
 public static XRect Union(XRect rect, XPoint point)
 {
     rect.Union(new XRect(point, point));
     return(rect);
 }
Esempio n. 4
0
 /// <summary>
 /// Initializes a new instance of the XRect class.
 /// </summary>
 public XRect(XPoint point, XVector vector)
     : this(point, point + vector)
 {
 }
        /// <summary>
        /// Appends a Bézier segment from a curve.
        /// </summary>
        public static BezierSegment CreateCurveSegment(XPoint pt0, XPoint pt1, XPoint pt2, XPoint pt3, double tension3)
        {
#if !SILVERLIGHT && !NETFX_CORE
            return(new BezierSegment(
                       new SysPoint(pt1.X + tension3 * (pt2.X - pt0.X), pt1.Y + tension3 * (pt2.Y - pt0.Y)),
                       new SysPoint(pt2.X - tension3 * (pt3.X - pt1.X), pt2.Y - tension3 * (pt3.Y - pt1.Y)),
                       new SysPoint(pt2.X, pt2.Y), true));
#else
            BezierSegment bezierSegment = new BezierSegment();
            bezierSegment.Point1 = new SysPoint(pt1.X + tension3 * (pt2.X - pt0.X), pt1.Y + tension3 * (pt2.Y - pt0.Y));
            bezierSegment.Point2 = new SysPoint(pt2.X - tension3 * (pt3.X - pt1.X), pt2.Y - tension3 * (pt3.Y - pt1.Y));
            bezierSegment.Point3 = new SysPoint(pt2.X, pt2.Y);
            return(bezierSegment);
#endif
        }
Esempio n. 6
0
 /// <summary>
 /// Sets current rectangle to the union of the current rectangle and the specified point.
 /// </summary>
 public void Union(XPoint point)
 {
     Union(new XRect(point, point));
 }
Esempio n. 7
0
 /// <summary>
 /// Indicates whether the specified points are equal.
 /// </summary>
 public static bool Equals(XPoint point1, XPoint point2)
 {
     return(point1.X.Equals(point2.X) && point1.Y.Equals(point2.Y));
 }
Esempio n. 8
0
        // ----- AddString ----------------------------------------------------------------------------

        /// <summary>
        /// Adds a text string to this path.
        /// </summary>
        public void AddString(string s, XFontFamily family, XFontStyle style, double emSize, XPoint origin,
                              XStringFormat format)
        {
            try
            {
                DiagnosticsHelper.HandleNotImplemented("XGraphicsPath.AddString");
            }
            catch
            {
                throw;
            }
        }
Esempio n. 9
0
 /// <summary>
 /// Subtracts a point from a point.
 /// </summary>
 public static XVector Subtract(XPoint point1, XPoint point2)
 {
     return(new XVector(point1._x - point2._x, point1._y - point2._y));
 }
Esempio n. 10
0
 /// <summary>
 /// Multiplies a point with a matrix.
 /// </summary>
 public static XPoint Multiply(XPoint point, XMatrix matrix)
 {
     return(matrix.Transform(point));
 }
Esempio n. 11
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));
 }
Esempio n. 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));
 }
Esempio n. 13
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);
        }
Esempio n. 14
0
        // ----- AddBezier ----------------------------------------------------------------------------

        /// <summary>
        /// Adds a cubic Bézier curve to the current figure.
        /// </summary>
        public void AddBezier(XPoint pt1, XPoint pt2, XPoint pt3, XPoint pt4)
        {
            AddBezier(pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
        }
Esempio n. 15
0
 /// <summary>
 /// Indicates whether this instance and a specified point are equal.
 /// </summary>
 public bool Equals(XPoint value)
 {
     return(Equals(this, value));
 }
Esempio n. 16
0
 /// <summary>
 /// Adds an elliptical arc to the current figure. The arc is specified WPF like.
 /// </summary>
 public void AddArc(XPoint point1, XPoint point2, XSize size, double rotationAngle, bool isLargeArg, XSweepDirection sweepDirection)
 {
     _corePath.AddArc(point1, point2, size, rotationAngle, isLargeArg, sweepDirection);
 }
Esempio n. 17
0
 /// <summary>
 /// Indicates whether the rectangle contains the specified point.
 /// </summary>
 public bool Contains(XPoint point)
 {
     return(Contains(point.X, point.Y));
 }
Esempio n. 18
0
        // ----- AddLine ------------------------------------------------------------------------------

        /// <summary>
        /// Adds  a line segment to current figure.
        /// </summary>
        public void AddLine(XPoint pt1, XPoint pt2)
        {
            AddLine(pt1.X, pt1.Y, pt2.X, pt2.Y);
        }
Esempio n. 19
0
        GetArcAngle(
            XPoint startPoint,   // Start point
            XPoint endPoint,     // End point
            bool isLargeArc,     // Choose the larger of the 2 possible arcs if TRUE
            //SweepDirection sweepDirection,      // Direction n which to sweep the arc.
            bool isClockwise,
            out double cosArcAngle, // Cosine of a the sweep angle of one arc piece
            out double sinArcAngle, // Sine of a the sweep angle of one arc piece
            out int pieces)         // Out: The number of pieces
        {
            double angle;

            // The points are on the unit circle, so:
            cosArcAngle = startPoint.X * endPoint.X + startPoint.Y * endPoint.Y;
            sinArcAngle = startPoint.X * endPoint.Y - startPoint.Y * endPoint.X;

            if (cosArcAngle >= 0)
            {
                if (isLargeArc)
                {
                    // The angle is between 270 and 360 degrees, so
                    pieces = 4;
                }
                else
                {
                    // The angle is between 0 and 90 degrees, so
                    pieces = 1;
                    return; // We already have the cosine and sine of the angle
                }
            }
            else
            {
                if (isLargeArc)
                {
                    // The angle is between 180 and 270 degrees, so
                    pieces = 3;
                }
                else
                {
                    // The angle is between 90 and 180 degrees, so
                    pieces = 2;
                }
            }

            // We have to chop the arc into the computed number of pieces.  For cPieces=2 and 4 we could
            // have uses the half-angle trig formulas, but for pieces=3 it requires solving a cubic
            // equation; the performance difference is not worth the extra code, so we'll get the angle,
            // divide it, and get its sine and cosine.

            Debug.Assert(pieces > 0);
            angle = Math.Atan2(sinArcAngle, cosArcAngle);

            if (isClockwise)
            {
                if (angle < 0)
                {
                    angle += Math.PI * 2;
                }
            }
            else
            {
                if (angle > 0)
                {
                    angle -= Math.PI * 2;
                }
            }

            angle      /= pieces;
            cosArcAngle = Math.Cos(angle);
            sinArcAngle = Math.Sin(angle);
        }