graphicslib.java
来自「用applet实现很多应用小程序」· Java 代码 · 共 791 行 · 第 1/3 页
JAVA
791 行
hull[2*i] = pts[stack[i]];
hull[2*i+1] = pts[stack[i]+1];
}
return hull;
}
/**
* Convex hull helper method for detecting a non left turn about 3 points
*/
private static boolean isNonLeft(int i0, int i1, int i2, int i3, double[] pts) {
double l1, l2, l4, l5, l6, angle1, angle2, angle;
l1 = Math.sqrt(Math.pow(pts[i2+1]-pts[i1+1],2) + Math.pow(pts[i2]-pts[i1],2));
l2 = Math.sqrt(Math.pow(pts[i3+1]-pts[i2+1],2) + Math.pow(pts[i3]-pts[i2],2));
l4 = Math.sqrt(Math.pow(pts[i3+1]-pts[i0+1],2) + Math.pow(pts[i3]-pts[i0],2));
l5 = Math.sqrt(Math.pow(pts[i1+1]-pts[i0+1],2) + Math.pow(pts[i1]-pts[i0],2));
l6 = Math.sqrt(Math.pow(pts[i2+1]-pts[i0+1],2) + Math.pow(pts[i2]-pts[i0],2));
angle1 = Math.acos( ( (l2*l2)+(l6*l6)-(l4*l4) ) / (2*l2*l6) );
angle2 = Math.acos( ( (l6*l6)+(l1*l1)-(l5*l5) ) / (2*l6*l1) );
angle = (Math.PI - angle1) - angle2;
if (angle <= 0.0) {
return(true);
} else {
return(false);
}
}
/**
* Computes the mean, or centroid, of a set of points
* @param pts the points array, in x1, y1, x2, y2, ... arrangement.
* @param len the length of the array to consider
* @return the centroid as a length-2 float array
*/
public static float[] centroid(float pts[], int len) {
float[] c = new float[] {0, 0};
for ( int i=0; i < len; i+=2 ) {
c[0] += pts[i];
c[1] += pts[i+1];
}
c[0] /= len/2;
c[1] /= len/2;
return c;
}
/**
* Expand a polygon by adding the given distance along the line from
* the centroid of the polyong.
* @param pts the polygon to expand, a set of points in a float array
* @param len the length of the range of the array to consider
* @param amt the amount by which to expand the polygon, each point
* will be moved this distance along the line from the centroid of the
* polygon to the given point.
*/
public static void growPolygon(float pts[], int len, float amt) {
float[] c = centroid(pts, len);
for ( int i=0; i < len; i+=2 ) {
float vx = pts[i]-c[0];
float vy = pts[i+1]-c[1];
float norm = (float)Math.sqrt(vx*vx+vy*vy);
pts[i] += amt*vx/norm;
pts[i+1] += amt*vy/norm;
}
}
/**
* Compute a cardinal spline, a series of cubic Bezier splines smoothly
* connecting a set of points. Cardinal splines maintain C(1)
* continuity, ensuring the connected spline segments form a differentiable
* curve, ensuring at least a minimum level of smoothness.
* @param pts the points to interpolate with a cardinal spline
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the cardinal spline should be closed (i.e. return
* to the starting point), false for an open curve
* @return the cardinal spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath cardinalSpline(float pts[], float slack, boolean closed) {
GeneralPath path = new GeneralPath();
path.moveTo(pts[0], pts[1]);
return cardinalSpline(path, pts, slack, closed, 0f, 0f);
}
/**
* Compute a cardinal spline, a series of cubic Bezier splines smoothly
* connecting a set of points. Cardinal splines maintain C(1)
* continuity, ensuring the connected spline segments form a differentiable
* curve, ensuring at least a minimum level of smoothness.
* @param pts the points to interpolate with a cardinal spline
* @param start the starting index from which to read points
* @param npoints the number of points to consider
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the cardinal spline should be closed (i.e. return
* to the starting point), false for an open curve
* @return the cardinal spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath cardinalSpline(float pts[], int start, int npoints,
float slack, boolean closed)
{
GeneralPath path = new GeneralPath();
path.moveTo(pts[start], pts[start+1]);
return cardinalSpline(path, pts, start, npoints, slack, closed, 0f, 0f);
}
/**
* Compute a cardinal spline, a series of cubic Bezier splines smoothly
* connecting a set of points. Cardinal splines maintain C(1)
* continuity, ensuring the connected spline segments form a differentiable
* curve, ensuring at least a minimum level of smoothness.
* @param p the GeneralPath instance to use to store the result
* @param pts the points to interpolate with a cardinal spline
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the cardinal spline should be closed (i.e. return
* to the starting point), false for an open curve
* @param tx a value by which to translate the curve along the x-dimension
* @param ty a value by which to translate the curve along the y-dimension
* @return the cardinal spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath cardinalSpline(GeneralPath p,
float pts[], float slack, boolean closed, float tx, float ty)
{
int npoints = 0;
for ( ; npoints<pts.length; ++npoints )
if ( Float.isNaN(pts[npoints]) ) break;
return cardinalSpline(p, pts, 0, npoints/2, slack, closed, tx, ty);
}
/**
* Compute a cardinal spline, a series of cubic Bezier splines smoothly
* connecting a set of points. Cardinal splines maintain C(1)
* continuity, ensuring the connected spline segments form a differentiable
* curve, ensuring at least a minimum level of smoothness.
* @param p the GeneralPath instance to use to store the result
* @param pts the points to interpolate with a cardinal spline
* @param start the starting index from which to read points
* @param npoints the number of points to consider
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the cardinal spline should be closed (i.e. return
* to the starting point), false for an open curve
* @param tx a value by which to translate the curve along the x-dimension
* @param ty a value by which to translate the curve along the y-dimension
* @return the cardinal spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath cardinalSpline(GeneralPath p,
float pts[], int start, int npoints,
float slack, boolean closed, float tx, float ty)
{
// compute the size of the path
int len = 2*npoints;
int end = start+len;
if ( len < 6 ) {
throw new IllegalArgumentException(
"To create spline requires at least 3 points");
}
float dx1, dy1, dx2, dy2;
// compute first control point
if ( closed ) {
dx2 = pts[start+2]-pts[end-2];
dy2 = pts[start+3]-pts[end-1];
} else {
dx2 = pts[start+4]-pts[start];
dy2 = pts[start+5]-pts[start+1];
}
// repeatedly compute next control point and append curve
int i;
for ( i=start+2; i<end-2; i+=2 ) {
dx1 = dx2; dy1 = dy2;
dx2 = pts[i+2]-pts[i-2];
dy2 = pts[i+3]-pts[i-1];
p.curveTo(tx+pts[i-2]+slack*dx1, ty+pts[i-1]+slack*dy1,
tx+pts[i] -slack*dx2, ty+pts[i+1]-slack*dy2,
tx+pts[i], ty+pts[i+1]);
}
// compute last control point
if ( closed ) {
dx1 = dx2; dy1 = dy2;
dx2 = pts[start]-pts[i-2];
dy2 = pts[start+1]-pts[i-1];
p.curveTo(tx+pts[i-2]+slack*dx1, ty+pts[i-1]+slack*dy1,
tx+pts[i] -slack*dx2, ty+pts[i+1]-slack*dy2,
tx+pts[i], ty+pts[i+1]);
dx1 = dx2; dy1 = dy2;
dx2 = pts[start+2]-pts[end-2];
dy2 = pts[start+3]-pts[end-1];
p.curveTo(tx+pts[end-2]+slack*dx1, ty+pts[end-1]+slack*dy1,
tx+pts[0] -slack*dx2, ty+pts[1] -slack*dy2,
tx+pts[0], ty+pts[1]);
p.closePath();
} else {
p.curveTo(tx+pts[i-2]+slack*dx2, ty+pts[i-1]+slack*dy2,
tx+pts[i] -slack*dx2, ty+pts[i+1]-slack*dy2,
tx+pts[i], ty+pts[i+1]);
}
return p;
}
/**
* Computes a set of curves using the cardinal spline approach, but
* using straight lines for completely horizontal or vertical segments.
* @param p the GeneralPath instance to use to store the result
* @param pts the points to interpolate with the spline
* @param epsilon threshold value under which to treat the difference
* between two values to be zero. Used to determine which segments to
* treat as lines rather than curves.
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the spline should be closed (i.e. return
* to the starting point), false for an open curve
* @param tx a value by which to translate the curve along the x-dimension
* @param ty a value by which to translate the curve along the y-dimension
* @return the stack spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath stackSpline(GeneralPath p, float[] pts,
float epsilon, float slack, boolean closed, float tx, float ty)
{
int npoints = 0;
for ( ; npoints<pts.length; ++npoints )
if ( Float.isNaN(pts[npoints]) ) break;
return stackSpline(p,pts,0,npoints/2,epsilon,slack,closed,tx,ty);
}
/**
* Computes a set of curves using the cardinal spline approach, but
* using straight lines for completely horizontal or vertical segments.
* @param p the GeneralPath instance to use to store the result
* @param pts the points to interpolate with the spline
* @param start the starting index from which to read points
* @param npoints the number of points to consider
* @param epsilon threshold value under which to treat the difference
* between two values to be zero. Used to determine which segments to
* treat as lines rather than curves.
* @param slack a parameter controlling the "tightness" of the spline to
* the control points, 0.10 is a typically suitable value
* @param closed true if the spline should be closed (i.e. return
* to the starting point), false for an open curve
* @param tx a value by which to translate the curve along the x-dimension
* @param ty a value by which to translate the curve along the y-dimension
* @return the stack spline as a Java2D {@link java.awt.geom.GeneralPath}
* instance.
*/
public static GeneralPath stackSpline(GeneralPath p,
float pts[], int start, int npoints, float epsilon,
float slack, boolean closed, float tx, float ty)
{
// compute the size of the path
int len = 2*npoints;
int end = start+len;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?