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 + -
显示快捷键?