⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spiral.java

📁 java 的164个例子的源代码,包括了 很多方面,供包括了19个方面的 源代码
💻 JAVA
字号:
/* * Copyright (c) 2000 David Flanagan.  All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.com/javaexamples2. */package com.davidflanagan.examples.graphics;import java.awt.*;import java.awt.geom.*;/** This Shape implementation represents a spiral curve */public class Spiral implements Shape {    double centerX, centerY;            // The center of the spiral    double startRadius, startAngle;     // The spiral starting point    double endRadius, endAngle;         // The spiral ending point    double outerRadius;                 // the bigger of the two radii    int angleDirection;                 // 1 if angle increases, -1 otherwise    /**     * The constructor.  It takes arguments for the center of the shape, the     * start point, and the end point.  The start and end points are specified     * in terms of angle and radius.  The spiral curve is formed by varying     * the angle and radius smoothly between the two end points.     **/    public Spiral(double centerX, double centerY,		  double startRadius, double startAngle,		  double endRadius, double endAngle)    {	// Save the parameters that describe the spiral	this.centerX = centerX; 	this.centerY = centerY;	this.startRadius = startRadius;	this.startAngle = startAngle;	this.endRadius = endRadius;	this.endAngle = endAngle;	// figure out the maximum radius, and the spiral direction	this.outerRadius = Math.max(startRadius, endRadius);	if (startAngle < endAngle) angleDirection = 1;	else angleDirection = -1;		if ((startRadius < 0) || (endRadius < 0))	    throw new IllegalArgumentException("Spiral radii must be >= 0");    }    /**      * The bounding box of a Spiral is the same as the bounding box of a     * circle with the same center and the maximum radius     **/    public Rectangle getBounds() {	return new Rectangle((int)(centerX-outerRadius),			     (int)(centerY-outerRadius),			     (int)(outerRadius*2), (int)(outerRadius*2));    }    /** Same as getBounds(), but with floating-point coordinates */    public Rectangle2D getBounds2D() {	return new Rectangle2D.Double(centerX-outerRadius, centerY-outerRadius,				      outerRadius*2, outerRadius*2);    }    /**      * A spiral is an open curve, not a not a closed area; it does not have an     * inside and an outsize, so the contains() methods always return false.     **/    public boolean contains(double x, double y) { return false; }    public boolean contains(Point2D p) { return false; }    public boolean contains(Rectangle2D r) { return false; }    public boolean contains(double x, double y, double w, double h) {	return false;    }    /**     * This method is allowed to approximate if it would be too computationally     * intensive to determine an exact answer.  Therefore, we check whether     * the rectangle intersects a circle of the outer radius.  This is a good     * guess for a tight spiral, but less good for a "loose" spiral.      **/    public boolean intersects(double x, double y, double w, double h) {	Shape approx = new Ellipse2D.Double(centerX-outerRadius,					    centerY-outerRadius,					    outerRadius*2, outerRadius*2);	return approx.intersects(x, y, w, h);    }    /** This version of intersects() just calls the one above */    public boolean intersects(Rectangle2D r) {	return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());    }    /**     * This method is the heart of all Shape implementations.  It returns a     * PathIterator that describes the shape in terms of the line and curve     * segments that comprise it.  Our iterator implementation approximates     * the shape of the spiral using line segments only.  We pass in a     * "flatness" argument that tells it how good the approximation must be.     * (smaller numbers mean a better approximation).     */    public PathIterator getPathIterator(AffineTransform at) {	return new SpiralIterator(at, outerRadius/500.0);    }    /**     * Return a PathIterator that describes the shape in terms of line     * segments only, with an approximation quality specified by flatness.     **/    public PathIterator getPathIterator(AffineTransform at, double flatness) {	return new SpiralIterator(at, flatness);    }    /**     * This inner class is the PathIterator for our Spiral shape.  For     * simplicity, it does not describe the spiral path in terms of Bezier     * curve segments, but simply approximates it with line segments.  The     * flatness property specifies how far the approximation is allowed to     * deviate from the true curve.     **/    class SpiralIterator implements PathIterator {	AffineTransform transform;    // How to transform generated coordinates	double flatness;              // How close an approximation	double angle = startAngle;    // Current angle	double radius = startRadius;  // Current radius	boolean done = false;         // Are we done yet?	/** A simple constructor.  Just store the parameters into fields */	public SpiralIterator(AffineTransform transform, double flatness) {	    this.transform = transform;	    this.flatness = flatness;	}	/** 	 * All PathIterators have a "winding rule" that helps to specify what	 * is the inside of a area and what is the outside.  If you fill a	 * spiral (which you're not supposed to do) the winding rule returned	 * here yields better results than the alternative, WIND_EVEN_ODD	 **/	public int getWindingRule() { return WIND_NON_ZERO; }	/** Returns true if the entire path has been iterated */	public boolean isDone() { return done; }	/**	 * Store the coordinates of the current segment of the path into the	 * specified array, and return the type of the segment.  Use	 * trigonometry to compute the coordinates based on the current angle	 * and radius.  If this was the first point, return a MOVETO segment,	 * otherwise return a LINETO segment. Also, check to see if we're done.	 **/	public int currentSegment(float[] coords) {	    // given the radius and the angle, compute the point coords	    coords[0] = (float)(centerX + radius*Math.cos(angle));	    coords[1] = (float)(centerY - radius*Math.sin(angle));	    // If a transform was specified, use it on the coordinates	    if (transform != null) transform.transform(coords, 0, coords, 0,1);	    // If we've reached the end of the spiral remember that fact	    if (angle == endAngle) done = true;	    // If this is the first point in the spiral then move to it	    if (angle == startAngle) return SEG_MOVETO;	    // Otherwise draw a line from the previous point to this one	    return SEG_LINETO;	}	/** This method is the same as above, except using double values */	public int currentSegment(double[] coords) {	    coords[0] = centerX + radius*Math.cos(angle);	    coords[1] = centerY - radius*Math.sin(angle);	    if (transform != null) transform.transform(coords, 0, coords, 0,1);	    if (angle == endAngle) done = true;	    if (angle == startAngle) return SEG_MOVETO;	    else return SEG_LINETO;	}	/** 	 * Move on to the next segment of the path.  Compute the angle and	 * radius values for the next point in the spiral.	 **/	public void next() {	    if (done) return;	    // First, figure out how much to increment the angle.  This	    // depends on the required flatness, and also upon the current	    // radius.  When drawing a circle (which we'll use as our	    // approximation) of radius r, we can maintain a flatness f by	    // using angular increments given by this formula:	    //      a = acos(2*(f/r)*(f/r) - 4*(f/r) + 1)	    // Use this formula to figure out how much we can increment the	    // angle for the next segment.  Note that the formula does not	    // work well for very small radii, so we special case those.	    double x = flatness/radius;	    if (Double.isNaN(x) || (x > .1))		angle += Math.PI/4*angleDirection; 	    else {		double y = 2*x*x - 4*x + 1;		angle += Math.acos(y)*angleDirection;	    }			    // Check whether we've gone past the end of the spiral	    if ((angle-endAngle)*angleDirection > 0) angle = endAngle;	    // Now that we know the new angle, we can use interpolation to	    // figure out what the corresponding radius is.	    double fractionComplete = (angle-startAngle)/(endAngle-startAngle);	    radius = startRadius + (endRadius-startRadius)*fractionComplete;	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -