2009-06-22 10 views
2

Ich schreibe ein Skript, bei dem Symbole um einen bestimmten Drehpunkt (oder Ursprung) rotieren. Ich konnte das machen, um die Symbole um eine Ellipse zu drehen, aber ich möchte auch, dass sie sich um den Umfang eines Rechtecks ​​mit einer bestimmten Breite, Höhe und Ursprung bewegen.Gegeben einen Winkel und Dimensionen, finden Sie eine Koordinate entlang des Umfangs eines Rechtecks ​​

Ich mache es auf diese Weise, weil mein aktueller Code alle Coords in einem Array speichert, wobei jeder Winkel ganzzahlig ist, und es wäre viel einfacher, diesen Code wiederzuverwenden.

Wenn mir jemand ein Beispiel für ein 100x150 Rechteck geben könnte, wäre das großartig.

EDIT: zu klären, durch Drehen um mich herum bewegen um den Umfang (oder umkreisen) einer Form.

Antwort

4

Sie kennen die Größe des Rechtecks ​​und müssen das ganze Winkelintervall in vier verschiedene teilen, damit Sie wissen, ob ein Strahl von der Mitte des Rechtecks ​​rechts, oben, links oder unten das Rechteck schneidet.

Wenn der Winkel ist: -atan (d/w) < alfa < atan (d/w) schneidet der Strahl die rechte Seite des Rechtecks. Dann, da Sie wissen, dass die x-Verschiebung von der Mitte des Rechtecks ​​zur rechten Seite d/2 ist, ist die Verschiebung dividiert durch d/2 tan (alfa), also

dy = d/2 * tan (alfa)

Sie würden dies ähnlich mit den anderen drei Winkelintervallen behandeln.

Ok, hier geht. Sie haben ein Rect mit der Breite w und der Tiefe d. In der Mitte haben Sie den Mittelpunkt, vgl. Ich nehme an, Sie wollen P für verschiedene Werte des Winkels alfa berechnen.

alt text

unterteilt I das Rechteck in vier verschiedenen Bereichen oder Winkelintervallen (1 bis 4). Das oben erwähnte Intervall ist das erste rechts. Ich hoffe, das macht für dich Sinn.

Zuerst müssen Sie die Winkelintervalle berechnen, diese werden komplett von w und d bestimmt. Abhängig davon, welchen Wert alfa hat, berechne P entsprechend, d. H. Wenn der "Strahl" von CP nach P die obere, untere, rechte oder linke Seite des Rechtecks ​​schneidet.

Prost

+0

Ich habe ein kleines Problem, Ihre Antwort zu verstehen, obwohl es wie die tatsächliche Lösung aussieht, nach der ich suche. Ich verstehe, es in 4 Dreiecke aufzuteilen und d = √ (w * w + h * h). Könntest du dir vorstellen, dass du mit einem Vollidioten in Mathe arbeitest und dann deine Antwort neu formulierst? –

+0

Das Kommentarsystem scheint keine HTML-Entitäten zu akzeptieren. √ bedeutet Quadratwurzel (√). –

+0

Ich werde zu dir zurückkommen, sobald ich nach Hause komme und ein vernünftiges Programm verwenden kann, um dir ein Bild zu malen :) Prost. – ralphtheninja

0

Wenn Sie denken, Sie meinen drehen wie die Erde die Sonne dreht sich um (nicht die Eigenrotation ... so Ihre Frage ist, wie entlang der Ränder eines Rechtecks ​​zu gleiten?)

Wenn ja, können Sie geben diesem einen Versuch:

# pseudo coode 
for i = 0 to 499 
    if i < 100: x++ 
    else if i < 250: y-- 
    else if i < 350: x-- 
    else y++ 

    drawTheIcon(x, y) 

Update: (siehe Kommentar unten)

einen Winkel zu verwenden, wird eine Zeile sein

y/x = tan(th)  # th is the angle 

Die anderen Zeilen sind einfach, da sie nur horizontal oder vertikal sind. also zum Beispiel ist es x = 50 und du kannst das in die obige Zeile setzen, um das y zu erhalten. tue das für den Schnittpunkt der horizontalen Linie und der vertikalen Linie (zum Beispiel ist der Winkel 60 Grad und erschießt "NorthEast" ... jetzt hast du zwei Punkte. Dann ist der Punkt, der dem Ursprung am nächsten ist, derjenige, der die trifft Rechteck zuerst).

+0

Danke für die Antwort. Das würde funktionieren, wenn ich tatsächlich den Umfang ausarbeite und von dort aus arbeite, aber ich speichere die Koordinaten tatsächlich in einer Reihe von Winkeln, also ist die Verwendung des Winkels in einer Gleichung eine Voraussetzung. –

+0

ich denke, dass wird die Gleichung für diese 2 Zeilen zu lösen, und finden Sie die x und y ... und da es zwei Zeilen in eine Richtung treffen kann, wählen Sie die, die den kleineren Abstand vom Ursprung hat. –

0

sich Zeichnen Sie eine Skizze auf einem Blatt Papier mit einem Rechteck und einem Drehzentrum. Übersetzen Sie zuerst das Rechteck in die Mitte des Ursprungs Ihres Koordinatensystems (beachten Sie die Übersetzungsparameter, Sie müssen die Übersetzung später umkehren). Drehen Sie das Rechteck so, dass seine Seiten parallel zu den Koordinatenachsen liegen (gleicher Grund).

Jetzt ein Dreieck mit bekannten Winkel am Ursprung haben, ist die gegenüberliegende Seite bekannter Länge (die Hälfte der Länge einer Seite des Rechtecks), und Sie können jetzt:

- lösen das Dreieck

- undo die Rotation

- undo die Übersetzung

0

eine einfache Möglichkeit, dies mit einem Winkel zu tun, wie ein Parameter ist einfach auf den X- und Y-Wert Clip der Grenzen des Rechtecks ​​verwendet wird. Mit anderen Worten: Berechnen Sie die Position so, als würde das Symbol um einen kreisförmigen oder elliptischen Pfad rotieren. Wenden Sie dann Folgendes an:

(Angenommen, das Achsen-ausgerichtete Rechteck zentriert um (0,0), mit der X-Achsenlänge von XAxis und Y -Achse Länge der Y-Achse):

if (X > XAxis/2)  
     X = XAxis/2; 

if (X < 0 - XAxis/2) 
     X = 0 - XAxis/2; 

if (Y > YAxis/2)  
     Y = YAxis/2; 

if (Y < 0 - YAxis/2)  
     Y = 0 - YAxis/2; 

das Problem bei diesem Ansatz ist, dass der Winkel nicht ganz korrekt sein wird, und die Geschwindigkeit entlang des Umfangs des Rechtecks ​​nicht konstant sein. Das Modellieren einer Ellipse, die das Rechteck an den Ecken umfasst, kann den Effekt minimieren. Wenn Sie jedoch nach einer glatten "Bahn" mit konstanter Geschwindigkeit suchen, ist diese Methode nicht geeignet.

+0

Die Bewegung der Icons wird animiert, also brauche ich eine glatte Bewegung. Danke trotzdem. –

0

Verwenden Sie eine 2D transformation matrix. Viele Sprachen (z. B. Java) unterstützen dies nativ (siehe AffineTransformation); Andernfalls schreibe eine Routine auf, um die Rotation selbst durchzuführen, debugge sie gut und benutze sie für immer. Ich muss fünf von ihnen in verschiedenen Sprachen geschrieben haben.

Sobald Sie die Rotation einfach tun können, finden Sie die Position auf dem Rechteck, indem Sie line-line intersection tun. Finden Sie die Mitte des umkreiste Symbol durch sich kreuz zwei Linien:

  1. Ein Strahl aus dem Zentrum der Drehung im Winkel Sie
  2. Einer der vier Seiten wünschen, begrenzt von welchem ​​Winkel Sie wollen (die vier Quadranten) .
0

Dies wurde für und auf dem Pebble Smartwatch arbeiten überprüft, aber seine Pseudo-Code geändert:

struct GPoint { 
    int x; 
    int y; 
} 

// Return point on rectangle edge. Rectangle is centered on (0,0) and has a width of w and height of h 
GPoint getPointOnRect(int angle, int w, int h) { 
    var sine = sin(angle), cosine = cos(angle); // Calculate once and store, to make quicker and cleaner 
    var dy = sin>0 ? h/2 : h/-2;     // Distance to top or bottom edge (from center) 
    var dx = cos>0 ? w/2 : w/-2;     // Distance to left or right edge (from center) 
    if(abs(dx*sine) < abs(dy*cosine)) {   // if (distance to vertical line) < (distance to horizontal line) 
    dy = (dx * sine)/cosine;     // calculate distance to vertical line 
    } else {          // else: (distance to top or bottom edge) < (distance to left or right edge) 
    dx = (dy * cosine)/sine;     // move to top or bottom line 
    } 
    return GPoint(dx, dy);      // Return point on rectangle edge 
} 


Use: 
rectangle_width = 100; 
rectangle_height = 150; 
rectangle_center_x = 300; 
rectangle_center_y = 300; 
draw_rect(rectangle_center_x - (rectangle_width/2), rectangle_center_y - (rectangle_center_h/2), rectangle_width, rectangle_height); 
GPoint point = getPointOnRect(angle, rectangle_width, rectangle_height); 
point.x += rectangle_center_x; 
point.y += rectangle_center_y; 
draw_line(rectangle_center_x, rectangle_center_y, point.x, point.y);