【问题标题】:Drawing line from points with given angle θ从具有给定角度 θ 的点绘制线
【发布时间】:2014-09-19 23:35:02
【问题描述】:

用具有一定度数或角度的点绘制一条线的最佳方法是什么。

例如,如果 x=ythen 这意味着点有 45 度。 显示

但我想给θ作为参数并在循环内画一条带有θ度的线,我有以下代码,但我不知道如何继续。

您能否解释一下影响给定θ 点数的最佳方法?

public struct MyPoint
{
    public double X { set; get; }
    public double Y { set; get; }

    public PointF ToPoint()
    {
        return new PointF((float)X, (float)Y);
    }
}

public partial class Form1 : Form
{
    List<MyPoint> points;
    public Form1()
    {
        InitializeComponent();

        // Initialize points to draw
        //-----------THIS IS PART TO DRAW LINE x=i and y = i meaning θ=45
        // [x,y] = [xcos(θ)−ysin(θ),xsin(θ)+ycos(θ)] 
        points=new List<MyPoint>(100);
        for (int i=0; i<=100; i++)
        {
            double θ=45;
            double x=i; //(i * Math.Cos(θ) - i * Math.Sin(θ));
            double y=i; //(i *Math.Sin(θ) + i * Math.Cos(θ));
            points.Add(new MyPoint() { X=x, Y=y });
        }
        //------------------------------
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        // smooth graphics
        e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;            
        // set margins inside the control client area in pixels
        var margin=new System.Drawing.Printing.Margins(16, 16, 16, 16);
        // set the domain of (x,y) values
        var range=new RectangleF(-3, -3, 6, 6);
        // scale graphics
        ScaleGraphics(e.Graphics, pictureBox1, range, margin);            
        // convert points to pixels
        PointF[] pixels=points.Select((v) => v.ToPoint()).ToArray();
        // draw arrow axes
        using (var pen=new Pen(Color.Black, 0))
        {
            pen.EndCap=System.Drawing.Drawing2D.LineCap.ArrowAnchor;
            e.Graphics.DrawLine(pen, range.Left, 0.0f, range.Right, 0.0f);
            e.Graphics.DrawLine(pen, 0.0f, range.Top, 0.0f, range.Bottom);
        }
        // draw bounding rectangle (on margin)
        using (var pen=new Pen(Color.LightGray, 0))
        {
            pen.DashStyle=DashStyle.Dash;
            e.Graphics.DrawRectangle(pen, Rectangle.Round(range));
        }
        // draw curve
        using (var pen = new Pen(Color.Blue, 0))
        {                
            //e.Graphics.DrawLines(pen, pixels);
            e.Graphics.DrawCurve(pen, pixels);
        }            
    }
    /// <summary>
    /// Scales the Graphics to fit a Control, given a domain of x,y values and side margins in pixels
    /// </summary>
    /// <param name="g">The Graphics object</param>
    /// <param name="control">The Control</param>
    /// <param name="domain">The value domain</param>
    /// <param name="margin">The margin</param>
    void ScaleGraphics(Graphics g, Control control, RectangleF domain, Margins margin)
    {
        // Find the drawable area in pixels (control-margins)
        int W=control.Width-margin.Left-margin.Right;
        int H=control.Height-margin.Bottom-margin.Top;
        // Ensure drawable area is at least 1 pixel wide
        W=Math.Max(1, W);
        H=Math.Max(1, H);
        // Find the origin (0,0) in pixels
        float OX=margin.Left-W*(domain.Left/domain.Width);
        float OY=margin.Top+H*(1+domain.Top/domain.Height);
        // Find the scale to fit the control
        float SX=W/domain.Width;
        float SY=H/domain.Height;
        // Transform the Graphics
        g.TranslateTransform(OX, OY);
        g.ScaleTransform(SX, -SY);
    }

    private void pictureBox1_SizeChanged(object sender, EventArgs e)
    {
        // redraw on resize
        pictureBox1.Refresh();
    }
}

【问题讨论】:

  • 可变结构是邪恶的。
  • 你想要一条穿过角度为 θ 的点 (x,y) 的线吗?
  • 为什么你想要 100 分而不是两个(开始,结束)?
  • @Matthias 很好的观察,我只是用 100 分进行测试,看看结果如何。但想存储所有积分,这就是为什么使用 100 积分
  • @ja72 简而言之,是的,怎么做?

标签: c# winforms graphics gdi+


【解决方案1】:

获取以一定角度通过点的线坐标是很容易的部分。找到要包含在显示矩形内的线的端点稍微复杂一些。

通过点P=(xp,yp) 的直线,角度为 θ,满足方程

(x-xp)*SIN(θ)-(y-yp)*COS(θ) = 0

以上是参数形式

P(t) = ( xp+t*COS(θ), yp+t*SIN(θ) )

其中t 是从点P 沿线的距离。

因此,如果您想要一条线跨越整个绘图边界(代码中的range 变量),您必须找到哪个t 对应于顶部、底部、左侧和右侧边界并在中间两者之间绘制。

// example angle at 15° through xp=2.0, yp=1.0
RectangleF range = new RectangleF(-3.0,-3.0, 6.0, 6.0);
double xp=2.0, yp=1.0;
double θ = 15.0*(Math.PI/180);   
// If angle is 0°, 90° etc, the following will fail
double[] t = new double[4];
t[0] = (range.Left-xp)/Math.Cos(θ);
t[1] = (range.Right-xp)/Math.Cos(θ);
t[2] = (range.Top-yp)/Math.Sin(θ);
t[3] = (range.Bottom-yp)/Math.Sin(θ);
Array.Sort(t);
// pick middle two points
var A = new MyPoint() { X = xp+t[1]*Math.Cos(θ), Y = yp+t[1]*Math.Sin(θ) };
var B = new MyPoint() { X = xp+t[2]*Math.Cos(θ), Y = yp+t[2]*Math.Sin(θ) };
g.DrawLine(pen, A.ToPoint(), B.ToPoint());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    相关资源
    最近更新 更多