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 是 NOON 位置,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 回答