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 }