001package squidpony.squidgrid;
002
003/**
004 * A way of measuring what cells are adjacent and how much further any adjacent cells are from other adjacent cells.
005 * In practice, this is used for pathfinding first and foremost, with some other code using this to fill nearby cells in
006 * some way. You will usually want to use either {@link #MANHATTAN} through an entire codebase when only moves in
007 * cardinal directions are allowed, {@link #EUCLIDEAN} when you want some things to look circular instead of always
008 * diamond-shaped as with MANHATTAN (this allows diagonal movement for pathfinders only if it is the best option), or
009 * maybe {@link #CHEBYSHEV} if you consider using EUCLIDEAN for pathfinding (CHEBYSHEV allows cardinal and diagonal
010 * movement with equal cost, but this permits pathfinders to make very strange choices).
011 */
012public enum Measurement {
013
014        /**
015         * The distance it takes when only the four primary directions can be
016         * moved in. The default.
017         */
018        MANHATTAN,
019        /**
020         * The distance it takes when diagonal movement costs the same as
021         * cardinal movement.
022         */
023        CHEBYSHEV,
024        /**
025         * The distance it takes as the crow flies. This will NOT affect movement cost when calculating a path,
026         * only the preferred squares to travel to (resulting in drastically more reasonable-looking paths).
027         */
028        EUCLIDEAN;
029
030        public double heuristic(Direction target) {
031                if (this == Measurement.EUCLIDEAN) {
032                        if (target == Direction.DOWN_LEFT || target == Direction.DOWN_RIGHT || target == Direction.UP_LEFT || target == Direction.UP_RIGHT) {
033                                return 1.4142135623730951; //Math.sqrt(2.0);
034                        }
035                }
036                return 1.0;
037        }
038
039        public int directionCount() {
040                return this == Measurement.MANHATTAN ? 4 : 8;
041        }
042        /**
043         * Gets the appropriate Measurement that matches a Radius enum.
044         * Matches SQUARE or CUBE to CHEBYSHEV, DIAMOND or OCTAHEDRON to MANHATTAN, and CIRCLE or SPHERE to EUCLIDEAN.
045         *
046         * @param radius the Radius to find the corresponding Measurement for
047         * @return a Measurement that matches radius; SQUARE to CHEBYSHEV, DIAMOND to MANHATTAN, etc.
048         */
049        public static Measurement matchingMeasurement(Radius radius) {
050                switch (radius)
051                {
052                        case CUBE:
053                        case SQUARE:
054                                return Measurement.CHEBYSHEV;
055                        case DIAMOND:
056                        case OCTAHEDRON:
057                                return Measurement.MANHATTAN;
058                        default:
059                                return Measurement.EUCLIDEAN;
060                }
061        }
062
063        /**
064         * Gets the appropriate Radius corresponding to a Measurement.
065         * Matches CHEBYSHEV to SQUARE, MANHATTAN to DIAMOND, and EUCLIDEAN to CIRCLE.
066         * @return a Radius enum that matches this Measurement; CHEBYSHEV to SQUARE, MANHATTAN to DIAMOND, etc.
067         */
068        public Radius matchingRadius() {
069                switch (this) {
070                        case CHEBYSHEV:
071                                return Radius.SQUARE;
072                        case EUCLIDEAN:
073                                return Radius.CIRCLE;
074                        default:
075                                return Radius.DIAMOND;
076                }
077        }
078}