1

簡単な答えがあることを願っています。多くの場合、Compact Frameworkから削除されたものは、一見回りくどい方法で実行されますが、完全なフレームワークと同じように機能します(またはより効率的にすることができます)。

簡単に言えば、Compact Framework 2.0のSystem.Drawing.Graphics.DrawArc(...)と同様の機能を実行できるようにしたいと考えています。

これは、UserControlのOnPaintオーバーライド用であり、既に塗りつぶした楕円の内側に円弧が描画されます。

基本的に(疑似コードを閉じます。パラメーターの欠陥は無視してください):

FillEllipse(ellipseFillBrush, largeEllipseRegion);
DrawArc(arcPen, innerEllipseRegion, startAngle, endAngle); //not available in CF

私は90度のスペースでのみ円弧を描いているので、楕円の円弧の右下隅、つまり左上隅です。任意の角度の答えが本当に回り道、難しい、または非効率的である場合、楕円の角だけを行うための簡単な解決策がありますが、前者は同様の質問をしている他の人を助けるでしょうが、後者は問題ありません。

4

3 に答える 3

4

このコードを使用してから、出力ポイントでFillPolygonまたはDrawPolygonを使用します。

private Point[] CreateArc(float StartAngle, float SweepAngle, int PointsInArc, int Radius, int xOffset, int yOffset, int LineWidth)
{
    if(PointsInArc < 0)
        PointsInArc = 0;

    if(PointsInArc > 360)
        PointsInArc = 360;

    Point[] points = new Point[PointsInArc * 2];
    int xo;
    int yo;
    int xi;
    int yi;
    float degs;
    double rads;

    for(int p = 0 ; p < PointsInArc ; p++)
    {
        degs = StartAngle + ((SweepAngle / PointsInArc) * p);

        rads = (degs * (Math.PI / 180));

        xo = (int)(Radius * Math.Sin(rads));
        yo = (int)(Radius * Math.Cos(rads));
        xi = (int)((Radius - LineWidth) * Math.Sin(rads));
        yi = (int)((Radius - LineWidth) * Math.Cos(rads));

        xo += (Radius + xOffset);
        yo = Radius - yo + yOffset;
        xi += (Radius + xOffset);
        yi = Radius - yi + yOffset;

        points[p] = new Point(xo, yo);
        points[(PointsInArc * 2) - (p + 1)] = new Point(xi, yi);
    }

    return points;
}
于 2012-08-27T15:57:40.220 に答える
1

私はまさにこの問題を抱えていました。私と私のチームは、コンパクトフレームワークグラフィックスクラスの拡張メソッドを作成することを解決しました。

私は誰かを助けることができるといいのですが、私はこの素晴らしい解決策を得るために多くの仕事を費やしました

マウリシオデスーザコエーリョ

組み込みソフトウェアエンジニア

public static class GraphicsExtension
{
    // Implements the native Graphics.DrawArc as an extension
    public static void DrawArc(this Graphics g, Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle)
    {
        //Configures the number of degrees for each line in the arc
        int degreesForNewLine = 5;

        //Calculates the number of points in the arc based on the degrees for new line configuration
        int pointsInArc = Convert.ToInt32(Math.Ceiling(sweepAngle / degreesForNewLine)) + 1;

        //Minimum points for an arc is 3
        pointsInArc = pointsInArc < 3 ? 3 : pointsInArc;

        float centerX = (x + width) / 2;
        float centerY = (y + height) / 2;

        Point previousPoint = GetEllipsePoint(x, y, width, height, startAngle);

        //Floating point precision error occurs here
        double angleStep = sweepAngle / pointsInArc;

        Point nextPoint;
        for (int i = 1; i < pointsInArc; i++)
        {
            //Increments angle and gets the ellipsis associated to the incremented angle
            nextPoint = GetEllipsePoint(x, y, width, height, (float)(startAngle + angleStep * i));

            //Connects the two points with a straight line
            g.DrawLine(pen, previousPoint.X, previousPoint.Y, nextPoint.X, nextPoint.Y);

            previousPoint = nextPoint;
        }

        //Garantees connection with the last point so that acumulated errors cannot
        //cause discontinuities on the drawing
        nextPoint = GetEllipsePoint(x, y, width, height, startAngle + sweepAngle);
        g.DrawLine(pen, previousPoint.X, previousPoint.Y, nextPoint.X, nextPoint.Y);
    }

    // Retrieves a point of an ellipse with equation:
    private static Point GetEllipsePoint(float x, float y, float width, float height, float angle)
    {
        return new Point(Convert.ToInt32(((Math.Cos(ToRadians(angle)) * width + 2 * x + width) / 2)), Convert.ToInt32(((Math.Sin(ToRadians(angle)) * height + 2 * y + height) / 2)));
    }

    // Converts an angle in degrees to the same angle in radians.
    private static float ToRadians(float angleInDegrees)
    {
        return (float)(angleInDegrees * Math.PI / 180);
    }
}
于 2014-06-05T20:26:17.433 に答える
0

円(高さ==幅)の円弧状のポリゴンを作成した@ctackeの応答に続いて、それをさらに編集し、ポリゴンではなく曲線のポイント配列を作成する関数を作成しました。任意の楕円。

注:ここでのStartAngleは正午の位置です。90度は3時の位置です。したがって、StartAngle=0およびSweepAngle=90は、正午から3時の位置まで弧を描きます。
元のDrawArcメソッドの3時は0度で、90度は6時の位置です。DrawArcをCreateArcに置き換え、続いてDrawLinesを結果のPoint[]配列に置き換える際の注意点です。
これをさらに変更して変更しますが、機能しているものを壊すのはなぜですか?

private Point[] CreateArc(float StartAngle, float SweepAngle, int PointsInArc, int ellipseWidth, int ellipseHeight, int xOffset, int yOffset)
{
    if (PointsInArc < 0)
        PointsInArc = 0;

    if (PointsInArc > 360)
        PointsInArc = 360;

    Point[] points = new Point[PointsInArc];
    int xo;
    int yo;
    float degs;
    double rads;

    //could have WidthRadius and HeightRadius be parameters, but easier
    // for maintenance to have the diameters sent in instead, matching closer
    // to DrawEllipse and similar methods
    double radiusW = (double)ellipseWidth / 2.0;
    double radiusH = (double)ellipseHeight / 2.0;

    for (int p = 0; p < PointsInArc; p++)
    {
        degs = StartAngle + ((SweepAngle / PointsInArc) * p);

        rads = (degs * (Math.PI / 180));

        xo = (int)Math.Round(radiusW * Math.Sin(rads), 0);
        yo = (int)Math.Round(radiusH * Math.Cos(rads), 0);

        xo += (int)Math.Round(radiusW, 0) + xOffset;
        yo = (int)Math.Round(radiusH, 0) - yo + yOffset;

        points[p] = new Point(xo, yo);
    }

    return points;
}
于 2012-08-28T13:59:36.237 に答える