【问题标题】:Calculate points to create a curve or spline to draw an ellipse计算点以创建曲线或样条曲线以绘制椭圆
【发布时间】:2010-02-17 11:23:09
【问题描述】:

我正在使用 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);
}

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

【问题讨论】:

    标签: c# algorithm graphics dundas


    【解决方案1】:
      double x = centre.x + radius*Math.cos(2*Math.PI/360 * i);
      double y = centre.y + radius*Math.sin(2*Math.PI/360 * i);
    

    一个圆圈。

    【讨论】:

      【解决方案2】:

      从我很久以前写的一个旧的 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() 相同。

      【讨论】:

      • 谢谢,旋转增量对我有用!
      • Hans,如果您还在,请介意在该代码中解释一些内容吗? dp 数组中的类型是什么?我猜是几何数组?它的“co”属性是什么?什么是规模?我猜它是双倍的,但数量级是多少。我有一个移植到 C# 的可编译版本,但距离工作代码还有很长的路要走。
      【解决方案3】:

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

      (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 的旋转和平移。任何好的计算机图形文本都会为您提供必要的方程式,最有可能是矩阵形式。

      【讨论】:

      • 谢谢!我正在使用您的建议进行椭圆实现。
      猜你喜欢
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多