View Javadoc

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 }