ΕΠΛ 131 - Φροντιστήριο 3
Ας δημιουργήσουμε τη δική μας Βιβλιοθήκη μεθόδων για το σχηματισμό κύκλων διαφόρων μορφών CircleDefs
public class CircleDefs void line_circle (double x, double y, double r, double density) void line_circle_with_gaps (double x, double y, double r, double density, double [] gaps) void radial_circle (double x, double y, double r, double density) void radial_circle_with_gaps (double x, double y, double r, double density, double [] gaps) void filled_circle (double x, double y, double r, double density) void filled_circle_with_gaps (double x, double y, double r, double density, double [] gaps)
public class CircleDefs void spider_web (double x, double y, double r, double density) void rainbow_circle (double x, double y, double r, double sa) void pie_chart (double x, double y, double r, double [] angles) void pie_chart_with_legend (double x, double y, double r, double [] angles, String [] ls) void multi_ring_circle (double x, double y, double r, int n) void dandelion (double x, double y, double r, double sa) void dots (int N, double r)
import java.awt.color; public class CircleDefs{ /* Βοηθητικές Μέθοδοι */ /* Η get_col επιστρέφει ένα τυχαίο χρώμα */ public static Color get_col(){ int r = (int) (Math.random() * 256.0); int g = (int) (Math.random() * 256.0); int b = (int) (Math.random() * 256.0); return new Color(r,g,b); /* Η included_in_gap ελέγχει κατά πόσο το angle περιλαμβάνεται σε κάποιο από τα διαστήματα (sectors) του angs που πρέπει να είναι κενά */ public static boolean included_in_gap(double angle, double [] angs){ for (int i= 0; i < angs.length - 1; i= i+2) if (angle >= angs[i] && angle <= angs[i+1]) return true; return false;
public static void line_circle (double x, double y, double r, double density){ double angle = 0.0; double x1 = x + r; double y1 = y; double x2, y2; while (angle <= 360.0){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; StdDraw.line(x1, y1, x2, y2); x1 = x2; y1 = y2; angle = angle + density; Σημείωση: Ο κύκλος κλείνει επειδή η γωνία (angle) αρχίζει από την τιμή 0.0 και τελειώνει με την τιμή 360.0 με προσαυξήσεις density, θεωρώντας ότι το 360.0 είναι πολλαπλάσιο του density
public class Polygon { /* Αξιοποιώντας την line_circle για το σχηματισμό κανονικών πολυγώνων */ public static void draw_polygon (double sides, double x, double y, double r){ double density = 360.0 / sides; CircleDefs.line_circle(x,y,r,density); public static void main (String [] args){ StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); StdDraw.setPenRadius(0.005); draw_polygon(3.0, 40.0, 30.0, 30.0); /* τρίγωνο */ StdDraw.setPenRadius(0.002); draw_polygon(8.0, 75.0, 75.0, 20.0); /* οκτάγωνο */ StdDraw.setPenRadius(0.001); draw_polygon(360.0, 25.0, 80.0, 10.0); /* πολύγωνο με 360 πλευρές κύκλος δηλαδή */
r (x, y)
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.setPenRadius(0.005); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); /* Ισοδύναμες εντολές για το τρίγωνο και το οκτάγωνο */ CircleDefs.line_circle(40.0, 30.0, 30.0, 120.0); /* τρίγωνο */ CircleDefs.line_circle(75.0, 75.0, 20.0, 45.0); /* οκτάγωνο */ /* Τι σχηματίζεται με την πιο κάτω εντολή; */ CircleDefs.line_circle(25.0, 80.0, 10.0, 28.0);
/* Για να μην υπάρχει το κενό όταν το 360 δεν διαιρείται ακριβώς με την προσαύξηση κάνουμε μια μικρή τροποποίηση στον ορισμό της line_circle */ public static void line_circle (double x, double y, double r, double density){ double angle = 0.0; double x1 = x + r; double y1 = y; double x2, y2; while (angle <= 360.0 + density){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; StdDraw.line(x1, y1, x2, y2); x1 = x2; y1 = y2; angle = angle + density; Σημείωση: Ο κύκλος τώρα κλείνει για κάθε περίπτωση. Όσες κλάσεις/μέθοδοι χρησιμοποιούν την line_circle (της CircleDefs) κληρονομούν το βελτιωμένο ορισμό, χωρίς οι ίδιες να πρέπει να μεταγλωττιστούν εκ νέου!
/* Συνεχίζοντας με τους ορισμούς των μεθόδων της CircleDefs */ public static void line_circle_with_gaps (double x, double y, double r, double density, double [] gaps){ double angle = 0.0; double x1 = x + r; double y1 = y; double x2, y2; while (angle <= 360.0){ /* Προσοχή: το angle περιορίζεται μέχρι το 360 */ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (!included_in_gap(angle, gaps)) StdDraw.line(x1, y1, x2, y2); x1 = x2; y1 = y2; angle = angle + density;
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); double gaps [] = {0.0, 10.0, 45.0, 55.0, 90.0, 100.0, 135.0, 145.0, 180.0, 190.0, 225.0, 235.0, 270.0, 280.0, 315.0, 325.0; double gs [] = {0.0, 20.0, 95.0, 125.0, 355.0, 360.0; double gss [] = {0.0, 90.0, 180.0, 270.0; StdDraw.setPenRadius(0.007); CircleDefs.line_circle_with_gaps(40.0, 30.0, 15.0, 1.0, gs); CircleDefs.line_circle_with_gaps(75.0, 75.0, 20.0, 1.0, gaps); CircleDefs.line_circle_with_gaps(25.0, 80.0, 10.0, 1.0, gss); Σημείωση: Για να λειτουργήσει ορθά η μέθοδος: (α) η ακολουθία των γωνιών που δίνεται στον πίνακα όρισμα, πρέπει να είναι ζυγού μεγέθους, και (β) στην κάθε δυάδα γωνιών (α1, α2) η α1 < α2, και α2 360. Σε περίπτωση λάθους, η βοηθητική μέθοδος included_in_gap αποτρέπει τον πρόωρο τερματισμό του προγράμματος, αλλά ο κύκλος δεν θα έχει τα ορθά κενά.
public static void radial_circle (double x, double y, double r, double density){ double angle = 0.0; double x2, y2; while (angle <= 360.0){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; StdDraw.line(x, y, x2, y2); angle = angle + density; public static void filled_circle (double x, double y, double r, double density){ double eps = density, rad = eps; while (rad <= r){ line_circle(x, y, rad, density * 2.0); rad = rad + eps;
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); StdDraw.setPenRadius(0.007); CircleDefs.radial_circle(40.0, 30.0, 15.0, 30.0); CircleDefs.radial_circle(75.0, 75.0, 20.0, 15.0); CircleDefs.radial_circle(25.0, 80.0, 10.0, 90.0); CircleDefs.radial_circle(80.0, 40.0, 10.0, 1.0);
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); StdDraw.setPenRadius(0.005); CircleDefs.filled_circle(40.0, 30.0, 15.0, 1.5); CircleDefs.filled_circle(75.0, 75.0, 20.0, 5.0); CircleDefs.filled_circle(25.0, 80.0, 10.0, 0.5); CircleDefs.filled_circle(80.0, 40.0, 10.0, 1.0);
Ας συγκρίνουμε τις υπολογιστικές απαιτήσεις των δύο μεθόδων, radial_circle και filled_circle, θεωρώντας ότι η βασική λειτουργία είναι η StdDraw.line: /* Στα σχόλια αναφέρεται ο αριθμός κλήσεων της StdDraw.line */ StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.YELLOW); CircleDefs.radial_circle(30.0, 80.0, 10.0, 1.0); /* 360 */ StdDraw.setPenColor(Color.GREEN); CircleDefs.filled_circle(60.0, 80.0, 10.0, 1.0); /* 1800 */ StdDraw.setPenColor(Color.RED); CircleDefs.filled_circle(60.0, 50.0, 10.0, 0.5); /* 7200 */ StdDraw.setPenColor(Color.YELLOW); CircleDefs.filled_circle(60.0, 20.0, 10.0, 0.25);/* 28800 */ Σημείωση: Χρειάζονται 80 φορές περισσότερες κλήσεις της StdDraw.line από την CircleDefs.filled_circle για να έχει συγκρίσιμη συμπεριφορά με την CircleDefs.radial_circle. Αυτό διαφαίνεται ξεκάθαρα από το χρόνο εκτέλεσης των σχετικών κλήσεων των δύο μεθόδων.
public static void spider_web (double x, double y, double r, double density){ filled_circle(x,y,r,density/2.0); radial_circle(x,y,r,density);
import java.awt.color; public class Spider { public static void main (String [] args){ StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); StdDraw.setPenColor(Color.WHITE); StdDraw.setPenRadius(0.005); CircleDefs.spider_web(40.0, 30.0, 30.0, 20.0); StdDraw.setPenRadius(0.002); CircleDefs.spider_web(75.0, 75.0, 20.0, 5.0); StdDraw.setPenRadius(0.001); CircleDefs.spider_web(25.0, 80.0, 10.0, 4.0);
public static void multi_ring_circle(double x, double y, double r, int n){ double rs = r/n; double rad = r, sec = 0.0; Color c = get_col(); StdDraw.setPenColor(c); while (rad > 0.0){ if (sec > rs) { sec = 0.0; c = get_col(); StdDraw.setPenColor(c); line_circle(x,y,rad,0.5); rad = rad - 0.1; sec = sec + 0.1;
import java.awt.color; public class MultiRing { public static void main (String [] args){ StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.WHITE); CircleDefs.multi_ring_circle(40.0, 30.0, 30.0, 20); CircleDefs.multi_ring_circle(75.0, 75.0, 20.0, 5); CircleDefs.multi_ring_circle(25.0, 80.0, 10.0, 4);
public static void rainbow_circle (double x, double y, double r, double sa){ double angle = 0.0, sec_a = 0.0; double x2, y2; Color c = get_col(); StdDraw.setPenColor(c); while (angle <= 360.0){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (sec_a > sa) { sec_a = 0.0; c = get_col(); StdDraw.setPenColor(c); StdDraw.line(x, y, x2, y2); angle = angle + 0.5; sec_a = sec_a + 0.5;
import java.awt.color; public class Rainbow { public static void main (String [] args){ StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.WHITE); CircleDefs.rainbow_circle(40.0, 30.0, 30.0, 20.0); CircleDefs.rainbow_circle(75.0, 75.0, 20.0, 5.0); CircleDefs.rainbow_circle(25.0, 80.0, 10.0, 4.0);
public static void filled_circle_with_gaps(double x, double y, double r, double density, double [] gaps){ double eps = density, rad = eps; while (rad <= r){ line_circle_with_gaps(x,y,rad, density * 2.0, gaps); rad = rad + eps;
import java.awt.color; public class Dans{ public static void main(string[] args){ int N = Integer.parseInt(args[0]); double angs [] = {0.0, 10.0, 45.0, 55.0, 90.0, 100.0, 135.0, 145.0, 180.0, 190.0, 225.0, 235.0, 270.0, 280.0, 315.0, 325.0; Color cs [] = {Color.GREEN, Color.CYAN, Color.RED, Color.BLACK, Color.ORANGE, Color.YELLOW; StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); while (true){ StdDraw.clear(Color.GRAY); for (int i = 0; i <= N; i++){ double x = Math.random() * 50.0; double y = Math.random() * 50.0; double r = Math.random() * 15; int c = (int) (Math.random() * 6.0); StdDraw.setPenColor(cs[c]); CircleDefs.filled_circle_with_gaps(x,y,r, 0.5, angs); StdDraw.show(50);
public static void radial_circle_with_gaps (double x, double y, double r, double density, double [] angs){ double angle = 0.0; double x2, y2; while (angle <= 360.0){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (!included_in_gap(angle, angs)) StdDraw.line(x, y, x2, y2); angle = angle + density; Ας τρέξουμε το ίδιο πρόγραμμα όπως και προηγουμένως (κλάση Dan) αλλά τώρα να καλείται η CircleDefs.radial_circle_with_gaps(..) με τα ίδια ορίσματα
public static void dandelion (double x, double y, double r, double sa){ double angle = 0.0, sec_a = 0.0; double gaps [] = {0.0, 10.0, 45.0, 55.0, 90.0, 100.0, 135.0, 145.0, 180.0, 190.0, 225.0, 235.0, 270.0, 280.0, 315.0, 325.0; double x2, y2; Color c = get_col(); StdDraw.setPenColor(c); while (angle <= 360.0){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (sec_a > sa) { sec_a = 0.0; c = get_col(); StdDraw.setPenColor(c); if (!included_in_gap(angle, gaps)) StdDraw.line(x, y, x2, y2); angle = angle + 0.5; sec_a = sec_a + 0.5;
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); CircleDefs.dandelion(50.0, 50.0, 30.0, 15.0);
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); CircleDefs.dandelion(50.0, 50.0, 30.0, 45.0);
import java.awt.color; public class Moving_Dan{ public static void main(string[] args){ StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); while (true) { StdDraw.setPenColor(Color.BLACK); StdDraw.clear(Color.BLACK); CircleDefs.dandelion(50.0, 50.0, 30.0, 15.0); StdDraw.setPenColor(Color.BLACK); StdDraw.filledCircle(50.0, 50.0, 7.0); StdDraw.setPenColor(Color.YELLOW); StdDraw.filledCircle(50.0, 50.0, 4.0); StdDraw.show(50);
public static void pie_chart (double x, double y, double r, double angs[]){ double angle = 0.0, sec_a = 0.0; for (int i = 0; i < angs.length ; i++) angs[i] = angs[i] * 3.6; double x2, y2; Color c = get_col(); StdDraw.setPenColor(c); int i = 0; while (angle <= 360.0 && i < angs.length){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (sec_a > angs[i]) { sec_a = 0.0; c = get_col(); StdDraw.setPenColor(c); i++; StdDraw.line(x, y, x2, y2); angle = angle + 0.5; sec_a = sec_a + 0.5;
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); double pie[] = {20.0, 30.0, 10.0, 10.0, 15.0, 5.0, 10.0; CircleDefs.pie_chart(50.0, 50.0, 20.0,pie);
public static void pie_chart_with_legend (double x, double y, double r, double angs[], String ls[]){ double angle = 0.0, sec_a = 0.0; for (int i = 0; i < angs.length ; i++) angs[i] = angs[i] * 3.6; double x2, y2; double px = x + 1.5*r, py = y + 0.75 * r; Color c = get_col(); StdDraw.setPenColor(c); StdDraw.text(px, py, ls[0]); py = py - 5; int i = 0; while (angle <= 360.0 && i < angs.length){ x2 = r * Math.cos(Math.toRadians(angle)) + x; y2 = r * Math.sin(Math.toRadians(angle)) + y; if (sec_a > angs[i]) { sec_a = 0.0; c = get_col(); StdDraw.setPenColor(c); i++; StdDraw.text(px, py, ls[i]); py = py -5; StdDraw.line(x, y, x2, y2); angle = angle + 0.5; sec_a = sec_a + 0.5;
StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.clear(Color.BLACK); double pie[] = {20.0, 30.0, 10.0, 10.0, 15.0, 5.0, 10.0; String legend[] = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7"; CircleDefs.pie_chart_with_legend(50.0, 50.0, 20.0,pie, legend);
public static void dots (int N, double r){ for (int i = 1; i <= N; i++){ Color c = get_col(); double x = Math.random() * 100.0; double y = Math.random() * 100.0; double rad = Math.random() * r; StdDraw.setPenColor(c); StdDraw.filledCircle(x,y,rad); StdDraw.setXscale(0.0, 100.0); StdDraw.setYscale(0.0, 100.0); StdDraw.setPenColor(Color.BLACK); CircleDefs.dots(300, 2.0);
Ως εξάσκηση ορίστε μεθόδους για τη δημιουργία των ακόλουθων σχημάτων αξιοποιώντας τις Βιβλιοθήκες StdDraw και CircleDefs