我正在尝试创建简单的形状,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);
}
}
答案 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,我不希望它抛出异常,因为我正在检查其他地方的数量。
我只是有一个问题,最好将边长作为参数传递,还是像我一样,从我的方法中调用方法?