1 /*** 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that the following conditions are 4 * met : 5 * 6 * . Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * 9 * . Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * . The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: AbstractHexagonBuilder.java,v 1.1 2005/09/09 18:24:28 mat007 Exp $ 29 */ 30 31 package jtge.util.grid.builder; 32 33 import java.awt.Point; 34 import java.awt.Polygon; 35 import java.util.Iterator; 36 import jtge.util.grid.Coordinate; 37 import jtge.util.grid.IGrid; 38 39 /*** 40 * @author Jean-Laurent 41 * @version $Id: AbstractHexagonBuilder.java,v 1.1 2005/09/09 18:24:28 mat007 Exp $ 42 */ 43 public abstract class AbstractHexagonBuilder implements IHexagonBuilder 44 { 45 /*** 46 * Cosinus 60. 47 */ 48 private static final double COS_60 = 0.5; 49 /*** 50 * Sinus 60. 51 */ 52 private static final double SIN_60 = 0.8660254; 53 /*** 54 * <code> 55 * | A | 56 * |R| _ _ 57 * /\ H 58 * / \ _ 59 * | | S B 60 * | | _ 61 * \ / 62 * \/ _ 63 * 64 * | B | 65 * |H||S| 66 * ___ _ _ 67 * / \ R 68 * / \ _ A 69 * \ / 70 * \___/ _ 71 * </code> 72 */ 73 protected final double S, R, H, A, B; 74 /*** 75 * Whether the map is shifted or not. 76 */ 77 protected final boolean shifted; 78 79 /*** 80 * Create an abstract hexagon builder. 81 * 82 * @param hexagonSideLength the length of the side of an hexagon in pixels 83 * @param shifted whether to shift the first hexagon (therefore the whole map) or not 84 */ 85 public AbstractHexagonBuilder( final int hexagonSideLength, final boolean shifted ) 86 { 87 S = hexagonSideLength; 88 R = S * SIN_60; 89 H = S * COS_60; 90 A = R * 2; 91 B = S + 2 * H; 92 this.shifted = shifted; 93 } 94 95 /*** 96 * {@inheritDoc} 97 */ 98 public final Polygon buildHexagon() 99 { 100 return buildHexagon( Coordinate.ORIGIN ); 101 } 102 103 /*** 104 * {@inheritDoc} 105 */ 106 public final Coordinate fromPixel( final Point point, final IGrid grid ) 107 { 108 if( grid != null ) 109 { 110 final Coordinate coordinate = find( approximate( point ), point, grid ); 111 if( grid.isValid( coordinate ) ) 112 return coordinate; 113 } 114 return null; 115 } 116 117 /*** 118 * Retrieve an approximated coordinate from a given point. 119 * 120 * @param point the point 121 * @return an approximated coordinate 122 */ 123 protected abstract Coordinate approximate( final Point point ); 124 125 private Coordinate find( final Coordinate coordinate, final Point point, final IGrid grid ) 126 { 127 if( buildHexagon( coordinate ).contains( point.x, point.y ) ) 128 return coordinate; 129 return findAmongNeighbours( grid.adjacentIterator( coordinate ), point ); 130 } 131 132 private Coordinate findAmongNeighbours( final Iterator iterator, final Point point ) 133 { 134 while( iterator.hasNext() ) 135 { 136 final Coordinate coordinate = (Coordinate)iterator.next(); 137 if( buildHexagon( coordinate ).contains( point.x, point.y ) ) 138 return coordinate; 139 } 140 return null; 141 } 142 143 /*** 144 * Floor an array of numbers. 145 * 146 * @param array the array to floor 147 * @return an integer array 148 */ 149 protected final int[] floor( final double[] array ) 150 { 151 final int[] result = new int[array.length]; 152 for( int i = 0; i < array.length; i++ ) 153 result[i] = floor( array[i] ); 154 return result; 155 } 156 157 /*** 158 * Floor a number. 159 * 160 * @param value the double value to floor. 161 * @return floor value 162 */ 163 protected final int floor( final double value ) 164 { 165 return (int)Math.floor( value ); 166 } 167 }