180 likes | 336 Views
24 Οκτώβρη 2002. Περιεχόμενα. Φωτοσκίαση καμπυλών σαν εικονίδια Δυο Φωτοσκιάσεις ενός Ευθύγραμμου Τμήματος Γενικές Στρατηγικές Φωτοσκίασης Καμπυλών Φωτοσκίαση Ευθύγραμμου Τμήματος (1) Υπολογισμοί Διαφόρισης Καμπυλών Φωτοσκίαση Ευθύγραμμου Τμήματος (2)-(6)
E N D
Περιεχόμενα • Φωτοσκίαση καμπυλών σαν εικονίδια • Δυο Φωτοσκιάσεις ενός Ευθύγραμμου Τμήματος • Γενικές Στρατηγικές Φωτοσκίασης Καμπυλών • Φωτοσκίαση Ευθύγραμμου Τμήματος (1) • Υπολογισμοί Διαφόρισης Καμπυλών • Φωτοσκίαση Ευθύγραμμου Τμήματος (2)-(6) • Σταδιακές βελτιώσεις σε 5 βήματα • Φωτοσκίαση Κύκλου • 1η Υλοποίηση • 2η Υλοποίηση • Αποτελέσματα
Εισαγωγή Η οθόνη των υπολογιστών συνήθως αποτελείται από ένα ορθογώνιο πλέγμα (πχ. 600x900) τετραγωνικών εικονιδίων. Κάθε εικονίδιο επιδεικνύει ένα συγκεκριμένο χρώμα. Η επίδειξη αυτή γίνετε με διάφορους τρόπους: • Άσπρο-μαύρη: Κάθε εικονίδιο έχει δυο μόνον πιθανές τιμές – μαύρο ή άσπρο. • Κλίμακα του γκρι: Κάθε εικονίδιο μπορεί να είναι μια απόχρωση του γκρι (πχ. 256 αποχρώσεις μεταξύ άσπρου και μαύρου). • Απεικονίσεις χρωματισμού: Κάθε εικονίδιο μπορεί να είναι ένα χρώμα που ανήκει σε ένα προκαθορισμένο σύνολο πεπερασμένου πληθικού αριθμού (πχ. από 256 διαφορετικά χρώματα). • Πλήρες χρωματισμός: Κάθε εικονίδιο μπορεί να είναι ένα χρώμα που ανήκει σε ένα ευρύ πεδίο χρωμάτων (πχ. Αυτό που καθορίζετε με την χρήση 8 bits για το κόκκινο, το πράσινο και το μπλε).
Φωτοσκίαση καμπυλών σαν εικονίδια Όταν επιδεικνύουμε μια καμπύλη σε συσκευή βασισμένη σε εικονίδια, πρέπει να χρωματίσουμε ένα σύνολο εικονιδίων το οποίο θα αποτελέσει μια προσέγγιση της καμπύλης. Για παράδειγμα: Η φωτοσκίαση αυτή υποθέτει ότι κάθε εικονίδιο μπορεί να πάρει μόνον δύο χρώματα. Μια καλλίτερη επιλογή είναι να χρησιμοποιήσουμε ενδιάμεσα σχήματα, εάν μπορεί φυσικά να τα επιδείξει η συσκευή, αλλά δεν θα ασχοληθούμε με το πως μπορεί να γίνει αυτό.
Δυο Φωτοσκιάσεις ενός Ευθύγραμμου Τμήματος Μια που φωτοσκιάζει κάθε εικονίδιο που τέμνει η γραμμή: Μια που φωτοσκιάζει ακριβώς ένα εικονίδιο σε κάθε στήλη: Είναι η μία καλλίτερη από την άλλη;
Γενικές Στρατηγικές Φωτοσκίασης Καμπυλών Υποθέστε ότι έχουμε την παραμετρική παράσταση μιας καμπύλης, σαν (x(t), y(t)), για t μέσα σε κάποιο πεδίο. Πώς μπορούμε να την φωτοσκιάσουμε; Πρώτη Στρατηγική: Για έναν αρκετά μεγάλο αριθμό τιμών του t στο πεδίο τιμών του: • Υπολόγισε τα x(t) και y(t). • Στρογγύλευσε τις τιμές αυτές στο πλησιέστερο εικονίδιο. • Θέσε στο εικονίδιο το επιθυμητό χρώμα. Δεύτερη Στρατηγική : Για τιμές του t σε μια περιοχή του πεδίου τιμών του: • Καθόρισε την κλίση της καμπύλης, και • προχώρησε κατά ένα εικονίδιο κατά μήκος του άξονα που είναι πλησιέστερος στην κλίση αυτή, • Θέσε στο εικονίδιο το επιθυμητό χρώμα.
Φωτοσκίαση Ευθύγραμμου Τμήματος (1) Θα γράψουμε ένα αποδοτικό πρόγραμμα φωτοσκίασης ευθύγραμμων τμημάτων. Θα ακολουθήσουμε την δεύτερη στρατηγική, και θα υποθέσουμε ότι η γραμμή αρχίσει από το (0,0) και έχει κλίση μεταξύ 0 και 1. Μπορούμε να μετασχηματίσουμε άλλες περιπτώσεις στην παραπάνω. Υποθέτουμε επίσης ότι τα άκρα είναι ακέραιοι. Περιμένουμε αυτό να μας δημιουργήσει προβλήματα; proc DrawLine (x, y : int; c : colour) var yt, m : real var yi : int m := y / x for xi : 0..x yt := m * xi yi := floor (yt + 1/2) PutPixel (xi, yi, c) end for end DrawLine Η παραπάνω μέθοδος δεν είναι αρκετά αποδοτική.
Υπολογισμοί Διαφόρισης Καμπυλών Έστω ότι χρειαζόμαστε να υπολογίσουμε τα x(t) και y(t) πολλές τιμές του t: t = t0 ; t0 + δ, t0 + 2δ, ... Αντί να υπολογίσουμε το x(t) ξεχωριστά για κάθε t, μπορούμε να υπολογίσουμε το we can evaluate x(t0) = x 0, και μετά να υπολογίσουμε τα xi+1 = x(ti+1) = xi+ δ dx/dt (ti) Ο παραπάνω τρόπος θα είναι πιο γρήγορος εάν είναι ευκολότερο να υπολογίσουμε τις τιμές της dx/dt ευκολότερα από τις τιμές της ίδιου του x(t).Για ένα ευθύγραμμο τμήμα η dx/dt είναι σταθερά. Από την άλλη μεριά, ίσως ανησυχούμε για την συσσώρευση των σφαλμάτων στρογγύλευσης και του σφάλματος από την μεταβολή του dx/dt καθώς το t μεταβάλλεται στο διάστημα δ.
Φωτοσκίαση Ευθύγραμμου Τμήματος (2) Μπορούμε να μετασχηματίσουμε το πρόγραμμα #1 έτσι ώστε αυτό να χρησιμοποιεί υπολογισμούς παραγώγων. Αυτό αντικαθιστά έναν πολλαπλασιασμό με μια πρόσθεση, που εκτελείται ταχύτερα. proc DrawLine (x, y : int; c : colour) var yt, m : real var yi : int yt := 0 m := y / x for xi : 0..x yi := floor (yt + 1/2) PutPixel (xi, yi, c) yt += m end for end DrawLine Κάνει το παραπάνω πρόγραμμα ακριβώς αυτό που κάνει και το πρόγραμμα #1;
Φωτοσκίαση Ευθύγραμμου Τμήματος (3) Μπορούμε να απαλείψουμε την πρόσθεση του ½ σε κάθε βήμα της ανακύκλωσης ως εξής: proc DrawLine (x, y : int; c : colour) var ys, m : real var yi : int ys := 1/2 m := y / x for xi : 0..x yi := floor(ys) PutPixel (xi, yi, c) ys += m end for end DrawLine
Φωτοσκίαση Ευθύγραμμου Τμήματος (4) Μετά, διασπάμε το ys σε δυο μεταβλητές, ysi και ysf, το ακέραιο και το δεκαδικό μέρος του αντίστοιχα. Το ακέραιο μέροςκατευθείαν καθορίζει την y συντεταγμένη του προς φωτοσκίαση εικονιδίου: proc DrawLine (x, y : int; c : colour) var ysf, m, mm : real var ysi : int m := y / x mm := m 1 ysi := 0 ysf := 1/2 for xi : 0..x PutPixel (xi, ysi, c) if (ysf+m?=1) then ysi += 1 ysf += mm else ysf += m end if end for end DrawLine
Φωτοσκίαση Ευθύγραμμου Τμήματος (5) Τώρα ας απαλλαχθούμε από τις ποσότητες κινητής-υποδιαστολής ysf, m, και mm, αντικαθιστώντας τες μεμια παράσταση τύπου σταθερής-υποδιαστολής σταθμισμένης με 2*x: proc DrawLine (x, y : int; c : colour) var Ysf, M, MM : int var ysi : int M := 2*y MM := M 2*x ysi := 0 Ysf := x for xi : 0..x PutPixel (xi, ysi, c) if (Ysf+M?=2*x) then ysi += 1 Ysf += MM else Ysf += M end if end for end DrawLine Πώς, η αλλαγή από παραστάσεις κινητής-υποδιαστολής σε σταθερής-υποδιαστολής αλλάζει το τι κάνει το πρόγραμμα;
Φωτοσκίαση Ευθύγραμμου Τμήματος (6) Τέλος, ορίζουμε r = Ysf + M 2*x = 2*y + 2*(ysf1)*x Αυτό μας επιτρέπει να ελέγχουμε εάν Ysf + M >= 2*x ελέγχοντας εάν r >= 0. Έτσι καταλήγουμε στον Αλγόριθμο του Bresenham: proc DrawLine (x, y : int; c : colour) var r, M, MM : int var ysi : int M := 2*y MM := M 2*x ysi := 0 r := 2*y x for xi : 0..x PutPixel (xi, ysi, c) if (r?=0) then ysi += 1 r += MM else r += M end if end for end DrawLine
Φωτοσκίαση Κύκλου Μπορούμε να φωτοσκιάσουμε έναν κύκλο χρησιμοποιώντας την πρώτη στρατηγική, χρησιμοποιώντας τιμές παραγώγων. Ένας κύκλος ακτίνας r και κέντρο στην αρχή των αξόνων μπορεί να παρασταθεί παραμετρικά ως εξής: x(u) = r cos(u); y(u) = r sin(u) Αυτό αντιστοιχεί στην εξής διαφορική μορφή: dx/du (u) = - r sin(u), dy/du (u) = r cos(u). Αυτό φαίνετε ότι είναι τόσο χρονοβόρο όσο και το αρχικό, μέχρι να συνειδητοποιήσουμε ότι είναι ισοδύναμο του dx/du (u) = - y(u), dy/du (u) = x(u). Η στρατηγική μας: Ξεκίνα με x(0) = r, y(0) = 0, και προχώρα με μικρά βήματα στο u, χρωματίζοντας τα εικονίδια καθώς τα προσπελάς. Επέλεξε το μήκος του βήματος αρκετά μικρός έτσι ώστε να μην δημιουργούνται διάκενα.
1η Υλοποίηση Για να υλοποιήσουμε την παραπάνω στρατηγική, πρέπει να ρυθμίσουμε μερικές λεπτομέρειες. Αφού θέσουμε x(0) = r και y(0) = 0, μπορούμε να επαναλάβουμε συνεχώς, για κάποιο μήκος βήματος δ, το παρακάτω: x(u + δ) = x(u) – y(u)δ y(u + δ) = y(u) – x(u)δ. Επιλέγουμε σαν μήκος βήματος, δ, το 1/r. Τότε, η συνολική απόσταση που διανύουμε σε κάθε βήμα θα πρέπει να είναι 1, οπότε δεν θα παραλείψουμε εικονίδια. Χρειάζεται να συνεχίσουμε εκτελώντας 2π/δ βήματα έτσι ώστε να ολοκληρώσουμε το δρόμο μας.
2η Υλοποίηση Μπορούμε να σταματήσουμε την προς τα έξω ελικοειδή κίνηση του κύκλου αλλάζοντας τις επαναλήψεις με τις εξής: x(u + δ) = x(u) – y(u)δ y(u + δ) = y(u) – x(u+δ)δ. Γιατί δουλεύει αυτό; Δεν επιτρέπει περιοχές σημείων να «επεκταθούν», επειδή κάθε βήμα είναι ένας «αποκομμένος» μετασχηματισμός ο οποίος δεν μεταβάλει το εμβαδόν μιας περιοχής: