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

📄 shapeutils.java

📁 利用BlueJ开发的一个类似小时候完的吃豆豆的小游戏
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package cs101.awt.geom;/* * ShapeUtils.java * * Created on March 2, 2003, 2:30 PM */import java.awt.Shape;import java.awt.Point;import java.awt.Rectangle;import java.awt.geom.Point2D;import java.awt.geom.Line2D;import java.awt.geom.GeneralPath;import java.awt.geom.PathIterator;import java.awt.geom.AffineTransform;import java.awt.geom.IllegalPathStateException;import java.awt.geom.NoninvertibleTransformException;import java.util.ArrayList;import java.util.List;/** * This utility class holds routines for doing conversions on classes that * implement the <code>Shape</code> interface. Generally the first step is * in each routine is to convert the shape to a <code>GeneralPath</code>, and * return values of type <code>Shape</code> will in fact be instances of * the <code>GeneralPath</code> class unless specified otherwise. * * <a id="knotpts"></a> * <p>Java's <code>GeneralPath</code> class is a series of concatenated line * segments, second order (quadratic) Bezier curves and third order (cubic) * Bezier curves. Bezier Curves consist of two types of points: <b>knot * points</b> which are points that lie on the curve, and <b>control points</b> * which do not lie on the curve but denote vectors that influence the shape * of the curve between knot points. * * <p>None of the routines in this class attempt to convert between lines, * quadratics, and cubics. A shape consisting entirely of lines, will remain * entirely line based, and a purely cubic shape will also remain cubic. Mixed * shapes will remain mixed, but the ratios of the number of segements of any * two types is almost certain to change. * * @author  Patrick G. Heck, Gus.heck@olin.edu * @version $Id: ShapeUtils.java,v 1.18 2003/09/23 15:23:40 gus Exp $ */public final class ShapeUtils {        /** Creates a new instance of ShapeUtils */    private ShapeUtils() {    }        /**     * Compute a velocity vector after a bounce off a given surface. The bounce     * is computed by rotating the system until the line is vertical,     * inverting the x component to calculate the bounce, and then performing     * the inverse transform to get the desired.     *     * @param surface The line representing the angle of the surface to bounce     *                off of.     * @param velVect A line with starting point 0,0 representing the velocity     *                vector to be bounced.     * @return  A line starting at 0,0 representing the new velocity vector.     */    public static Line2D.Float bounce(Line2D.Float surface, Line2D.Float velVect) {        AffineTransform rotateVert, rotateBack;        double lineSlant = angleToVert(surface);        rotateVert = AffineTransform.getRotateInstance(lineSlant);                try {            rotateBack = rotateVert.createInverse();        } catch (NoninvertibleTransformException nte) {            System.out.println("NoninvertableTransformException! bounce not calculated.");            throw new Error("Rotations shoud be invertable!");        }                // this should rotate the line around 0,0 which is the x1,y1 point        Shape s = rotateVert.createTransformedShape(velVect);        PointIterator iter = new PointIterator(s);        velVect = new Line2D.Float(iter.nextPoint(),iter.nextPoint());                // bouncing off a vertical line is just a matter of inverting the        // x component        velVect.setLine(0,0,-velVect.getX2(),velVect.getY2());                s = rotateBack.createTransformedShape(velVect);        iter = new PointIterator(s);        velVect = new Line2D.Float(iter.nextPoint(),iter.nextPoint());                return velVect;    }            /**     * Find the resultant velocity from the collision of a mobile and imobile     * shape. The two shapes must have already collided and be in a state of     * overlap, and must be shapes consisting of more than one point.     *     * @param s1 The moving shape (tiny mass)     * @param s2 The imobile shape (infinite mass)     * @param v1X The x component of the velocity of s1     * @param v1Y The y component of the velocity of s1     * @return a line starting at the origin and representing the new velocity     *         vector     */    public static Line2D.Float doReflect(Shape s1, Shape s2, double v1X, double v1Y) {        if (!isOverlapping(s1,s2)) {            //System.exit(1);            throw new ShapesDontOverlapException("Cannot reflect shapes until"+            "they hit each other");        }        Line2D.Float nearSeg = null;                Line2D.Float velVect = new Line2D.Float(0,0,        new Double(v1X).floatValue(),        new Double(v1Y).floatValue());        Point2D.Float insidePt;        try {            insidePt = meanContainedPoint(s2,s1); // points conatained by stationary object        } catch (NotEnoughPointsException nepe) {            try {            insidePt = meanContainedPoint(s1,s2);             } catch (NotEnoughPointsException nepe2) {                throw new Error("overlapping but neither conatins the other point!");            }        }        try {            nearSeg = nearestSegment(s2,insidePt);        } catch (NotEnoughPointsException nepe) {            System.out.println("Ignoring malformed shape:" + nepe.getMessage());            return velVect; // pretend malformed shapes arn't there        } catch (NoUniqueLineException nule) {            Point2D.Float nearest = getNearestPoint(s1,insidePt);            nearSeg = getLineFromNeighbors(s1,nearest);        }                return bounce(nearSeg, velVect);            }            /**     * Find the resultant velocity from the collision of a mobile and imobile     * shape. The two shapes must have already collided and be in a state of     * overlap, and must be shapes consisting of more than one point.     *     * @param s1 The moving shape (tiny mass)     * @param s2 The imobile shape (infinite mass)     * @param velVect1 The velocity vector of s1, (x1,y1 point at 0.0 x2,y2     *                 representing the x and y components of the velocity)     * @return a line starting at the origin and representing the new velocity     *         vector     */    public static Line2D.Float doReflect(Shape s1, Shape s2, Line2D.Float velVect1) {        return doReflect(s1,s2,velVect1.getX2(),velVect1.getY2());    }        /**     * Find the new x velocity after reflecting a moving shape from a imobile     * shape.     *     * @param s1 The moving shape (tiny mass)     * @param s2 The imobile shape (infinite mass)     * @param v1X The x component of the velocity of s1     * @param v1Y The y component of the velocity of s1     */    public static double doXReflect(Shape s1, Shape s2, double v1X, double v1Y) {                return doReflect(s1,s2,v1X,v1Y).getX2();            }        /**     * Find the new x velocity after reflecting a moving shape from a imobile     * shape.     *     * @param s1 The moving shape (tiny mass)     * @param s2 The imobile shape (infinite mass)     * @param v1X The x component of the velocity of s1     * @param v1Y The y component of the velocity of s1     */    public static double doYReflect(Shape s1, Shape s2, double v1X, double v1Y) {                return doReflect(s1,s2,v1X,v1Y).getY2();            }        /**     * Find the angle between a given line segment and the vertical axis in     * direction that roataes the positive x axis towards positive y axis     *     * @param aLine  A line to find the angle of     * @return The angle in radians.     */    public static double angleToVert(Line2D.Float aLine) {                Point2D.Float start = new Point2D.Float();        Point2D.Float end  = new Point2D.Float();        Point2D.Float near, far;                start.setLocation(aLine.getX1(),aLine.getY1());        end.setLocation(aLine.getX2(),aLine.getY2());                double rise = start.y - end.y;        double run = start.x - end.x;                double tanTheta = rise/run;                    return Math.PI/2 - Math.atan(tanTheta);            }        /**     * Find the line between points on either side of a knot point on a given     * shape. If the shape is unclosed, and the point queried is the start     * or end of the shape then the line between the querried point and the     * nearest point will be returned. The shape must have more than one point.     *     * @param s The shape to find points from, comprised of than one point.     * @param pt The point that is a knot of s for which we want a neighbors     *           line.     */        public static Line2D.Float getLineFromNeighbors(Shape s, Point2D.Float pt) {        PointIterator iter = new PointIterator(s);        Point2D.Float preceding = null;        Point2D.Float following = null;        Point2D.Float prevPt = null;        Point2D.Float currPt = iter.nextPoint();        Point2D.Float startPt = currPt;                while (iter.hasNext() && iter.isStart(startPt)) {            if (startPt.equals(pt)) {                if (iter.hasNext()) {                    following = iter.nextPoint();                    currPt = following;                } else {                    throw new IllegalArgumentException("Shape has only one Point!");                }                while (iter.hasNext() && iter.isStart(startPt) && (currPt != startPt)) {                    prevPt = currPt;                    currPt = iter.nextPoint();                }                if (currPt == startPt) {       // closed shape                    return new Line2D.Float(prevPt,following);                }                                // open or discontinuous shape                return new Line2D.Float(startPt,following);                            }            prevPt = currPt;            currPt = iter.nextPoint();                        if (currPt.equals(pt)) {                preceding = prevPt;                if(iter.hasNext()) {                    currPt = iter.nextPoint();                }                return new Line2D.Float(preceding,currPt);            }                    }                throw new IllegalArgumentException("Point was not a knot of the supplied Shape");            }        /**     * Find the knot point in the given shape that is closest to the specified     * point. In the case of equidistant points, the qualifying point closest     * to the start of the shape will be returned. The shape passed to this     * method must have at least one point.     *     * @param s The shape to find a point from     * @param pt The point to which the points of the shape are compared.     * @return A point on the shape that is as close or closer than any other     *         point on the shape to pt     */        public static Point2D.Float getNearestPoint(Shape s, Point2D.Float pt) {

⌨️ 快捷键说明

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