繁体   English   中英

计算点以创建曲线或样条曲线以绘制椭圆

[英]Calculate points to create a curve or spline to draw an ellipse

我正在使用Dundas地图,因此需要在地图上覆盖一些描述某些数据的气泡。 我想在地图上添加形状以实现此目的。 我可以添加一个三角形(或任何直线多边形),如下所示:

public static void AddShape(this MapControl map, List<MapPoint> points, Color color, string name)
{
    if (points[0].X != points[points.Count - 1].X && points[0].Y != points[points.Count - 1].Y)
        points.Add(points[0]);
    var shape = new Shape
    {
        Name = name,
        BorderColor = color,
        BorderStyle = MapDashStyle.Solid,
        BorderWidth = 1,
        Color = Color.FromArgb((int)(255 * (0.3)), color)
    };
    var segments = new[] {new ShapeSegment {Type = SegmentType.Polygon, Length = points.Count}};
    shape.AddSegments(points.ToArray(), segments);
    map.Shapes.Add(shape);
}

public static void AddBermudaTriangle(this MapControl map)
{
    var points = new List<MapPoint>
                     {
                         new MapPoint(-80.15, 26.0667),
                         new MapPoint(-64.75, 32.333),
                         new MapPoint(-66.07, 18.41)
                     };
    map.AddShape(points, Color.Red, "Bermuda Triangle");
}

百慕大三角

您会看到百慕大三角以红色覆盖了地图。 现在,我想计算一组要传递到我的AddShape方法的点,该方法将绘制椭圆或圆形。 我只需要一个简单的算法即可计算给定点数的x和y坐标。 也许从代表圆心的给定点开始。 例如:

public static void AddCircle(this MapControl map, Point centre, double radius, string name)
{
    var points = new List<MapPoint>();
    const int n = 360;
    for(var i = 0; i < n; i++)
    {
        //calculate x & y using n, radius and centre
        double x = 0;
        double y = 0;
        points.Add(new MapPoint(x, y));
    }
    map.AddShape(points, Color.Red, name);
}

我知道x,y的计算是简单的三角函数,但是我正陷入大脑冻结。 救命!

编辑(使用tur!ng的代码解决):

public static void AddCircle(this MapControl map, Color color, MapPoint centre, double radius, string name)
{
    var points = new List<MapPoint>();
    const int n = 360;
    for(var i = 0; i < n; i++)
    {
        var x = (radius * Math.Cos(i * Math.PI / 180)) + centre.X;
        var y = (radius * Math.Sin(i * Math.PI / 180)) + centre.Y;
        points.Add(new MapPoint(x, y));
    }
    map.AddShape(points, color, name);
}

替代文字

由于罗宾逊网格上的地图投影,蓝色圆圈(格林威治上)变形了。

  double x = centre.x + radius*Math.cos(2*Math.PI/360 * i);
  double y = centre.y + radius*Math.sin(2*Math.PI/360 * i);

一圈。

从我很久以前写的一个旧的C ++程序复制过来的,它仍然可以在许多地方运行:

  // Approximate arc with small line segments
  double sa = dp[ix].center.angle(dp[ix].co);
  double ea = dp[ix].center.angle(dp[ix+1].co);
  double r = scale * dp[ix].radius;
  double rot = ea - sa;
  double inc = rot;
  if (dp[ix].dir == ROTCW) rot = -rot;
  if (rot < 0) rot += 2*PI;
  // Compute rotation increment that generates less than 1/4 pixel error
  if (r > 2) inc = 2*acos(1-0.25/r);
  if (inc >= rot || r < 2) addPoint(x, y);
  else {
    int cnt = int(1 + rot / inc);
    inc = rot / cnt;
    if (dp[ix].dir == ROTCW) inc = -inc;
    for (int jx = 0; jx < cnt; ++jx) {
      x = offsx + scale * dp[ix].center.x + r * cos(sa);
      y = offsy + scale * dp[ix].center.y + r * sin(sa);
      addPoint(x, y);
      sa += inc;
    }
  }

acos()与Math.Acos()相同。

回想一下,圆的公式可以表示为

(x/r)**2 + (y/r)**2 = 1

其中x和y是坐标,r是半径。

椭圆的公式可以表示为

(x/a)**2 + (y/b)**2 = 1

其中a和b是半长轴和半短轴(无特定顺序)。 选择a和b给您一个看起来“不错”的椭圆。

通常,您希望以相等的角度步长围绕圆点拾取点,以使逼真多边形看起来更逼真。 为此,您使用替代

x = r cos theta
y = r sin theta

并从零到2 * pi运行theta循环。 对于椭圆,您将使用

x = a cos theta
y = b sin theta

这样可以使椭圆形的半长轴和半短轴平行于X和Y轴,并以原点为中心。 如果要使用任意位置的任意方向,则需要旋转角度phi和平移。 任何好的计算机图形文字都会为您提供必要的方程式,最有可能采用矩阵形式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM