Κυριακή, 8 Μαρτίου 2020

Δένδρο του Πυθαγόρα (Αναδρομή)

Ένα πρόγραμμα που δείχνει πως λειτουργεί η αναδρομή με τον αλγόριθμο που φτιάχνει το δένδρο του Πυθαγόρα. Κάθε τετράγωνο αν δεν είναι φύλλο έχει άλλα δυο τετράγωνα μικρότερα που σχηματίζουν τρίγωνο στη μια πλευρά του.

Οι ρουτίνες βλέπουν ότι υπάρχει σε ένα τμήμα, ακόμα και το όνομά τους, και έτσι μπορούν να το καλέσουν. Οι παράμετροι και οι τοπικές μεταβλητές με το πέρας εκτέλεσης μιας ρουτίνας διαγράφονται. Αν έχουμε καλέσει τη ρουτίνα του παραδείγματος σε βάθος έστω τρεις κλήσεις τότε πριν την πρώτη Χάραξε θα υπάρχουν στην μνήμη του διερμηνευτή όλες οι προηγούμενες τοπικές μεταβλητές (και οι παράμετροι της ρουτίνας που είναι επίσης τοπικές μεταβλητές, και εξ ορισμού οι κλήσεις στη Μ2000 γίνονται με πέρασμα με τιμή).

Για να πετύχει η αναδρομή χρειάζεται μια συνθήκη εξόδου. Η έξοδος πρέπει να γίνει πριν κληθεί ξανά η ίδια ρουτίνα. Η συνθήκη εδώ είναι ο έλεγχος της τάξης δένδρου, με νούμερο 6, δηλαδή φτιάχνει 6 δένδρα (βάση τετράγωνο, πλευρές μικρά τετράγωνα), όπου το καθένα εκτός από το πρώτο έχει το προηγούμενο ως βάση!

Για την εμφάνιση του δένδρου χρησιμοποιούμε δυο εντολές, την Θέση που δέχεται απόλυτη τιμή καρτεσιανών συντεταγμένων (η πάνω αριστερή γωνία είναι το 0,0 και το ύψος αυξάνει προς τα κάτω οπότε η κάτω δεξιά γωνία είναι η χ.σημεία-πλάτος.σημείου, υ.σημεία-ύψος.σημείου). Οι μονάδες είναι τα twips, και ένα pixel έχει πλάτος όσο το πλάτος.σημείου και ύψος όσο το ύψος.σημείου. Τα 1440 twips είναι μια λογική ίντσα στην οθόνη και μια κανονική στο χαρτί του εκτυπωτή. Η λογική ίντσα λέγεται έτσι γιατί ένα μόνιτορ μπορεί να αλλάζει το πραγματικό μήκος της, αλλά και η θέση μας από αυτήν αλλάζει το μέγεθος επίσης.

Το πρόγραμμα ρυθμίζει τα χρώματα φόντου και γραμμών/κειμένου, σε Ματζέντα και Κίτρινο.
Μπορούμε να δώσουμε html χρώματα όπου το #FF0000 είναι το κόκκινο, η με την Χρώμα(255, 0,0).

Επίσης ενεργοποιεί την χάραξη γραμμών με anti-aliasing μια διαδικασία που είναι αργότερη από την απλή χάραξη αλλά ομαλοποιεί τα σκαλοπάτια που δημιουργούν οι πλάγιες γραμμές.

Η Στη ή Let εδώ μπήκε για ομορφιά! Αν δεν την βάζαμε θα έπρεπε μεταξύ δυο εκχωρήσεων να βάλουμε την αλλαγή εντολής την άνω και κάτω τελεία και όχι το κόμμα.

Για να βγει το δένδρο στη μέση της οθόνης (όπως φαίνεται στην εικόνα παρακάτω) κάνουμε μερικούς υπολογισμούς για το πρώτο δένδρο και κατόπιν το καλούμε.


ΤΜΗΜΑ Δένδρο_Πυθαγόρα {
 ΟΘΟΝΗ 5, 0  ' ΜΑΤΖΕΝΤΑ, ΧΩΡΙΣ ΧΩΡΙΣΤΗ ΟΘΟΝΗ
 ΠΕΝΑ 14   ' ΚΙΤΡΙΝΟ
 ΟΜΑΛΑ ΝΑΙ  ' χρήση GDI+ για ομαλοποίηση στις γραμμές
 
 ΣΤΗ π =Χ.ΣΗΜΕΙΑ , υ = π * 11 ΔΙΑ 16
 ΣΤΗ π2 = π ΔΙΑ 2, διαφορά = π ΔΙΑ 12
 ΣΤΗ ΤάξηΔένδρου = 6
 Δένδρο_Πυθαγόρα(π2 - διαφορά, υ-10, π2 + διαφορά, υ-10, 0)
 
 ΡΟΥΤΙΝΑ Δένδρο_Πυθαγόρα(χ1, ψ1, χ2, ψ2, βάθος)
 
     ΑΝ βάθος > ΤάξηΔένδρου ΤΟΤΕ ΕΞΟΔΟΣ ΡΟΥΤΙΝΑΣ
 
     ΤΟΠΙΚΗ δχ = χ2 - χ1, δψ = ψ1 - ψ2
     ΤΟΠΙΚΗ χ3 = χ2 - δψ, ψ3 = ψ2 - δχ
     ΤΟΠΙΚΗ χ4 = χ1 - δψ, ψ4 = ψ1 - δχ
     ΤΟΠΙΚΗ χ5 = χ4 + (δχ - δψ) / 2
     ΤΟΠΙΚΗ ψ5 = ψ4 - (δχ + δψ) / 2
     ΘΕΣΗ χ1, ψ1
     ΧΑΡΑΞΕ ΕΩΣ χ2, ψ2
     ΧΑΡΑΞΕ ΕΩΣ χ3, ψ3
     ΧΑΡΑΞΕ ΕΩΣ χ4, ψ4
     ΧΑΡΑΞΕ ΕΩΣ χ1, ψ1
     Δένδρο_Πυθαγόρα(χ4, ψ4, χ5, ψ5, βάθος+1)
     Δένδρο_Πυθαγόρα(χ5, ψ5, χ3, ψ3, βάθος+1)
 
 ΤΕΛΟΣ ΡΟΥΤΙΝΑΣ
}
Δένδρο_Πυθαγόρα


Παραλλαγή του προγράμματος με χρήση τμήματος αντί για ρουτίνα.
Τα τμήματα είναι πιο βαριές κατασκευές από τις ρουτίνες.

Για να καλέσουμε ένα τμήμα πρέπει να έχει δοθεί από πριν ο ορισμός του. Επίσης για να καλέσουμε ένα τμήμα με αναδρομή πρέπει να χρησιμοποιήσουμε τη ΚΑΛΕΣΕ,

Εδώ έχουμε το εσωτερικό τμήμα με το ίδιο όνομα με το εξωτερικό. Η πρώτη κλήση καλεί το εσωτερικό και η δεύτερη επειδή είναι με την ΚΑΛΕΣΕ καλεί το τρέχον.

Δείτε τις αλλαγές:
1. Το έξοδος δεν έχει τη λέξη ΡΟΥΤΙΝΑΣ
2. Οι μεταβλητές που θέλουμε να διαβάζονται σε κάθε κλήση αναδρομής πρέπει να είναι γενικές, γιατί εντός τμήματος θέαση υπάρχει μόνο για τοπικές του τμήματος και γενικές.

Οι γενικές που φτιάχτηκαν σε ένα τμήμα διαγράφονται στο πέρας εκτέλεσης αυτού. Αν καλούσαμε ένα τμήμα μέσα από αυτό που φτιάξαμε μια γενική έστω Α και σε αυτό φτιάξουμε μια νέα γενική Α τότε η δεύτερη θα ισχύει μέχρι το τμήμα που τη δημιούργησε τερματίσει και στην επιστροφή η γενική Α θα υπάρχει με την τιμή που φτιάχτηκε στο πρώτο τμήμα. Με αυτό το τρόπο "σκίασης" μεταβλητών μπορούμε να έχουμε τμήματα με γενικές μεταβλητές δικές του χωρίς να ενοχλεί υπάρχουσες γενικές. Επίσης για να αλλάξουμε τιμή σε μια γενική έχουμε το <= και όχι το =. Αν υπάρχει γενική Β και σε ένα τμήμα δώσουμε το Β=100 τότε η γενική σκιάζεται με τη τοπική Β. Οι τοπικές σκιάζουν τις γενικές και νεότερες γενικές σκιάζουν υπάρχουσες γενικές (όταν έχουμε ίδιο όνομα σε κάθε περίπτωση).


Οι κλήσεις τμημάτων περιορίζονται σε βάθος σε μερικές χιλιάδες. Σε αντίθεση η κλήση ρουτινών μπορεί να είναι σε βάθος σε εκατοντάδες χιλιάδες.

ΤΜΗΜΑ Δένδρο_Πυθαγόρα {
 ΟΘΟΝΗ 5, 0  ' ΜΑΤΖΕΝΤΑ, ΧΩΡΙΣ ΧΩΡΙΣΤΗ ΟΘΟΝΗ
 ΠΕΝΑ 14   ' ΚΙΤΡΙΝΟ
 ΟΜΑΛΑ ΝΑΙ  ' χρήση GDI+ για ομαλοποίηση στις γραμμές
 
 ΓΕΝΙΚΕΣ π =Χ.ΣΗΜΕΙΑ , υ = π * 11 ΔΙΑ 16
 ΓΕΝΙΚΕΣ π2 = π ΔΙΑ 2, διαφορά = π ΔΙΑ 12
 ΓΕΝΙΚΕΣ ΤάξηΔένδρου = 6
 ΤΜΗΜΑ Δένδρο_Πυθαγόρα(χ1, ψ1, χ2, ψ2, βάθος) {
 
     ΑΝ βάθος > ΤάξηΔένδρου ΤΟΤΕ ΕΞΟΔΟΣ
 
     ΣΤΗ δχ = χ2 - χ1, δψ = ψ1 - ψ2
     ΣΤΗ χ3 = χ2 - δψ, ψ3 = ψ2 - δχ
     ΣΤΗ χ4 = χ1 - δψ, ψ4 = ψ1 - δχ
     ΣΤΗ χ5 = χ4 + (δχ - δψ) / 2
     ΣΤΗ ψ5 = ψ4 - (δχ + δψ) / 2
     ΘΕΣΗ χ1, ψ1
     ΧΑΡΑΞΕ ΕΩΣ χ2, ψ2
     ΧΑΡΑΞΕ ΕΩΣ χ3, ψ3
     ΧΑΡΑΞΕ ΕΩΣ χ4, ψ4
     ΧΑΡΑΞΕ ΕΩΣ χ1, ψ1
     ΚΑΛΕΣΕ Δένδρο_Πυθαγόρα χ4, ψ4, χ5, ψ5, βάθος+1
     ΚΑΛΕΣΕ Δένδρο_Πυθαγόρα χ5, ψ5, χ3, ψ3, βάθος+1
 }
 Δένδρο_Πυθαγόρα π2 - διαφορά, υ-10, π2 + διαφορά, υ-10, 0
}
Δένδρο_Πυθαγόρα







Στο Info αρχείο που υπάρχει στην εγκατάσταση της γλώσσας υπάρχει το Pyth με αγγλικές εντολές το πρώτο πρόγραμμα καθώς και το Pyth1 επίσης με αγγλικές εντολές με εμφάνιση δυο δένδρων υπό γωνία το ένα αντικριστό από το άλλο:

Pyth1:

MODULE Pythagoras_Example{
 CLS 5, 0  ' MAGENTA, split line = 0  
 PEN 14  ' YELLOW
 \\ Linux smoothing not work (we can use the statement but without effect)
 IF ISWINE ELSE SMOOTH ON
 \\ PYTHAGORAS TREE
 \\ by definition all variables ar type of a double
 GLOBAL p=7, p4=PI/4, p2=PI/2, s2=SQRT(2)/2
 MODULE center_p (r, t){
  MODULE pythagoras_tree (r, dx, depth) {
   r2=r-p2
   DRAW ANGLE r, dx
   DRAW ANGLE r2, dx
   DRAW ANGLE r, -dx
   DRAW ANGLE r2, -dx
   IF depth>10 THEN EXIT
   s3=dx*s2
   depth++
   STEP ANGLE r+p4, s3*2
   CALL pythagoras_tree r-p4,  s3, depth
   STEP ANGLE r, -dx-s3
   STEP ANGLE r, s3
   STEP ANGLE r+p4, -s3
   CALL pythagoras_tree r+p4,  s3, depth
   STEP ANGLE r-p4, s3  
  } 
  MOVE SCALE.X/2, SCALE.Y/2 
  STEP ANGLE PI-p4+r, t*s2
  CALL pythagoras_tree r, t, 1
 }
 r=PI/3
 pixels=100
 center_p r, 100*TWIPSX
 center_p r+PI, 100*TWIPSX
 CopyImageToClipboard()
 
 Sub CopyImageToClipboard()
  LOCAL Scr$=""
  MOVE 0,0
  COPY SCALE.X, SCALE.Y TO Scr$
  CLIPBOARD Scr$
 END SUB
}
Pythagoras_Example



Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου