如何在一张照片中添加更多凸包

时间:2018-05-23 11:04:16

标签: c# image draw

我正在Visual Studio 2017中做作业。 我必须创建一个凸包,然后添加更多凸壳,而不更改其他。所以我找到了如何制作一个凸包,但我不知道如何在这段代码中添加更多。我必须在代码中创建新的botton(添加凸包)然后我不知道如何继续。 谢谢你的所有答案。

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        Point zacasna = new Point();
        zacasna.X = e.X;
        zacasna.Y = e.Y;
        seznamTock.Add(zacasna);


        pictureBox1.Image = Image.FromFile(file);
        using (var g = Graphics.FromImage(pictureBox1.Image))
        {
            for (int i = 0; i < seznamTock.Count; i++)
            {
                g.DrawEllipse(barva_tock, seznamTock[i].X, seznamTock[i].Y, 
      5, 5);
            }
            pictureBox1.Refresh();
        }
    }

    private List<Point> konveksnaLupina(List<Point> tocka)
    {
        List<Point> hull = new List<Point>();
        Point vPointOnHull = tocka.Where(p => p.X == tocka.Min(min => 
        min.X)).First();

        Point vEndpoint;
        do
        {
            hull.Add(vPointOnHull);
            vEndpoint = tocka[0];

            for (int i = 1; i < tocka.Count; i++)
            {
                if ((vPointOnHull == vEndpoint)
                    || (Orientacija(vPointOnHull, vEndpoint, tocka[i]) == 
                 -1))
                {
                    vEndpoint = tocka[i];
                }
            }

            vPointOnHull = vEndpoint;

        }
        while (vEndpoint != hull[0]);

        return hull;
    }

    private static int Orientacija(Point p1, Point p2, Point p)
    {
        // Determinanta
        int Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - 
          p1.Y);

        if (Orin > 0)
        {
            return -1; //orientacija v levo
        }
        if (Orin < 0)
        {
            return 1; //orientacija v desno
        }

        return 0; //neutralna orientacija
    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (seznamTock.Count < 3)
        {
            MessageBox.Show("Premalo tock!");
            return;
        }

        List<Point> hull = new List<Point>();
        hull = konveksnaLupina(seznamTock);
        pictureBox1.Image = Image.FromFile(file);


        using (var g = Graphics.FromImage(pictureBox1.Image))
        {

            for (int j = 0; j < seznamTock.Count; j++)
            {
                g.DrawEllipse(barva_tock, seznamTock[j].X, seznamTock[j].Y, 
                5, 5);
            }
            for (int j = 0; j < hull.Count; j++)
            {
                Point tocka1 = new Point(hull[j].X, hull[j].Y);
                Point tocka2 = new Point(hull[(j + 1) % hull.Count].X, 
               hull[(j + 1) % hull.Count].Y);
                g.DrawLine(barva_kon_lupine, tocka1, tocka2);
            }
            for (int j = 0; j < hull.Count; j++)
            {
                g.DrawEllipse(barva_tock_kon_lupine, hull[j].X, hull[j].Y, 
           `enter code here`5, 5);
             }

            pictureBox1.Refresh();
        }
    }
    }

2 个答案:

答案 0 :(得分:0)

  

将新点添加到新列表中,但不更改上一个数字

你在想List<Point>是真实的。嗯,不是。它是一个点列表。数字可能有更多的属性,如果你有几个数字存储为点数组 - 你怎么知道哪个点属于哪个数字?

OOP可以使其更清晰:

abstract class Figure
{
    public abstract void Draw(Graphics graphics);
}

class Convex: Figure
{
    public List<Point> Points { get; set; }
    public Color Color { get; set; } = Color.Black;
    ... // more properties

    public override void Draw(Graphics graphics) 
    {
        if(Points != null)
            using(var pen = new Pen(Color))
                graphics.DrawLines(pen, Points.ToArray());
    }
}

... // more figures

您可以在List<Figure>中保留不同的数字,只需添加新数字:

class Billboard
{
    public List<Figure> Figures { get; } = new List<Figure>();

    public void Add(Figure figure) => Figures.Add(figure);
    ... // more methods
}

重绘:

Billboard _billboard = new Billboard();

void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    foreach(var figure in _billboard.Figures)
        figure.Draw(e.Graphics);
}

答案 1 :(得分:0)

我喜欢Sinatrs的方法。但是,这是一个替代方案,只需使用集合和现有代码。不是,最好的mod。想想,它会做你想要的。

enter image description here

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        Collection<List<Point>> test = new Collection<List<Point>>();
        List<Point> seznamTock = new List<Point>();

        Pen barva_tock = new Pen(Color.Blue);
        Pen barva_kon_lupine = new Pen(Color.Black);
        Pen barva_tock_kon_lupine = new Pen(Color.Yellow);

        public Form1()
        {
            InitializeComponent();

            test.Add(seznamTock);
        }

        private List<Point> konveksnaLupina(List<Point> tocka)
        {
            List<Point> hull = new List<Point>();
            Point vPointOnHull = tocka.Where(p => p.X == tocka.Min(min =>
            min.X)).First();

            Point vEndpoint;
            do
            {
                hull.Add(vPointOnHull);
                vEndpoint = tocka[0];

                for (int i = 1; i < tocka.Count; i++)
                {
                    if ((vPointOnHull == vEndpoint)
                        || (Orientacija(vPointOnHull, vEndpoint, tocka[i]) ==
                     -1))
                    {
                        vEndpoint = tocka[i];
                    }
                }

                vPointOnHull = vEndpoint;

            }
            while (vEndpoint != hull[0]);

            return hull;
        }

        private static int Orientacija(Point p1, Point p2, Point p)
        {
            // Determinanta
            int Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);

            return (Orin == 0) ? Orin : ((Orin > 0) ? -1 : 1);

            //if (Orin > 0)
            //{
            //    return -1; //orientacija v levo
            //}
            //if (Orin < 0)
            //{
            //    return 1; //orientacija v desno
            //}

            //return 0; //neutralna orientacija
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            Point zacasna = new Point();
            zacasna.X = e.X;
            zacasna.Y = e.Y;
            seznamTock.Add(zacasna);

            //pictureBox1.Image = Image.FromFile(file);
            using (var g = Graphics.FromImage(pictureBox1.Image))
            {
                for (int i = 0; i < seznamTock.Count; i++) { g.DrawEllipse(barva_tock, seznamTock[i].X, seznamTock[i].Y, 5, 5); }

                pictureBox1.Refresh();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //if (seznamTock.Count < 3)
            //{
            //    MessageBox.Show("Premalo tock!");
            //    return;
            //}

            List<Point> hull = new List<Point>();
            hull = konveksnaLupina(seznamTock);
            //pictureBox1.Image = Image.FromFile(file);

            using (var g = Graphics.FromImage(pictureBox1.Image))
            {

                for (int j = 0; j < seznamTock.Count; j++)
                {
                    g.DrawEllipse(barva_tock, seznamTock[j].X, seznamTock[j].Y,
                    5, 5);
                }
                for (int j = 0; j < hull.Count; j++)
                {
                    Point tocka1 = new Point(hull[j].X, hull[j].Y);
                    Point tocka2 = new Point(hull[(j + 1) % hull.Count].X,
                   hull[(j + 1) % hull.Count].Y);
                    g.DrawLine(barva_kon_lupine, tocka1, tocka2);
                }
                for (int j = 0; j < hull.Count; j++)
                {
                    g.DrawEllipse(barva_tock_kon_lupine, hull[j].X, hull[j].Y, 5, 5);
                }

                pictureBox1.Refresh();

                test.Add(seznamTock);
                seznamTock = new List<Point>();
            }
        }
    }
}