绘制椭圆经过3个点

时间:2017-11-21 15:22:35

标签: c# wpf graphics gdi+ gdi

我有下一个任务 - 绘制椭圆槽3点(如图所示)。 ellipse
用户可以拖动那些改变椭圆大小的点。两个点放在大轴的边缘。在我的解决方案中,我使用GDI throug Graphics类。 现在我的解决方案是计算对应椭圆的矩形并使用 DrawEllipse方法和旋转变换(如果需要)。但是这个解决方案有很多数学计算。也许有最简单的方法来解决这个问题?

2 个答案:

答案 0 :(得分:2)

以下是如何使用旋转,短轴和两个顶点的DrawEllipse方法。

首先,我们计算边界Size的{​​{1}}:

鉴于Rectangle坐在Points A and B长度的短边上,我们得到了一个带有一点Pythagoras的长边:

smallSize

所以:

int longSide = (int)(Math.Sqrt((A.Y - B.Y) * (A.Y - B.Y) + (B.X - A.X) * (B.X - A.X)));

接下来我们需要旋转角度:

Size size = new System.Drawing.Size(longSide, smallSize);

这样可以更轻松地获得中心float angle = -(float)(Math.Atan2(A.Y - B.Y, B.X - A.X) * 180f / Math.PI);

Point C

我们想要的最后一件事是绘制一个给定Point C = new Point((A.X + B.X)/ 2, (A.Y + B.Y)/ 2); 的椭圆的例程,以一定的角度围绕Size旋转:

C

[![在此处输入图像说明] [1]] [1]

这是一个小小的测试平台,将它们整合在一起:

void DrawEllipse(Graphics G, Pen pen, Point center, Size size, float angle)
{
    int h2 = size.Height / 2;
    int w2 = size.Width / 2;
    Rectangle rect = new Rectangle( new Point(center.X - w2, center.Y - h2), size );

    G.TranslateTransform(center.X, center.Y);
    G.RotateTransform(angle);
    G.TranslateTransform(-center.X, -center.Y);
    G.DrawEllipse(pen, rect);
    G.ResetTransform();
}

网格是一个很好的帮手:

Point A = new Point(200, 200); // *
Point B = new Point(500, 250);
int smallSize = 50;


void doTheDraw(PictureBox pb)
{
    Bitmap bmp = new Bitmap(pb.Width, pb.Height);

    float angle = -(float)(Math.Atan2(A.Y - B.Y, B.X - A.X) * 180f / Math.PI);
    int longSide = (int)(Math.Sqrt((A.Y - B.Y) * (A.Y - B.Y) + (B.X - A.X) * (B.X - A.X)));
    Point C = new Point((A.X + B.X) / 2, (A.Y + B.Y) / 2);
    Size size = new System.Drawing.Size((int)longSide, smallSize);

    using (Pen pen = new Pen(Color.Orange, 3f))
    using (Graphics g = Graphics.FromImage(bmp))
    {
        // a nice background grid (optional):
        DrawGrid(g, 0, 0, 100, 50, 10,
            Color.LightSlateGray, Color.DarkGray, Color.Gainsboro);

        // show the points we use (optional):
        g.FillEllipse(Brushes.Red, A.X - 4, A.Y - 4, 8, 8);
        g.FillRectangle(Brushes.Red, B.X - 3, B.Y - 3, 7, 7);
        g.FillEllipse(Brushes.Red, C.X - 5, C.Y - 5, 11, 11);

        // show the connection line (optional):
        g.DrawLine(Pens.Orange, A, B);

        // here comes the ellipse:
        DrawEllipse(g, pen, C, size, angle);
    }
    pb.Image = bmp;
}

请注意,我创建了void DrawGrid(Graphics G, int ox, int oy, int major, int medium, int minor, Color c1, Color c2, Color c3) { using (Pen pen1 = new Pen(c1, 1f)) using (Pen pen2 = new Pen(c2, 1f)) using (Pen pen3 = new Pen(c3, 1f)) { pen2.DashStyle = DashStyle.Dash; pen3.DashStyle = DashStyle.Dot; for (int x = ox; x < G.VisibleClipBounds.Width; x += major) G.DrawLine(pen1, x, 0, x, G.VisibleClipBounds.Height); for (int y = oy; y < G.VisibleClipBounds.Height; y += major) G.DrawLine(pen1, 0, y, G.VisibleClipBounds.Width, y); for (int x = ox; x < G.VisibleClipBounds.Width; x += medium) G.DrawLine(pen2, x, 0, x, G.VisibleClipBounds.Height); for (int y = oy; y < G.VisibleClipBounds.Height; y += medium) G.DrawLine(pen2, 0, y, G.VisibleClipBounds.Width, y); for (int x = ox; x < G.VisibleClipBounds.Width; x += minor) G.DrawLine(pen3, x, 0, x, G.VisibleClipBounds.Height); for (int y = oy; y < G.VisibleClipBounds.Height; y += minor) G.DrawLine(pen3, 0, y, G.VisibleClipBounds.Width, y); } } 类级变量,因此我可以在测试期间修改它们(我做A, B, smallSide)..

正如您所看到的,我添加了*以使TrackBar动态;为了更有趣,我添加了这个smallside事件:

MouseClick

我希望我的一些逻辑可以帮助你实现你想要实现的目标。您提出的下一个问题是尝试添加更多信息并减少通用。

答案 1 :(得分:0)

计算将前两个点带到(-a, 0)(a, 0)的相似性变换(平移和旋转)。 [这可以通过矩阵变换或复数来完成。]

将相同的变换应用于第三点。现在,简化椭圆的方程是

x² / a² + y² / b² = 1.

您只需通过插入第三个点的缩小坐标

来确定参数b
b = y / √(1 - x²/a²).

现在你有了

  • 中心,
  • 轴的方向,
  • 长轴的长度,
  • 短轴的长度。