C#使用角度和Trig绘制多边形

时间:2010-11-11 07:36:25

标签: c# gdi+ trigonometry

我正在尝试创建简单的形状,Hexagon,五角大楼,三角形等,通过一个起点并计算每个顶点的其他点应该在哪里。我会不断创建直线或奇怪的重叠多边形。 我使用下面的方法尝试计算Hexagon的顶点,然后做一个简单的graphics.DrawPolygon(pen, aptsVertices)以便稍后绘制它。 任何帮助,将不胜感激。

protected override void CalculateVertices()
{
    //member variables
    aptsVertices = new Point[6];
    deg = 120;
    rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for(int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new Point((int)x, (int)y);

        //recalculate the degree for the next vertex
        deg += 120;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);
    }
}

4 个答案:

答案 0 :(得分:3)

好的,问题发生在deg += 120。实际上,您需要将deg减少step = 60°(或增加,具体取决于您所需的施工方向)*。

以下是通用数量的代码:

public static Point[] CalculateVertices(int nSides, int nSideLength, Point ptFirstVertex)
{
    if (nSides < 3)
        throw new ArgumentException("Polygons can't have less than 3 sides...");

    var aptsVertices = new Point[nSides];
    var deg = (180.0 * (nSides - 2)) / nSides;
    var step = 360.0 / nSides;
    var rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for (int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new Point((int)x, (int)y);


        //recalculate the degree for the next vertex
        deg -= step;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);

    }
    return aptsVertices;
}

*

减去该步骤,您将构建一个逆时针添加边的多边形 添加步骤,您将构建一个顺时针添加边的多边形 如果您想更改第一面的倾斜度,只需将初始deg偏移所需的角度即可。

<强> P.S。
我做了一个静态方法只是因为我更方便测试,但你仍然可以使用你的实例方法。

答案 1 :(得分:0)

虽然我没有考虑你的算法;恕我直言,更好的方法是定义中心点;并使用point [i] = new Point (center.x + sideLength * cos ((Math.PI * i) / 6), center.y + sideLength * sin ((Math.PI * i) / 6));让您的代码计算其他点(六位,如果是六边形)。

答案 2 :(得分:0)

上面的静态函数是正确的,但是因为它将点计算为整数,所以舍入误差会逐渐变小。即使对于5边多边形,顶点计算也会偏离几个像素。

我替换了一个使用双精度而不是整数的Point类来消除舍入误差。绘制顶点时,您可以舍入到最接近的整数。

否则,代码完全相同。

public static PointD[] CalculateVertices(int nSides, int nSideLength, PointD ptFirstVertex)
{
    //calculate the points for a polygon of N sides
    if (nSides < 3)
        throw new ArgumentException("Polygons can't have less than 3 sides...");

    var aptsVertices = new PointD[nSides];
    var deg = (180.0 * (nSides - 2)) / nSides;
    var step = 360.0 / nSides;
    var rad = deg * (Math.PI / 180);

    double nSinDeg = Math.Sin(rad);
    double nCosDeg = Math.Cos(rad);

    aptsVertices[0] = ptFirstVertex;

    for (int i = 1; i < aptsVertices.Length; i++)
    {
        double x = aptsVertices[i - 1].X - nCosDeg * nSideLength;
        double y = aptsVertices[i - 1].Y - nSinDeg * nSideLength;
        aptsVertices[i] = new PointD(x, y);

        //recalculate the degree for the next vertex
        deg -= step;
        rad = deg * (Math.PI / 180);

        nSinDeg = Math.Sin(rad);
        nCosDeg = Math.Cos(rad);

    }
    return aptsVertices;
}

这是新的点类。

public class PointD
{
    public double X, Y;
    public PointD(double _x, double _y)
    {
        X = _x;
        Y = _y;
    }
}

答案 3 :(得分:0)

我知道这是一个旧线程,但我最近使用过它,所以我想我添加了一些可能对某些人有帮助的修改。

我使用了上面的代码,但是通过使用中心点设置第一个顶点并偏移第一个度数,我能够围绕中心点创建一个多边形。我还添加了一种基于半径计算边长的方法。

这是我提出的(Objective-C中的代码):

-(NSArray *) calculateVertices:(int)numSides center:(CGPoint)ctr{
NSMutableArray *vertices = [[NSMutableArray alloc] init];

if (numSides < 3) {
    return vertices;
}

float deg = ((180.0 * (numSides-2) / numSides)-180)/2;

float step = 360.0 / numSides;
float rad = deg * (M_PI / 180);

double nSinDeg = sin(rad);
double nCosDeg = cos(rad);

int sl = [self calculateSideLength:numSides];

CGPoint firstPoint = CGPointMake(ctr.x, ctr.y-radius);    
[vertices addObject:[NSValue valueWithCGPoint:firstPoint]];

for (int i = 1; i < numSides; i++) {
    NSValue *vp = [vertices objectAtIndex:i-1];
    CGPoint pp =[vp CGPointValue];
    double x = pp.x - nCosDeg * sl;
    double y = pp.y - nSinDeg * sl;
    CGPoint np = CGPointMake(x, y);
    [vertices addObject:[NSValue valueWithCGPoint:np]];

    deg -= step;
    rad = deg * (M_PI / 180);

    nSinDeg = sin(rad);
    nCosDeg = cos(rad);

}

return vertices;

}

-(int) calculateSideLength:(int)numSides{
   int length = (2*radius)*sin(M_PI/numSides);
   return length;
}

注意:radius被设置为类属性,这就是为什么你没有看到它被设置在任何地方。此外,如果双方小于3,我不希望它抛出异常,因为我正在检查其他地方的数量。

我只是有一个问题,最好将边长作为参数传递,还是像我一样,从我的方法中调用方法?