Tujuan : Mahasiswa memahami output primitive grafika komputer . Mahasiswa mampu memahami algoritma pembentukan garis dan lingkaran
A.Grafika Komputer Grafika komputer atau dalam bahasa Inggris computer graphics dapat diartikan sebagai perangkat alat yang terdiri dari hardware dan software untuk membuat gambar , grafik atau citra realistik untuk seni , game komputer , foto dan film animasi . Grafika computer merupakan bagian yang paling menarik dari bidang ilmu komputer , ini dikarenakan untuk dapat memahaminya dengan baik diperlukan kemampuan matematika dan juga keahlian untuk memprogram dan kreativitas .
Gambar dapat dijelaskan dengan beberapa cara , bila menggunakan raster display, gambar ditentukan oleh satu set intensitas untuk posisi display pada display. Sedangkan dengan scene tampilan gambar dengan loading array dari pixel ke dalam buffer atau dengan mengkonversikan scan dari grafik geometri tertentu ke dalam pola pixel. Paket grafika dilengkapi dengan fungsi untuk menyatakan scene dalam bentuk struktur . Paket pemrograman grafika dilengkapi dengan fungsi untuk menyatakan scene dalam bentuk struktur dasar geometri yang disebut output primitif , dengan memasukkan output primitif tersebut sebagai struktur yang lebih kompleks .
B.Elemen Gambar untuk Menciptakan Gambar dalam Komputer Penghasilan citra pada grafik komputer menggunakan primitif grafik dasar . Primitif ini memudahkan untuk merender ( menggambar pada layar monitor) sebagaimana penggunaan persamaan geometri sederhana . Primitif grafik dasar yangdipakai dalam algoritma berbasis visual interaktif diantaranya : 1. Titik 2. Garis
1. Pengenalan Titik (Point) Titik pada komputer merupakan sebuah koordinat yang mengandung identitas warna yang diletakkan pada Cathoda -Ray-Tube (CRT) monitor. Titik merupakan satuan gambar / grafis yang terkecil . Dengan menggambar titik maka kita dapat menggambar obyek apapun . Termasuk bentuk geometri dibawah merupakan bentuk – bentuk yang pada dasarnya berasal dari titik-titik . Operasi titik ini sering digunakan pada pengolahan citra ( Image processing). Setiap titik pada monitor memiliki parameter: koordinat dan warna . Atribut ( semua parameter yang mempengaruhi bagaimana primitive grafis ditampilkan ) dasar untuk titik adalah ukuran dan warna . Ukuran titik direpresentasikan sebagai beberapa piksel .
2. Pengenalan Garis (Line) Garis adalah kumpulan titik-titik /pixel yang tersusun secara lurus dan linier dari titik awal sampai titik akhir . Penggambaran garis dilakukan dengan menghitung posisi-posisi sepanjang jalur lurus antara dua posisi titik . Jalur lurus yang menghubungkan dua titik tersebut sebenarnya adalah titik-titik yang saling berdempetan mengikuti arah jalur lurus tersebut . Atribut dasar untuk garis lurus adalah type ( tipe ), width ( tebal ), dan color ( warna ). Dalam berapa paket aplikasi grafik , garis dapat ditampilkan dengan menggunakan pen atau brush. Pada algoritma penggambaran garis , atribut tebal (width) dapat ditentukan seperti juga panjang dan spasi antar titik .
Atribut Tipe Garis Atribut tipe atau style pada garis dibagi menjadi 3 ( tiga ) yaitu : 1 . Solid line Algoritma pembentukan garis dilengkapi dengan pengaturan panjang dan jarak yang menampilkan bagian solid sepanjang garis . 2. Dashed line ( garis putus ) Garis putus dibuat dengan memberikan jarak dengan bagian solid yang sama . 3. Dotted line ( garis titik-titik ) Garis titik-titik dapat ditampilkan dengan memberikan jarak yang lebih besar dari bagian
Atribut Tebal Garis - Implementasi dari tebal garis tergantung dari kemampuan alat output yang digunakan . Garis tebal pada video monitor dapat ditampilkan sebagai garis adjacent parallel ( kumpulan garis sejajar yang berdekatan ), sedangkan pada plotter mungkin menggunakan ukuran pen yang berbeda . - Pada implementasi raster, tebal garis standar diperoleh dengan menempatkan satu pixel pada tiap posisi , seperti algoritma Bressenham . Garis dengan ketebalan didapatkan dengan perkalian integer positif dari garis standar , dan menempatkan tambahan pixel pada posisi sejajar . Untuk garis dengan slope kurang dari 1, routine pembentukan garis dapat dimodifikasi untuk menampilkan ketebalan garis dengan menempatkan pada posisi vertical setiap posisi x sepanjang garis . Untuk garis dengan slope lebih besar dari 1, ketebalan garis dapat dibuat dengan horizontal span.
Atribut Warna Garis Bila suatu sistem dilengkapi dengan pilihan warna ( atau intensitas ), parameter yang akan diberikan pada indeks warna termasuk dalam daftar nilai atribut dari sistem . Routine polyline membuat garis pada warna tertentu dengan mengatur nilai warna pada frame buffer untuk setiap posisi pixel, menggunakan prosedur set pixel. Jumlah warna tergantung pada jumlah bit yang akan digunakan untuk menyimpan informasi warna .
Atribut Penggunaan Pen dan Brush Pada beberapa paket aplikasi grafik , dapat ditampilkan dengan pilihan pen maupun brush. Kategori ini meliputi bentuk , ukuran , dan pola (pattern). Ketebalan yang bermacam-macam dari garis yang mempunyai bentuk pen dan brush dapat ditampilkan dengan cara mengubah ukuran dari mask.
C.Algoritma pembentukan garis Persamaan garis menurut koordinat Cartesian adalah : y = m.x+b dimana m adalah slope ( kemiringan ) dari garis yang dibentuk oleh dua titik yaitu (x 1 , y 1 ) dan (x 2 , y 2 ). Untuk penambahan x sepanjang garis yaitu dx akan mendapatkan penambahan y sebesar : Δ y = m. Δ x
Algoritma garis DDA Algoritma Digital Differential Analyzer (DDA) adalah algoritma pembentukan garis berdasarkan perhitungan Δ x dan Δ y, menggunakan rumus Δ y = m. Δ x. Garis dibuat dengan menentukan dua endpoint yaitu titik awal dan titik akhir . Setiap koordinat titik yang membentuk garis diperoleh dari perhitungan , kemudian dikonversikan menjadi nilai integer.
Algoritma Garis Bressenhem Bressenham mengembangkan algoritma klasik yang lebih menarik , karena hanya menggunakan perhitungan matematika dengan bilangan integer. Dengan demikian tidak perlu membulatkan nilai posisi setiap pixel setiap waktu . Algoritma garis Bressenhem disebut juga midpoint line algorithm adalah algoritma konversi penambahan nilai integer yang juga dapat diadaptasi untuk menggambar sebuah lingkaran
Program Java Bentuk Titik Pixel import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; public class MyDrawpixel extends Frame { public Point mypoint = new Point(); public static void drawPixel (Graphics g, int x, int y, int size, Paint color) { Graphics2D ga = (Graphics2D)g; Shape circle = new Ellipse2D.Float(x, y, size, size); ga.setPaint (color); ga.draw (circle); ga.setPaint (color); ga.fill (circle); }
public void paint(Graphics g) { Graphics2D ga = (Graphics2D)g; drawPixel (g, mypoint.x , mypoint.y , 3, Color.blue ); } public static int ReadInteger () { try { InputStreamReader input = new InputStreamReader ( System.in ); BufferedReader reader = new BufferedReader (input); return Integer.parseInt ( reader.readLine ()); } catch (Exception e) { e.printStackTrace (); return 0; } }
public static void main(String args []) { System.out.format ("Enter Point X: "); int x = ReadInteger (); System.out.format ("Enter Point Y: "); int y = ReadInteger (); MyDrawpixel frame = new MyDrawpixel (); frame.mypoint.x = x; frame.mypoint.y = y; frame.addWindowListener ( new WindowAdapter () { public void windowClosing ( WindowEvent we) { System.exit (0); } } ); frame.setSize (400, 400); frame.setVisible (true); } }
Count number of pixels used in drawLine function import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; import java.awt.Image .*; import javax.swing.JFrame ; import javax.swing.JPanel ; public class CountPixels_Line extends JPanel { static public int pixelDrawnCount = 0; static public int width = 300; static public int height = 300; public java.awt.image.BufferedImage myshape = new java.awt.image.BufferedImage ( width,height , java.awt.image.BufferedImage.TYPE_INT_RGB ); public int CountPixelsInLine ( int x1, int y1, int x2, int y2) { Graphics2D gtemp = myshape.createGraphics (); gtemp.setPaint ( Color.white ); gtemp.fillRect (0,0,width,width); gtemp.setPaint ( Color.red ); gtemp.drawLine (x1,y1,x2,y2);
int pixelcount = 0; for( int i = 0; i < width; i ++) { for( int j = 0; j < height; j++) { int color = myshape.getRGB ( i,j ); int red = (color & 0x00ff0000) >> 16; int green = (color & 0x0000ff00) >> 8; int blue = color & 0x000000ff; if(red == 255 && green == 0 && blue == 0) { pixelcount ++; } } } gtemp.dispose (); return pixelcount ; }
Count number of pixels used in drawRect function import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; import java.awt.Image .*; import javax.swing.JFrame ; import javax.swing.JPanel ; public class CountPixels_DrawRect extends JPanel { static public int pixelDrawnCount = 0; static public int width = 300; static public int height = 300; public java.awt.image.BufferedImage myshape = new java.awt.image.BufferedImage ( width,height , java.awt.image.BufferedImage.TYPE_INT_RGB );
public int CountPixelsIn_drawRect ( int x1, int y1, int x2, int y2) { Graphics2D gtemp = myshape.createGraphics (); gtemp.setPaint ( Color.white ); gtemp.fillRect (0,0,width,width); gtemp.setPaint ( Color.red ); gtemp.drawRect (x1,y1,x2,y2); int pixelcount = 0; for( int i = 0; i < width; i ++) { for( int j = 0; j < height; j++) { int color = myshape.getRGB ( i,j ); int red = (color & 0x00ff0000) >> 16; int green = (color & 0x0000ff00) >> 8; int blue = color & 0x000000ff; if(red == 255 && green == 0 && blue == 0) { pixelcount ++; } } } gtemp.dispose (); return pixelcount ; }
Draw Polygon using drawPolygon import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; public class DrawPolygon extends Frame { public Polygon mypolygon = new Polygon(); public void paint(Graphics g) { Graphics2D ga = (Graphics2D)g; ga.setPaint ( Color.red ); ga.drawPolygon ( mypolygon ); ga.setPaint ( Color.green ); }
public static void main(String args []) { List< Integer > srcpoints = new ArrayList < Integer >(); srcpoints.add (100); srcpoints.add (100); srcpoints.add (75); srcpoints.add (75); srcpoints.add (150); srcpoints.add (100); srcpoints.add (75); srcpoints.add (125); srcpoints.add ( srcpoints.get (0)); srcpoints.add ( srcpoints.get (1)); DrawPolygon frame = new DrawPolygon (); for( int i = 0; i < srcpoints.size (); i ++) { int x = srcpoints.get ( i ++); int y = srcpoints.get ( i ); frame.mypolygon.addPoint (x, y); }
frame.addWindowListener ( new WindowAdapter () { public void windowClosing ( WindowEvent we) { System.exit (0); } } ); frame.setSize (400, 400); frame.setVisible (true); } } /*** Enter Number of points: 4 Enter x[1]: 100 Enter y[1]: 100 Enter x[2]: 150 Enter y[2]: 100 Enter x[3]: 150 Enter y[3]: 150 Enter x[4]: 100 Enter y[4]: 150 ***/
Draw Triangle and Check Given Point is Inside or Outside import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; public class PointInTriangle extends Frame { public Polygon mypolygon = new Polygon(); public Point mypoint = new Point();
public static void drawPixel (Graphics g, int x, int y, int size, Paint color) { Graphics2D ga = (Graphics2D)g; Shape circle = new Ellipse2D.Float(x, y, size, size); ga.setPaint (color); ga.draw (circle); ga.setPaint (color); ga.fill (circle); } public void paint(Graphics g) { Graphics2D ga = (Graphics2D)g; ga.setPaint ( Color.red ); ga.draw ( mypolygon ); ga.setPaint ( Color.green ); drawPixel (g, mypoint.x , mypoint.y , 3, Color.blue ); }
public static int IsPointInBoundingBox (float x1, float y1, float x2, float y2, float px , float py ) { float left, top, right, bottom; // Bounding Box For Line Segment // For Bounding Box if(x1 < x2) { left = x1; right = x2; } else { left = x2; right = x1; } if(y1 < y2) { top = y1; bottom = y2; }
else { top = y2; bottom = y1; } if( (px+0.01) >= left && (px-0.01) <= right && (py+0.01) >= top && (py-0.01) <= bottom ) { return 1; } else return 0; }
public static int LineSegmentIntersection (float l1x1, float l1y1, float l1x2, float l1y2, float l2x1, float l2y1, float l2x2, float l2y2) { float dx , dy ; float intersection_X = 0; float intersection_Y = 0; dx = l1x2 - l1x1; dy = l1y2 - l1y1; float m1 = dy / dx ; float c1 = l1y1 - m1 * l1x1; // which is same as y2 - slope * x2 dx = l2x2 - l2x1; dy = l2y2 - l2y1;
public static int ReadInteger () { try { InputStreamReader input = new InputStreamReader ( System.in ); BufferedReader reader = new BufferedReader (input); return Integer.parseInt ( reader.readLine ()); } catch (Exception e) { e.printStackTrace (); return 0; } }
public static void main(String args []) { List< Integer > srcpoints = new ArrayList < Integer >(); for( int i = 0; i < 3; i ++) { System.out.format ("Enter x[%d]: ", i + 1); srcpoints.add ( ReadInteger ()); System.out.format ("Enter y[%d]: ", i + 1); srcpoints.add ( ReadInteger ()); } /*** srcpoints.add (200); srcpoints.add (200); srcpoints.add (75); srcpoints.add (75); srcpoints.add (100); srcpoints.add (200); srcpoints.add ( srcpoints.get (0)); srcpoints.add ( srcpoints.get (1)); ***/
PointInTriangle frame = new PointInTriangle (); for( int i = 0; i < srcpoints.size (); i ++) { int x = srcpoints.get ( i ++); int y = srcpoints.get ( i ); frame.mypolygon.addPoint (x, y); } System.out.format ("Enter Point X: "); int x = ReadInteger (); System.out.format ("Enter Point Y: "); int y = ReadInteger (); /*** int x = 85; int y = 100; ***/ int px = x + 1000; int py = y; frame.mypoint.x = x; frame.mypoint.y = y;
Graphics program to draw a triangle using drawPolygon function import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; public class DrawTriangle extends Frame { public Polygon mypolygon = new Polygon(); public void paint(Graphics g) { Graphics2D ga = (Graphics2D)g; ga.setPaint ( Color.red ); ga.drawPolygon ( mypolygon ); }
public static void main(String args []) { List< Integer > srcpoints = new ArrayList < Integer >(); srcpoints.add (200); srcpoints.add (200); srcpoints.add (75); srcpoints.add (75); srcpoints.add (100); srcpoints.add (200); srcpoints.add ( srcpoints.get (0)); srcpoints.add ( srcpoints.get (1)); DrawTriangle frame = new DrawTriangle (); for( int i = 0; i < srcpoints.size (); i ++) { int x = srcpoints.get ( i ++); int y = srcpoints.get ( i ); frame.mypolygon.addPoint (x, y); }
int nCountIntersections = 0; nCountIntersections += LineSegmentIntersection ( srcpoints.get (0), srcpoints.get (1), srcpoints.get (2), srcpoints.get (3), x, y, px , py ); nCountIntersections += LineSegmentIntersection ( srcpoints.get (2), srcpoints.get (3), srcpoints.get (4), srcpoints.get (5), x, y, px , py ); nCountIntersections += LineSegmentIntersection ( srcpoints.get (4), srcpoints.get (5), srcpoints.get (0), srcpoints.get (1), x, y, px , py ); if( ( nCountIntersections % 2) == 1) System.out.println ("The Given Point is inside the triangle"); else System.out.println ("The Given Point is outside the triangle"); frame.addWindowListener ( new WindowAdapter () { public void windowClosing ( WindowEvent we) { System.exit (0); } } );
frame.setSize (300, 250); frame.setVisible (true); } } /*** Enter x[1]: 200 Enter y[1]: 200 Enter x[2]: 75 Enter y[2]: 75 Enter x[3]: 100 Enter y[3]: 200 Enter Point X: 85 Enter Point Y: 100 The Given Point is inside the triangle ***/
Fill Polygon using fillPolygon import java.lang .*; import java.util .*; import java.util.List ; import java.io.*; import java.awt.*; import java.awt.event .*; import java.awt.geom .*; public class MyFillPolygon extends Frame { public Polygon mypolygon = new Polygon(); public void paint(Graphics g) { Graphics2D ga = (Graphics2D)g; ga.setPaint ( Color.red ); ga.fillPolygon ( mypolygon ); }
public static void main(String args []) { List< Integer > srcpoints = new ArrayList < Integer >(); srcpoints.add (100); srcpoints.add (100); srcpoints.add (75); srcpoints.add (75); srcpoints.add (150); srcpoints.add (100); srcpoints.add (75); srcpoints.add (125); srcpoints.add ( srcpoints.get (0)); srcpoints.add ( srcpoints.get (1)); MyFillPolygon frame = new MyFillPolygon (); for( int i = 0; i < srcpoints.size (); i ++) { int x = srcpoints.get ( i ++); int y = srcpoints.get ( i ); frame.mypolygon.addPoint (x, y); } frame.addWindowListener ( new WindowAdapter () { public void windowClosing ( WindowEvent we) { System.exit (0); } } ); frame.setSize (400, 400); frame.setVisible (true); } }
Algoritma Garis DDA dan Bressenham
Garis Dinyatakan dengan 4 nilai : x1,y1,x2,y2 Koordinat / titik awal (x1,y1) Koordinat / titik akhir (x2,y2)
Kuadran Garis Kuadran Kriteria Arah Garis Contoh I X1<X2 dan Y1<Y2 (1,1) dan (10,10) II X1>X2 dan Y1<Y2 (10,5) dan (5,20) III X1>X2 dan Y1>Y2 (10,5) dan (5,2) IV X1<X2 dan Y1>Y2 (5,10) dan (10,4)
m = gradien / kemiringan garis Persamaan garis lurus : Y = mx + c M : gradien C : konstanta
Algoritma DDA (Digital Differential Analyzer) Algoritma sederhana untuk menggambar garis Garis dikelompokkan ke dalam 3 bentuk : mendatar, cenderung tegak dan miring 45 derajat Nilai untuk gradien : m>1, m=1, 0<m<1
Bentuk Garis Cenderung mendatar Gradien bernilai 0 < m < 1 Pixel bertambah 1 pada sumbu x dan bertambah sebesar m pixel pada sumbu y Sumbu x sebagai parameter Sumbu y sebagai hasil dari fungsi
Bentuk Garis Cenderung tegak Gradien bernilai m > 1 Pixel bertambah 1 pada sumbu y dan bertambah sebesar 1/m pixel pada sumbu x Sumbu y sebagai parameter Sumbu x sebagai hasil dari fungsi
Bentuk Garis Miring 45 o Gradien bernilai m = 1 Pixel bertambah 1 pada sumbu x dan bertambah sebesar 1 pixel pada sumbu y
Hasil dari fungsi : bilangan riil Koordinat pixel : integer Harus dibulatkan ke dalam integer terdekat
Algoritma Garis DDA x = x1 ; y = y1; m = (y2 – y1) / (x2 – x1) if m>0 and m<1 then while x <= x2 do gambar pixel pada (x,y) x = x + 1 y = mx + c endwhile Else if m>1 then while y<=y2 do gambar pixel pada (x,y) x=x+1/m y=y+1 endwhile Else if m=1 then while x<=x2 do gambar pixel pada (x,y) x=x+1 y=y+1 endwhile
Kelemahan DDA Hanya dapat digunakan untuk nilai x1<x2 dan y1<y2 (kuadran I) Menggunakan pembagian serta pembulatan sehingga kurang akurat
Langkah-Langkah Algoritma Bresenham Langkah-langkah pembentukan garis berdasarkan algoritma Bressenham adalah: 1. Tentukan dua titik yang akan dihubungkan dalam pembentukan garis. 2. Tentukan salah satu sebagai titik awal ( x , y ) dan titik akhir ( x 1 , y 1 ). Hitung dx , dy , 2 dy dan 2 dy - 2 dx Hitung parameter : p o = 2 dy - dx 5. Untuk setiap x k sepanjang jalur garis, dimulai dengan k=0 - bila p k < 0 maka titik selanjutnya adalah: ( x k +1, y k ) dan p k +1 = p k + 2dy - bila tidak, titik selanjutnya adalah: ( x k +1, y k +1) dan p k +1 = p k + 2dy – 2dx 6. Ulangi nomor 5 untuk menentukan posisi pixel berikutnya, sampai x = x 1 atau y = y 1 .
public static void main(String[] args ) { System.out.println ("Pascal Triangle Program"); System.out.print ("Enter the number of rows: "); int n = ReadInteger (); for ( int y = 0; y < n; y++) { int c = 1; for ( int q = 0; q < n - y; q++) { System.out.print (" "); } for ( int x = 0; x <= y; x++) { System.out.format (" %3d ", c); c = c * (y - x) / (x + 1); } System.out.println (); System.out.println (); } System.out.println (); } }