370 likes | 606 Views
Java. נכתב ע"י משה חדד. Previously ,on CG…. תכנות מונחה אירועים ישור קו :מושגים בסיסים בגרפיקה הצגה גראפית שיטות שונות למידול שמירת פוליגון. היום. Java AWT Event listener Graphics נקודה בתוך פוליגון Crossing number Winding number מילוי פוליגון בצבע FloodFill Scan conversion.
E N D
Java נכתב ע"י משה חדד
Previously ,on CG… • תכנות מונחה אירועים • ישור קו :מושגים בסיסים בגרפיקה • הצגה גראפית • שיטות שונות למידול • שמירת פוליגון
היום • Java • AWT • Event listener • Graphics • נקודה בתוך פוליגון • Crossing number • Winding number • מילוי פוליגון בצבע • FloodFill • Scan conversion
AWT (Abstract window Toolkit) • שימוש ב AWT נעשה ע"י import java.awt.* • מחלקת AWT מכילה • מיכלים (containers) • רכיבים (components) • מיכלים • מיכל יכול להכיל בתוכו רכיבים שונים • מיכל בעצמו רכיב ולכן יכול להיות מוכל במיכלים אחרים • מיכלים שונים • Window,Panel,Frame
אובייקט רכיב Label Canvas מיכל Button Swing Panel Window Frame Applet AWT (Abstract window Toolkit) • היררכיה רכיבים שונים של AWT
AWT (Abstract window Toolkit) • רכיבים שונים • Canvas ,Label ,TextComponent • TextArea , list ,Button ,Choice • כל הרכיבים המוצגים הם רכיבים של סביבת העבודה (windows ,Linux, Macintosh etc’) • Canvas • משטח ריבועי פשוט שניתן לצייר עליו • ניתן לעצב מחדש את המתודות של המשטח ע"מ לצייר עליו בצורה דינאמית (מתודת paint)
AWT (Abstract window Toolkit) • שלושה שלבים עיקרים • יצירת GUI • הגדרת מיכל,רכיבים והסידור שלהם (Layout Manager) • לצורך הקורס אנחנו בעיקר נשמש ב canvas • הגדרת Event handlers לטפל באירועים • נגדיר ל Canvas את כל ה event handlers שקיימים כדי שנוכל להגיב על אירועים שמתרחשים בCanvas (פונקציות callback ) • ציור המנשק שבנינו למסך
AWT (Abstract window Toolkit) • הגדרת מיכל ורכיבים import java.awt .*; public static void main(String[] args){ Frame MyFrame = new Frame("ex1"); Canvas myCanvas =new Canvas(); MyFrame.add(myCanvas); MyFrame.pack(); MyFrame.setVisible(true); }
AWT (Abstract window Toolkit) • הגדרת Event Handler לחלון • החלון שלנו צריך להיסגר • נוסיף קריאה למחלקות import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; WindowAdapter Wa=new WindowAdapter(){ public void windowClosing (){ System.exit(0); } }; MyFrame.addWindowListener(Wa); הערה : windowsAdapter מממש בשבילנו את כל מחלקות האבסטרקטיות של WindowListener
AWT (Abstract window Toolkit) • הגדרת Canvas • נגדיר מחלקה חדשה MyCanvasשיורשת את Canvas ומממשת ActionListener • ונוסיף את MyCanvas כמאזין לאירועים בעצמו וברכיבים אחרים (כגון Button וכו') • נממש את הפונקציה paint() ע"מ שנוכל לצייר • נשים לב שצריך לממש את כל המחלקות האבסטרקטיות
AWT (Abstract window Toolkit) class myCanvas extends Canvas implements MouseListener{ boolean moshe; public myCanvas() { setSize(600,400); addMouseListener(this); } public void paint(Graphics g){ g.drawLine(10,10,100,100); if(moshe) g.drawString("Moses is in the house",100,100); } public void mouseClicked(MouseEvent arg0) { moshe=true; repaint(); } … … .. }
AWT (Abstract window Toolkit) • המתודה Paint מקבלת Graphics g • פונקציות שימושיות ב Graphics • g.drawLine(x,y,x1,y1); • g.drawString(“Msg",x,y); • g.drawPolyline( int[] x, int[] y, nPoints); • g.drawPolygon( int[] x, int[] y, nPoints); • g.drawPolygon(Polygon p); • g.drawRect(x0,y0,x1,y1); • g.fillRect(x0,y0,width,height);
AWT (Abstract window Toolkit) • המבנה polygon ב graphics • Npoints –מספר הנקודות בפוליגון • Int[] x – מערך של X-ים • Int[] y – מערך של Y-ים • addPoint- הוספת נקודה לפוליגון • Contains –מחזיר true אם נקודה נמצאת בתוך הפוליגון (אנחנו לא נשתמש בזה) • Translate- מבצע טרנספורמציה על הפוליגון (גם בזה לא נשתמש)
נקודה בתוך פוליגון • איך יודעים אם נקודה נמצאת בתוך פוליגון? • Crossing number • כמה פעמים קרן שיורים מהנקודה חוצה את גבולות הפוליגון • הנקודה בפנים כאשר cn אי זוגי, ובחוץ אם זוגי • נקרא גם odd parity rule • Winding number • כמה פעמים הפוליגון "מתקפל" מסביב לנקודה • הנקודה בפנים אם wn!=0 ובחוץ אם wn=0
נקודה בתוך פוליגון Crossing number Winding number
נקודה בתוך פוליגון • Crossing number • Crossing number • יורים קרן מהנקודה לכל כיוון cn=0 • כל פעם שהקרן חוצה פאה של הפוליגון cn++
נקודה בתוך פוליגון • בעיות במקרי קצה כאשר הקרן חוצה vertex היא צריכה לספור פעמיים או פעם אחת? כאשר הקרן חוצה קו אופקי כמה פעמים לספור?
נקודה בתוך פוליגון • פתרון • חוקים • בחציית פאה בכיוון מעלה מחשיבים את נקודת ההתחלה ולא מחשיבים את נקודת הסיום • בחציית פאה בכיוון מטה מחשיבים את נקודת הסוף ולא מחשיבים את נקודת ההתחלה • לא מחשיבים קווים אופקיים • סופרים רק את הפאות שמימין לקרן
נקודה בתוך פוליגון Odd parity rule VS. Non Zero rule Odd parity rule CN רגיל 1+ בחציית פאה Cn=2 even outSide Non zero rule בחצית פאה בכיוון מעלה 1+ בחציית פאה בכיוון מטה 1- cn = -2 inside
נקודה בתוך פוליגון • Winding number • Wn הוא מספר הפעמים שהפוליגון "מתקפל" מסביב לנקודה • עוברים עם האצבע על הפוליגון • בודקים כמה פעמים הקפנו את הנקודה • כל היקף עם כיוון השעון נקדם את wn באחת • כל היקף נגד כיוון השעון נפחית מ –wn אחת • אם wn=0 הנקודה בחוץ
נקודה בתוך פוליגון • Winding number • איך מחשבים?? • עוברים על כל הקודקודים של הפוליגון • עבור כל שני קודקוד מחשבים ווקטור לנקודה • לפי כיוון המעבר על הקודקודים מחשבים זווית בין הווקטורים • סוכמים ומחלקים ב 360
נקודה בתוך פוליגון • Winding number
נקודה בתוך פוליגון • Winding number
נקודה בתוך פוליגון • האלגוריתם Cn_poly (Point pn ,Polygon P) { int cn=0; //crossing number for( each edge E in polygon) { if( E[i] crosses upword or E[i] crosses downward) { if( Pn.x < intersect_x of E[i] with P.y) ++cn; } } Return cn; } • איך מזהים חציה בכיוון מעלה או מטה? • איך נכלול נקודות בחציה? (איך נממש את החוקים)
נקודה בתוך פוליגון • איך נמצא את נקודת החיתוך? • משוואה פרמטרית של קו • את ה-y בנקודת החיתוך כבר יש לנו מהנקודה עצמה (יורים רק לצד ימין) • ערכי ה-y בנקודת החיתוך ידוע של נקודות הפאה גם ידועות • נוכל למצוא את הפרמטר t ע"י הצבה של y • הצבה של t במשוואה של X תתן לנו את ה-X בנקודת החיתוך
נקודה בתוך פוליגון (x2,y2) (x ,y) (x1,y1)
מילוי פוליגון • Flood fill: • אלגוריתם רקורסיבי • מתחילים מנקודה אחת בתוך הפוליגון • צובעים ימינה,שמאלה,למעלה,למטה • עוצרים כאשר מגיעים לקצוות של הפוליגון • בעיות • איטי • צורך זיכרון (ממלא את המחסנית)
מילוי פוליגון • אלגוריתם:FloodFill FloodFill(x,y) { If (onBoundary(x,y) or Colored(x,y)) return Else { PutPixel(x,y,c); FloodFill(x+1,y); FloodFill(x,y+1); FloodFill(x,y-1); FloodFill(x-1,y); } {
מילוי פוליגון • ScanConversion • עוברים בקו סריקה מ Y=0 עד הקצה • אוספים את נקודות החיתוך עבור כל Y נוכחי • מחברים כל שתי נקודות בקו (span )
מילוי פוליגון • ScanConversion • בעיות במקרי קצה
xi-1 yi-1 yi xi מילוי פוליגון • ScanConversion • שיפור • נגדיר מבנה פאה המכיל את Ymxn, Xmin, Slope של כל הפאה בפוליגון (צריך לשים לב שבהגדרת פאה (y1<y2) • ננצל את העובדה שה-X משתנה מעט בין Yi ל Yi+1 (משתנה לפי השיפוע)
מילוי פוליגון • ScanConversion • נחזיק שתי רשימות • ET (edge table) , • AET (active edge table) • נמיין ב-bucket sort את כל הפאות ונכניס ל ET לפי Ymin • עבור כל scan line יהיו לנו כמה פאות שנחתכות בנקודת המינימום שלהם עם ה scan line • על AET נבצע עבור כל Y • נבדוק את הפאות מול y הנוכחי • אם Ymax=y נוציא את הפאה מAET • נעדכן את ערכי ה-X של כל הפאות שנשארו ב-AET • נעדכן את AET מ ET נוסיף את כל הפאות ש ymin=y • נמיין את כל הפאות לפי ערכי X • נחבר זוגות של X-ים בקו • נשים לב שאין צורך להחשיב קוים מאוזנים • קודקודי המקסימום לא יצוירו
מילוי פוליגון • הפאות של הפוליגון • טבלת ה-ET Edge Label Coordinates y1 Structure a (1 , 1) to (4 , 7) 1 (7 , 1 , 0.5) b (7 , 2) to (4 , 7) 2 (7 , 7 , -0.6) c (7 , 2) to (4 , 4) 2 (4 , 7 , -1.5) d (1 , 1) to (4 , 4) 1 (4 , 1 , 1) y1 Sequence of Edges 1 (7,1,0.5), (4, 1, 1) 2 (7,7,-0.6), (4, 7, -1.5)
מילוי פוליגון Line Active Edge Table Spans 0 empty 1 (7 , 1 , 0.5), (4 , 1 , 1) 1 to 1 2 (7 , 1.5 , 0.5), (4 , 2 , 1), (4 , 7,-1.5), (7,7,-0.6) 1.5 to 2, 7 to 7 3 (7, 2.0 , 0.5), (4 , 3 , 1), (4 , 5.5 , -1.5), (7 , 6.4 , -0.6) 2.0 to 3, 5.5 to 6.4 4 (7 , 2.5 , 0.5), (7 , 5.8 , -0.6) 2.5 to 5.8 5 (7 , 3.0 , 0.5), (7 , 5.2 , -0.6) 3.0 to 5.2 6 (7 , 3.5 , 0.5), (7 , 4.6 , -0.6) 3.5 to 4.6 7 empty 8 empty y1 Sequence of Edges 1 (7 , 1 , 0.5), (4 , 1 , 1) 2 (7 , 7, -0.6), (4, 7, -1.5)