2016-04-01 9 views
2

Ich versuche, zufällige gleichseitige Dreiecke auf dem Bildschirm der Konsole zu produzieren.Dreiecke, die manchmal gleichseitig sind und manchmal nicht?

Die von mir verwendete Methode erstellt einen Mittelpunkt für das Dreieck (zufällig positioniert), verschiebt den Mittelpunkt zum Ursprung (0,0) und erstellt dann 3 Punkte vom Mittelpunkt (addiert den Radius (Zufallszahl) des Dreiecks zur Y-Achse jedes Punktes). Dann rotiere ich 2 der Punkte, einen bei 120 Grad und den anderen bei 240, mache ein gleichseitiges Dreieck und zeichne dann Linien zwischen den Punkten. Dann bringen Sie die Punkte zurück auf die ursprüngliche Handlung in Bezug auf den Schwerpunkt.

Dies für die Vergangenheit der Zeit funktioniert und ich bekomme ein gleichseitiges Dreieck, aber manchmal bekomme ich nicht ganz ein gleichseitiges Dreieck und ich bin völlig verloren, warum.

Ich benutze Brenshams Linienalgorithmus, um die Linie zwischen Punkten zu zeichnen.

Bild Arbeits Dreieck: http://imgur.com/GpF406O

Bild von gebrochenen Dreieck: http://imgur.com/Oa2BYun

Hier ist der Code, der die Koordinaten für das Dreieck Plots:

void Triangle::createVertex(Vertex cent) 
{ 
// angle of 120 in radians 
double s120 = sin(2.0943951024); 
double c120 = cos(2.0943951024); 
// angle of 240 in radians 
double s240 = sin(4.1887902048); 
double c240 = cos(4.1887902048); 

// bringing centroid to the origin and saving old pos to move later on 
int x = cent.getX(); 
int y = cent.getY(); 
cent.setX(0); 
cent.setY(0); 

// creating the points all equal distance from the centroid 
Vertex v1(cent.getX(), cent.getY() + radius); 
Vertex v2(cent.getX(), cent.getY() + radius); 
Vertex v3(cent.getX(), cent.getY() + radius); 

// rotate points 
double newx = v1.getX() * c120 - v1.getY() * s120; 
double newy = v1.getY() * c120 + v1.getX() * s120; 

double xnew = v2.getX() * c240 - v2.getY() * s240; 
double ynew = v2.getY() * c240 + v2.getX() * s240; 

// giving the points the actual location in relation the the old pos of the centroid 
v1.setX(newx + x); 
v1.setY(newy + y); 

v2.setX(xnew + x); 
v2.setY(ynew + y); 

v3.setX(x); 
v3.setY(y + radius); 

// adding the to a list (list is used in a function to draw the lines) 
vertices.push_back(v1); 
vertices.push_back(v2); 
vertices.push_back(v3); 
} 
+0

Wenn Sie sich die Bilder Ihrer zwei Dreiecke ansehen, sieht es so aus, als würden Sie die Dreiecke mit Pixeln zeichnen (dargestellt durch Textzeichen), um diskrete zulässige Positionen für jeden Eckpunkt zu zeichnen (entweder diese oder die nächste).) Meine Vermutung ist, dass Ihr Algorithmus zum Zeichnen der Linien irgendeine Art von Aufruf machen muss (zeichnen Sie dieses Pixel in Zeile a oder Zeile b) und die gleiche Zeile wird nicht für beide Knoten ausgewählt. Ohne weitere Details zur Implementierung sind Sie Für den Linienzeichnungsalgorithmus wäre es jedoch schwierig, das eine oder das andere zu sagen. – Tuffwer

+0

Die Diskrepanz bei der Auswahl der Zeile, in die der Scheitelpunkt gedruckt werden soll, liegt vor, wenn der zu bewertende Höhenwert auf der Höhe der Grenze zwischen den beiden Zeilen liegt oder sehr nahe beieinander liegt und der Gleitkommafehler genau darüber liegt knapp unter. Meistens in Software, wenn das passiert, wird ein Stockwerk aufgerufen, so dass das nächste gerade unten in der nächsten Reihe endet. – Tuffwer

Antwort

1

auf die Bilder der Suche Ihrer beiden Dreiecke (und betrachten den Linienzeichnungsalgorithmus) Sie zeichnen Linien als eine Reihe von diskreten Pixeln. Das bedeutet, dass ein Eckpunkt in ein Pixel fallen muss (es kann nicht an einer Grenze sein) wie in diesem image.

Was passiert also, wenn Ihr Scheitelpunkt auf * eine Grenze zwischen Pixeln fällt? Ihre Linienzeichnung Algorithmus hat eine Entscheidung zu treffen, auf dem Pixel in den Scheitelpunkt zu setzen.

Mit Blick auf die Algorithmusbeschreibung auf wikipedia und der C++ Implementierung auf einer Seite ein www.cs.helsinki.fi Ich sehe, dass beide Listenimplementierungen mit Integer-Arithmetik ** was in diesem Fall nicht unangemessen ist, wenn Sie diskrete Reihen von Pixeln haben. Dies bedeutet, dass wenn Ihre Gleitkommaberechnungen einen Eckpunkt über den Schwellenwert der ganzzahligen Beschriftung für die nächste Reihe von Pixeln setzen, wenn der Boden (Umwandlung von Float nach Int) erfolgt, der andere Eckpunkt jedoch unter diesem Schwellenwert liegt, dann werden die beiden Eckpunkte in verschiedenen Reihen platziert werden.

denken v1.y = 5.00000000000000000001 und v2.y = 4.99999999999999999999 die 5 auf Zeile wird platziert v1 führt und auf Zeile platziert v2 wird 4.

Dies erklärt, warum nur Sie das Problem gelegentlich auftreten sehen, Sie nur gelegentlich haben Ihre Scheitelpunkte auf einer Grenze landen so was.

Um ein paar Dinge in den Sinn kommen zu beheben:

es Fix, wenn Sie Werte Ihren Eckpunkten zuweisen, sind die y-Werte die sowieso gleich.

gegeben:

v1.getX() = v2.getX() = 0 (defined by your code) 
v1.getY() = v2.getY() = radius (defined by your code) 
cos(120 degrees) = cos(240 degrees) ('tis true) 

Dies zu

Ihre zwei y-Werte reduziert
double newy = v1.getY() * c120 
double ynew = v1.getY() * c120 

ergo:

v1.setY(newy + y); 
v2.setY(newy + y); 

Wenn Sie Ihren eigenen Brensenham-Algorithmus Implementierung schrieb einen Scheck hinzufügen könnte in dieser Code, um sicherzustellen, dass Ihre Scheitelpunkte auf der gleichen Höhe sind, aber das scheint wie ein wirklich schlechter Pla Diese Art von Prüfung wird durchgeführt, da die Höhe der Endpunkte spezifisch für Ihr Problem ist und keine Linien im Allgemeinen zeichnen.


* Oder auch nicht genau, aber nah genug, um Sie nicht den Unterschied nach Berücksichtigung Gleitkommafehler sagen kann

** Der Algorithmus ist nicht auf Integer-Arithmetik beschränkt, aber ich vermute, angesichts der Unregelmäßigkeit Ihr Problem und die Art, wie der Algorithmus dargestellt wurde, zusammen mit der Tatsache, dass Sie diskrete Zeichen für die Zeilen in Ihren Bildern verwenden, ist die Ganzzahlarithmetik.