2013-02-12 14 views
8

Ho cercato di ruotare un gruppo di linee di 90 gradi (che insieme formano una polilinea). Ogni riga contiene due vertici, ad esempio (x1, y1) e (x2, y2). Quello che sto cercando di fare è ruotare attorno al punto centrale della linea, dato i punti centrali | x1 - x2 | e | y1 - y2 |. Per qualche ragione (non sono molto matematicamente esperto) non riesco a far ruotare correttamente le linee.Ruota la linea attorno al punto centrale dato due vertici

Qualcuno potrebbe verificare che la matematica qui sia corretta? Sto pensando che potrebbe essere corretto, tuttavia, quando ho impostato i vertici della linea ai nuovi vertici ruotati, la linea successiva potrebbe non afferrare il nuovo vertice (x2, y2) dalla riga precedente, causando una rotazione scorretta delle linee .

Ecco quello che ho scritto:

def rotate_lines(self, deg=-90): 
    # Convert from degrees to radians 
    theta = math.radians(deg) 

    for pl in self.polylines: 
     self.curr_pl = pl 
     for line in pl.lines: 
      # Get the vertices of the line 
      # (px, py) = first vertex 
      # (ox, oy) = second vertex 
      px, ox = line.get_xdata() 
      py, oy = line.get_ydata() 

      # Get the center of the line 
      cx = math.fabs(px-ox) 
      cy = math.fabs(py-oy) 

      # Rotate line around center point 
      p1x = cx - ((px-cx) * math.cos(theta)) - ((py-cy) * math.sin(theta)) 
      p1y = cy - ((px-cx) * math.sin(theta)) + ((py-cy) * math.cos(theta)) 

      p2x = cx - ((ox-cx) * math.cos(theta)) - ((oy-cy) * math.sin(theta)) 
      p2y = cy - ((ox-cx) * math.sin(theta)) + ((oy-cy) * math.cos(theta)) 

      self.curr_pl.set_line(line, [p1x, p2x], [p1y, p2y]) 
+1

La formula 'p2y' è sbagliata per il segno meno. – didierc

+0

Buona cattura, grazie. È stato un errore di battitura! – adchilds

+0

allora non importa. – didierc

risposta

17

Le coordinate del punto centrale di un segmento tra i punti (x1, y1) e (x2, y2) è:

center_x = (x1 + x2)/2 
center_y = (y1 + y2)/2 

In altre parole, è solo la media o la media aritmetica delle coppie di valori di coordinate xey.

Per una linea a più segmenti o polilinea, le coordinate xey del punto centrale logico sono solo la media corrispondente dei valori xey di tutti i punti. Una media è solo la somma dei valori divisa per il numero di essi.

Per ruotare una poligonale circa qualsiasi punto arbitrario, compreso il suo proprio centro, prima sottrarre il valore X e Y del punto di rotazione da ciascuna delle sue coordinate, quindi ruotare il risultato intermedio dall'angolo desiderato, e infine aggiungi il valore xey del punto di rotazione indietro alla xey di ogni coordinata. In termini geometrici: Translate → Rotate → Untranslate.

Il risultato numerico delle tre serie di calcoli può essere combinato ed espresso con una coppia di formule matematiche che le eseguono tutte contemporaneamente. Quindi un nuovo punto (x ', y') può essere ottenuta ruotando un punto esistente (x, y) θ   radianti intorno al punto (cx, cy) utilizzando:

x′ = ( (x - cx) * cos(θ) + (y - cy) * sin(θ)) + cx 
    y′ = (-(x - cx) * sin(θ) + (y - cy) * cos(θ)) + cy 

Incorporando questo matematico/geometrico concetto nella tua funzione produce quanto segue:

from math import sin, cos, radians 

def rotate_lines(self, deg=-90): 
    """ Rotate self.polylines the given angle about their centers. """ 
    theta = radians(deg) # Convert angle from degrees to radians 
    cosang, sinang = cos(theta), sin(theta) 

    for pl in self.polylines: 
     # Find logical center (avg x and avg y) of entire polyline 
     n = len(pl.lines)*2 # Total number of points in polyline 
     cx = sum(sum(line.get_xdata()) for line in pl.lines)/n 
     cy = sum(sum(line.get_ydata()) for line in pl.lines)/n 

     for line in pl.lines: 
      # Retrieve vertices of the line 
      x1, x2 = line.get_xdata() 
      y1, y2 = line.get_ydata() 

      # Rotate each around whole polyline's center point 
      tx1, ty1 = x1-cx, y1-cy 
      p1x = (tx1*cosang + ty1*sinang) + cx 
      p1y = (-tx1*sinang + ty1*cosang) + cy 
      tx2, ty2 = x2-cx, y2-cy 
      p2x = (tx2*cosang + ty2*sinang) + cx 
      p2y = (-tx2*sinang + ty2*cosang) + cy 

      # Replace vertices with updated values 
      pl.set_line(line, [p1x, p2x], [p1y, p2y]) 
+0

Il tuo codice è sbagliato - devi aggiungere la lunghezza media alle coordinate iniziali. – sdasdadas

+0

@martineau: prendi i punti (1, 1) e (4, 4), il tuo algoritmo darebbe un centro a (1.5, 1.5). – sdasdadas

+0

Votare per traduzione/rotazione però. : D – sdasdadas

2

tuo punto centrale sarà:

centerX = (x2 - x1)/2 + x1 
centerY = (y2 - y1)/2 + y1 

perché si prende la metà della lunghezza (x2 - x1)/2 e aggiungerlo al punto in cui la linea comincia a diventare al centro

Come esercizio, prendere due linee:

line1 = (0, 0) -> (5, 5) 
then: |x1 - x2| = 5, when the center x value is at 2.5. 

line2 = (2, 2) -> (7, 7) 
then: |x1 - x2| = 5, which can't be right because that's the center for 
the line that's parallel to it but shifted downwards and to the left 
+0

Grazie, sembra aver risolto il problema della rotazione; tuttavia, devo ancora connettere correttamente ogni singola linea (ruotano individualmente al momento). Anche se, questo risolve il problema che mi interessava di più. Grazie. – adchilds

+0

@adchilds: se vuoi ruotare tutte le linee contemporaneamente (presumo che una polilinea sia un po 'come un poligono?), Devi trovare il centro di massa della polilinea e ruotare tutti i punti delle linee intorno a quel centro . – sdasdadas

+1

non l'ho visto! – didierc

Problemi correlati