Comprobar si un punto está en el interior de un polígono

El algoritmo se basa en aplicar una línea horizontal desde el punto de control y comprobar cuantas veces se corta con las aristas del polígono. Si el resultado es un número impar significa que el punto se encuentra en el interior, si es par significa que está fuera.

En este código se controla también la posibilidad de que el punto se encuentre justo en alguna de las aristas, en ese caso también o da como punto interno.

Cuando necesites saber si un punto se encuentra dentro de un polígono, definido por sus vértices, puedes utilizar el siguiente código.

        /// <summary>

        /// Establece si un punto se encuentra en el interior de un polígono.

        /// </summary>

        /// <param name=”vertex“>Lista de puntos que componen el polígono</param>

        /// <param name=”pt“>Punto a verificar</param>

        /// <returns></returns>

        public static bool InternalPoint (List<Point3D>vertex, Point3D pt, int precision)

        {

            try

            {

                // Primera comprobación. Verificar si el punto se encuentra en alguna de las aristas

                List<line> edges = CalculeEdges(vertex); // Obtenemos las aristas del polígono para probar

                foreach (line edge in edges)

                {

                    if (PointInLine(pt, edge.StartPoint, edge.EndPoint, precision))

                    {

                        return true; //Si está en la línea lo damos por interno. no hace falta seguir

                    }

                }

                // Segunda comprobación. Verificar si el punto se encuentra dentro de la caja

                // de abarque del polígono.

                Point3D minPt = new Point3D();

                Point3D maxPt = new Point3D();

                if (!BoundBox(vertex, ref minPt, ref maxPt))

                {

                    return false; // falló la obtención de las coordenadas de la caja

                }

                // Solo operaremos si el punto se encuentra entre las coordenadas mínima y máxima

                if (pt.x > minPt.x && pt.y > minPt.y && pt.x < maxPt.x && pt.y < maxPt.y)

                {

                    // Trazamos una línea horizontal hasta el límite de la caja de abarque

                    line nl = new line(pt, new Point3D(minPt.x, pt.y, 0));

                    // Declaramos una lista de puntos para almacenar las intersecciones obtenidas

                    List<Point3D> ListInts = new List<Point3D>();

                    // Ahora comprobamos la cantidad de intrsecciones que se producen con las aristas

                    foreach (line edge in edges)

                    {

                        Point3D ptInters = Inters2D(nl.StartPoint, nl.EndPoint, edge.StartPoint, edge.EndPoint);

                        if (ptInters != null)

                        {

                            // Comprobamos que no haya puntos duplicados. Eso ocurriría si la proyección

                            // del punto coincidira con un vértice

                            if (!ListInts.Contains(ptInters))

                            {

                                ListInts.Add(ptInters);

                            }

                        }

                    }

                    // Ya se han comprobado todas las intersecciones.

                    // Vamos a resolver el problema.

                    return (ListInts.Count > 0) && ((ListInts.Count % 2) != 0);

                    // Si el número de intersecciones es impar significa que está dentro

                    // En caso contrario o si no hay intersecciones significa que está fuera.

                }

                else

                {

                    return false;

                }

            }

            catch (Exception ex)

            {

                MessageBox.Show(“Error:” + Environment.NewLine + ex.Message, “Test”,

                                MessageBoxButtons.OK, MessageBoxIcon.Error);

                return false;

            }

        }

Para ponerlo a prueba puedes escribir una función parecida a la siguiente:

        private void puntoInternoToolStripMenuItem_Click(object sender, EventArgs e)

        {

            List<Point3D> pts = new List<Point3D>();

            pts.Add(new Point3D(10, 5, 0));

            pts.Add(new Point3D(10, 10, 0));

            pts.Add(new Point3D(12.5, 10, 0));

            pts.Add(new Point3D(15, 12.5, 0));

            pts.Add(new Point3D(17.5, 12.5, 0));

            pts.Add(new Point3D(17.5, 5, 0));

            pts.Add(new Point3D(15, 5, 0));

            pts.Add(new Point3D(15, 7.5, 0));

            pts.Add(new Point3D(12.5, 5, 0));

            Point3D pt = new Point3D(12, 6.5, 0);

            // Prueba con el punto interno

            if (MyClase.InternalPoint(pts, pt, 2))

            {

                MessageBox.Show(“El punto está dentro”, “Test”,MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            else

            {

                MessageBox.Show(“El punto está fuera”, “Test”,MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            // Otra prueba con el punto fuera

            pt = new Point3D(18.5, 6.5, 0);

            if (MyClase.InternalPoint(pts, pt, 2))

            {

                MessageBox.Show(“El punto está dentro”, “Test”,MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            else

            {

                MessageBox.Show(“El punto está fuera”, “Test”,MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

        }

La prueba está basada en el siguiente caso:

Ponlo a prueba, piensa en cómo mejorarlo y comparte con nosotros tus progresos.

 

¿Te gustaría aprender a programar en .NET sobre AutoCAD?

Si te inscribes recibirás un cupón de descuento adicional con el que el coste del curso quedará reducido al 50%. También tendrás opción a recibir soporte técnico en programación sobre AutoCAD o Bricscad por correo electrónico sin coste.

Deja un comentario

Tu dirección de correo electrónico no será publicada.

Información básica sobre protección de datos Ver más

  • Responsable: MTB Software de Ponent, SLU.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a Hostinet, SL que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Ir arriba
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Ver Política de cookies
Privacidad