绘制一个具有指定"肥度的椭圆"两点之间

时间:2016-05-01 12:31:53

标签: c# graphics gdi

我有一个C#位图对象,我能够从A点到B点画一条线。

我在图的边缘有2个点,我想绘制一个从A到B的椭圆。基本的g.DrawEllipse()只能完美地水平或垂直绘制椭圆,但我需要椭圆来从图像的一端到另一端的对角线。

My bitmap:    200 tall by 500 wide
Point A:      Column 0, Row 20   (0,20)
Point B:      Column 499, Row 60 (499, 60)
Widest Point: 30  - Narrow Radius of the ellipse

这是我到目前为止,绘制椭圆没有我需要的重载,所以请帮助那里:

    using (Graphics g = Graphics.FromImage(bmp))
    {
        g.DrawLine(pen, new Point(20,0), new Point(499,60));
        g.DrawEllipse(pen, 20, 0, someWidth, someHeight);
    }

2 个答案:

答案 0 :(得分:6)

以下是如何使用旋转,短轴和两个顶点的import flash.media.Sound; //button 1, see if the first text field equals the answer, if it does it plays the correct scene, if it doesnt it plays incorrect scene myTextField11.addEventListener(MouseEvent.MOUSE_UP,state11); function state11(evt:MouseEvent) { if (myTextField11.text == answer1) { trace("Correct answer!!"); gotoAndPlay(2,"quiz1"); count = count + 10; scoreBox.text = (count).toString(); setTimeout(gotoAndPlay, 1250, 1, "quiz2"); } else { trace(myTextField11); gotoAndPlay(3,"quiz1"); var mySound:Sound = new WrongAnswer(); //WrongAnswer.play(); mySound.play(); setTimeout(gotoAndPlay, 1250, 1,"quiz2"); } } 方法。

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

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

Points A and B

所以:

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

enter image description here

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

C

网格是一个很好的帮手:

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 :(得分:1)

如果您希望使用Graphics创建对角线椭圆,也许您可​​以使用DrawBezier()方法。 以下是一些代码:

// Draws an ellipse using 2 beziers.
private void DrawEllipse(Graphics g, PointF center, float width, float height, double rotation)
{
  // Unrotated ellipse frame
  float left   = center.X - width / 2;
  float right  = center.X + width / 2;
  float top      = center.Y - height / 2;
  float bottom   = center.Y + height / 2;
  PointF p1 = new PointF(left, center.Y);
  PointF p2 = new PointF(left, top);
  PointF p3 = new PointF(right, top);
  PointF p4 = new PointF(right, center.Y);
  PointF p5 = new PointF(right, bottom);
  PointF p6 = new PointF(left, bottom);

  // Draw ellipse with rotated points.
  g.DrawBezier(Pens.Black, Rotate(p1, center, rotation), Rotate(p2, center, rotation), Rotate(p3, center, rotation), Rotate(p4, center, rotation));
  g.DrawBezier(Pens.Black, Rotate(p4, center, rotation), Rotate(p5, center, rotation), Rotate(p6, center, rotation), Rotate(p1, center, rotation));
}

// Rotating a given point by given angel around a given pivot.
private PointF Rotate(PointF point, PointF pivot, double angle)
{
  float x = point.X - pivot.X;
  float y = point.Y - pivot.Y;
  double a = Math.Atan(y / x);
  if (x < 0)
  {
    a += Math.PI;
  }
  float size = (float)Math.Sqrt(x * x + y * y);

  double newAngel = a + angle;
  float newX = ((float)Math.Cos(newAngel) * size);
  float newY = ((float)Math.Sin(newAngel) * size);
  return pivot + new SizeF(newX, newY);
}

上面的代码计算点p1,p2,...,p6处椭圆的框架(旋转的原理)。然后,将椭圆绘制为2个贝塞尔曲线,椭圆框架旋转点。