用一定程度或角度绘制一条直线的最佳方法是什么。
例如,如果x=y
那么这意味着点数为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();
}
}
答案 0 :(得分:2)
让线坐标以一定角度穿过一个点是很容易的部分。找到要包含在显示矩形中的行的终点稍微复杂一些。
通过角度θ的点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());