[英]Drawing a straight line from points
I am trying to make a simple chart application and I have stumbled upon a problem. 我正在尝试制作一个简单的图表应用程序,但我偶然发现了一个问题。 I have an array of points which represent a 45 degree line (y = x) of 100 points.
我有一个点数组,它们代表100个点的45度线(y = x)。 I then try to draw the line by converting each point's value to its pixel value and then draw lines from one point to another using
graphic.DrawLines()
. 然后,我尝试通过将每个点的值转换为其像素值来绘制线,然后使用
graphic.DrawLines()
将线从一个点绘制到另一点。
The the basic code: 基本代码:
struct MyPoint
{
double X { set; get; }
double Y { set; get; }
}
List<MyPoint> Values;
List<System.Drawing.Point> Points;
for (int i = 0; i < Values.Count; i++)
{
// convert point value to pixel coordinate
int x = (int)((Values[i].X - MinimumX) * (double)Control.Width / (MaximumX - MinimumX) + 0.5);
int y = (int)((Values[i].Y - MinimumY) * (double)Control.Height / (MaximumY - MinimumY)) + 0.5;
Points.Add(new System.Drawing.Point(x, y));
}
graphic.DrawLines(pen, Points.ToArray());
Note: MaximumX and MaximumY are 100 (number of points) and minimums are 0. 注意:MaximumX和MaximumY为100(点数),最小值为0。
The thing is that this kind of line is not very straight :) So my question is, how would I draw a straight line through those points, so that it would look the same as 问题是这种线不是很直:)所以我的问题是,我将如何通过这些点画一条直线,使其看起来与
graphic.DrawLine(pen, 0, 0, Control.Width-1, Control.Height-1);
Thanks in advance! 提前致谢!
Since you are doing a graph, I have a basic framework for fitting values within a control like this example: 由于您正在绘制图形,因此我有一个基本的框架,可以在控件中拟合值,例如以下示例:
public struct MyPoint
{
public double X { set; get; }
public double Y { set; get; }
public PointF ToPoint()
{
return new PointF((float)X, (float)Y);
}
}
/// <summary>
/// For http://stackoverflow.com/questions/19459519/drawing-a-straight-line-from-points
/// </summary>
public partial class Form1 : Form
{
List<MyPoint> points;
public Form1()
{
InitializeComponent();
// Initialize points to draw
points=new List<MyPoint>(100);
for (int i=0; i<=100; i++)
{
double θ=2*Math.PI*(i/100.0);
double x=(1+θ/Math.PI)*Math.Cos(θ);
double y=(1+θ/Math.PI)*Math.Sin(θ);
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();
}
}
I think the problem is because your points are Integers. 我认为问题是因为您的观点是整数。 Precisions are lost.
精度下降。
Trying using 尝试使用
float x = (float)((Values[i] ...
List<System.Drawing.PointF> PointFs;
instead of 代替
int x = (int)((Values[i] ...
List<System.Drawing.Point> Points;
You probably need something like this: 您可能需要这样的东西:
private void DrawLine()
{
int xInitial = 0, yInitial = 0, xFinal = Control.Width - 1, yFinal = Control.Height - 1;
int dx = xFinal - xInitial, dy = yFinal - yInitial, steps, k, xf, yf;
float xIncrement, yIncrement, x = xInitial, y = yInitial;
if (Math.Abs(dx) > Math.Abs(dy))
steps = Math.Abs(dx);
else
steps = Math.Abs(dy);
xIncrement = dx / (float)steps;
yIncrement = dy / (float)steps;
for (k = 0; k < steps; k++)
{
x += xIncrement;
xf = (int)x;
y += yIncrement;
yf = (int)y;
Points.Add(new System.Drawing.Point(xf, yf));
}
graphic.DrawLines(pen, Points.ToArray());
}
For more details see: Bresenham's line algorithm 有关更多详细信息,请参见: Bresenham的行算法
If your points already calculated correctly by algorithm, than simple: 如果您的点数已经通过算法正确计算,则不那么简单:
int x = (int) Values[i].X;
int y = (int) Values[i].Y;
Should be enough. 应该足够了。
here is my solution: 这是我的解决方案:
System.Drawing.Pen myPen;
myPen = new System.Drawing.Pen(System.Drawing.Color.Red);
System.Drawing.Graphics formGraphics = this.CreateGraphics();
formGraphics.DrawLine(myPen, 0, 0, 200, 200);
myPen.Dispose();
formGraphics.Dispose();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.