2009-12-13 23 views
10

Tengo una gran colección de rectángulos, todos del mismo tamaño. Estoy generando puntos aleatorios que no deberían caer en estos rectángulos, así que lo que deseo hacer es probar si el punto generado se encuentra en uno de los rectángulos, y si lo hace, generar un nuevo punto.Prueba si el punto está en algún rectángulo

El uso de árboles R parece funcionar, pero están destinados a rectángulos y no a puntos. Podría usar una versión modificada de un algoritmo de árbol R que también funciona con puntos, pero prefiero no reinventar la rueda, si ya hay alguna solución mejor. No estoy muy familiarizado con las estructuras de datos, ¿entonces quizás ya exista alguna estructura que funcione para mi problema?

En resumen, básicamente lo que estoy preguntando es si alguien sabe de un buen algoritmo, que funciona en Python, que se puede utilizar para comprobar si un punto se encuentra en cualquier rectángulo en un conjunto dado de rectángulos.

editar: Esto está en 2D y los rectángulos no se giran.

+3

¿Están los lados de sus rectángulos alineados con los ejes, o están orientados en ángulos arbitrarios a los ejes? –

+0

Están todos alineados, sin rotación ni nada de fantasía como ese – pafcu

+0

¿se superponen los rectángulos en absoluto? –

Respuesta

8

Este hilo Reddit aborda el problema:

I have a set of rectangles, and need to determine whether a point is contained within any of them. What are some good data structures to do this, with fast lookup being important?

Si el universo es número entero, o si el nivel de precisión es bien conocida y no es demasiado alto, puede utilizar abelsson 's sugerencia de la hilo, utilizando O (1) las operaciones de búsqueda utilizando colorante:

Como de costumbre se puede comerciar espacio para tiempo .. aquí hay una O (1) las operaciones de búsqueda con muy baja constante. init: crea un mapa de bits lo suficientemente grande para envolver todos los rectángulos con suficiente precisión, inicialízalo en negro. Colorea todos los píxeles que contengan cualquier rectángulo blanco. O (1) búsqueda: ¿el punto (x, y) es blanco? Si , se golpeó un rectángulo.

Te recomiendo que vayas a esa publicación y leas completamente la respuesta de ModernRonin que es la más aceptada. Lo pegué aquí:

Primero, el problema micro. Tiene un rectángulo rotado arbitrariamente y un punto . ¿Está el punto dentro del rectángulo ?

Hay muchas formas de hacerlo. Pero lo mejor, creo, es el uso del producto 2d vector cruzado. Primero, asegúrese de que los puntos del rectángulo estén almacenados en el sentido de las agujas del reloj. A continuación, haga el vector producto cruzado con 1) el vector formado por los dos puntos del lado y 2) un vector desde el primer punto del lado hasta el punto de prueba. Compruebe el signo del resultado - positivo es dentro (a la derecha de) el lado, negativo está afuera. Si está dentro de los en los cuatro lados, está dentro del rectángulo . O, de forma equivalente, si es fuera de cualquiera de los lados, está fuera del rectángulo . More explanation here.

Este método se llevará a 3 resta por vector * veces 2 vectores por lado, más un producto cruzado por cada lado que es tres multiplica y dos añade.11 fracasos por lado, 44 ​​fracasos por rectángulo.

Si no te gusta el producto vectorial, entonces se podría hacer algo como: averiguar la inscripción y círculos circunscritos de cada rectángulo, comprobar si el punto dentro de la inscrita uno. Si es así, también está en el rectángulo . De lo contrario, verifique si está fuera del rectángulo circunscrito. Si es así, está fuera del rectángulo también. Si cae entre los dos círculos, está f **** d y usted tiene que comprobarlo de la manera difícil.

Encontrar si un punto está dentro de un círculo en 2d toma dos sustracciones y dos squarings (= multiplica), y luego se comparar la distancia al cuadrado para evitar tener que hacer una raíz cuadrada. Eso es 4 fracasos, multiplicado por dos círculos es de 8 fracasos - pero a veces todavía no lo sabrá. También esto supone que usted no paga tiempo de CPU para calcular los círculos circunscritos o inscritos, que puede o no puede ser cierto dependiendo de la cantidad de pre-cálculo que está dispuesto a hacer en su conjunto rectángulo .

En cualquier caso, probablemente no es una gran idea para probar el punto en contra cada rectángulo, sobre todo si se tiene cien millones de ellos.

Lo que nos lleva al problema macro. ¿Cómo evitar probar el punto en contra de en cada rectángulo del conjunto? En 2D, este es probablemente un problema quad-tree . En 3D, lo que generic_handle dijo: un octárbol. De la parte superior de mi cabeza , probablemente lo implementaría como a B+ tree. Es tentador usar d = 5, para que cada nodo pueda tener hasta 4 niños, ya que se asigna tan bien a la abstracción del árbol cuádruple. Pero si el conjunto de rectángulos es demasiado grande para ajuste en la memoria principal (no muy probable estos días), entonces tienen nodos del mismo tamaño como bloques de disco es probablemente el camino a seguir.

Cuidado con degenerada molesto casos, como un conjunto de datos que tiene diez mil rectángulos casi idénticos con centros en el mismo punto exacto. : P

¿Por qué es importante este problema? Es útil en gráficos de computadora, para verificar si un rayo se cruza con un polígono. Es decir, ¿Acaso ese rifle de francotirador disparó solo golpeó a la persona a la que estaba disparando ? También se usa en el software de mapas en tiempo real, como unidades de GPS. El GPS le indica las coordenadas en que se encuentra, , pero el software de mapas tiene que encontrar dónde ese punto está en una gran cantidad de datos de mapa , y hacerlo varias veces por segundos.

Una vez más, el crédito al ModernRonin ...

+1

Me cuesta imaginar cómo el método "producto vectorial" de ModernRonin puede ser más rápido que simplemente comprobar si min_x <= x <= max_x y min_y <= y <= max_y ... I ' No estoy seguro tampoco del acercamiento de quadtree, ya que en su mayoría ayudan a almacenar puntos, no rectángulos ... – EOL

+2

El producto vectorial permite un rectángulo de orientación arbitraria; Estoy seguro de que otros métodos son más apropiados cuando todos los rectángulos están alineados con los ejes de algún sistema de coordenadas. – musicinmybrain

+0

Además, el método de producto vectorial permite verificar si un punto está dentro de cualquier forma de 4 lados, ya sea o no un rectángulo. –

0

le sugiero que tome un vistazo a BSP trees (y posibles quadtrees o octrees, enlaces disponibles en esa página también). Se usan para dividir todo el espacio de manera recursiva y permiten verificar rápidamente en qué punto deben rectificarse los rectángulos.

Como mínimo, solo tiene una gran partición y necesita comprobar todos los rectángulos, como máximo, sus particiones son tan pequeñas que se reducen al tamaño de los rectángulos individuales. Por supuesto, cuanto más fina sea la partición, más tiempo tendrá que caminar por el árbol para encontrar los rectángulos que desea verificar.

Sin embargo, puede decidir libremente cuántos rectángulos son adecuados para verificar un punto y luego crear la estructura correspondiente.

Sin embargo, preste atención a la superposición de rectángulos. Como el árbol BSP necesita ser precalculado de todos modos, también puede eliminar superposiciones durante ese tiempo, para que pueda obtener particiones claras.

0

Su enfoque R-tree es el mejor enfoque que conozco (ese es el enfoque que elegiría sobre quadtrees, árboles B + o árboles BSP, ya que los R-trees parecen convenientes de construir en su caso). Advertencia: ¡No soy un experto, aunque recuerdo algunas cosas de mi clase de algoritmo de último año de la universidad!

1

Por qué no probar esto. Parece bastante ligero tanto en computación como en memoria.

Considerar las proyecciones de todos los rectángulos en la línea de base de su espacio. Denotar ese conjunto de intervalos de línea como

{[Rl1, Rr1], [Rl2, Rr2],..., [Rln, Rrn]}, ordered by increasing left coordinates. 

Ahora supongamos que el punto es (x, y), iniciar una búsqueda en la parte izquierda de este conjunto hasta llegar a un intervalo de línea que contiene el punto x.

Si ninguno lo hace, su punto (x, y) se encuentra fuera de los rectángulos.

Si algunos lo hacen, digamos [Rlk, Rrk], ..., [Rlh, Rrh], (k < = h) luego simplemente verifique si y está dentro de la extensión vertical de cualquiera de estos rectángulos.

Listo.

Buena suerte.

John Doner

2

Para los rectángulos que están alineados con los ejes, sólo se necesitan dos puntos (cuatro números) para identificar el rectángulo - esquinas superior derecha convencionalmente, de abajo e izquierda.Para establecer si un punto dado (X prueba, Y prueba) se solapa con un rectángulo (X BL, Y BL, X TR, Y TR) mediante pruebas de los dos:

  • X prueba> = X BL & & X prueba < = X TR
  • Y prueba> = Y BL & & Y prueba < = Y TR

Claramente, para un gran conjunto suficiente de puntos para poner a prueba, esto podría ser bastante tiempo . La pregunta, entonces, es cómo optimizar las pruebas.

Claramente, una optimización es establecer los valores mínimo y máximo de X e Y de la caja que rodea todos los rectángulos (el cuadro delimitador): una prueba rápida en esta muestra si hay alguna necesidad de buscar más.

  • X prueba> = X min & & X prueba < = X max
  • Y prueba> = Y min & & Y prueba < = Y max

Dependiendo de la superficie total cubierta por rectángulos, es posible que pueda encontrar subáreas que no se solapen y que contengan rectángulos, y luego podría evitar buscar aquellas subáreas que no pueden contener un rectángulo. rectángulo superpuesto al punto, guardando de nuevo las comparaciones durante la búsqueda al costo de precálculo de estructuras de datos adecuadas. Si el conjunto de rectángulos es lo suficientemente escaso, puede que no haya superposición, en cuyo caso esto degenerará en la búsqueda de fuerza bruta. Igualmente, si el conjunto de rectángulos es tan denso que no hay rangos secundarios en el cuadro delimitador que puedan dividirse sin romper rectángulos.

Sin embargo, también podría dividir arbitrariamente el área delimitada en, digamos, trimestres (la mitad en cada dirección). A continuación, utilizaría una lista de cuadros que incluiría más cuadros que en el conjunto original (dos o cuatro casillas por cada casillero que se solaparan con uno de los límites arbitrarios). La ventaja de esto es que luego puede eliminar tres de los cuatro trimestres de la búsqueda, lo que reduce la cantidad de búsquedas que se deben realizar en total, a expensas del almacenamiento auxiliar.

Por lo tanto, hay intercambios de espacio-tiempo, como siempre. Y precomputación versus trade-offs de búsqueda. Si tiene mala suerte, el precálculo no logra nada (por ejemplo, solo hay dos casillas y no se superponen en ninguno de los ejes). Por otro lado, podría lograr un considerable beneficio de tiempo de búsqueda.

Cuestiones relacionadas