This code is used in Exercise 5d to support Flakes, while Exercise 5e.uses a version with integer arithmetic but the same functionality.
>
/*
* @rPoint60 2.0 001210
*
* © A-Square, Inc. 1996-2000
* 1648 Waters Edge Lane, Reston Virginia, 20190, USA
*/
import java.awt.*;
import java.lang.Math;
/**
* rPoint60 stands for relative origin. An rPoint60 serves as the center of a
* flake in the Flakes universe but serves also as the origin of any branch.
*
* The rPoint60 class encapsulates the geometry of flakes, that is, branches
* of 60 or 30 degrees. The branches are 1, 3 or 5 pixels wide. Each
* rPoint60 is associated with a direction 0, 1, 2, . . . 11 corresponding to
* 0, 30, 60, . . . 330 degrees.
*
* @Author Jan Aminoff 1996-2000.
*
* Version 2.0 is exactly the same functionally as Version 1.0 released with
* RDK 1.0 beta. This version is cleaned up for documentation purposes. It is
* part of the Introduction to Java Tutorial, Exercise 5d.
*
*/
final class rPoint60 {
// Static variables having to do with geometry
private static double d30=Math.PI/6.0;
private static double d60=Math.PI/3.0;
private static double d90=Math.PI/2.0;
private static double d120=d60*2;
private static double d150=d30*5;
private static double d180=Math.PI;
private static double sin30=.5;
private static double cos30=Math.sqrt(3)/2.0;
private static double sin[]={0,sin30,cos30,1,cos30,sin30,
0,-sin30,-cos30,-1,-cos30,-sin30};
private static double cos[]={1,cos30,sin30,0,-sin30,-cos30,
-1,-cos30,-sin30,0,sin30,cos30};
private static double dir2rad[]={0, d30, d60, d90, d120, d150,
d180, d30, d60, d90, d120, d150, 0};
// Static variables used for color and for blueshading
private static int satValue[]={0,10,20,35,55,75,90};
private static Color Blues[]= new Color[7];
// Instance variables
// Coordinates relative to Origin at x0,y0
public int x,y;
// Direction of a line is indicated as 0, 1, 2 , . . 11 corresponding to
// 0, 30, 60, . . 330 or in 30 degree increments counting counterclockvise.
public int dir;
// Origin
private Point P0;
// Origin of reference coordinate system in absolute coordinates
private int x0,y0;
// Signal Origin has been set
private boolean originSet=false;
/**
* Constructor 1, Sets the origin, must be first constructor called
*
* @Param Point P The point of origin in absolute coordinates
*/
public rPoint60(Point P){
if (!originSet){
for(int i=0; i<7;i++)
// Construct shades of blue for shadowing
Blues[i]=Color.getHSBColor((float)240/360,
(float)satValue[i]/100, (float)100/100);
P0=P;
x0=P.x;
y0=P.y;
dir=1;
originSet=true;
}else{
System.out.println
("Attempt to set Origin in rPoint60 more than once");
}
} // end rPoint60 constructor 1
/**
* Constructor 2, Creates a new rPoint60 given its direction
* and coordinates relative to the origin Po.
*
* @param Dir direction from origin to
* this point
* @param X,Y coordinates relative to Po
* @param Point Po the origin
*/
public rPoint60(int Dir, int X, int Y, Point Po){
this(Po);
if (originSet){
x=X;
y=Y;
dir=Dir;
}else{
System.out.println
("Attempt to invoke rPoint60 without having set origin");
}
} // end rPoint60 constructor 2
/**
* Constructor 3 Creates a new rPoint60 at a point PA
* given its direction relative to the origin Po.
*
* @param Dir direction from origin to
* this point
* @param Point PA point relative to Po
* @param Point Po the origin
*/
public rPoint60(int Dir, Point PA, Point Po){
this(Po);
if (originSet){
x=PA.x-x0;
y=PA.y-y0;
dir=Dir;
}else{
System.out.println
("Attempt to invoke rPoint60 without having set origin");
}
} // end rPoint60 constructor 3
/**
* Draws a shadowed line of length r and width w from a point p
* in the direction dir.
*
* @param rPoint60 p origin of the line
* @param dir direction (as an integer 0, 1, 2, . . 11.)
* @param r length of the line
* @param Graphics g graphics context
* @param w width of the line
*
* @return rPoint60 a new rPoint60 at the end of the line
*
*/
public static rPoint60 extendBranch60
(rPoint60 p,int dir, int r, Graphics g, int w){
int x1=p.x+p.x0;
int y1=p.y+p.y0;
int di=(dir<0)?dir+12:dir;
int xr=p.x+(int)(r*cos[di]);
int yr=p.y+(int)(r*sin[di]);
int x2=xr+p.x0;
int y2=yr+p.y0;
drawShadowedLine60(x1,y1,x2,y2,di,g,w);
rPoint60 P= new rPoint60(di,xr,yr,p.P0);
return P;
} // end extendBranch60
/**
* draws a line between two rPoint60 points P1 and P2 five times, each time
* rotated 60 degrees relative to the origin.
*
* @param rPoint60 P1 one endpoint of the line
* @param rPoint60 P2 the other endpoint od the line
* @param Graphics g the graphics context
* @param w the width of the line
*/
public static void rotateLine60(rPoint60 P1, rPoint60 P2, Graphics g, int w){
rPoint60 pa,pb;
//rotates the line from P1 to P2 around origo 5 times in 60 degree increments
for (int i=1;i<6;i++){
pa= rotate60(P1,2*i);
pb= rotate60(P2,2*i);
drawLine60(pa,pb,g,w);
}
} // end rotateLine60
/**
* Draws a line between two rPoints
*
* @param rPoint60 P1 origin of line
* @param rPoint60 P2 termination of line
* @param Graphics g the graphics context
* @param w width of the line (1, 3 or 5 pixels)
*/
private static void drawLine60
(rPoint60 P1, rPoint60 P2, Graphics g, int w){
//Prepares for invocation of drawShadowedLine
int x1=P1.x+P1.x0;
int y1=P1.y+P1.y0;
int x2=P2.x+P2.x0;
int y2=P2.y+P2.y0;
int dir=0;
// Find the direction of the line
float delta=(float).05;
float r=(float)Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
if (r<.5) return;
float co=(x2-x1)/r;
float si=(y2-y1)/r;
for (int i=0; i<12; i++){
if ((Math.abs(co-cos[i])<delta)&&(Math.abs(si-sin[i])<delta)){
dir=i;
//System.out.println("cos: "+co+" sin: "+ si+" dir: "+i);
break;
}
}
drawShadowedLine60(x1,y1,x2,y2,dir,g, w);
} // end drawLine60
/**
* Draws a line between two points with coordinates x1, y1 and x2, y2,
* in the direction dir and width w shadowed in shades of blue.
* Used by drawLine60 and extendBranch60
* @param x1, y1 coordinates of starting point
* @param x2, y2 coordinates of end point
* @param dir direction of line
* @param Graphics g graphics context
* @param w width (1, 3 or 5) of line
*/
private static void drawShadowedLine60
(int x1,int y1,int x2,int y2, int dir, Graphics g,int w){
int dx,dy;
g.setColor(Blues[1]);
g.drawLine(x1,y1,x2,y2);
if (w>1){
switch ((dir<6)?dir:dir-6){
case 0: // 0 degrees
dy=(w<5)?1:2;
g.setColor(Blues[1]);
g.drawLine(x1,y1-dy,x2,y2-dy);
g.setColor(Blues[3]);
g.drawLine(x1,y1+dy,x2,y2+dy);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1,y1-1,x2,y2-1);
g.drawLine(x1,y1+1,x2,y2+1);
break;
case 1: //30 degrees
dy=(w<5)?1:2;
g.setColor(Blues[0]);
g.drawLine(x1-1,y1-dy,x2-1,y2-dy);
g.setColor(Blues[4]);
g.drawLine(x1+1,y1+dy,x2+1,y2+dy);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1,y1-1,x2,y2-1);
g.drawLine(x1,y1+1,x2,y2+1);
break;
case 2: //60 degrees
dx=(w<5)?1:2;
g.setColor(Blues[6]);
g.drawLine(x1-dx,y1-1,x2-dx,y2+1);
g.setColor(Blues[0]);
g.drawLine(x1+dx,y1+1,x2+dx,y2+1);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1-1,y1,x2-1,y2);
g.drawLine(x1+1,y1,x2+1,y2);
break;
case 3: //90 degrees
dx=(w<5)?1:2;
g.setColor(Blues[4]);
g.drawLine(x1-dx,y1,x2-dx,y2);
g.setColor(Blues[0]);
g.drawLine(x1+dx,y1,x2+dx,y2);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1-1,y1,x2-1,y2);
g.drawLine(x1+1,y1,x2+1,y2);
break;
case 4: // 120 degrees
dx=(w<5)?1:2;
g.setColor(Blues[3]);
g.drawLine(x1-dx,y1-1,x2-dx,y2-1);
g.setColor(Blues[0]);
g.drawLine(x1+dx,y1+1,x2+dx,y2+1);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1-1,y1,x2-1,y2);
g.drawLine(x1+1,y1,x2+1,y2);
break;
case 5: // 150 degrees
dy=(w<5)?1:2;
g.setColor(Blues[1]);
g.drawLine(x1-1,y1-dy,x2-1,y2-dy);
g.setColor(Blues[1]);
g.drawLine(x1+1,y1+dy,x2+1,y2+dy);
if (w<5) break;
g.setColor(Blues[1]);
g.drawLine(x1,y1+1,x2,y2+1);
g.drawLine(x1,y1-1,x2,y2-1);
break;
} // end switch
}
} // end drawShadowedLine60
/**
* Reflects the point P1 in a line through the origin at P0 in direction
* dir and returns the virtual point of reflexion.
*
* @param rPoint60 P1 the point to be reflected
* @param dir the direction ( 0, 1, 2 ... 11) of the line in
* which P1 is reflected
* @return rPoint60 the virtual reflection of P1
*/
private static rPoint60 reflect60(rPoint60 P1, int dir){
//
int di=(2*P1.dir-dir+12)%12;
int twodir=(2*dir)%12;
int xr=(int)(cos[twodir]*P1.x+sin[twodir]*P1.y);
int yr=(int)(sin[twodir]*P1.x-cos[twodir]*P1.y);
rPoint60 P2= new rPoint60(di,xr,yr,P1.P0);
return P2;
}
/**
* rotates the point P1 an angle dir*pi/12 radians, that is dir*30
* degrees, and returns a new rPoint60 as rotated
*
* @param rPoint60 P1 the rPoint60 to be rotated
* @param dir the multiple of 30 degree angles P1 will be rotated
*
* @return rPoint60 a new rPoint60 rotated dir*30 degrees relative to P1
*/
private static rPoint60 rotate60(rPoint60 P1, int dir){
//
int di=(P1.dir+dir)%12;
int xr=(int)(cos[dir]*P1.x-sin[dir]*P1.y);
int yr=(int)(sin[dir]*P1.x+cos[dir]*P1.y);
rPoint60 P2= new rPoint60(di, xr,yr,P1.P0);
return P2;
} // end rotate60
} // end of class rPoint60
>