我有一个绘制基本图形形状的图形程序,并对其进行一些基本操作。在以前绘制的对象上创建新图形时,没有问题就像你在图中看到的那样绘制的角度线是OK。
如果你看下面绘图结果中的黄色圆圈,圆角命令会按照预期的方式制作线条圆角,但是如何使黄色圆圈中的前一条线条消失?
一种解决办法可能是无效,但它会清除整个面板,从而清除具有测量角度的面板。
我可以将点存储在数组中,并在每次面板无效时调用它重绘,但两行有3个点。
如果我绘制一个多边形,它可能有三个以上并且有所不同。
如何在单个数组中存储可变数量的点?
如有必要,我可以提供代码。
List<System.Drawing.Point> PointLine = new List<System.Drawing.Point>();
private void panel1_MouseDown(object sender, MouseEventArgs e)// On mouse down
{
Graphics g = this.panel1.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
if (dist == false && circ == false)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
mouseisdown = true;
DrawPoint(e.X, e.Y, Color.White);
}
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
leftdown = true;
g.DrawRectangle(RPen, e.X, e.Y, 0.5f, 0.5f);
PointLine.Add(new System.Drawing.Point(e.X, e.Y)); //Add points on each click
PointF[] pts = new PointF[] { new PointF(e.X, e.Y) };
gp.AddLines(pts);
if (PointLine.Count > 1)
{
DrawLineP(PointLine[PointLine.Count - 2].X, PointLine[PointLine.Count - 2].Y, e.X, e.Y);
}
}
}
else if (dist == true)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
DsP1 = new PointF(e.X, e.Y);
label9.Font = font4;
label10.Font = font3;
g.DrawRectangle(RPen, new System.Drawing.Rectangle(e.X, e.Y, 1, 1));
}
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
DsP2 = new PointF(e.X, e.Y);
double x = DsP1.X - DsP2.X;
double y = DsP1.Y - DsP2.Y;
double d = Math.Abs(x + y);
float midX = (DsP1.X + DsP2.X) / 2;
float midY = (DsP1.Y + DsP2.Y) / 2;
DrawDist(DsP1, DsP2, d, midX, midY, Color.White);
}
}
if (circ == true)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
DsP1 = new PointF(e.X, e.Y);
label9.Font = font4;
label10.Font = font3;
g.DrawRectangle(RPen, new System.Drawing.Rectangle(e.X, e.Y, 1, 1));
}
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
DsP2 = new PointF(e.X, e.Y);
double x = DsP1.X - DsP2.X;
double y = DsP1.Y - DsP2.Y;
double d = Math.Abs(x + y);
float midX = (DsP1.X + DsP2.X) / 2;
float midY = (DsP1.Y + DsP2.Y) / 2;
DrawCirc(DsP1, DsP2, Color.White);
}
}
if (ModifierKeys == Keys.Shift)
{
mouseisdown = false;
leftdown = false;
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
PointF[] pts = gp.PathPoints;
if (pts.Contains(new PointF(e.X, e.Y)))
{
MessageBox.Show("Line Selected");
}
}
}
}
public void DrawCirc(PointF p1, PointF p2, Color color)
{
Graphics g = this.panel1.CreateGraphics();
int width = (int)(DsP2.X - DsP1.X);
int height = (int)(DsP2.Y - DsP1.Y);
if (width > height || width < height)
{
width = height;
}
double radius = (DsP2.Y - DsP1.Y) / 2;
double xloc = (DsP2.X + DsP1.X) / 2;
double yloc = (DsP2.Y + DsP1.Y) / 2;
g.DrawEllipse(new Pen(Color.White, 2f), new System.Drawing.Rectangle((int)DsP1.X, (int)DsP1.Y, width, height));
g.DrawString("R<-- " + radius.ToString(), new System.Drawing.Font("Arial", 7), new SolidBrush(Color.White), new PointF((float)xloc - (DsP2.X - DsP1.X) / 4, (float)yloc - 5));
g.DrawRectangle(Pens.White, new System.Drawing.Rectangle((int)xloc - 5, (int)yloc, 1, 1));
circ = false;
label9.Text = "Radius= " + radius.ToString();
label10.Text = "";
PointLine.Clear();
}
public void DrawDist(PointF p1, PointF p2, double d, float midX, float midY, Color color)
{
Graphics g = this.panel1.CreateGraphics();
g.DrawLine(new Pen(Color.Blue, 2F), DsP1, DsP2);
g.DrawRectangle(RPen, new System.Drawing.Rectangle((int)DsP2.X, (int)DsP2.Y, 1, 1));
dist = false;
PointLine.Clear();
label9.Text = "Distance= " + d.ToString();
label10.Text = "";
g.DrawString(d.ToString(), new System.Drawing.Font("Arial", 7), new SolidBrush(Color.White), new PointF(midX + 5, midY));
}
GraphicsPath gp = new GraphicsPath();
public void DrawLineP(int x1, int y1, int x2, int y2)
{
Graphics g = this.panel1.CreateGraphics();
g.DrawLine(new Pen(Color.White, 2F), x1, y1, x2, y2);
}
private void btn_ctr_Click(object sender, EventArgs e)
{
// Area of Runtime Polygon
for (int i = 0; i < PointLine.Count - 1; i++)
{
area2 += (PointLine[i].X * PointLine[i + 1].Y) - (PointLine[i].Y * PointLine[i + 1].X);
}
area2 += (PointLine[PointLine.Count - 1].X * PointLine[0].Y) - (PointLine[PointLine.Count - 1].Y * PointLine[0].X);
label4.Text = "Area";
lbl_area.Text = Math.Abs(Math.Round(area2, 2)).ToString() + " Sq-m";
PointLine.Clear();
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
mouseisdown = false;
}
private void DrawGrid()
{
Graphics g = this.panel1.CreateGraphics();
Pen pen = new Pen(Color.Gray, (float)0.1);
pen.DashStyle = DashStyle.Dash;
for(int i = 0; i <= 1020; i += 10)
{
for(int j = 0; j <= 645; j += 10)
{
System.Drawing.Rectangle rec = new System.Drawing.Rectangle(new System.Drawing.Point(i, j), new Size(1, 1));
g.FillRectangle(Brushes.Gray, rec);
}
// g.DrawLine(pen, new System.Drawing.Point(i, 10), new System.Drawing.Point(i, 640));
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics grp = e.Graphics;
DrawPolygon(grp);
DrawAxes(grp);
DrawGrid();
}
private void btn_area_Click(object sender, EventArgs e)
{
area = 0.0f;
parameterY = 0.0f;
paramterX = 0.0f;
parameter_total = 0.0f;
area2 = 0.0f;
// { Applying Irregular Polygon Area Algorithm
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
area += ((float)Convert.ToDouble(dataGridView1.Rows[i].Cells[0].Value) * (float)Convert.ToDouble(dataGridView1.Rows[i + 1].Cells[1].Value)) - ((float)Convert.ToDouble(dataGridView1.Rows[i + 1].Cells[0].Value) * (float)Convert.ToDouble(dataGridView1.Rows[i].Cells[1].Value));
}
//Add last vertix with respect to start vertix
area += ((float)Convert.ToDouble(dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[0].Value) * (float)Convert.ToDouble(dataGridView1.Rows[0].Cells[1].Value)) - ((float)Convert.ToDouble(dataGridView1.Rows[0].Cells[0].Value) * (float)Convert.ToDouble(dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[1].Value));
area = area / 2.0f;
// } Algorithm Ends..
//Parameter Length of Polygon
for (int i = 0; i < dataGridView1.Rows.Count - 2; i++)
{
paramterX += Math.Abs(((float)Convert.ToDouble(dataGridView1.Rows[i + 1].Cells[0].Value) - (float)Convert.ToDouble(dataGridView1.Rows[i].Cells[0].Value)));
parameterY += Math.Abs(((float)Convert.ToDouble(dataGridView1.Rows[i + 1].Cells[1].Value) - (float)Convert.ToDouble(dataGridView1.Rows[i].Cells[1].Value)));
}
parameter_total = paramterX + parameterY;
label4.Text = "Area";
label5.Text = "Perimeter";
lbl_param.Text = parameter_total.ToString() + " m";
lbl_area.Text = Math.Abs(Math.Round(area, 2)).ToString() + " Sq-m" + " " + Math.Abs(Math.Round(area / 4046, 2)).ToString() + " Acre";
}
private void panel1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
Points.AddRange(PointLine);
}
}
private void button1_Click(object sender, EventArgs e)
{
//Change Drawing Color
colorDialog1.ShowDialog();
RPen = new Pen(colorDialog1.Color, 2);
}
private void btn_clr_Click(object sender, EventArgs e)
{
PointLine.Clear();
panel2.Hide();
label9.Text = "";
label10.Text = "";
this.panel1.CreateGraphics().Clear(panel1.BackColor);
panel1.Invalidate();
DrawGrid();
DrawAxes(g);
}
private void btn_angle_Click(object sender, EventArgs e)
{// Angle between Lines
if (PointLine.Count >= 3)
{
angle_select = true;
double angle = Math.Atan2(PointLine[1].Y - PointLine[0].Y, PointLine[1].X - PointLine[0].X) - Math.Atan2(PointLine[2].Y - PointLine[1].Y, PointLine[2].X - PointLine[1].X);
angle = Math.Round((angle * 180) / Math.PI, 0);
angle = 180 - angle;
if (angle > 180)
{
angle = 360 - angle;
}
System.Drawing.Font font3 = new System.Drawing.Font("couriner new", 8);
lbl_area.Text = angle.ToString() + "°";
int MPX1 = (PointLine[1].X + PointLine[0].X) / 2;
int MPY1 = (PointLine[1].Y + PointLine[0].Y) / 2;
int MPX2 = (PointLine[2].X + PointLine[1].X) / 2;
int MPY2 = (PointLine[2].Y + PointLine[1].Y) / 2;
System.Drawing.Point MP1 = new System.Drawing.Point(MPX1, MPY1);
System.Drawing.Point MP2 = new System.Drawing.Point(MPX2, MPY2);
//Calculate Midpoint for angle
int MidPointX = (MPX1 + MPX2) / 2;
int MidPointY = (MPY1 + MPY2) / 2;
PointF[] parray = { MP1, MP2 };
RPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
Graphics g = this.panel1.CreateGraphics();
g.DrawString(angle.ToString() + "°", font3, Brushes.Yellow, new System.Drawing.Point(MidPointX - 3, MidPointY + 3));
// g.DrawCurve(new Pen(Color.Yellow), parray, 0.0f);
g.DrawBezier(new Pen(Color.Blue, 2), MP1, new PointF(MP1.X + 40, MP1.Y + 10), MP2, MP2);
panel2.Show();
label9.Text ="Angle: "+ angle.ToString() + "°";
}
PointLine.Clear();
}
System.Drawing.Font font3 = new System.Drawing.Font(DefaultFont, FontStyle.Bold);
System.Drawing.Font font4 = new System.Drawing.Font(DefaultFont, FontStyle.Regular);
private void btn_dist_Click(object sender, EventArgs e)
{
dist = true;
label9.Text = "Select First Point";
label10.Text = "Select Second Point";
label9.Font = font3;
}
private void button1_Click_1(object sender, EventArgs e)
{
circ = true;
panel2.Show();
timer1.Start();
label9.Text = "Select first point of Circle";
label9.Font = font3;
label10.Text = "Select Second Piont of Circle";
}
private void button2_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = null; //Reset Values
dataGridView1.Rows.Clear();
area = 0.0f;
parameterY = 0.0f;
paramterX = 0.0f;
parameter_total = 0.0f;
label5.Text = "";
label4.Text = "";
lbl_area.Text = "";
lbl_param.Text = "";
/* Microsoft.Office.Interop.Excel.Workbook ExWorkbook; //Excel Object
Microsoft.Office.Interop.Excel.Worksheet ExWorksheet;
Microsoft.Office.Interop.Excel.Range ExRange;
Microsoft.Office.Interop.Excel.Application ExObj = new Microsoft.Office.Interop.Excel.Application();*/
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("Point");
openFileDialog1.Filter = "Excel Files|*.txt";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
string[] ptText = System.IO.File.ReadAllLines("C:\\Users\\Point.txt");
for (int i = 0; i <= ptText.Length - 1; i++)
{
DataRow drow = dt.NewRow();
drow["Point"] = ptText[i];
dt.Rows.Add(drow);
}
dataGridView1.DataSource = dt;
label6.Text = openFileDialog1.FileName;
}
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void linesFillet()
{
Graphics grp = this.panel1.CreateGraphics();
circ = false;
dist = false;
angle_select = false;
string rad = txt_cmd.Text.Substring(7, txt_cmd.Text.Length - 7);
float radius = (float)Convert.ToDouble(rad);
if (PointLine.Count >= 3)
{
Fillet(grp, PointLine[0], PointLine[1], PointLine[2], radius);
}
PointLine.Clear();
}
private void btn_filletOK_Click(object sender, EventArgs e)
{
}
private void angleToolStripMenuItem_Click(object sender, EventArgs e)
{
btn_angle.PerformClick();
}
private void enableToolStripMenuItem_Click(object sender, EventArgs e)
{
DrawGrid();
}
private void DisableGrid()
{
PointLine.Clear();
panel2.Hide();
label9.Text = "";
label10.Text = "";
this.panel1.CreateGraphics().Clear(panel1.BackColor);
panel1.Invalidate();
DrawAxes(g);
}
private void disableToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void SnapToGrid(System.Drawing.Point point)
{
/* int GridGap = 10;
int x = GridGap * (int)Math.Round((float)point.X / GridGap);
int y = GridGap * (int)Math.Round((float)point.Y / GridGap);
Cursor.Position = new System.Drawing.Point(x, y);*/
foreach (var rec in GridList)
{
if (rec.Contains(point))
{
Cursor.Position = new System.Drawing.Point(rec.X, rec.Y);
}
}
}
private void oNToolStripMenuItem_Click(object sender, EventArgs e)
{
snap = true;
}
private void snapToolStripMenuItem1_Click(object sender, EventArgs e)
{
snap = true;
}
private void button3_Click_2(object sender, EventArgs e)
{
this.Close();
}
private void button4_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
private void txt_cmd_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
label13.Text += "\n" + txt_cmd.Text;
if (txt_cmd.Text == "angle")
{
btn_angle.PerformClick();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "circle")
{
button1.PerformClick();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "measure")
{
btn_dist.PerformClick();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "polyarea")
{
btn_ctr.PerformClick();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "clear")
{
btn_clr.PerformClick();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "fillet")
{
txt_cmd.Text = "Radius:";
}
else if (txt_cmd.Text.Substring(0,6)=="Radius:")
{
linesFillet();
txt_cmd.Clear();
}
else if (txt_cmd.Text == "clear previous commands")
{
label13.Text = "";
txt_cmd.Clear();
}
else if (txt_cmd.Text == "exit")
{
this.Close();
}
}
}
private void textBox4_TextChanged(object sender, EventArgs e)
{
}
private void txt_cmd_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
//Cursor CMD
CreateCaret(textBox1.Handle, IntPtr.Zero, 25, 5);
ShowCaret(txt_cmd.Handle);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
txt_cmd.Focus();
}
//Fillet
public void Fillet(Graphics g, System.Drawing.Point p1, System.Drawing.Point p, System.Drawing.Point p2, float radius)
{
//Vector 1
double dx1 = p.X - p1.X;
double dy1 = p.Y - p1.Y;
//Vector 2
double dx2 = p.X - p2.X;
double dy2 = p.Y - p2.Y;
//Angle between vector 1 and vector 2 divided by 2
double angle = (Math.Atan2(dy1, dx1) - Math.Atan2(dy2, dx2)) / 2;
// The length of segment between angular point and the
// points of intersection with the circle of a given radius
double tan = Math.Abs(Math.Tan(angle));
double segment = radius / tan;
//Check the segment
double length1 = GetLength(dx1, dy1);
double length2 = GetLength(dx2, dy2);
double length = Math.Min(length1, length2);
if (segment > length)
{
segment = length;
radius = (float)(length * tan);
}
// Points of intersection are calculated by the proportion between
// the coordinates of the vector, length of vector and the length of the segment.
var p1Cross = GetProportionPoint(p, segment, length1, dx1, dy1);
var p2Cross = GetProportionPoint(p, segment, length2, dx2, dy2);
// Calculation of the coordinates of the circle
// center by the addition of angular vectors.
double dx = p.X * 2 - p1Cross.X - p2Cross.X;
double dy = p.Y * 2 - p1Cross.Y - p2Cross.Y;
double L = GetLength(dx, dy);
double d = GetLength(segment, radius);
var circlePoint = GetProportionPoint(p, d, L, dx, dy);
//StartAngle and EndAngle of arc
var startAngle = Math.Atan2(p1Cross.Y - circlePoint.Y, p1Cross.X - circlePoint.X);
var endAngle = Math.Atan2(p2Cross.Y - circlePoint.Y, p2Cross.X - circlePoint.X);
//Sweep angle
var sweepAngle = endAngle - startAngle;
//Some additional checks
if (sweepAngle < 0)
{
startAngle = endAngle;
sweepAngle = -sweepAngle;
}
if (sweepAngle > Math.PI)
sweepAngle = Math.PI - sweepAngle;
//Draw result using graphics
var pen = new Pen(Color.White);
g = this.panel1.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawLine(pen, p1, p1Cross);
g.DrawLine(pen, p2, p2Cross);
var left = circlePoint.X - radius;
var top = circlePoint.Y - radius;
var diameter = 2 * radius;
var degreeFactor = 180 / Math.PI;
g.DrawArc(pen, left, top, diameter, diameter,
(float)(startAngle * degreeFactor),
(float)(sweepAngle * degreeFactor));
}
private double GetLength(double dx, double dy)
{
return Math.Sqrt(dx * dx + dy * dy);
}
private PointF GetProportionPoint(PointF point, double segment,
double length, double dx, double dy)
{
double factor = segment / length;
return new PointF((float)(point.X - dx * factor),
(float)(point.Y - dy * factor));
}
private void btn_fillet_Click(object sender, EventArgs e)
{
linesFillet();
}
}
}
答案 0 :(得分:0)
您基本上应该将一个形状表示为点数组System.Drawing.Point[]
(或列表List<System.Drawing.Point>
,这样更易于修改)。
然后,您可以将所有形状重新组合在一个形状列表中,以使它们清晰分开。
因此,您的所有形状应该形成一系列点数列表List<System.Drawing.Point[]>
或点列表列表List<List<System.Drawing.Point>>
更进一步,正如我对你的问题所评论的那样,在'代码工程'和面向对象的观点上,将你的形状表示为他们自己的类Shape是有益的。
这是有道理的,因为你的形状不仅仅代表一个简单的“点列表”。他们可以有颜色,名字,线条等......
此类将点列表作为属性之一,与之前提到的类型相同。
同样有利于清晰:形状列表很简单......代码中的List<Shape>
。