2010-02-08 13 views
8

Hey ragazzi, sto imparando processing.js, e ho trovato un problema matematico, che non riesco a risolvere con la mia limitata conoscenza della geometria e della trigonometria o con l'aiuto di Wikipedia.Conoscendo due punti di un rettangolo, come posso capire gli altri due?

Ho bisogno di disegnare un rettangolo. Per disegnare questo rettangolo, ho bisogno di conoscere i punti di coordinate di ogni angolo. Tutto quello che so è xey per i punti medi della parte superiore e inferiore della scatola e la lunghezza di tutti e quattro i lati.

Non è possibile garantire l'orientamento della scatola.

Qualsiasi aiuto? Sembra che dovrebbe essere facile, ma mi sta davvero bloccando.

+0

prendo la mia risposta indietro .. Questo è risolvibile! – Dolph

+0

Suppongo che questo possa essere ruotato da qualsiasi angolazione e non si conosce l'angolo? – Casey

+0

@Casey, corretto. – icco

risposta

8

Se questo quadrilatero è un rettangolo (tutti e quattro gli angoli sono di 90 gradi), allora può essere risolto. (se può essere un quadrilatero, allora non è risolvibile)

se i punti sono (x1, y1) e (x2, y2), e se i due punti non sono perfettamente verticali (x1 = x2) o orizzontale (y1 = y2), quindi la pendenza di un bordo del rettangolo è

m1 = (y2-y1)/(x2-x1) 

e la pendenza della altro bordo è:

m2 = - 1/m1 

Se si conoscono le lunghezze dei lati, e i punti medi di due lati opposti, quindi i punti del corrner sono facilmente determinati aggiungendo dx, dy ai punti medi: (se L è la lunghezza dei lati che i punti medi sono)

dx = Sqrt(L^2/(1 + m2^2))/2 

e

dy = m2 * dx 

NOTA: se i punti sono allineati verticalmente o orizzontalmente, questa tecnica non funzionerà, anche se la soluzione più ovvia per quei casi degenerative è molto più semplice.

+0

Fantastico. Questo è proprio quello di cui avevo bisogno. Grazie. – icco

+0

Con questo metodo è necessario assicurarsi di aggiungere casi speciali per quando 'x1 == x2' o' y1 == y2' altrimenti finirai per dividere per zero.Il calcolo con i vettori anziché le pendenze evita questo (anche se è ancora necessario verificare che i due punti non siano esattamente gli stessi). – Dave

+0

@Dave, corretto, signore, ho modificato la mia risposta per risolvere questo caso. –

0

È decisamente un rettangolo? Quindi conosci l'orientamento dei lati corti (sono paralleli alla linea tra i tuoi punti), e quindi l'orientamento dei lati lunghi.

Conoscete l'orientamento e la lunghezza dei lati lunghi e conoscete i loro punti medi, quindi è facile trovare gli angoli da lì.

L'implementazione è lasciata come esercizio al lettore.

+0

i lati lunghi sono paralleli a quella linea che conosco si. Conosco anche la lunghezza dei lati corti e la loro pendenza, perché conosco la pendenza di una linea perpendicolare a loro. Non so ancora come ottenere quei quattro punti. Forse questo ti sembra semplice, ma ho pochissimo background matematico. – icco

+0

Conosci il punto medio e la lunghezza del lato in cui si trova il punto medio. Ciò significa che l'angolo è "lunghezza/2" da quel punto. Quindi conosci la direzione e sai la distanza ... cos'altro hai bisogno di sapere? –

0

Ciò significa che ci saranno due linee parallele alla linea tra i due punti che hai. Ottieni gli angoli traducendo la linea che hai 1/2 della lunghezza del lato superiore in ogni direzione perpendicolare alla linea che hai.

0

Se si conosce il punto medio per la parte superiore e la lunghezza della parte superiore, allora si sa che y rimarrà lo stesso per entrambi gli angoli superiori, e la x sarà il punto medio più/meno la larghezza del rettangolo . Questo sarà anche vero per il fondo.

Una volta ottenuti i quattro angoli, non è necessario preoccuparsi delle lunghezze laterali, poiché i loro punti sono uguali a quelli utilizzati per la parte superiore e inferiore.

      midpoint 
    x,10     10,10     x,10 
     *--------------------------------------------* 
         width = 30 

    mx = midpoint x. 
    top left corner = (w/2) - mx or 15 - 10 
    top left corner coords = -5,10 

    mx = midpoint x. 
    top right corner = (w/2) + mx or 15 + 10 
    top left corner coords = 25,10 
+0

Questa casella è ad un angolo sconosciuto, come posso supporre che rimarrà la stessa? – icco

0

C'è una differenza tra un "quadrilatero" e un "rettangolo".

Se si ha il punto medio in alto e in basso e le lunghezze dei lati, il resto è semplice.

Dato:

(x1, y1) -- (top_middle_x, top_middle_y) -- (x2, y1) 

(x1, y2) -- (btm_middle_x, btm_middle_y) -- (x2, y2) 

e top/bottom lunghezza insieme destra/sinistra lunghezza.

x1 = top_middle_x - top/bottom_length/2; x2 = x1 + top/bottom_length;

y1 = top_middle_y y2 = bottom_middle_y

Ovviamente, questo è il caso più semplice e supponendo che la linea di (TMX, tmy) (bmx, BMY) è unicamente lungo l'asse Y.

Chiameremo quella linea la "linea mediana".

Il trucco successivo consiste nel prendere la linea mediana e calcolarne l'offset rotazionale dall'asse Y.

Ora, il mio trigma è super arrugginito.

dx = tmx - bmx, dy = tmy - bmy.

Quindi, la tangente dell'angolo è dy/dx. L'arcotangente (dy/dx) è l'angolo della linea.

Da ciò è possibile ottenere l'orientamento.

(mente, ci sono alcune partite con quadranti, e segni, e roba per ottenere questo diritto - ma questa è l'essenza di esso.)

Una volta che avete l'orientamento, è possibile "ruotare" la linea torna all'asse Y. Cerca la grafica 2D per la matematica, è semplice.

Questo ti porta il tuo orientamento normale. Quindi calcola i punti rettangoli, in questa nuova forma normale, e infine, ruotali indietro.

Viola. Rettangolo.

Altre cose che puoi fare è "ruotare" una linea che è metà della lunghezza della linea "in alto" fino a dove è 90 gradi della linea mediana. Quindi, dì che hai una linea mediana di 45 gradi. Avviate questa linea su tmx, tmy e ruotate questa linea di 135 gradi (90 + 45). Quel punto sarebbe il tuo angolo "in alto a sinistra". Ruota -45 (45 - 90) per ottenere il punto "in alto a destra". Quindi fai qualcosa di simile con i punti più bassi.

0

Calcolare l'angolo della linea che unisce i due punti medi utilizzando una funzione tangente all'arco applicata al vettore che si ottiene tra di essi.

Sottrarre 90 gradi dalla quell'angolo per ottenere la direzione del bordo superiore

Partendo dal punto centrale in alto, spostarsi rispetto (1/2 superiore larghezza x sin (angolo), 1/2 superiore larghezza x cos (angle)) - che ottiene il punto in alto a destra.

Continua attorno al rettangolo utilizzando il peccato e cos degli angoli e larghezze a seconda dei casi

Come una prova: Controllare che hai fatto di nuovo al punto di

5

di partenza Se si conosce il quadrilatero è un rettangolo, quindi puoi utilizzare alcuni semplici strumenti matematici vettoriali per trovare le coordinate degli angoli.Le incognite sono:

  • (x1,y1) - la coordinata del punto medio sulla riga superiore
  • (x2,y2) - la coordinata del punto medio sulla linea di fondo
  • l1 - la lunghezza della parte superiore e linee di fondo
  • l2 - la lunghezza delle altre due linee

in primo luogo, troviamo il vettore tra i due punti noti. Questo vettore è parallela alle linee laterali:

(vx, vy) = (x2 - x1, y2 - y1)

Dobbiamo normalizzare questo vettore (cioè fanno lunghezza 1) in modo che possiamo usare in seguito come base per trovare le nostre coordinate.

vlen = sqrt(vx*vx + vy*vy)

(v1x, v1y) = (vx/vlen, vy/vlen)

Successivamente, ruotare in senso antiorario il vettore di 90 gradi. Il vettore ruotato sarà parallelo alle linee superiore e inferiore. La rotazione di 90 gradi risulta essere solo scambiando le coordinate e annullando una di esse. Puoi vederlo solo provandolo su carta. Oppure dai un'occhiata allo equations for 2D rotations e sostituiscilo a 90 gradi.

(u1x, u1y) = (-v1y, v1x)

Ora abbiamo abbastanza informazioni per trovare l'angolo 'in alto a sinistra'. Abbiamo semplicemente iniziamo il nostro punto (x1, y1) e tornare lungo quel lato della metà della lunghezza del lato:

(p1x, p1y) = (x1 - u1x * l1/2, y1 - u1y * l1/2)

Da qui si possono trovare i punti rimanenti solo con l'aggiunta i multipli appropriati dei nostri vettori di base. Nell'attuare questo ovviamente è possibile accelerarlo da solo calcolando ogni moltiplicazione unica una sola volta:

(p2x, p2y) = (p1x + u1x * l1, p1y + u1y * l1)

(p3x, p3y) = (p1x + v1x * l2, p1y + v1y * l2)

(p4x, p4y) = (p3x + u1x * l1, p3y + u1y * l1)

0
/* rcx = center x rectangle, rcy = center y rectangle, rw = width rectangle, rh = height rectangle, rr = rotation in radian from the rectangle (around it's center point) */ 

function toRectObjectFromCenter(rcx, rcy, rw, rh, rr){ 
    var a = { 
     x: rcx+(Math.sin((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)), 
     y: rcy-(Math.cos((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)) 
    }; 
    var b = { 
     x: a.x+Math.cos(rr)*rw, 
     y: a.y+Math.sin(rr)*rw 
    }; 
    var c = { 
     x: b.x+Math.cos(degToRad(radToDeg(rr)+90))*rh, 
     y: b.y+Math.sin(degToRad(radToDeg(rr)+90))*rh 
    }; 
    var d = { 
     x: a.x+Math.cos(degToRad(radToDeg(rr)+90))*rh, 
     y: a.y+Math.sin(degToRad(radToDeg(rr)+90))*rh 
    }; 
    return {a:a,b:b,c:c,d:d}; 
} 
2
function getFirstPoint(x1,y1,x2,y2,l1,l2) 
    distanceV = {x2 - x1, y2 - y1} 
    vlen = math.sqrt(distanceV[1]^2 + distanceV[2]^2) 
    normalized = {distanceV[1]/vlen, distanceV[2]/vlen} 
    rotated = {-normalized[2], normalized[1]} 
    p1 = {x1 - rotated[1] * l1/2, y1 - rotated[2] * l1/2} 
    p2 = {p1[1] + rotated[1] * l1, p1[2] + rotated[2] * l1} 
    p3 = {p1[1] + normalized[1] * l2, p1[2] + normalized[2] * l2} 
    p4 = {p3[1] + rotated[1] * l1, p3[2] + rotated[2] * l1} 
    points = { p1 , p2 , p3 , p4} 
    return p1 
end