Qual è l'idea alla base della definizione di rettangoli con due punti? [chiuso]


14

Non è che ciò non abbia senso, ma risolve semplicemente il 99% delle volte.

Spesso nei rettangoli grafici 2D vengono inizializzati, archiviati e manipolati come una coppia di punti. In nessuna lingua particolare,

class Rect:
   p1, p2: point

Ha più senso definire un rettangolo come due valori xe due valori y, in questo modo:

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

Con due punti, se in qualche punto del codice sorgente vuoi usare il valore y della cima, dovresti dire rect.p1.y (hmmm, fermati e pensa, è p1 o p2) ma con i quattro valori come semplici membri di dati, è chiaro e diretto: rect.ytop (non è necessario pensare!) L'uso di due punti significa che nel trattare con la verticale, devi ingarbugliare l'orizzontale; c'è una relazione estranea tra elementi indipendenti.

Come è nata questa idea in due punti e perché persiste? Ha qualche vantaggio rispetto alle coordinate nude xey?

NOTA AGGIUNTA: questa domanda è nel contesto dei rettangoli allineati XY, come nei gestori di finestre e nei toolkit della GUI, non nel contesto di forme arbitrarie nell'app di disegno e pittura.


8
Hai scritto una notevole quantità di codice usando Rects?

6
Un rettangolo è definito da due punti, quindi rappresentarli come due punti ha molto senso.
Adam Crossland,

2
Un rettangolo è più naturalmente definito come un intervallo di valori x e un intervallo di valori y.
DarenW,

2
Ottima domanda! Non ci ho mai pensato da solo, ma tu fai una discussione interessante! FWIW, Windows ha anche un RECT come tu descrivi (in alto, a sinistra, in basso, a destra)
Dean Harding

3
Come si definisce un rettangolo con due punti? Si presume che non abbia rotazione?
Nick T,

Risposte:


8

Hai considerato che è meno soggetto a errori?

Se si utilizza (Punto1, Punto2) è quindi molto chiaro cosa si sta specificando. Se si forniscono 2 punti, l'unico errore possibile è che l'utente ha mischiato i loro xey durante la costruzione dei punti poiché l'ordine dei punti non ha importanza.

Se fornisci 4 numeri interi, se qualcuno non sta prestando attenzione, potrebbe fornire (x1, x2, y1, y2) quando lo desideri (x1, y1, x2, y2) o viceversa. Inoltre, alcune API come la struttura Rect di WCF definiscono un rettangolo come (x, y, larghezza, altezza) che potrebbe quindi creare confusione sul significato di (1, 2, 3, 4). È (x, y, w, h) o (x1, y1, x2, y2) o (x1, x2, y1, y2)?

Tutto sommato, (Point1, Point2) mi sembra un po 'più sicuro.


3
Che dire di qualcosa come Rect (xrange (x1, x2), yrange (y1, y2))? Sembra il massimo in termini di sicurezza ed eleganza nell'uso delle API.
DarenW,

9

Mi è sempre piaciuto definire un rettangolo come punto + larghezza e altezza, dove il punto è l'angolo superiore sinistro del rettangolo.

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

Quindi aggiungi i metodi di cui hai bisogno per recuperare le altre metriche. Come la versione Java


4
L'altezza y + superiore, l'altezza y o solo y?
Cameron MacFarland l'

2
@Cameron MacFarland: dipende dal sistema di coordinate dell'applicazione, che non riguarda un modesto rettangolo.
Jon Purdy,

2
@Martin Wickman: Qual è il vantaggio rispetto all'utilizzo di 2 punti?
Kramii,

@Kramii: un vantaggio è che devi tradurre solo un punto se stai spostando l'intero retto. A proposito, puoi sempre calcolare il "punto mancante" se ne hai bisogno (compromesso CPU / memoria).
Martin Wickman,

Anche questo appare nella vita reale. Lo trovo complicato perché una delle cose più comuni che faccio con i rettangoli è testare se un punto è contenuto all'interno. Anche il disegno è comune. In entrambi i casi è necessario eseguire l'aggiunta, il che disturba i contatori di cicli di clock ad alte prestazioni come me.
DarenW,

7

In realtà, un rettangolo non è definito da 2 punti. Un rettangolo può essere definito da due punti solo se è parallelo agli assi.

Esistono diversi modi per rappresentare rettangoli paralleli agli assi:

  1. Due punti diagonalmente opposti
  2. Un punto d'angolo, altezza e larghezza
  3. Punto centrale, metà altezza e larghezza (non comune, ma a volte utile).
  4. Come due coordinate X e due coordinate Y.

Per (1), molte librerie usano una convenzione per determinare quali due punti vengono usati, ad esempio topLeft e bottomRight.

La scelta della rappresentazione può essere guidata dallo scopo originale della definizione del rettangolo, ma immagino che sia spesso arbitraria . Le rappresentazioni sono equivalenti nelle informazioni che trasportano. Differiscono, tuttavia, per la facilità con cui le proprietà del rettangolo possono essere calcolate e la comodità con cui le operazioni possono essere eseguite sul rettangolo.

I vantaggi della definizione (1) rispetto ad altri includono:

  • Coerenza dell'API con altri poligoni, linee, ecc.
  • topLeft, bottomRight può essere passato a qualsiasi metodo che accetta punti
  • I metodi della classe Point possono essere chiamati su topLeft, bottomRight
  • La maggior parte delle proprietà può essere derivata facilmente, ad es. bottomLeft, topRight, larghezza, altezza, centro, lunghezza diagonale, ecc.

6

Bene p1: Pointe p2: Pointsono ogni andando ad avere due intcoordinate in loro comunque, quindi non lo fa la vostra quantità di classe per la stessa cosa?

E se memorizzi quei due punti come Pointoggetti di prima classe , non ottieni un po 'più di utilità da loro? Nella maggior parte dei sistemi di coordinate grafiche che conosco, i punti vengono suddivisi in sottoclassi in questo modo per creare una gerarchia di oggetti: point -> circle -> ellipsee così via.

Quindi, se crei un oggetto che non utilizza la Pointclasse, hai divorziato da quell'oggetto dal resto della gerarchia di classi.


1
Il vantaggio che vedo della rappresentazione di OP è se vuoi conoscere il valore y più basso di un rettangolo, sai che è "ybottom", dove come con p1 / p2 devi capire quale è più basso. Questo a meno che tu non garantisca che p1 sarà comunque i valori più bassi.
Jason Viers,

1
Mentre è vero che le due diverse strutture si riducono entrambe a quattro coordinate, la versione a due punti introduce un livello estraneo che raccoglie una xe una y, senza una logica particolare alla quale x va con cui y. Non vedo questo livello extra come fornire alcuna utilità, dopo molti anni di programmazione grafica.
DarenW,

1
@Jason: buon punto. Con l' approccio ytop/ ybottom, tuttavia, ci dovrebbe essere anche una garanzia da qualche parte che ybottomè effettivamente inferiore ytop.
Apprendista Dr. Wily,

Oppure chiamali em y1 e y2 e usa min (y1, y2) e max (y1, y2) - ovviamente sarebbe più maldestro anche se l'accesso attraverso due punti p1, p2.
DarenW,

la denominazione di top / bottom non ti compra nulla in quanto nulla impedisce bottomx <topx, a meno che non lo specifichi specificamente. Penso che aggiungerebbe solo confusione.
kg

5

Questo è il motivo per cui mi piace Delphi TRect. È definito come un record di variante (struttura del sindacato in C-speak) che può essere interpretato come punto TopLeft e BottomRight o numeri interi Top, Left, Bottom e Right, a seconda di quale sia più conveniente al momento.


1
Sì, questa è una funzione molto utile.
orbita il

4

Sicuramente se definisci il tuo rettangolo come:

class Rect
{
    Point bottomLeft;
    Point topRight;
}

allora sai subito quale punto è quale.

Ancora meglio sarebbe aggiungere proprietà extra che ti permettessero di manipolare il rettangolo in tutti i modi necessari per la tua applicazione. Questi semplicemente aggiornerebbero la struttura di dati sottostante.

Aggiungendo una trasformazione alla forma puoi orientare il tuo rettangolo nel modo che preferisci. Avresti ancora bisogno di un riquadro di delimitazione allineato agli assi per i controlli rapidi di accettazione / rifiuto :)

Tuttavia, se il modello consente rettangoli con qualsiasi orientamento senza applicare una trasformazione, "in basso a sinistra" e "in alto a destra" non hanno alcun significato, il che porta a "p1" e "p2" (o qualcosa di equivalente).


Quindi cosa succede quando si ruota il rettangolo di 90 gradi? Ora stai monitorando due punti diversi rispetto a quando eri inizialmente, oppure il tuo "topRight" ora è a sinistra di "bottomLeft"?
Inaimathi,

@Inaimathi - se aggiungi una matrice di trasformazione puoi mantenere il rettangolo orientato con gli assi. Tuttavia, dipende dalla tua applicazione.
ChrisF

2

penso che abbia più senso che un rettangolo sia rappresentato da un'estensione xey e un punto; potresti persino fare in modo che la posizione punti al centro del rettangolo in modo che sia indipendente dalla rotazione

ma probabilmente era più facile codificarlo come due punti!


Come sarebbe più facile codificare come due punti?
DarenW,

@DaremW: le tipiche funzioni della libreria draw-rectangle considerano i punti in alto a sinistra e in basso a destra come argomenti
Steven A. Lowe,

Ma perché quelle API sono progettate in questo modo? Oltre a imitare inconsapevolmente le librerie precedenti, cioè.
DarenW,

@DarenW: la mia ipotesi sarebbe che le biblioteche utilizzino una routine di disegno a tratteggio di Bresenham, che prende due punti come input ed è molto efficiente
Steven A. Lowe,

2

Non mi piace perché abbiamo buttato fuori un potenziale grado di libertà, che essenzialmente consente una rotazione arbitraria. Un rettangolo 2D generale ha cinque incognite (gradi di libertà). Potremmo specificarli come coordinate di un punto, le lunghezze dei due lati che formano un vertice con questo punto e l'angolo dall'orizzontale della prima linea (l'altro che si presume abbia un angolo maggiore di 90 gradi). È possibile utilizzare anche un numero infinito di altre possibilità, ma è necessario specificare cinque quantità indipendenti. Alcune scelte porteranno ad un'algebra più semplice di altre, a seconda di ciò che viene fatto con esse.


5
È importante rendersi conto che una struttura rettangolare "standard" non è un rettangolo matematico rigorosamente definito, ma una versione semplificata che è sempre parallela agli assi X e Y, perché è stata creata per essere utilizzata per una cosa molto specifica: definire le regioni rettangolari per un gestore di finestre, che sono (quasi) sempre parallele agli assi X e Y.
Mason Wheeler,

+1, la struttura sinistra / destra / superiore / inferiore è preordinata e quindi ha meno informazioni
Javier

Buon punto, circa i rettangoli allineati xy. Avevo pensato che, e si estende anche come usato nella modellazione 3D, e alcune altre cose, ma tutte le xy (forse anche -z) allineate.
DarenW,

1

Non è esattamente la stessa cosa di 2 punti? Come è imbarazzante ... la maggior parte delle routine di disegno richiedono punti, non componenti separati x / y.


1

La definizione di rettangoli come coppie di punti consente di riutilizzare il punto come vertice per un'altra forma. Solo un pensiero...


Ma sembra giocare con mezzo mazzo, per mantenere solo due punti per definire una forma a quattro punte. Se ti capita di aver bisogno in alto a sinistra, bello, ma se hai bisogno di in alto a destra, devi fare alcuni dati stravaganti, relativamente parlando.
DarenW,

se esiste un accessorio definito come punto AX punto BY e punto BX punto AY lo rende più leggero in memoria / su disco penso di memorizzare metà del numero massimo di vertici e di puntarli solo (a seconda della dimensione massima della griglia). Capisco dove stai andando con il tuo range pensato, ma non stai giocando con metà del mazzo, non stai semplicemente memorizzando dati duplicati .... e gli altri punti da sottolineare sono quali sono i vincoli di memoria? quali sono le implicazioni per la reimplementazione di ricodifica dei rects in tutto il codice interconnesso.
RobotHumans,

e poiché non devi fare alcun "lavoro" per
liberare

1

Credo che sia principalmente quello di stabilire l'uniformità tra tutti i primitivi di forma.

Sicuro che puoi definire il rettangolo in molti modi diversi, ma come definisci un triangolo, una stella o un cerchio in un modo che possa usare strutture di dati simili?

Tutti i poligoni possono essere definiti dai loro punti, con una breve quantità di logica per determinare cosa fare con i punti.

Le librerie grafiche operano principalmente su questi poligoni in termini di vertici e spigoli, quindi i punti e le linee tra loro, tutti i calcoli funzionano su queste due caratteristiche, bene che e sfaccettature, ma che di per sé è solo una funzione dei bordi.


1

In due dimensioni, la memorizzazione di un rettangolo come due punti è più chiara della definizione di un angolo particolare e una larghezza e altezza - considerare la larghezza o l'altezza negativa, oppure i calcoli necessari per determinare ciascuna opzione dall'altra.

L'esecuzione di rotazioni su un rettangolo definito da punti è anche molto più semplice di una definita con un punto più larghezza e altezza.

Mi aspetterei che l'incapsulamento rendesse questa differenziazione non importante come utente della classe.

Un rettangolo dovrebbe essere definito come tre punti per essere ben definito in 3 dimensioni. Non sono del tutto sicuro del requisito per la definizione di un rettangolo in 4 o più dimensioni.


1

È completamente arbitrario. Per disegnare un rettangolo sono necessarie quattro informazioni. Il / i progettista / i della biblioteca ha deciso di rappresentarlo con due punti (ciascuno con una coordinata xy), ma avrebbe potuto facilmente farlo con x / y / w / ho top / bottom / left / right.

Suppongo che la vera domanda del PO sia: perché è stata fatta questa scelta particolare?


1

La scelta dei parametri è importante solo per i progettisti / programmatori di basso livello.

Gli utenti di alto livello devono solo pensare a:

  • IsPointInRect
  • La zona
  • Intersezione (o ritaglio)
  • HasOverlap (uguale a Intersection.Area> 0)
  • Unione (diventa un elenco di rettangoli)
  • Sottrazione (un elenco di rettangoli che rappresentano lo stesso set di punti che si trova nel rettangolo A ma non nel rettangolo B)
  • Trasformare
    • Cambia in X e Y
    • Rotazione (0, 90, 180, 270)
    • Ridimensionamento in X e Y (vedi nota)
  • Sintassi semplice per le proprietà Xmin, Xmax, Ymin, Ymax, Larghezza, Altezza in modo che l'utente non debba conoscere la scelta esatta dei parametri.

Nota: al fine di ridurre al minimo la perdita di precisione durante la trasformazione del ridimensionamento, a volte è opportuno implementare una seconda classe Rect che utilizza coordinate in virgola mobile, in modo che i risultati intermedi possano essere archiviati accuratamente in una sequenza di trasformazioni e arrotondati all'intero solo nella ultimo passo.


0

Come dice @Steven, penso che dovrebbe essere in termini di un vettore di dimensioni (x, y) e un vettore di dimensioni (w, h). Questo perché è facile cadere in un'ambiguità. Supponiamo di avere il seguente rettangolo compilato a partire dal punto (0,0).

  012
0 XXX
1 XXX
2 XXX

Chiaramente è larghezza, altezza sono (3,3), ma qual è il secondo punto? È (2,2) o (3,3)?

Questa ambiguità può causare tutti i tipi di problemi.

Ho imparato anni fa che è meglio pensare alle coordinate grafiche come le linee tra i pixel, non come le linee su cui si trovano i pixel . In questo modo non c'è ambiguità.


2
Le routine originali QuickDraw su Mac (quelle degli anni '80) utilizzavano il modello matematico secondo cui i punti erano infinitamente piccoli. I punti sullo schermo si trovano tra i pixel. Quindi una linea tracciata da (3,5) a (10,5) aveva una lunghezza di 7 e occupava 7 pixel. Nelle coordinate di oggi, quella linea avrebbe una lunghezza di 8.
Barry Brown

@Barry: Questo ha senso, dal momento che ha usato molto XOR, e se stai mettendo insieme le linee, vuoi che si connettano senza un pixel mancante dove si incontrano. In realtà ho pubblicato un documento sigografico sul riempimento di poligoni, considerando entrambi i sistemi di coordinate.
Mike Dunlavey,

0
Pa(x,y)*-----------------------------------*Pb(x,y)
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
       |                                   |
Pc(x,y)*-----------------------------------*Pd(x,y)

Possiamo così definire sia Pb che Pc:

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

e

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

Quindi non è necessario definire tutti e quattro i punti a causa della simmetria

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.