/* cube.java by Gengbin Zheng using Z-Buffer to perform hidden surface elimination */ import java.awt.*; import java.applet.*; public class cube extends Applet implements Runnable { Button moveButton, scaleButton, RotateButton, resetButton; Checkbox slowCheck; myCanvas canvas; TextField statusBar; Thread thread; public void init() { GridBagLayout layout = new GridBagLayout(); setLayout(layout); moveButton = new Button("Move"); scaleButton = new Button("Scale"); RotateButton = new Button("Rotate"); resetButton = new Button("Reset"); slowCheck = new Checkbox("Too slow?", null, false); GridBagConstraints constraints = new GridBagConstraints(); canvas = new myCanvas(slowCheck); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 1; constraints.gridheight = 5; constraints.gridwidth = GridBagConstraints.RELATIVE; constraints.weighty = 1; layout.setConstraints(canvas, constraints); add(canvas); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 0; constraints.gridheight = 1; constraints.gridwidth = GridBagConstraints.REMAINDER; layout.setConstraints(moveButton, constraints); add(moveButton); layout.setConstraints(scaleButton, constraints); add(scaleButton); layout.setConstraints(RotateButton, constraints); add(RotateButton); layout.setConstraints(resetButton, constraints); add(resetButton); layout.setConstraints(slowCheck, constraints); add(slowCheck); statusBar = new TextField("Move"); statusBar.setEditable(false); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 1; constraints.gridheight = 1; constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.weighty = 0; layout.setConstraints(statusBar, constraints); add(statusBar); resize(450,350); } public void start() { thread = new Thread(this); thread.start(); } public void run() { } public void stop() { thread.stop(); } void HandleButtons(Object label) { String helpMsg; if (label == "Move") helpMsg = "Move"; else if (label == "Scale") helpMsg = "Scale"; else if (label == "Rotate") helpMsg = "Rotate"; else helpMsg = ""; if (helpMsg != "") statusBar.setText(helpMsg); canvas.HandleButtons(label); } public boolean action(Event evt, Object arg) { if (evt.target instanceof Button) { HandleButtons(arg); } else if (evt.target instanceof Checkbox) { canvas.HandleCheckbox(evt); } return true; } } class myCanvas extends Canvas { Mycube mycube; Point oldPt, newPt; boolean working; // double buffering Image img = null; Graphics backg; final int MOVE=1, SCALE=2, ROTATE=3; int action; Checkbox slowCheck; public myCanvas(Checkbox box) { mycube = new Mycube(); working = false; action = MOVE; slowCheck = box; } void setcursor(boolean working) { Cursor curs; if (working) curs = new Cursor(Cursor.HAND_CURSOR); else curs = new Cursor(Cursor.DEFAULT_CURSOR); setCursor(curs); } public boolean mouseDown(Event evt, int x, int y) { if (action == MOVE) { if (working == false) { working = true; oldPt = new Point(x,y); mycube.setShow(!slowCheck.getState()); setcursor(true); } } if (action == SCALE) { if (working == false) { working = true; oldPt = new Point(x,y); mycube.setShow(!slowCheck.getState()); setcursor(true); } } if (action == ROTATE) { if (working == false) { working = true; oldPt = new Point(x,y); mycube.setShow(!slowCheck.getState()); setcursor(true); } } return true; } public boolean mouseUp(Event evt, int x, int y) { if (working) { working = false; mycube.setShow(true); if (slowCheck.getState() == true) repaint(); setcursor(false); } return true; } public boolean mouseDrag(Event evt, int x, int y) { if (action == MOVE) { if (working) { newPt = new Point(x,y); mycube.move(oldPt, newPt); oldPt = newPt; repaint(); } } if (action == SCALE) { if (working) { newPt = new Point(x,y); mycube.scale(oldPt, newPt); oldPt = newPt; repaint(); } } if (action == ROTATE) { if (working) { newPt = new Point(x,y); mycube.rotate(oldPt, newPt); oldPt = newPt; repaint(); } } return true; } public void HandleButtons(Object label) { if (label == "Move") { action = MOVE; } else if (label == "Scale") { action = SCALE; } else if (label == "Rotate") { action = ROTATE; } else if (label == "Reset") { mycube.reset(); repaint(); } } public void HandleCheckbox(Event evt) { String label = slowCheck.getLabel(); if (label == "Too slow?") { // mycube.setShow(!slowCheck.getState()); } } public void paint(Graphics g) { update(g); } public void update(Graphics g) { Dimension d=size(); if (img == null) { img = createImage(d.width, d.height); backg = img.getGraphics(); } backg.setColor(new Color(255,255,255)); //Set color for background backg.fillRect(0,0, d.width, d.height); //Draw Backround mycube.draw(g, backg, d); g.drawImage(img, 0, 0, this); } } class Mycube { CVector points[][]; CVector v[]; int nPlanes; int nVertex; final int size = 60; final int SHIFT = 130; final int zshift = 300; final int BUFWID = 400; final int BUFHIG = 350; double a,b,c,d; double aa,bb,cc,dd; // int maxx,maxy; // int pcb,pct,pcl,pcr; int xpc1,ypc1,xpc2,ypc2; P_Y_TONG py_tong[]; Y_TONG y_tong[]; P_Y_TONG p_aet; EDGE_ELE edge_aet; double buf[]; Color planeColor[]; CVector center; boolean show; // tmp double cosv, sinv; class P_Y_TONG { double a,b,c,d; int deltay; int id; Color color; P_Y_TONG next; } class Y_TONG { double xup; double deltax; int deltay; int id; Y_TONG next; } class EDGE_ELE { double xl, deltaxl; int deltayl; double xr, deltaxr; int deltayr; double zl, deltazx, deltazy; int id; EDGE_ELE next; } Mycube() { int i; nPlanes = 6; nVertex = 4; v = new CVector[8]; for (i=0; i<8; i++) v[i] = new CVector(); init_pos(v); points = new CVector[6][4]; int plane[] = new int[4]; plane[0]=0 ; plane[1]=1; plane[2]=2; plane[3]=3; for (i=0; i<4 ; i++) points[0][i] = v[plane[i]]; plane[0]=4 ; plane[1]=5; plane[2]=6; plane[3]=7; for (i=0; i<4 ; i++) points[1][i] = v[plane[i]]; plane[0]=1 ; plane[1]=2; plane[2]=6; plane[3]=5; for (i=0; i<4 ; i++) points[2][i] = v[plane[i]]; plane[0]=0 ; plane[1]=3; plane[2]=7; plane[3]=4; for (i=0; i<4 ; i++) points[3][i] = v[plane[i]]; plane[0]=2 ; plane[1]=3; plane[2]=7; plane[3]=6; for (i=0; i<4 ; i++) points[4][i] = v[plane[i]]; plane[0]=1 ; plane[1]=0; plane[2]=4; plane[3]=5; for (i=0; i<4 ; i++) points[5][i] = v[plane[i]]; planeColor = new Color[nPlanes]; for (i=0; i<nPlanes; i++) { switch (i) { case 0: case 1: planeColor[i] = new Color(255,0,0); break; case 2: case 3: planeColor[i] = new Color(0, 255, 0); break; case 4: case 5: planeColor[i] = new Color(0, 0, 255); break; } // randomely // planeColor[i] = new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)); } py_tong = new P_Y_TONG[BUFHIG+10]; y_tong = new Y_TONG[BUFHIG+10]; p_aet= new P_Y_TONG(); edge_aet = new EDGE_ELE(); buf = new double[BUFWID]; center = new CVector(); show = true; init3d(); } void init_pos(CVector v[]) { int i; v[0].set(0,0,0); v[1].set(0,size,0); v[2].set(size,size,0); v[3].set(size,0,0); v[4].set(0,0,size); v[5].set(0,size,size); v[6].set(size,size,size); v[7].set(size,0,size); CVector vshift = new CVector(SHIFT,SHIFT,SHIFT); for (i=0; i<8; i++) v[i].add(vshift); CVector vcenter = new CVector(); vcenter.x = (v[0].x + v[6].x)/2; vcenter.y = (v[0].y + v[6].y)/2; vcenter.z = (v[0].z + v[6].z)/2; for (i=0; i<8; i++) { v[i].sub(vcenter); v[i].rotatex(45.0); v[i].rotatey(45.0); v[i].rotatez(45.0); v[i].add(vcenter); } } void init3d() { final double VXL=-200.0,VXR=200.0,WXR=200.0,WXL=-200.0; final double VYT=200.0,VYB=-200.0,WYT=200.0,WYB=-200.0; a=(VXR-VXL)/(WXR-WXL); b=VXL-a*WXL; c=(VYT-VYB)/(WYT-WYB); d=VYB-c*WYB; } /* void set_abcd(int mx, int my) { maxx=mx; maxy=my; pcb=maxy-1; pct=0; pcr=maxx-1; pcl=0; a=(pcr-pcl)/(1+1); b=pcl-a*(-1); c=(pct-pcb)/(1+1); d=pcb-c*(-1); } */ void get_abcd(CVector v1, CVector v2, CVector v3) { CVector t1,t2; t1 = new CVector(v1); t1.sub(v3); t2 = new CVector(v1); t2.sub(v2); aa = t1.y*t2.z - t1.z*t2.y; bb=-t1.x*t2.z + t1.z*t2.x; cc=t1.x*t2.y - t2.x*t1.y; dd=-(aa*v1.x+bb*v1.y+cc*v1.z); } Color GetColor(int id) { P_Y_TONG ptr; for (ptr=p_aet ; ptr != null; ptr=ptr.next) if (ptr.id == id ) return ptr.color; return new Color(0,0,0); } P_Y_TONG GetP_Y_Tong(int id) { P_Y_TONG ptr; for (ptr=p_aet ; ptr!=null; ptr=ptr.next) if (ptr.id == id ) return ptr; return null; } EDGE_ELE GetEdgePair(int col,P_Y_TONG py_ptr1) { Y_TONG y_ptr,yl_ptr,yr_ptr; int flag; EDGE_ELE e_ptr; flag=0; yl_ptr=yr_ptr=null; for (y_ptr=y_tong[col] ; y_ptr != null ; y_ptr=y_ptr.next) { if (y_ptr.id != py_ptr1.id) continue; // parallel line if (y_ptr.deltay == 0) continue; if (flag == 0) { yl_ptr=y_ptr; flag++; } else yr_ptr=y_ptr; } // no proper edge ! if (yl_ptr==null) return null; if (yl_ptr.xup > yr_ptr.xup || (yl_ptr.xup==yr_ptr.xup && yl_ptr.deltax > yr_ptr.deltax)) { y_ptr=yl_ptr; yl_ptr=yr_ptr; yr_ptr=y_ptr; } e_ptr= new EDGE_ELE(); e_ptr.id =py_ptr1.id; e_ptr.xl=yl_ptr.xup; e_ptr.deltaxl=yl_ptr.deltax; e_ptr.deltayl=yl_ptr.deltay; e_ptr.xr=yr_ptr.xup; e_ptr.deltaxr=yr_ptr.deltax; e_ptr.deltayr=yr_ptr.deltay; e_ptr.zl= py_ptr1.c !=0 ?-(py_ptr1.d+ py_ptr1.a*yl_ptr.xup + py_ptr1.b*col)/py_ptr1.c:0; e_ptr.deltazx = py_ptr1.c !=0? -py_ptr1.a/py_ptr1.c:0; e_ptr.deltazy = py_ptr1.c !=0 ? py_ptr1.b/py_ptr1.c:0; return e_ptr; } void z_buffer(Graphics g, int width, int height) { int i,j; int ymax, ymin, yy, maxy, miny, maxx, minx; P_Y_TONG py_ptr, py_head, py_ptr1; Y_TONG y_ptr,y_head,yl_ptr; EDGE_ELE e_ptr,e_tmp; CVector v1, v2, v3; for (i=0; i<BUFHIG; i++) { py_tong[i] = null; y_tong[i] = null; } p_aet = null; edge_aet = null; // create Polygon Y Tong & Y Tong maxy=-65530; miny=65530; maxx=-65530; minx=65530; for (i=0; i<nPlanes; i++) { py_ptr = new P_Y_TONG(); py_ptr.id = i; py_ptr.color = planeColor[i]; v1 = points[i][0]; v2 = points[i][1]; v3 = points[i][2]; get_abcd(v1,v2,v3); py_ptr.a = aa; py_ptr.b = bb; py_ptr.c = cc; py_ptr.d = dd; ymax=-65530; ymin=65530; for (j=1; j<= nVertex; j++) { y_ptr = new Y_TONG(); y_ptr.id=i; v1 = points[i][j-1]; v2 = points[i][j%nVertex]; xpc1=(int)v1.x; ypc1=(int)v1.y; xpc2=(int)v2.x; ypc2=(int)v2.y; double del = 1.0*(xpc2-xpc1)/(ypc2-ypc1); if (ypc1 > BUFHIG) { ypc1 = BUFHIG-1; xpc1 = (int)(xpc2 - del*(ypc2-ypc1)); } if (ypc2 > BUFHIG) { ypc2 = BUFHIG-1; xpc2 = (int)(v1.x + del*(ypc2-v1.y)); } y_ptr.deltay=Math.abs(ypc2 - ypc1); y_ptr.deltax=ypc2==ypc1?0:-del; y_ptr.xup=ypc2 > ypc1 ? xpc2 : xpc1; if (ypc1>ymax) ymax=ypc1; if (ypc1<ymin) ymin=ypc1; if (ypc2>ymax) ymax=ypc2; if (ypc2<ymin) ymin=ypc2; // insert to Y Tong yy=Math.max(ypc1,ypc2); if (yy>=0 && yy<BUFHIG) { y_head=y_tong[yy]; y_ptr.next=y_head; y_tong[yy]=y_ptr; } } py_ptr.deltay=ymax-ymin; if (ymax >= 0 && ymax<BUFHIG) { py_head=py_tong[ymax]; py_ptr.next=py_head; py_tong[ymax]=py_ptr; } if (ymax > maxy) maxy = ymax; if (ymin < miny) miny = ymin; /* if (xpc1 > maxx) maxx = xpc1; if (xpc1 < minx) minx = xpc1; if (xpc2 > maxx) maxx = xpc2; if (xpc2 < minx) minx = xpc2; */ } for (i=BUFHIG-1; i>=0 ; i--) // for (i=maxy; i>=miny ; i--) { for (j=0; j<BUFWID;j++) buf[j]=-65530.0; // new P_Y tong insert if (py_tong[i] != null) { for (py_ptr=py_tong[i] ; py_ptr.next != null ; py_ptr=py_ptr.next); py_ptr.next=p_aet; p_aet=py_tong[i]; // new line pairs for (py_ptr1=p_aet; py_ptr1 != py_ptr.next ; py_ptr1=py_ptr1.next) { e_ptr=GetEdgePair(i,py_ptr1); if (e_ptr == null) continue; e_ptr.next=edge_aet; edge_aet=e_ptr; } } for (e_ptr=edge_aet; e_ptr != null; e_ptr=e_ptr.next) { if (e_ptr.deltayl != 0 && e_ptr.deltayr != 0) continue; if (e_ptr.deltayl == 0 && e_ptr.deltayr == 0) { py_ptr=GetP_Y_Tong(e_ptr.id); if (py_ptr != null) { e_tmp=GetEdgePair(i,py_ptr); if (e_tmp != null) { e_tmp.next=edge_aet; edge_aet=e_tmp; } } continue; } // search new line yl_ptr=null; for (y_ptr=y_tong[i] ; y_ptr != null;y_ptr=y_ptr.next) { if (y_ptr.id != e_ptr.id ) continue; if (y_ptr.deltay == 0) continue; break; } if (y_ptr != null) { double tmpx,tmpdx; int tmpdy; tmpx=e_ptr.deltayl != 0? e_ptr.xl: e_ptr.xr; tmpdx=e_ptr.deltayl != 0? e_ptr.deltaxl: e_ptr.deltaxr; tmpdy=e_ptr.deltayl != 0? e_ptr.deltayl: e_ptr.deltayr; if (tmpx < y_ptr.xup || (tmpx==y_ptr.xup && tmpdx<y_ptr.deltax)) { e_ptr.xl=tmpx; e_ptr.deltaxl=tmpdx; e_ptr.deltayl=tmpdy; e_ptr.xr = y_ptr.xup; e_ptr.deltaxr=y_ptr.deltax; e_ptr.deltayr=y_ptr.deltay; } else { e_ptr.xr=tmpx; e_ptr.deltaxr=tmpdx; e_ptr.deltayr=tmpdy; e_ptr.xl = y_ptr.xup; e_ptr.deltaxl=y_ptr.deltax; e_ptr.deltayl=y_ptr.deltay; } } } // for (e_ptr=edge_aet ; e_ptr != null; e_ptr=e_ptr.next) { int k; double zx; Color acolor; if (e_ptr.deltayl ==0 && e_ptr.deltayr==0 ) continue; if (e_ptr.xl > e_ptr.xr) continue; zx=e_ptr.zl; // tranform xpc1=(int)(a*e_ptr.xl+b+0.5); ypc1=(int)(c*i+d+0.5); xpc2=(int)(a*e_ptr.xr+b+0.5); int s0, s1; s0 = s1= -1; acolor=GetColor(e_ptr.id); g.setColor(acolor); for (k=xpc1 ; k<=xpc2 ; k++) { zx+=e_ptr.deltazx; if (k>=0 && k< BUFWID && zx > buf[k]) { buf[k]=zx; if (s0 == -1) s0 = s1 = k; else { if (k == s1+1) s1++; else { g.drawLine(s0, ypc1, s1, ypc1); s0 = s1 = -1; } } } } if (s0 != -1) g.drawLine(s0, ypc1, s1, ypc1); } // modified Y_AET table for (e_ptr=edge_aet ; e_ptr != null; e_ptr=e_ptr.next) { if (e_ptr.deltayl ==0 && e_ptr.deltayr==0 ) continue; e_ptr.deltayl--; e_ptr.deltayr--; e_ptr.xl+=e_ptr.deltaxl; e_ptr.xr+=e_ptr.deltaxr; e_ptr.zl+=e_ptr.deltazx*e_ptr.deltaxl + e_ptr.deltazy; } // modified P_Y_tong for (py_ptr=p_aet ; py_ptr != null; py_ptr=py_ptr.next) if (py_ptr.deltay != 0) py_ptr.deltay--; } } double dot(CVector v1,CVector v2) { return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z; } void move(Point pt1, Point pt2) { center.x = (points[0][0].x + points[1][2].x)/2; center.y = (points[0][0].y + points[1][2].y)/2; center.z = (points[0][0].z + points[1][2].z)/2; CVector v1=new CVector(pt1.x,pt1.y,zshift); CVector v2=new CVector(pt2.x,pt2.y,zshift); v1.sub(center); v2.sub(center); CVector dist = new CVector(); dist.x = v2.x - v1.x; dist.y = v2.y - v1.y; dist.z = v2.z - v1.z; for (int i=0; i<4; i++) { v1=points[0][i]; v1.sub(center); v1.add(dist); v1.add(center); v2=points[1][i]; v2.sub(center); v2.add(dist); v2.add(center); } } void scale(Point pt1, Point pt2) { double scale; center.x = (points[0][0].x + points[1][2].x)/2; center.y = (points[0][0].y + points[1][2].y)/2; center.z = (points[0][0].z + points[1][2].z)/2; CVector v1=new CVector(pt1.x,pt1.y,zshift); CVector v2=new CVector(pt2.x,pt2.y,zshift); v1.sub(center); v2.sub(center); scale = v2.mag()/v1.mag(); for (int i=0; i<4; i++) { v1=points[0][i]; v1.sub(center); v1.mul(scale); v1.add(center); v2=points[1][i]; v2.sub(center); v2.mul(scale); v2.add(center); } } void cal_cossin(int dim,CVector v1,CVector v2) { double t1,t2,t; cosv=dot(v1.unit(),v2.unit()); t=1.0-cosv*cosv; if (t<1e-5) sinv=0.0; else sinv=Math.sqrt(t); switch (dim) { case 1: t1=Math.atan2(v1.z,v1.y); t2=Math.atan2(v2.z,v2.y); break; case 2: t1=Math.atan2(v1.x,v1.z); t2=Math.atan2(v2.x,v2.z); break; case 3: t1=Math.atan2(v1.y,v1.x); t2=Math.atan2(v2.y,v2.x); break; default: t1 = t2 = 0; } if (t1 * t2 < 0 && Math.max(t1,t2) > 3.14159265/2.0 ) { if (t1<0) t1+=2.0*3.1415; else t2+=2.0*3.1415; } if ( t1 > t2) sinv=-sinv; } void rotate(Point pt1, Point pt2) { double cosx,sinx,cosy,siny,cosz,sinz; center.x = (points[0][0].x + points[1][2].x)/2; center.y = (points[0][0].y + points[1][2].y)/2; center.z = (points[0][0].z + points[1][2].z)/2; CVector v1=new CVector(0,pt1.y,zshift); CVector v2=new CVector(0,pt2.y,zshift); v1.sub(center); v2.sub(center); cal_cossin(1,v1,v2); cosx = cosv; sinx = sinv; v1.x = pt1.x; v1.y = 0; v1.z = zshift; v2.x = pt2.x; v2.y = 0; v2.z = zshift; v1.sub(center); v2.sub(center); cal_cossin(2,v1,v2); cosy = cosv; siny = sinv; v1.x = pt1.x; v1.y = pt1.y; v1.z = 0; v2.x = pt2.x; v2.y = pt2.y; v2.z = 0; v1.sub(center); v2.sub(center); cal_cossin(3,v1,v2); cosz = cosv; sinz = sinv; for (int i=0; i<4; i++) { v1 = points[0][i]; v1.sub(center); v1.rotatex(cosx,sinx); v1.rotatey(cosy,siny); v1.rotatez(cosz,sinz); v1.add(center); v2 = points[1][i]; v2.sub(center); v2.rotatex(cosx,sinx); v2.rotatey(cosy,siny); v2.rotatez(cosz,sinz); v2.add(center); } } void reset() { init_pos(v); } void draw(Graphics g, Graphics backg, Dimension d) { if (!show) { CVector v1,v2; backg.setColor(new Color(0,0,0)); //Set color for background for (int i=0; i< nPlanes; i++) { for (int j=1; j <= nVertex; j++) { v1 = points[i][j-1]; v2 = points[i][j%nVertex]; backg.drawLine((int)v1.x, (int)v1.y, (int)v2.x, (int)v2.y); } } } else z_buffer(backg, d.width, d.height); } void setShow(boolean val) { show = val; } } class CVector { double x,y,z; CVector() { x = 0.0; y = 0.0; z = 0.0; } CVector(double xx, double yy, double zz) { x = xx; y = yy; z = zz; } CVector(CVector a) { x = a.x; y = a.y; z = a.z; } void copy(CVector c) { x = c.x; y = c.y; z = c.z; } void set(double xx, double yy, double zz) { x = xx; y = yy; z = zz; } double mag() { double m; m=Math.sqrt(x*x+y*y+z*z); return m; } void add (CVector v2) { x = x + v2.x; y = y + v2.y; z = z + v2.z; } void sub (CVector v2) { x = x - v2.x; y = y - v2.y; z = z - v2.z; } void mul(double d) { x *= d; y *= d; z *= d; } void div(double d) { x /= d; y /= d; z /= d; } CVector unit() { double m = mag(); CVector n = new CVector(); n.x = x / m; n.y = y / m; n.z = z / m; return n; } void rotatex (double a) { double ty,tz; double b; b=a*3.14159265/180.0; ty=Math.cos(b)*y-Math.sin(b)*z; tz=Math.sin(b)*y+Math.cos(b)*z; y=ty; z=tz; } void rotatex(double cosb,double sinb) { double ty,tz; ty=cosb*y-sinb*z; tz=sinb*y+cosb*z; y=ty; z=tz; } void rotatey(double a) { double tx,tz; double b; b=a*3.14159265/180.0; tx=Math.cos(b)*x+Math.sin(b)*z; tz=-Math.sin(b)*x+Math.cos(b)*z; x=tx; z=tz; } void rotatey(double cosb,double sinb) { double tx,tz; tx=cosb*x+sinb*z; tz=-sinb*x+cosb*z; x=tx; z=tz; } void rotatez (double a) { double tx,ty; double b; b=a*3.14159265/180.0; tx=Math.cos(b)*x-Math.sin(b)*y; ty=Math.sin(b)*x+Math.cos(b)*y; x=tx; y=ty; } void rotatez (double cosb,double sinb) { double tx,ty; tx=cosb*x-sinb*y; ty=sinb*x+cosb*y; x=tx; y=ty; } } class Point { int x,y; Point(Point p) { x = p.x; y = p.y; } Point(int _x, int _y) { x = _x; y = _y; } Point() { x = 0; y = 0; } void copy(Point p) { x = p.x; y = p.y; } }