¿Cuál es la idea detrás de definir rectángulos con dos puntos? [cerrado]

14

No es que esto no tenga sentido, pero simplemente resulta incómodo el 99% del tiempo.

A menudo, en gráficos 2D, los rectángulos se inicializan, almacenan y manipulan como un par de puntos. En ningún idioma en particular,

class Rect:
   p1, p2: point

Tiene más sentido definir un rectángulo como dos valores xy dos valores y, así:

class Rect
   xleft, xright: int
   ytop, ybottom: int

Con dos puntos, si en algún lugar del código fuente desea utilizar el valor y de la parte superior, tendría que decir rect.p1.y (hmmm, deténgase y piense, es p1 o p2) pero con los cuatro valores como miembros de datos simples, es claro y directo: rect.ytop (¡no se requiere pensar!) El uso de dos puntos significa que al tratar con la vertical, debe enredar la horizontal; Hay una relación extraña entre los elementos independientes.

¿Cómo surgió esta idea de dos puntos y por qué persiste? ¿Tiene algún beneficio sobre las coordenadas x e y desnudas?

NOTA AGREGADA: Esta pregunta está en el contexto de rectángulos alineados XY, como en los administradores de ventanas y los kits de herramientas GUI, no en el contexto de formas arbitrarias en la aplicación de dibujo y pintura.

DarenW
fuente
8
¿Has escrito una cantidad sustancial de código usando Rects?
66
Un rectángulo está definido por dos puntos, por lo que representarlos como dos puntos tiene mucho sentido.
Adam Crossland
2
Un rectángulo se define más naturalmente como un rango de valores xy un rango de valores y.
DarenW
2
Gran pregunta! ¡Nunca lo pensé, pero haces un argumento interesante! FWIW, Windows también tiene un RECT como el que usted describe (arriba, izquierda, abajo, derecha)
Dean Harding
3
¿Cómo se define un rectángulo con dos puntos? ¿Se supone que no tiene rotación?
Nick T

Respuestas:

8

¿Has considerado que es menos propenso a errores?

Si usa (Punto1, Punto2), entonces queda muy claro lo que está especificando. Si proporciona 2 puntos, entonces el único error posible es que el usuario ha mezclado sus x e y al construir los puntos, ya que el orden de los puntos no importa.

Si proporciona 4 enteros, si alguien no está prestando atención, puede suministrar (x1, x2, y1, y2) cuando lo desee (x1, y1, x2, y2) o viceversa. Además, algunas API, como la estructura Rect de WCF, definen un rectángulo como (x, y, ancho, alto) que podría causar confusión sobre lo que significa (1, 2, 3, 4). ¿Es eso (x, y, w, h) o (x1, y1, x2, y2) o (x1, x2, y1, y2)?

En general, (Punto1, Punto2) me parece un poco más seguro.

desaparecido en combate
fuente
3
¿Qué pasa con algo como Rect (xrange (x1, x2), yrange (y1, y2))? Eso parece lo último en seguridad y elegancia en el uso de API.
DarenW
9

Siempre me gustó definir un rectángulo como punto + ancho y alto, donde el punto es la esquina superior izquierda del rectángulo.

class Rect {
  float x, y;
  float width, height;
}

Y luego agregue los métodos que necesite para obtener las otras métricas. Como la versión de Java

Martin Wickman
fuente
44
¿Es la altura y + superior, la altura y o solo y?
Cameron MacFarland
2
@Cameron MacFarland: Eso depende del sistema de coordenadas de la aplicación, que no es una preocupación de un rectángulo bajo.
Jon Purdy
2
@ Martin Wickman: ¿Cuál es la ventaja sobre el uso de 2 puntos?
Kramii
@Kramii: Una ventaja es que solo tienes que traducir un punto si estás moviendo todo el rectángulo. Por cierto, siempre puede calcular el "punto faltante" si lo necesita (compensación de CPU / memoria).
Martin Wickman
Esto también aparece en la vida real. Me resulta complicado, ya que una de las cosas más comunes que hago con los rectángulos es probar si un punto está contenido dentro. El dibujo también es común. En ambos casos, se debe realizar una adición, lo que molesta a los contadores de ciclos de reloj de alto rendimiento como yo.
DarenW
7

En realidad, un rectángulo no está definido por 2 puntos. Un rectángulo solo puede definirse por dos puntos si es paralelo a los ejes.

Hay varias formas de representar rectángulos que son paralelos a los ejes:

  1. Dos puntos diagonalmente opuestos
  2. Un punto de esquina, altura y ancho
  3. Punto central, media altura y ancho (poco común, pero a veces útil).
  4. Como dos coordenadas X y dos coordenadas Y

Para (1), muchas bibliotecas usan una convención para determinar qué dos puntos se utilizan: topLeft y bottomRight, por ejemplo.

La elección de la representación puede estar impulsada por el propósito original de la definición del rectángulo, pero imagino que a menudo es arbitraria . Las representaciones son equivalentes en la información que llevan. Sin embargo, difieren en la facilidad con que se pueden calcular las propiedades del rectángulo y la conveniencia con la que se pueden realizar operaciones en el rectángulo.

Los beneficios de la definición (1) sobre otros incluyen:

  • Consistencia de API con otros polígonos, líneas, etc.
  • topLeft, bottomRight se puede pasar a cualquier método que acepte puntos
  • Los métodos de la clase Point se pueden invocar en topLeft, bottomRight
  • La mayoría de las propiedades se pueden derivar fácilmente, por ejemplo. bottomLeft, topRight, ancho, altura, centro, longitud diagonal, etc.
Kramii
fuente
6

Bueno, p1: Pointy p2: Pointcada uno tendrá dos intcoordenadas de todos modos, entonces, ¿su clase no equivale a lo mismo?

Y si almacena esos dos puntos como Pointobjetos de primera clase , ¿no obtiene un poco más de utilidad de ellos? En la mayoría de los sistemas de coordenadas gráficas que conozco, los puntos se subclasifican de esta manera para crear una jerarquía de objetos: point -> circle -> ellipsey así sucesivamente.

Entonces, si crea un objeto que no usa la Pointclase, se ha divorciado de ese objeto del resto de la jerarquía de clases.

Robert Harvey
fuente
1
La ventaja que veo de la representación de OP es que si quieres saber el valor y más bajo de un rectángulo, sabes que es "ybottom", donde con p1 / p2 necesitas averiguar cuál es más bajo. Esto es a menos que garantice que p1 será los valores más bajos, de todos modos.
Jason Viers
1
Si bien es cierto que las dos estructuras diferentes se reducen a cuatro coordenadas, la versión de dos puntos introduce un nivel extraño que reúne una xy una y, sin una razón particular a la que x va con qué y. No veo que este nivel adicional proporcione ninguna utilidad, después de muchos años de programación gráfica.
DarenW
1
@ Jason: Buen punto. Sin embargo, con el enfoque ytop/ ybottom, también debería haber una garantía en algún lugar que ybottomesté realmente debajo ytop.
Aprendiz del Dr. Wily
O llámalos y1 e y2, y usa min (y1, y2) y max (y1, y2), por supuesto, eso sería más torpe incluso que el acceso a través de dos puntos p1, p2.
DarenW
el nombramiento de top / bottom no le compra nada, ya que nada impide bottomx <topx, a menos que codifique eso específicamente. Creo que solo agregaría confusión.
kg
5

Por eso me gusta Delphi's TRect. Se define como un registro variante (estructura de unión en C-speak) que se puede interpretar como un punto superior izquierdo y uno inferior derecho, o enteros superior, izquierdo, inferior y derecho, lo que sea más conveniente en este momento.

Mason Wheeler
fuente
1
Sí, característica muy útil que.
Orbling
4

Seguramente si define su rectángulo como:

class Rect
{
    Point bottomLeft;
    Point topRight;
}

entonces sabes de inmediato qué punto es cuál.

Aún mejor sería agregar propiedades adicionales que le permitieran manipular el rectángulo de cualquier forma que necesitara para su aplicación. Estos simplemente actualizarían la estructura de datos subyacente.

Al agregar una transformación a la forma, puede orientar su rectángulo de la forma que desee. Aún necesitaría un cuadro delimitador alineado con el eje para verificaciones de aceptación / rechazo rápidas :)

Sin embargo, si su modelo permite rectángulos en cualquier orientación sin aplicar una transformación, entonces "abajo a la izquierda" y "arriba a la derecha" no tienen significado, lo que lleva de nuevo a "p1" y "p2" (o algo equivalente).

ChrisF
fuente
Entonces, ¿qué sucede cuando giras el rectángulo 90 grados? ¿Ahora está rastreando dos puntos diferentes de lo que era inicialmente, o su "topRight" ahora está a la izquierda de "bottomLeft"?
Inaimathi
@Inaimathi: si agrega una matriz de transformación, puede mantener el rectángulo orientado con los ejes. Sin embargo, depende de su aplicación.
ChrisF
2

Creo que tiene más sentido que un rectángulo esté representado por una extensión x e y y un punto; incluso podría hacer que la ubicación apunte al centro del rectángulo para que sea independiente de la rotación

¡pero probablemente fue más fácil codificarlo como dos puntos!

Steven A. Lowe
fuente
¿Cómo sería más fácil codificar como dos puntos?
DarenW
@DaremW: las funciones típicas de la biblioteca de rectángulo de dibujo toman los puntos superior izquierdo e inferior derecho como argumentos
Steven A. Lowe
Pero, ¿por qué esas API están diseñadas de esa manera? Además de imitar sin pensar las bibliotecas anteriores, eso es.
DarenW
@DarenW: supongo que las bibliotecas usan una rutina de dibujo lineal de Bresenham, que toma dos puntos como entradas y es muy eficiente
Steven A. Lowe
2

No me gusta porque hemos arrojado un posible grado de libertad, que esencialmente permite una rotación arbitraria. Un rectángulo 2D general tiene cinco incógnitas (grados de libertad). Podríamos especificarlos como las coordenadas de un punto, las longitudes de los dos lados que forman un vértice con este punto y el ángulo desde la horizontal de la primera línea (se supone que el otro tiene un ángulo 90 grados mayor). También se podría utilizar un número infinito de otras posibilidades, pero hay cinco cantidades independientes que deben especificarse. Algunas opciones conducirán a un álgebra más fácil que otras, dependiendo de lo que se haga con ellas.

Omega Centauri
fuente
55
Es importante darse cuenta de que una estructura de rectángulo "estándar" no es un rectángulo matemático rigurosamente definido, sino una versión simplificada que siempre es paralela a los ejes X e Y, porque se creó para usarse para una cosa muy específica: definir regiones rectangulares para un administrador de ventanas, que son (casi) siempre paralelos a los ejes X e Y.
Mason Wheeler
+1, la estructura izquierda / derecha / superior / inferior está clasificada previamente y, por lo tanto, tiene menos información
Javier
Buen punto, sobre rectángulos alineados xy. Tenía en cuenta eso, y también las extensiones que se usan en el modelado 3D y algunas otras cosas, pero todas alineadas xy (tal vez también -z).
DarenW
1

¿No es exactamente lo mismo que 2 puntos? Cómo es esto incómodo ... la mayoría de las rutinas de dibujo requieren puntos, no componentes separados x / y.

Gran maestro B
fuente
1

La definición de rectángulos como pares de puntos le permite reutilizar el punto como vértice para otra forma. Solo un pensamiento...

RobotHumanos
fuente
Pero parece jugar con media baraja, para mantener solo dos puntos para definir una forma de cuatro esquinas. Si necesita la parte superior izquierda, genial, pero si necesita la parte superior derecha, debe hacer un poco de captura de datos sofisticada, en términos relativos.
DarenW
si hay un descriptor de acceso definido como punto AX, punto BY y punto BX, punto AY, lo hace más claro en la memoria / en el disco, creo que almacena la mitad de los vértices y solo los señala (dependiendo del tamaño máximo de la cuadrícula). Llegué a donde vas con tu rango de pensamiento, pero no estás jugando con la mitad del mazo, simplemente no estás almacenando datos duplicados ... y los otros puntos a destacar son ¿cuáles son las restricciones de memoria? cuáles son las implicaciones de la reimplementación reestructurando los rectificadores en todo el código interconectado.
RobotHumans
y puesto que usted no tiene que hacer ningún "trabajo" para obtener los dos primeros vértices fuera de la memoria, es probable que sea más rápido
RobotHumans
1

Creo que es principalmente para establecer la uniformidad entre todas las primitivas de forma.

Claro que puede definir un rectángulo de muchas maneras diferentes, pero ¿cómo define un triángulo, una estrella o un círculo de manera que pueda usar estructuras de datos similares?

Todos los polígonos se pueden definir por sus puntos, con una pequeña cantidad de lógica para determinar qué hacer con los puntos.

Las bibliotecas de gráficos operan principalmente en estos polígonos en términos de vértices y bordes, por lo que los puntos y las líneas entre ellos, todos los cálculos funcionan en estas dos características, bien eso y facetas, pero eso en sí mismo es solo una función de los bordes.

Orbling
fuente
1

En dos dimensiones, almacenar un rectángulo como dos puntos es más claro que definir una esquina particular y un ancho y alto: considere el ancho o alto negativo, o los cálculos necesarios para determinar cada opción a partir de la otra.

Realizar rotaciones en un rectángulo definido por puntos también es mucho más simple que uno definido con un punto más ancho y alto.

Esperaría que la encapsulación haga que esta diferenciación no sea importante como usuario de la clase.

Un rectángulo debe definirse como tres puntos para estar bien definido en 3 dimensiones. No estoy completamente seguro del requisito para definir un rectángulo en 4 o más dimensiones.

Armand
fuente
1

Es completamente arbitrario. Necesita cuatro piezas de información para dibujar un rectángulo. El diseñador de la biblioteca decidió representarlo con dos puntos (cada uno con una coordenada xy), pero podría haberlo hecho fácilmente con x / y / w / ho arriba / abajo / izquierda / derecha.

Supongo que la verdadera pregunta del OP es: ¿ por qué se hizo esta elección en particular?

Barry Brown
fuente
1

La elección de los parámetros solo es importante para los diseñadores / codificadores de bajo nivel.

Los usuarios de alto nivel solo necesitan pensar en:

  • IsPointInRect
  • Zona
  • Intersección (o recorte)
  • HasOverlap (igual que Intersection.Area> 0)
  • Unión (se convierte en una lista de rectángulos)
  • Resta (una lista de rectángulos que representan el mismo conjunto de puntos que está en el rectángulo A pero no en el rectángulo B)
  • Transformar
    • Cambios en X e Y
    • Rotación (0, 90, 180, 270)
    • Escalado en X e Y (ver nota)
  • Sintaxis simple para las propiedades Xmin, Xmax, Ymin, Ymax, Width, Height para que el usuario no necesite conocer la elección exacta de los parámetros.

Nota: Para minimizar la pérdida de precisión durante la transformación de escala, a veces es apropiado implementar una segunda clase Rect que utiliza coordenadas de punto flotante, de modo que los resultados intermedios se puedan almacenar con precisión en una secuencia de transformaciones y solo redondearse a entero en el último paso.

rwong
fuente
0

Como dice @Steven, creo que debería ser en términos de un punto (x, y) y un vector de tamaño (w, h). Eso es porque es fácil caer en una ambigüedad. Suponga que tiene el siguiente rectángulo relleno comenzando en el punto (0,0).

  012
0 XXX
1 XXX
2 XXX

Claramente su ancho, altura son (3,3), pero ¿cuál es su segundo punto? ¿Es (2,2) o (3,3)?

Esta ambigüedad puede causar todo tipo de problemas.

Aprendí hace la forma en años duros que es mejor pensar en coordenadas gráficas como las líneas entre los píxeles, no como las líneas de los píxeles son en . De esa manera no hay ambigüedad.

Mike Dunlavey
fuente
2
Las rutinas originales de QuickDraw en Mac (las de la década de 1980) usaban el modelo matemático de que los puntos eran infinitamente pequeños. Los puntos en la pantalla se encuentran entre los píxeles. Entonces, una línea dibujada de (3,5) a (10,5) tenía una longitud de 7 y ocupaba 7 píxeles. En las coordenadas de hoy, esa línea tendría una longitud de 8.
Barry Brown
@Barry: Eso tiene sentido, ya que usó XOR mucho, y si está uniendo líneas, desea que se conecten sin un píxel perdido donde se encuentran. De hecho, publiqué un documento de firma sobre el llenado de polígonos, considerando ambos sistemas de coordenadas.
Mike Dunlavey
0
Pa(x,y)*-----------------------------------*Pb(x,y)
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)

Podemos definir tanto Pb como Pc así:

Pb (Pd (x), Pa (y))

y

Pc (Pa (x), Pd (y))

Por lo tanto, no es necesario definir los cuatro puntos debido a la simetría

Noche oscura
fuente