存储数组中的可变点数

时间:2017-11-29 10:39:52

标签: c# arrays drawing gdi point

我有一个绘制基本图形形状的图形程序,并对其进行一些基本操作。在以前绘制的对象上创建新图形时,没有问题就像你在图中看到的那样绘制的角度线是OK。

如果你看下面绘图结果中的黄色圆圈,圆角命令会按照预期的方式制作线条圆角,但是如何使黄色圆圈中的前一条线条消失?

Drawing result

一种解决办法可能是无效,但它会清除整个面板,从而清除具有测量角度的面板。

我可以将点存储在数组中,并在每次面板无效时调用它重绘,但两行有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();
    }
}

}

1 个答案:

答案 0 :(得分:0)

您基本上应该将一个形状表示为点数组System.Drawing.Point[](或列表List<System.Drawing.Point>,这样更易​​于修改)。

然后,您可以将所有形状重新组合在一个形状列表中,以使它们清晰分开。

因此,您的所有形状应该形成一系列点数列表List<System.Drawing.Point[]>或点列表列表List<List<System.Drawing.Point>>

更进一步,正如我对你的问题所评论的那样,在'代码工程'和面向对象的观点上,将你的形状表示为他们自己的类Shape是有益的。

这是有道理的,因为你的形状不仅仅代表一个简单的“点列表”。他们可以有颜色,名字,线条等......

此类将点列表作为属性之一,与之前提到的类型相同。

同样有利于清晰:形状列表很简单......代码中的List<Shape>