C# 如何绘制三维图形来表示空间中的对象
我有一个机器人,可以输出x,y,z在空间中的位置。我的问题是,我只能使用图表在windows窗体中找到2D绘图 我想在3D空间里画我的机器人。我能用什么工具 类似于此: 我需要一个免费的软件解决方案 编辑: 我的2D图形atm:C# 如何绘制三维图形来表示空间中的对象,c#,plot,charts,3d,C#,Plot,Charts,3d,我有一个机器人,可以输出x,y,z在空间中的位置。我的问题是,我只能使用图表在windows窗体中找到2D绘图 我想在3D空间里画我的机器人。我能用什么工具 类似于此: 我需要一个免费的软件解决方案 编辑: 我的2D图形atm: chart1.ChartAreas[0].AxisX.Minimum = 0; chart1.ChartAreas[0].AxisX.Maximum = 12; chart1.ChartAreas[0].AxisX.In
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Maximum = 12;
chart1.ChartAreas[0].AxisX.Interval = 1;
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Maximum = 7;
chart1.ChartAreas[0].AxisY.Interval = 1;
//example
posicao_atual_master.X = 10;
posicao_atual_master.Y = 5;
chart1.Series[0].Points.Clear();
chart1.Series[0].Points.AddXY(posicao_atual_master.X, posicao_atual_master.Y);
设计师:
// chart1
//
chartArea1.AxisX.MajorGrid.Enabled = false;
chartArea1.AxisX.MajorTickMark.Enabled = false;
chartArea1.AxisY.MajorGrid.Enabled = false;
chartArea1.AxisY.MajorTickMark.Enabled = false;
chartArea1.Name = "ChartArea1";
chartArea1.Position.Auto = false;
chartArea1.Position.Height = 100F;
chartArea1.Position.Width = 90F;
this.chart1.ChartAreas.Add(chartArea1);
legend1.BackColor = System.Drawing.Color.Transparent;
legend1.BorderColor = System.Drawing.Color.Transparent;
legend1.Font = new System.Drawing.Font("Microsoft Sans Serif", 4F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Millimeter, ((byte)(1)), true);
legend1.IsTextAutoFit = false;
legend1.Name = "legen";
legend1.TableStyle = System.Windows.Forms.DataVisualization.Charting.LegendTableStyle.Tall;
this.chart1.Legends.Add(legend1);
this.chart1.Location = new System.Drawing.Point(543, 49);
this.chart1.Name = "chart1";
series1.ChartArea = "ChartArea1";
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point;
series1.Color = System.Drawing.Color.Transparent;
series1.Legend = "legen";
series1.MarkerBorderColor = System.Drawing.Color.Black;
series1.MarkerImage = "C:\\Users\\Tiago\\Desktop\\CODIGO_TESE_FINAL_BACKUP1408_BOM\\C# - AR.Drone SDK\\AR.Dron" +
"e\\icone_drone_verde.png";
series1.MarkerImageTransparentColor = System.Drawing.Color.Red;
series1.Name = "Master";
series2.ChartArea = "ChartArea1";
series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point;
series2.Legend = "legen";
series2.MarkerImage = "C:\\Users\\Tiago\\Desktop\\CODIGO_TESE_FINAL_BACKUP1408_BOM\\Fotos dos Relatórios\\icon" +
"e_drone_vermelho.png";
series2.Name = "Slave";
this.chart1.Series.Add(series1);
this.chart1.Series.Add(series2);
this.chart1.Size = new System.Drawing.Size(1159, 359);
this.chart1.TabIndex = 7;
this.chart1.Text = "chart1";
this.chart1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.chart1_MouseDown);
this.chart1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.chart1_MouseMove);
this.chart1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.chart1_MouseUp);
编辑:您是正确的,在图表控件中没有正确的方法使用真实的z轴 不过它确实有一个3D风格,可以用于一个相当不错的图表区域 不过,您必须在代码中绘制图形,因为内置的z轴只支持图表中的
系列
中的尽可能多或尽可能少的离散值
这对于某些事情来说是可以的,比如颜色立方体,但是当您需要任意数据值时,它就不行了
相反,您可以这样做:
- 将每个数据点的z值与Y值一起存储在YValues数组中
- 为此,您需要一个支持多个Y值的ChartType
- 对xxxPaint事件之一进行编码以绘制图形
- 为此,需要将值转换为像素
void prepare3dChart(Chart chart, ChartArea ca)
{
ca.Area3DStyle.Enable3D = true; // set the chartarea to 3D!
ca.AxisX.Minimum = -250;
ca.AxisY.Minimum = -250;
ca.AxisX.Maximum = 250;
ca.AxisY.Maximum = 250;
ca.AxisX.Interval = 50;
ca.AxisY.Interval = 50;
ca.AxisX.Title = "X-Achse";
ca.AxisY.Title = "Y-Achse";
ca.AxisX.MajorGrid.Interval = 250;
ca.AxisY.MajorGrid.Interval = 250;
ca.AxisX.MinorGrid.Enabled = true;
ca.AxisY.MinorGrid.Enabled = true;
ca.AxisX.MinorGrid.Interval = 50;
ca.AxisY.MinorGrid.Interval = 50;
ca.AxisX.MinorGrid.LineColor = Color.LightSlateGray;
ca.AxisY.MinorGrid.LineColor = Color.LightSlateGray;
// we add two series:
chart.Series.Clear();
for (int i = 0; i < 2; i++)
{
Series s = chart.Series.Add("S" + i.ToString("00"));
s.ChartType = SeriesChartType.Bubble; // this ChartType has a YValue array
s.MarkerStyle = MarkerStyle.Circle;
s["PixelPointWidth"] = "100";
s["PixelPointGapDepth"] = "1";
}
chart.ApplyPaletteColors();
addTestData(chart);
}
如果此绘制事件发生,我们将按照自己喜欢的方式绘制数据。以下是直线或点:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart;
if (chart .Series.Count < 1) return;
if (chart .Series[0].Points.Count < 1) return;
ChartArea ca = chart .ChartAreas[0];
e.ChartGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
List<List<PointF>> data = new List<List<PointF>>();
foreach (Series s in chart .Series)
data.Add(GetPointsFrom3D(ca, s, s.Points.ToList(), e.ChartGraphics));
renderLines(data, e.ChartGraphics.Graphics, chart , true); // pick one!
renderPoints(data, e.ChartGraphics.Graphics, chart , 6); // pick one!
}
private void chart1_PostPaint(对象发送方,ChartPaintEventArgs e)
{
Chart Chart=发送者作为图表;
如果(chart.Series.Count<1)返回;
if(chart.Series[0].Points.Count<1)返回;
ChartArea ca=chart.ChartAreas[0];
e、 ChartGraphics.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
列表数据=新列表();
foreach(图表中的系列s.系列)
添加(GetPointsFrom3D(ca,s,s.Points.ToList(),e.ChartGraphics));
renderLines(数据,e.ChartGraphics.Graphics,chart,true);//选择一个!
renderPoints(数据,例如ChartGraphics.Graphics,chart,6);//选择一个!
}
坐标系使用轴方法计算:
List<PointF> GetPointsFrom3D(ChartArea ca, Series s,
List<DataPoint> dPoints, ChartGraphics cg)
{
var p3t = dPoints.Select(x => new Point3D((float)ca.AxisX.ValueToPosition(x.XValue),
(float)ca.AxisY.ValueToPosition(x.YValues[0]),
(float)ca.AxisY.ValueToPosition(x.YValues[1]))).ToArray();
ca.TransformPoints(p3t.ToArray());
return p3t.Select(x => cg.GetAbsolutePoint(new PointF(x.X, x.Y))).ToList();
}
列出GetPointsFrom3D(ChartArea ca,系列s,
列出数据点,图表(cg)
{
var p3t=dPoints.Select(x=>newpoint3d((float)ca.axix.ValueToPosition(x.XValue)),
(浮动)约轴值位置(x.Y值[0]),
(float)ca.AxisY.ValueToPosition(x.y值[1])).ToArray();
ca.TransformPoints(p3t.ToArray());
返回p3t.Select(x=>cg.GetAbsolutePoint(新点f(x.x,x.Y))).ToList();
}
实际绘图发生在这些例程中;一个画线,另一个画点:
void renderLines(List<List<PointF>> data, Graphics graphics, Chart chart, bool curves)
{
for (int i = 0; i < chart.Series.Count; i++)
{
if (data[i].Count > 1)
using (Pen pen = new Pen(Color.FromArgb(64, chart.Series[i].Color), 2.5f))
if (curves) graphics.DrawCurve(pen, data[i].ToArray());
else graphics.DrawLines(pen, data[i].ToArray());
}
}
void renderPoints(List<List<PointF>> data, Graphics graphics, Chart chart, float width)
{
for (int s = 0; s < chart.Series.Count; s++)
{
Series S = chart.Series[s];
for (int p = 0; p < S.Points.Count; p++)
using (SolidBrush brush = new SolidBrush(Color.FromArgb(64, S.Color)))
graphics.FillEllipse(brush, data[s][p].X-width/2,
data[s][p].Y-width/2,width, width);
}
}
void渲染线(列表数据、图形、图表、布尔曲线)
{
对于(int i=0;i1)
使用(画笔=新画笔(Color.FromArgb(64,chart.Series[i].Color),2.5f))
if(curves)graphics.DrawCurve(画笔,数据[i].ToArray());
else graphics.DrawLines(画笔,数据[i].ToArray());
}
}
无效渲染点(列表数据、图形、图表、浮动宽度)
{
对于(int s=0;s
也可以对网格或区域等其他绘图例程进行编码。。只需使用用户GDI+方法添加新例程,如DrawCurve或FillPolygon,甚至DrawImage
您可以为不同的视图设置ChartArea.Area3DStyle.Rotation
和ChartArea.Area3DStyle.Indeption
,如动画中所示
Edit我已经更新了PostPaint
方法来最小化依赖关系
您是对的,在图表控件中没有正确的方法使用真实的z轴 不过它确实有一个3D风格,可以用于一个相当不错的图表区域 不过,您必须在代码中绘制图形,因为内置的z轴只支持图表中的
系列
中的尽可能多或尽可能少的离散值
这对于某些事情来说是可以的,比如颜色立方体,但是当您需要任意数据值时,它就不行了
相反,您可以这样做:
- 将每个数据点的z值与Y值一起存储在YValues数组中
- 为此,您需要一个支持多个Y值的ChartType
- 对xxxPaint事件之一进行编码以绘制图形
- 为此,需要将值转换为像素
void prepare3dChart(Chart chart, ChartArea ca)
{
ca.Area3DStyle.Enable3D = true; // set the chartarea to 3D!
ca.AxisX.Minimum = -250;
ca.AxisY.Minimum = -250;
ca.AxisX.Maximum = 250;
ca.AxisY.Maximum = 250;
ca.AxisX.Interval = 50;
ca.AxisY.Interval = 50;
ca.AxisX.Title = "X-Achse";
ca.AxisY.Title = "Y-Achse";
ca.AxisX.MajorGrid.Interval = 250;
ca.AxisY.MajorGrid.Interval = 250;
ca.AxisX.MinorGrid.Enabled = true;
ca.AxisY.MinorGrid.Enabled = true;
ca.AxisX.MinorGrid.Interval = 50;
ca.AxisY.MinorGrid.Interval = 50;
ca.AxisX.MinorGrid.LineColor = Color.LightSlateGray;
ca.AxisY.MinorGrid.LineColor = Color.LightSlateGray;
// we add two series:
chart.Series.Clear();
for (int i = 0; i < 2; i++)
{
Series s = chart.Series.Add("S" + i.ToString("00"));
s.ChartType = SeriesChartType.Bubble; // this ChartType has a YValue array
s.MarkerStyle = MarkerStyle.Circle;
s["PixelPointWidth"] = "100";
s["PixelPointGapDepth"] = "1";
}
chart.ApplyPaletteColors();
addTestData(chart);
}
如果此绘制事件发生,我们将按照自己喜欢的方式绘制数据。以下是直线或点:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
Chart chart = sender as Chart;
if (chart .Series.Count < 1) return;
if (chart .Series[0].Points.Count < 1) return;
ChartArea ca = chart .ChartAreas[0];
e.ChartGraphics.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
List<List<PointF>> data = new List<List<PointF>>();
foreach (Series s in chart .Series)
data.Add(GetPointsFrom3D(ca, s, s.Points.ToList(), e.ChartGraphics));
renderLines(data, e.ChartGraphics.Graphics, chart , true); // pick one!
renderPoints(data, e.ChartGraphics.Graphics, chart , 6); // pick one!
}
private void chart1_PostPaint(对象发送方,ChartPaintEventArgs e)
{
Chart Chart=发送者作为图表;
如果(chart.Series.Count<1)返回;
if(chart.Series[0].Points.Count<1)返回;
ChartArea ca=chart.ChartAreas[0];
e、 ChartGraphics.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
列表数据=新列表();
foreach(图表中的系列s.系列)
添加(GetPointsFrom3D(ca,s,s.Points.ToList(),e.ChartGraphics));
renderLines(数据,e.ChartGraphics.Graphics,chart,true);//选择一个!
renderPoints(数据,例如ChartGraphics.Graphics,chart,6);//选择一个!
}
坐标系使用轴方法计算:
List<PointF> GetPointsFrom3D(ChartArea ca, Series s,
List<DataPoint> dPoints, ChartGraphics cg)
{
var p3t = dPoints.Select(x => new Point3D((float)ca.AxisX.ValueToPosition(x.XValue),
(float)ca.AxisY.ValueToPosition(x.YValues[0]),
(float)ca.AxisY.ValueToPosition(x.YValues[1]))).ToArray();
ca.TransformPoints(p3t.ToArray());
return p3t.Select(x => cg.GetAbsolutePoint(new PointF(x.X, x.Y))).ToList();
}
列出GetPointsFrom3D(ChartArea ca,系列s,
列出数据点,图表(cg)
{
var p3t=dPoints.Select(x=>newpoint3d((float)ca.axix.ValueToPosition(x.XValue)),
(浮动)约轴值位置(x.Y值[0]),
(float)ca.AxisY.ValueToPosition(x.y值[1])).ToArray();
ca.TransformPoints(p3t.ToArray());
返回p3t.Select(x=>cg.GetAbsolutePoint(新