Exemplo n.º 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);
        }
Exemplo n.º 2
0
 public static bool Equals(XVector vector1, XVector vector2)
 {
     if (vector1.X.Equals(vector2.X))
     {
         return(vector1.Y.Equals(vector2.Y));
     }
     return(false);
 }
Exemplo n.º 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);
        }
Exemplo n.º 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;
 }
Exemplo n.º 5
0
        public override bool Equals(object o)
        {
            if ((o == null) || !(o is XVector))
            {
                return(false);
            }
            XVector vector = (XVector)o;

            return(Equals(this, vector));
        }
Exemplo n.º 6
0
 public static double Multiply(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._x + vector1._y * vector2._y);
 }
Exemplo n.º 7
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;
        }
Exemplo n.º 8
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);
 }
Exemplo n.º 9
0
 public static XPoint Add(XVector vector, XPoint point)
 {
     return(new XPoint(point.X + vector._x, point.Y + vector._y));
 }
Exemplo n.º 10
0
 /// <summary>
 /// Transforms the specified vectors by this matrix.
 /// </summary>
 public void Transform(XVector[] vectors)
 {
   if (vectors != null)
   {
     int count = vectors.Length;
     for (int idx = 0; idx < count; idx++)
       MultiplyVector(ref vectors[idx].x, ref vectors[idx].y);
   }
 }
Exemplo n.º 11
0
 public static XVector Subtract(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1.x - vector2.x, vector1.y - vector2.y));
 }
Exemplo n.º 12
0
 public static XVector Multiply(XVector vector, XMatrix matrix)
 {
     return(matrix.Transform(vector));
 }
Exemplo n.º 13
0
 /// <summary>
 /// Initializes a new instance of the XRect class.
 /// </summary>
 public XRect(XPoint point, XVector vector)
   : this(point, point + vector)
 { }
Exemplo n.º 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));
 }
Exemplo n.º 15
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]));
   this.x += offsetVector.x;
   this.y += offsetVector.y;
 }
Exemplo n.º 16
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;
 }
Exemplo n.º 17
0
    /// <summary>
    /// Calculates the distance between an old anchor point and a new anchor point.
    /// </summary>
    /// <param name="oldType"></param>
    /// <param name="newType"></param>
    /// <param name="size"></param>
    public static XVector CalcDistance(AnchorType oldType, AnchorType newType, XSize size)
    {
      if (oldType == newType)
        return new XVector();

      XVector result;
      Delta delta = CodeBase.deltas[(int)oldType, (int)newType];
      result = new XVector(size.width / 2 * delta.x, size.height / 2 * delta.y);
      return result;
    }
Exemplo n.º 18
0
        public void DrawGraph(XGraphics gfx)
        {
            double yOff = page_.Height * 0.11;

            XRect rect = new XRect(20, yOff, page_.Width - 40, page_.Height - (yOff + 20));
            DrawingUtil.DrawOutlineRect(rect, gfx, cornerRadius);

            gfx.DrawRoundedRectangle(backgroundBrush, rect, cornerRadius);
            XPoint center = new XPoint(page_.Width * 0.5, page_.Height * 0.45);

            //Left & right boxes
            XRect leftRect = new XRect(center.X - 250, yOff + 5, 160, 25);
            XRect rightRect = new XRect(center.X + 90, yOff + 5, 160, 25);
            DrawingUtil.DrawOutlineRect(leftRect, gfx, new XSize(10,10));
            gfx.DrawRoundedRectangle(XBrushes.Yellow, leftRect, new XSize(10, 10));
            DrawingUtil.DrawOutlineRect(rightRect, gfx, new XSize(10,10));
            gfx.DrawRoundedRectangle(XBrushes.CornflowerBlue, rightRect, new XSize(10, 10));
            gfx.DrawString("Left", new XFont("Arial", 20), XBrushes.Black, new XPoint(leftRect.X + 80, leftRect.Y + 15), XStringFormats.Center);
            gfx.DrawString("Right", new XFont("Arial", 20), XBrushes.Black, new XPoint(rightRect.X + 80, rightRect.Y + 15), XStringFormats.Center);

            float graphSize = (float)page_.Height * 0.175f;
            XPoint[] polyPoints = DrawingUtil.Instance.GeneratePoints(center, graphSize, 7, gfx);
            gfx.DrawPolygon(backgroundBrush, polyPoints, XFillMode.Winding);

            XPen yellowPen = new XPen(XColors.Yellow, 2.5);
            XPen greenPen = new XPen(XColors.Green, 2.5);
            XPen perimeterPen = XPens.LightGray;
            XPen redPen = new XPen(XColors.Red, 2.5);

            GraphIcon hipFlexImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\HipFlex.png"),"Hip Flexion");
            GraphIcon hamStringImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\HSExt.png"), "Hamstring Extension");
            GraphIcon hipAbdImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\HipAbd.png"), "Hip Abduction");
            GraphIcon hipIntImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\HipInt.png"), "Hip Internal Rotation");
            GraphIcon hipExtImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\HipExt.png"), "Hip External Rotation");
            GraphIcon kneeFlexImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\KneeFlex.png"), "Knee Flexion");
            GraphIcon AnkleFlexImg = new GraphIcon(XImage.FromFile(Directory.GetCurrentDirectory() + @"\Content\AnkleFlex.png"), "Ankle Flexion");

            GraphIcon[] icons = new GraphIcon[] { hipFlexImg, hamStringImg, hipAbdImg, hipIntImg, hipExtImg, kneeFlexImg, AnkleFlexImg };

            //center out
            for (int l = 0; l < polyPoints.Length - 1; l++)
                gfx.DrawLine(greenPen, center, polyPoints[l]);

            //percentage Lines & icons
            gfx.DrawString(0 + "%", new XFont("Arial", 10), XBrushes.Black, center + new XPoint(5, 0));
            for (int j = 0; j < polyPoints.Length - 1; j++)
            {
                XPoint pt1 = polyPoints[j];
                XPoint pt2 = polyPoints[j + 1];

                for (int i = 10; i > 0; i--)
                {
                    float increment = -i * 0.1f;
                    if (j < 1)
                        gfx.DrawString((i * 10).ToString() + '%', new XFont("Arial", 8), XBrushes.Black, DrawingUtil.Instance.Interpolate(center, polyPoints[0], increment) + new XPoint(5, 0));

                    gfx.DrawLine(perimeterPen,
                        DrawingUtil.Instance.Interpolate(center, pt1, increment),
                        DrawingUtil.Instance.Interpolate(center, pt2, increment));
                }

                XVector vec = new XVector(pt1.X, pt1.Y);
                XVector vec2 = new XVector(center.X, center.Y);

                XImage img = icons[j].img;
                double wRatio = (double)img.PixelWidth / (double)img.PixelHeight;

                XVector dir = vec2 - vec;
                dir.Normalize();
                double txtOffset = dir.X * -10;
                XPoint halfmg = new XPoint(-20, -20);
                XPoint imgpos = new XPoint(dir.X * (-graphSize - 50), dir.Y * (-graphSize - 50)) + center + halfmg;
                gfx.DrawImage(img, new XRect(imgpos, new XSize(wRatio * 60, 60)));
                gfx.DrawString(icons[j].txt, arialSmall, XBrushes.Black, imgpos + new XPoint(txtOffset, -10), XStringFormats.Center);
            }

            //leftSide
            XPoint[] percentagePoints = new XPoint[polyPoints.Length - 1];
            for (int k = 0; k < polyPoints.Length - 1; k++)
            {
                Parameter kv = userParameters_.ElementAt(k);
                percentagePoints[k] = DrawingUtil.Instance.Interpolate(center, polyPoints[k], -kv.Percentage);
                gfx.DrawLine(yellowPen, center, DrawingUtil.Instance.Interpolate(center, polyPoints[k], -kv.AmberVal));
                gfx.DrawLine(redPen, center, DrawingUtil.Instance.Interpolate(center, polyPoints[k], -kv.RedVal));
            }

            gfx.DrawPolygon(new XPen(XColor.FromArgb(1, 0, 255, 255)),
                new XSolidBrush(XColor.FromArgb(100, 255, 255, 0)),
                percentagePoints,
                XFillMode.Alternate);
            XPoint[] linePoints = new XPoint[percentagePoints.Length + 1];
            for (int i = 0; i < percentagePoints.Length; i++)
            {
                linePoints[i] = percentagePoints[i];
            }

            linePoints[linePoints.Length - 1] = percentagePoints[0];
            gfx.DrawLines(new XPen(XColor.FromArgb(255, 255, 255, 0), 2), linePoints);

            //right side
            for (int k = 10; k < polyPoints.Length + 9; k++)
            {
                Parameter kv = userParameters_.ElementAt(k);
                percentagePoints[k - 10] = DrawingUtil.Instance.Interpolate(center, polyPoints[k - 10], -kv.Percentage);
                gfx.DrawLine(yellowPen, center, DrawingUtil.Instance.Interpolate(center, polyPoints[k -10], -kv.AmberVal));
                gfx.DrawLine(redPen, center, DrawingUtil.Instance.Interpolate(center, polyPoints[k - 10], -kv.RedVal));
            }

            gfx.DrawPolygon(new XPen(XColor.FromArgb(1, 0, 255, 255)),
                new XSolidBrush(XColor.FromArgb(100, 54, 127, 180)),
                percentagePoints,
                XFillMode.Alternate);

            for (int i = 0; i < percentagePoints.Length; i++)
            {
                linePoints[i] = percentagePoints[i];
            }
            linePoints[linePoints.Length - 1] = percentagePoints[0];
            gfx.DrawLines(new XPen(XColor.FromArgb(255, 54, 127, 180), 2), linePoints);

            XRect leftRectLSI = new XRect(center.X - 250, page_.Height * 0.725, 120, 25);
            XRect rightRectLSI = new XRect(center.X + 70, page_.Height * 0.725, 120, 25);
            XRect LSIRect = new XRect(page_.Width - 100, page_.Height * 0.725, 35, 25);

            XSize rad = new XSize(10, 10);

            DrawingUtil.DrawOutlineRect(leftRectLSI, gfx, rad);
            DrawingUtil.DrawOutlineRect(rightRectLSI, gfx, rad);
            DrawingUtil.DrawOutlineRect(LSIRect, gfx, rad);

            gfx.DrawRoundedRectangle(XBrushes.Yellow, leftRectLSI,rad);
            gfx.DrawRoundedRectangle(XBrushes.CornflowerBlue, rightRectLSI, rad);
            gfx.DrawRoundedRectangle(XBrushes.LightGray, LSIRect, rad);
            gfx.DrawString("Left", new XFont("Arial", 14), XBrushes.Black, new XPoint(leftRectLSI.X + 60, leftRectLSI.Y + 12.5), XStringFormats.Center);
            gfx.DrawString("Right", new XFont("Arial", 14), XBrushes.Black, new XPoint(rightRectLSI.X + 60, rightRectLSI.Y + 12.5), XStringFormats.Center);
            gfx.DrawString("LSI", new XFont("Arial", 14), XBrushes.Black, new XPoint(LSIRect.X + 17.5, LSIRect.Y + 10), XStringFormats.Center);

            for (int l = 0; l < polyPoints.Length - 1; l++)
            {
                XBrush leftParamCol = XBrushes.Green;
                XBrush rightParamCol = XBrushes.Green;
                XBrush lsiParamCol = XBrushes.Green;

                XFont arial = new XFont("Arial", 13,XFontStyle.Bold);

                Parameter leftParam = userParameters_.ElementAt(l);
                Parameter rightParam = userParameters_.ElementAt(l + 10);;

                leftParamCol = DrawingUtil.Instance.ChooseBrushColor(leftParam.Color);
                rightParamCol = DrawingUtil.Instance.ChooseBrushColor(rightParam.Color);

                char degree = Convert.ToChar('\u00b0');

                double increment = l * page_.Height * 0.025;
                double y = page_.Height * 0.775 + increment;

                XRect rl = new XRect(leftRectLSI.X + (leftRectLSI.Width * 0.5) - 25, y, 50, 15);
                DrawingUtil.DrawOutlineRect(rl, gfx, rad);

                gfx.DrawRoundedRectangle(leftParamCol, rl, rad);
                gfx.DrawString(leftParam.Value.ToString() + degree, arial, XBrushes.Black, new XPoint(rl.X + 25, rl.Y + 7.5), XStringFormats.Center);

                XRect rr = new XRect(rightRectLSI.X + (rightRectLSI.Width * 0.5) - 25, y, 50, 15);
                DrawingUtil.DrawOutlineRect(rr, gfx, rad);

                gfx.DrawRoundedRectangle(rightParamCol, rr, rad);
                gfx.DrawString(rightParam.Value.ToString() + degree, arial, XBrushes.Black, new XPoint(rr.X + 25, rr.Y + 7.5), XStringFormats.Center);

                XRect rlsi = new XRect(LSIRect.X + (LSIRect.Width * 0.5) - 17.5, y, 35, 15);
                DrawingUtil.DrawOutlineRect(rlsi, gfx, rad);

                lsiParamCol = DrawingUtil.Instance.ChooseBrushColor(leftParam.LSI, 49, 74);
                gfx.DrawRoundedRectangle(lsiParamCol, rlsi, rad);
                gfx.DrawString(leftParam.LSI.ToString("0") + "%", arial, XBrushes.Black, new XPoint(rlsi.X + 17.5, rlsi.Y + 7.5), XStringFormats.Center);

                gfx.DrawString(leftParam.Name.Substring(4,leftParam.Name.Length - 4), new XFont("Arial", 10), XBrushes.Black,
                    DrawingUtil.Instance.Interpolate(new XPoint(rl.X + rl.Width, y + 7.5), new XPoint(rr.X, y), -0.5), XStringFormats.TopCenter);

                gfx.DrawLine(XPens.DarkSlateGray, new XPoint(leftRectLSI.X, rl.Y + 17.5), new XPoint(rlsi.X + 35, rl.Y + 17.5));
            }
        }
Exemplo n.º 19
0
 public static double Determinant(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._y - vector1._y * vector2._x);
 }
Exemplo n.º 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);
        }
Exemplo n.º 21
0
 public static bool Equals(XVector vector1, XVector vector2)
 {
   return vector1.x == vector2.x && vector1.y == vector2.y;
 }
Exemplo n.º 22
0
 public static XVector Add(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1._x + vector2._x, vector1._y + vector2._y));
 }
Exemplo n.º 23
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));
 }
Exemplo n.º 24
0
 public static XVector Multiply(double scalar, XVector vector)
 {
     return(new XVector(vector.x * scalar, vector.y * scalar));
 }
Exemplo n.º 25
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));
 }
Exemplo n.º 26
0
 public static double Determinant(XVector vector1, XVector vector2)
 {
     return(vector1.x * vector2.y - vector1.y * vector2.x);
 }
Exemplo n.º 27
0
 public static double CrossProduct(XVector vector1, XVector vector2)
 {
   return vector1.x * vector2.y - vector1.y * vector2.x;
 }
Exemplo n.º 28
0
 /// <summary>
 /// Transforms the specified vector by this Matrix and returns the result.
 /// </summary>
 public XVector Transform(XVector vector)
 {
   XVector vector2 = vector;
   MultiplyVector(ref vector2.x, ref vector2.y);
   return vector2;
 }
Exemplo n.º 29
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);
 }
Exemplo n.º 30
0
        /// <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);
        }
Exemplo n.º 31
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);
 }
Exemplo n.º 32
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);
 }
Exemplo n.º 33
0
 /// <summary>
 /// Initializes a new instance of the XRect class.
 /// </summary>
 public XRect(XPoint point, XVector vector)
     : this(point, point + vector)
 {
 }
Exemplo n.º 34
0
 public static XVector Add(XVector vector1, XVector vector2)
 {
   return new XVector(vector1.x + vector2.x, vector1.y + vector2.y);
 }
Exemplo n.º 35
0
 public static XVector Multiply(XVector vector, double scalar)
 {
     return(new XVector(vector._x * scalar, vector._y * scalar));
 }
Exemplo n.º 36
0
 /// <summary>
 /// Indicates whether the values are so close that they can be considered as equal.
 /// </summary>
 public static bool AreClose(XVector vector1, XVector vector2)
 {
   return AreClose(vector1.X, vector2.X) && AreClose(vector1.Y, vector2.Y);
 }
Exemplo n.º 37
0
 public static XVector Subtract(XVector vector1, XVector vector2)
 {
   return new XVector(vector1.x - vector2.x, vector1.y - vector2.y);
 }
Exemplo n.º 38
0
        /// <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));
        }
Exemplo n.º 39
0
 public static XVector Multiply(double scalar, XVector vector)
 {
   return new XVector(vector.x * scalar, vector.y * scalar);
 }
Exemplo n.º 40
0
 public static double CrossProduct(XVector vector1, XVector vector2)
 {
     return(vector1.x * vector2.y - vector1.y * vector2.x);
 }
Exemplo n.º 41
0
 public static XVector Divide(XVector vector, double scalar)
 {
   return vector * (1.0 / scalar);
 }
Exemplo n.º 42
0
 public static XVector Add(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1.x + vector2.x, vector1.y + vector2.y));
 }
Exemplo n.º 43
0
 public static XVector Multiply(XVector vector, XMatrix matrix)
 {
   return matrix.Transform(vector);
 }
Exemplo n.º 44
0
 public static XPoint Add(XVector vector, XPoint point)
 {
     return(new XPoint(point.x + vector.x, point.y + vector.y));
 }
Exemplo n.º 45
0
 public static double Multiply(XVector vector1, XVector vector2)
 {
   return vector1.x * vector2.x + vector1.y * vector2.y;
 }
Exemplo n.º 46
0
 public static XVector Divide(XVector vector, double scalar)
 {
     return(vector * (1.0 / scalar));
 }
Exemplo n.º 47
0
 public static double CrossProduct(XVector vector1, XVector vector2)
 {
     return(vector1._x * vector2._y - vector1._y * vector2._x);
 }
Exemplo n.º 48
0
 public static double Multiply(XVector vector1, XVector vector2)
 {
     return(vector1.x * vector2.x + vector1.y * vector2.y);
 }
Exemplo n.º 49
0
 public bool Equals(XVector value)
 {
   return Equals(this, value);
 }
Exemplo n.º 50
0
 public static double Determinant(XVector vector1, XVector vector2)
 {
   return vector1.x * vector2.y - vector1.y * vector2.x;
 }
Exemplo n.º 51
0
 public static XVector Subtract(XVector vector1, XVector vector2)
 {
     return(new XVector(vector1._x - vector2._x, vector1._y - vector2._y));
 }
Exemplo n.º 52
0
 public bool Equals(XVector value)
 {
     return(Equals(this, value));
 }
Exemplo n.º 53
0
 public static bool Equals(XVector vector1, XVector vector2)
 {
   if (vector1.X.Equals(vector2.X))
     return vector1.Y.Equals(vector2.Y);
   return false;
 }