bottom = new LinkedHashMap<>();
108 | bottom.put(Adjacent.EVEN, Neighbors.BOTTOM_LEFT);
109 | bottom.put(Adjacent.ODD, Neighbors.LEFT_BOTTOM);
110 | neighbors.put(Adjacent.TOP, right);
111 | neighbors.put(Adjacent.BOTTOM, left);
112 | neighbors.put(Adjacent.RIGHT, top);
113 | neighbors.put(Adjacent.LEFT, bottom);
114 | }
115 | }
116 |
117 | /** The Constant BOTTOM. */
118 | public static final String BOTTOM = "bottom";
119 |
120 | /** The Constant BOTTOM_BOTTOM. */
121 | public static final String BOTTOM_BOTTOM = "bottom_bottom";
122 |
123 | /** The Constant BOTTOM_LEFT. */
124 | public static final String BOTTOM_LEFT = "bottomleft";
125 |
126 | /** The Constant BOTTOM_LEFT_BOTTOM. */
127 | public static final String BOTTOM_LEFT_BOTTOM = "bottomleft_bottom";
128 |
129 | /** The Constant BOTTOM_LEFT_BOTTOM_LEFT. */
130 | public static final String BOTTOM_LEFT_BOTTOM_LEFT = "bottomleft_bottom_left";
131 |
132 | /** The Constant BOTTOM_LEFT_LEFT. */
133 | public static final String BOTTOM_LEFT_LEFT = "bottomleft_left";
134 |
135 | /** The Constant BOTTOM_RIGHT. */
136 | public static final String BOTTOM_RIGHT = "bottomright";
137 |
138 | /** The Constant BOTTOM_RIGHT_BOTTOM. */
139 | public static final String BOTTOM_RIGHT_BOTTOM = "bottomright_bottom";
140 |
141 | /** The Constant BOTTOM_RIGHT_BOTTOM_RIGHT. */
142 | public static final String BOTTOM_RIGHT_BOTTOM_RIGHT = "bottomright_bottom_right";
143 |
144 | /** The Constant BOTTOM_RIGHT_RIGHT. */
145 | public static final String BOTTOM_RIGHT_RIGHT = "bottomright_right";
146 |
147 | /** The Constant CENTER. */
148 | public static final String CENTER = "center";
149 |
150 | /** The Constant EVEN. */
151 | public static final String EVEN = "even";
152 |
153 | /** The Constant LEFT. */
154 | public static final String LEFT = "left";
155 |
156 | /** The Constant LEFT_LEFT. */
157 | public static final String LEFT_LEFT = "left_left";
158 |
159 | /** The Constant ODD. */
160 | public static final String ODD = "odd";
161 |
162 | /** The Constant RIGHT. */
163 | public static final String RIGHT = "right";
164 |
165 | /** The Constant RIGHT_RIGHT. */
166 | public static final String RIGHT_RIGHT = "right_right";
167 |
168 | /** The Constant TOP. */
169 | public static final String TOP = "top";
170 |
171 | /** The Constant TOP_LEFT. */
172 | public static final String TOP_LEFT = "topleft";
173 |
174 | /** The Constant TOP_LEFT_LEFT. */
175 | public static final String TOP_LEFT_LEFT = "topleft_left";
176 |
177 | /** The Constant TOP_LEFT_TOP. */
178 | public static final String TOP_LEFT_TOP = "topleft_top";
179 |
180 | /** The Constant TOP_LEFT_TOP_LEFT. */
181 | public static final String TOP_LEFT_TOP_LEFT = "topleft_top_left";
182 |
183 | /** The Constant TOP_RIGHT. */
184 | public static final String TOP_RIGHT = "topright";
185 |
186 | /** The Constant TOP_RIGHT_RIGHT. */
187 | public static final String TOP_RIGHT_RIGHT = "topright_right";
188 |
189 | /** The Constant TOP_RIGHT_TOP. */
190 | public static final String TOP_RIGHT_TOP = "topright_top";
191 |
192 | /** The Constant TOP_RIGHT_RIGHT_TOP. */
193 | public static final String TOP_RIGHT_TOP_RIGHT = "topright_top_right";
194 |
195 | /** The Constant TOP_TOP. */
196 | public static final String TOP_TOP = "top_top";
197 |
198 | }
--------------------------------------------------------------------------------
/jgeohash-core/src/test/java/de/alpharogroup/jgeohash/model/SectionTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2010 Asterios Raptis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.alpharogroup.jgeohash.model;
17 |
18 | import static org.testng.Assert.assertEquals;
19 |
20 | import org.testng.annotations.Test;
21 |
22 | import de.alpharogroup.evaluate.object.verifier.ContractVerifier;
23 |
24 | /**
25 | * The unit test class for the class {@link Section}
26 | */
27 | public class SectionTest
28 | {
29 |
30 | /**
31 | * Test method for {@link Section#isBetween(Section)}.
32 | */
33 | @Test
34 | public void testIsBetween()
35 | {
36 | boolean expected;
37 | boolean actual;
38 | Section section;
39 | Section other;
40 |
41 | section = Section.builder().start(23).end(45).build();
42 | other = Section.builder().start(22).end(44).build();
43 |
44 | actual = section.isBetween(other);
45 | expected = false;
46 | assertEquals(expected, actual);
47 |
48 | section = Section.builder().start(23).end(45).build();
49 | other = Section.builder().start(23).end(45).build();
50 |
51 | actual = section.isBetween(other);
52 | expected = true;
53 | assertEquals(expected, actual);
54 |
55 | section = Section.builder().start(23).end(45).build();
56 | other = Section.builder().start(24).end(44).build();
57 |
58 | actual = section.isBetween(other);
59 | expected = true;
60 | assertEquals(expected, actual);
61 |
62 | section = Section.builder().start(23).end(45).build();
63 | other = Section.builder().start(23).end(46).build();
64 |
65 | actual = section.isBetween(other);
66 | expected = false;
67 | assertEquals(expected, actual);
68 |
69 | section = Section.builder().start(23).end(45).build();
70 | other = Section.builder().start(24).end(46).build();
71 |
72 | actual = section.isBetween(other);
73 | expected = false;
74 | assertEquals(expected, actual);
75 | }
76 |
77 | /**
78 | * Test method for {@link Section#isBetween(int, int, int, boolean, boolean)}.
79 | */
80 | @Test
81 | public void testIsBetweenIntIntIntBooleanBoolean()
82 | {
83 | boolean expected;
84 | boolean actual;
85 | int min;
86 | int max;
87 | int index;
88 | final int primitiveOne = 1;
89 | boolean includeMin;
90 | boolean includeMax;
91 | min = 0;
92 | max = 10;
93 | // first test case
94 | index = min;
95 | includeMin = false;
96 | includeMax = false;
97 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
98 | expected = false;
99 | assertEquals(actual, expected);
100 | for (index = min + primitiveOne; index < max; index++)
101 | {
102 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
103 | expected = true;
104 | assertEquals(actual, expected);
105 | }
106 | index = max;
107 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
108 | expected = false;
109 | assertEquals(actual, expected);
110 |
111 | // Now check negative cases
112 | index = min - primitiveOne;
113 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
114 | expected = false;
115 | assertEquals(actual, expected);
116 | index = max + primitiveOne;
117 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
118 | expected = false;
119 | assertEquals(actual, expected);
120 |
121 | // second test case
122 | index = min;
123 | includeMin = true;
124 | includeMax = true;
125 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
126 | expected = true;
127 | assertEquals(actual, expected);
128 | for (index = min + primitiveOne; index < max; index++)
129 | {
130 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
131 | expected = true;
132 | assertEquals(actual, expected);
133 | }
134 | index = max;
135 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
136 | expected = true;
137 | assertEquals(actual, expected);
138 | // Now check negative cases
139 | index = min - primitiveOne;
140 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
141 | expected = false;
142 | assertEquals(actual, expected);
143 | index = max + primitiveOne;
144 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
145 | expected = false;
146 | assertEquals(actual, expected);
147 |
148 | // third test case
149 | index = min;
150 | includeMin = false;
151 | includeMax = true;
152 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
153 | expected = false;
154 | assertEquals(actual, expected);
155 | for (index = min + primitiveOne; index < max; index++)
156 | {
157 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
158 | expected = true;
159 | assertEquals(actual, expected);
160 | }
161 | index = max;
162 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
163 | expected = true;
164 | assertEquals(actual, expected);
165 | // Now check negative cases
166 | index = min - primitiveOne;
167 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
168 | expected = false;
169 | assertEquals(actual, expected);
170 | index = max + primitiveOne;
171 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
172 | expected = false;
173 | assertEquals(actual, expected);
174 |
175 | // fourth test case
176 | index = min;
177 | includeMin = true;
178 | includeMax = false;
179 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
180 | expected = true;
181 | assertEquals(actual, expected);
182 | for (index = min + primitiveOne; index < max; index++)
183 | {
184 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
185 | expected = true;
186 | assertEquals(actual, expected);
187 | }
188 | index = max;
189 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
190 | expected = false;
191 | assertEquals(actual, expected);
192 | // Now check negative cases
193 | index = min - primitiveOne;
194 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
195 | expected = false;
196 | assertEquals(actual, expected);
197 | index = max + primitiveOne;
198 | actual = Section.isBetween(min, max, index, includeMin, includeMax);
199 | expected = false;
200 | assertEquals(actual, expected);
201 | }
202 |
203 | /**
204 | * Test method for {@link Section#equals(Object)} , {@link Section#hashCode()} and
205 | * {@link Section#toString()}
206 | */
207 | @Test
208 | public void verifyEqualsHashcodeAndToStringWithClass()
209 | {
210 | ContractVerifier.of(Section.class).verify();
211 | }
212 |
213 | }
214 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 |
4 | [](https://travis-ci.com/astrapi69/jgeohash)
5 | [](https://github.com/astrapi69/jgeohash/actions/workflows/build-test.yml)
6 | [](https://codecov.io/gh/astrapi69/jgeohash)
7 | [](https://coveralls.io/github/astrapi69/jgeohash?branch=develop)
8 | [](https://github.com/astrapi69/jgeohash/issues)
9 | [](http://www.apache.org/licenses/LICENSE-2.0)
10 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=GVBTWLRAZ7HB8)
11 |
12 |
13 |
14 | An easy-to-implement library that can assist Java developers in using the [GeoHash](https://en.wikipedia.org/wiki/Geohash) algorithm in order to create geocodes based on custom latitude and longitude values.
15 |
16 | With the help of jGeohash, Java developers will be able to quickly and easily generate a geohash code using user-defined latitude and longitude values. By using the GeoHash algorithm, the space can be divided into multiple grid shapes.
17 |
18 | This library is a basic implementation from the GeoHash algorithm written in the java and can be applied to generate from the latitude and longitude a geohash code and reverse.
19 |
20 | The library is kept simple and have no dependencies to other libraries.
21 |
22 |
23 | > Please support this project by simply putting a Github
24 | Star ⭐. Share this library with friends on Twitter and everywhere else you can.
25 | If you love this project [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=GVBTWLRAZ7HB8)
26 |
27 | ## Note
28 |
29 | No animals were harmed in the making of this library.
30 |
31 | # Donations
32 |
33 | This project is kept as an open source product and relies on contributions to remain being
34 | developed. If you like this library, please consider a donation
35 |
36 | over paypal:
37 |
38 |
39 |
40 |
41 | or over bitcoin(BTC) with this address:
42 |
43 | bc1ql2y99q7e8psndhcc3gferk03esw3qqf677rhjy
44 |
45 |
47 |
48 | or over FIO with this address:
49 |
50 | FIO7tFMUVAA9cHiPPqKMfMXiSxHrbpiFyRYqTketNuM67aULuwjop
51 |
52 |
54 |
55 | or over Ethereum(ETH) with:
56 |
57 | 0xc057D159D3C8f3311E73568b334FF6fE82EB2b7D
58 |
59 |
61 |
62 | or over Ethereum Classic(ETC) with:
63 |
64 | 0xF708cA86D86C246B69c3F4BAe431eBbe0c2bfddD
65 |
66 |
68 |
69 | or over Dogecoin(DOGE) with:
70 |
71 | D5yi4Um8cpakd6yPRm2hGWuQ5nrVzhSSW1
72 |
73 |
75 |
76 | or over Monero(XMR) with:
77 |
78 | 49bqeRQ7Bf49oJFVC72pqpe5hFbb62pfXDYPdLsadGGF81KZW2ZfrPZ8PbAVu5X2v1TYAspeczMya3cYQysNS4usRRPQHVw
79 |
80 |
82 |
83 | or over flattr:
84 |
85 |
86 |
87 |
88 |
89 | ## Key features:
90 |
91 | 1. Very small size (<35Kb)
92 | 2. Can get the adjacent geohash area from the given direction
93 | 3. Can get the geohash from an ip address
94 | 4. Can calculate distance between two geohash values in various measuring units like miles, km, meters
95 | 5. Can get the geohash cells around from the first, second or thrird ring from a given geohash cell
96 |
97 | ## License
98 |
99 | The source code comes under the liberal Apache License V2.0, making jgeohash great for all types of applications.
100 |
101 | ## Maven Central
102 |
103 | [](https://maven-badges.herokuapp.com/maven-central/de.alpharogroup/jgeohash-core) jgeohash-core
104 |
105 | [](https://maven-badges.herokuapp.com/maven-central/de.alpharogroup/jgeohash-geoip) jgeohash-geoip
106 |
107 | ## javadoc
108 |
109 | [](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-core) jgeohash-core
110 |
111 | [](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-geoip) jgeohash-geoip
112 |
113 | ## javadoc
114 |
115 | jgeohash-core [](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-core)
116 |
117 | jgeohash-geoip [](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-geoip)
118 |
119 | ## Maven dependency
120 |
121 | Maven dependency is now on sonatype.
122 | Check out [sonatype repository](https://oss.sonatype.org/index.html#nexus-search;quick~jgeohash) for latest snapshots and releases.
123 |
124 | You can add the following maven dependencies to your project `pom.xml` if you want to import the library.
125 |
126 | You can first define the version properties:
127 |
128 |
129 | ...
130 |
131 | 2.5.2
132 | ${jgeohash.version}
133 | ${jgeohash.version}
134 | ...
135 |
136 |
137 | Add the following maven dependency to your project `pom.xml` if you want to import the core functionality of jgeohash:
138 |
139 |
140 | ...
141 |
142 |
143 | de.alpharogroup
144 | jgeohash-core
145 | ${jgeohash-core.version}
146 |
147 |
148 |
149 | Add the following maven dependency to your project `pom.xml` if you want to import the geoip functionality of jgeohash:
150 |
151 |
152 | ...
153 |
154 |
155 | de.alpharogroup
156 | jgeohash-geoip
157 | ${jgeohash-geoip.version}
158 |
159 |
160 |
161 | ## Semantic Versioning
162 |
163 | The versions of jgeohash are maintained with the Semantic Versioning guidelines.
164 |
165 | Release version numbers will be incremented in the following format:
166 |
167 | `..`
168 |
169 | For detailed information on versioning for this project you can visit this [wiki page](https://github.com/lightblueseas/mvn-parent-projects/wiki/Semantic-Versioning).
170 |
171 | ## Want to Help and improve it? ###
172 |
173 | The source code for jGeohash are on GitHub. Please feel free to fork and send pull requests!
174 |
175 | Create your own fork of [astrapi69/jgeohash/fork](https://github.com/astrapi69/jgeohash/fork)
176 |
177 | To share your changes, [submit a pull request](https://github.com/astrapi69/jgeohash/pull/new/develop).
178 |
179 | Don't forget to add new units tests on your changes.
180 |
181 | ## Contacting the Developer
182 |
183 | Do not hesitate to contact the jgeohash developers with your questions, concerns, comments, bug reports, or feature requests.
184 | - Feature requests, questions and bug reports can be reported at the [issues page](https://github.com/astrapi69/jgeohash/issues).
185 |
186 | ## Examples
187 |
188 | * [SpatialDataQueries][SpatialDataQueries]
189 | * [Simple-example][Simple-example]
190 | * [Hibernate-example][Hibernate-example]
191 |
192 | [SpatialDataQueries]: https://github.com/astrapi69/jgeohash/wiki/Adding-spatial-data-queries-to-Phoenix-on-HBase "Adding spatial data queries to Phoenix on HBase"
193 | [Simple-example]: https://github.com/astrapi69/jgeohash/wiki/Simple-example "Simple-example"
194 | [Hibernate-example]: https://github.com/astrapi69/jgeohash/wiki/Hibernate-example "Hibernate-example"
195 |
196 |
197 | ## Similar projects
198 |
199 | Here is a list of awesome projects that uses geohash:
200 |
201 | * [geohash-java](https://github.com/kungfoo/geohash-java) Another implementation of Geohashes in pure Java.
202 | * [geo](https://github.com/davidmoten/geo) Geohash utitlies in java
203 |
204 | ## Blogs
205 |
206 | * [Designing a Spacial Index](https://dzone.com/articles/designing-spacial-index)
207 |
208 | ## Useful links
209 |
210 | * [geohash.org browser](http://geohash.org/)
211 | * [alternative geohash browser](https://www.movable-type.co.uk/scripts/geohash.html)
212 |
213 | ## Change log
214 |
215 | The changelog is moved in its own file. It can be found on following [page](https://github.com/astrapi69/jgeohash/blob/develop/CHANGELOG.md)
216 |
217 | ## Credits
218 |
219 | |**Travis CI**|
220 | | :---: |
221 | |
|
222 | |[](https://travis-ci.com/astrapi69/jgeohash) |
223 | |Special thanks to [Travis CI](https://travis-ci.com) for providing a free continuous integration service for open source projects|
224 | |
|
225 |
226 | |**Nexus Sonatype repositories**|
227 | | :---: |
228 | |[](https://oss.sonatype.org/index.html#nexus-search;gav~de.alpharogroup~jgeohash-core~~~) jgeohash-core|
229 | |[](https://oss.sonatype.org/index.html#nexus-search;gav~de.alpharogroup~jgeohash-geoip~~~) jgeohash-geoip|
230 | |Special thanks to [sonatype repository](https://www.sonatype.com) for providing a free maven repository service for open source projects|
231 | |
|
232 |
233 | |**coveralls.io**|
234 | | :---: |
235 | |[](https://coveralls.io/github/astrapi69/jgeohash?branch=master)|
236 | |Special thanks to [coveralls.io](https://coveralls.io) for providing a free code coverage for open source projects|
237 | |
|
238 |
239 | |**javadoc.io**|
240 | | :---: |
241 | |[](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-core) jgeohash-core|
242 | |[](http://www.javadoc.io/doc/de.alpharogroup/jgeohash-geoip) jgeohash-geoip|
243 | |Special thanks to [javadoc.io](http://www.javadoc.io) for providing a free javadoc documentation for open source projects|
244 | |
|
245 |
--------------------------------------------------------------------------------
/jgeohash-core/src/test/java/de/alpharogroup/jgeohash/GeoHashExtensionsTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2010 Asterios Raptis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.alpharogroup.jgeohash;
17 |
18 | import static org.testng.Assert.assertNotNull;
19 | import static org.testng.Assert.assertTrue;
20 | import static org.testng.AssertJUnit.assertEquals;
21 |
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.Map.Entry;
25 |
26 | import org.meanbean.factories.ObjectCreationException;
27 | import org.meanbean.test.BeanTestException;
28 | import org.meanbean.test.BeanTester;
29 | import org.testng.annotations.Test;
30 |
31 | import de.alpharogroup.collections.list.ListFactory;
32 | import de.alpharogroup.collections.map.MapFactory;
33 | import de.alpharogroup.jgeohash.model.FirstAndSecondRingRegion;
34 | import de.alpharogroup.jgeohash.model.FirstRingRegion;
35 |
36 | /**
37 | * The unit test class for the class {@link GeoHashExtensions}.
38 | */
39 | public class GeoHashExtensionsTest
40 | {
41 |
42 | /**
43 | * Test method for {@link GeoHashExtensions#decode(String)}.
44 | */
45 | @Test
46 | public void testDecode()
47 | {
48 | double[] actual;
49 | double[] expected;
50 | String geohash;
51 | expected = new double[2];
52 |
53 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
54 | expected[0] = 53.55263943783939d;
55 | expected[1] = 10.006710458546877d;
56 | actual = GeoHashExtensions.decode(geohash);
57 | assertEquals(expected[0], actual[0]);
58 | assertEquals(expected[1], actual[1]);
59 |
60 | geohash = GeoHashExtensions.encode(30.0, -90.0);
61 | expected[0] = 29.999999972060323d;
62 | expected[1] = -90.00000016763806d;
63 | actual = GeoHashExtensions.decode(geohash);
64 | assertEquals(expected[0], actual[0]);
65 | assertEquals(expected[1], actual[1]);
66 |
67 | geohash = GeoHashExtensions.encode(51.4797, -0.0124);
68 | expected[0] = 51.47970006801188d;
69 | expected[1] = -0.01240001991391182d;
70 | actual = GeoHashExtensions.decode(geohash);
71 | assertEquals(expected[0], actual[0]);
72 | assertEquals(expected[1], actual[1]);
73 | }
74 |
75 | /**
76 | * Test method for {@link GeoHashExtensions#decodeAndRound(String)}.
77 | */
78 | @Test
79 | public void testDecodeAndRound()
80 | {
81 | double[] actual;
82 | double[] expected;
83 | String geohash;
84 | expected = new double[2];
85 |
86 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
87 | expected[0] = 53.552639d;
88 | expected[1] = 10.00671d;
89 | actual = GeoHashExtensions.decodeAndRound(geohash);
90 | assertEquals(expected[0], actual[0]);
91 | assertEquals(expected[1], actual[1]);
92 |
93 | geohash = GeoHashExtensions.encode(30.0, -90.0);
94 | expected[0] = 29.999999d;
95 | expected[1] = -90.0d;
96 | actual = GeoHashExtensions.decodeAndRound(geohash);
97 | assertEquals(expected[0], actual[0]);
98 | assertEquals(expected[1], actual[1]);
99 |
100 | geohash = GeoHashExtensions.encode(51.4797, -0.0124);
101 | expected[0] = 51.4797d;
102 | expected[1] = -0.0124d;
103 | actual = GeoHashExtensions.decodeAndRound(geohash);
104 | assertEquals(expected[0], actual[0]);
105 | assertEquals(expected[1], actual[1]);
106 | }
107 |
108 | /**
109 | * Test method for {@link GeoHashExtensions#decode(String)} with empty value
110 | */
111 | @Test(expectedExceptions = IllegalArgumentException.class)
112 | public final void testDecodeWithEmptyValue()
113 | {
114 | GeoHashExtensions.decode("");
115 | }
116 |
117 | /**
118 | * Test method for {@link GeoHashExtensions#decode(String)} with null value
119 | */
120 | @Test(expectedExceptions = IllegalArgumentException.class)
121 | public final void testDecodeWithNullValue()
122 | {
123 | GeoHashExtensions.decode(null);
124 | }
125 |
126 | /**
127 | * Test method for {@link GeoHashExtensions#encode(double, double)}.
128 | */
129 | @Test
130 | public void testEncode()
131 | {
132 | String expected;
133 | String actual;
134 |
135 | actual = GeoHashExtensions.encode(53.5526394, 10.0067103);
136 | expected = "u1x0esywtr81";
137 | assertEquals(expected, actual);
138 |
139 | actual = GeoHashExtensions.encode(30.0, -90.0);
140 | expected = "9vrfxvrfxvrf";
141 | assertEquals(expected, actual);
142 |
143 | actual = GeoHashExtensions.encode(51.4797, -0.0124);
144 | expected = "gcpuzewfzp9u";
145 | assertEquals(expected, actual);
146 | }
147 |
148 | /**
149 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String)}
150 | */
151 | @Test(enabled = true)
152 | public void testGetAdjacentStringString()
153 | {
154 | String expected;
155 | String actual;
156 | String alterTeichwegGeohash;
157 | String geohash;
158 | String right;
159 | String left;
160 |
161 | alterTeichwegGeohash = "u1x0v54rmjwej";
162 | geohash = alterTeichwegGeohash;
163 |
164 | expected = "h";
165 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.TOP);
166 | assertEquals(expected, actual);
167 |
168 | expected = "v";
169 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.RIGHT);
170 | assertEquals(expected, actual);
171 |
172 | expected = "s";
173 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.BOTTOM);
174 | assertEquals(expected, actual);
175 |
176 | expected = "g";
177 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.LEFT);
178 | assertEquals(expected, actual);
179 |
180 | expected = "dr";
181 | actual = GeoHashExtensions.getAdjacent("dq", Adjacent.TOP);
182 | assertEquals(expected, actual);
183 |
184 | expected = "dw";
185 | actual = GeoHashExtensions.getAdjacent("dq", Adjacent.RIGHT);
186 | assertEquals(expected, actual);
187 |
188 | expected = "u1x0v54rmjwem";
189 | actual = GeoHashExtensions.getAdjacent(geohash, "top");
190 | assertEquals(expected, actual);
191 |
192 | expected = "u1x0v54rmjwdv";
193 | actual = GeoHashExtensions.getAdjacent(geohash, "bottom");
194 | assertEquals(expected, actual);
195 |
196 | expected = "u1x0v54rmjwen";
197 | actual = GeoHashExtensions.getAdjacent(geohash, "right");
198 | right = actual;
199 | assertEquals(expected, actual);
200 |
201 | expected = "u1x0v54rmjweh";
202 | actual = GeoHashExtensions.getAdjacent(geohash, "left");
203 | left = actual;
204 | assertEquals(expected, actual);
205 |
206 | expected = "u1x0v54rmjwek";
207 | actual = GeoHashExtensions.getAdjacent(left, "top");
208 | assertEquals(expected, actual);
209 |
210 | expected = "u1x0v54rmjweq";
211 | actual = GeoHashExtensions.getAdjacent(right, "top");
212 | assertEquals(expected, actual);
213 |
214 | expected = "u1x0v54rmjwdy";
215 | actual = GeoHashExtensions.getAdjacent(right, "bottom");
216 | assertEquals(expected, actual);
217 |
218 | expected = "u1x0v54rmjwdu";
219 | actual = GeoHashExtensions.getAdjacent(left, "bottom");
220 | assertEquals(expected, actual);
221 | }
222 |
223 | /**
224 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String...)}
225 | */
226 | @Test(enabled = true)
227 | public void testGetAdjacentStringStringArray()
228 | {
229 | String expected;
230 | String actual;
231 | String geohash;
232 | String subGeohash;
233 |
234 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
235 | subGeohash = geohash.substring(0, 7);
236 | expected = "u1x0etp";
237 | actual = GeoHashExtensions.getAdjacent(subGeohash, Adjacent.TOP, Adjacent.RIGHT);
238 | assertEquals(expected, actual);
239 |
240 | expected = "u1x0etj";
241 | actual = GeoHashExtensions.getAdjacent(subGeohash, Adjacent.TOP, Adjacent.LEFT);
242 | assertEquals(expected, actual);
243 | expected = "u1x0etq";
244 | actual = GeoHashExtensions.getAdjacent(subGeohash, Adjacent.TOP, Adjacent.TOP);
245 | assertEquals(expected, actual);
246 |
247 | expected = "j";
248 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.TOP, Adjacent.RIGHT);
249 | assertEquals(expected, actual);
250 |
251 | expected = "t";
252 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.BOTTOM, Adjacent.RIGHT);
253 | assertEquals(expected, actual);
254 |
255 | expected = "e";
256 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.BOTTOM, Adjacent.LEFT);
257 | assertEquals(expected, actual);
258 |
259 | expected = "5";
260 | actual = GeoHashExtensions.getAdjacent("u", Adjacent.LEFT, Adjacent.TOP);
261 | assertEquals(expected, actual);
262 | }
263 |
264 | /**
265 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String)} with direction empty
266 | * value
267 | */
268 | @Test(expectedExceptions = IllegalArgumentException.class)
269 | public final void testGetAdjacentStringStringDirectionEmptyValue()
270 | {
271 | GeoHashExtensions.getAdjacent("u", "");
272 | }
273 |
274 | /**
275 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String)} with direction null
276 | * value
277 | */
278 | @Test(expectedExceptions = IllegalArgumentException.class)
279 | public final void testGetAdjacentStringStringDirectionNullValue()
280 | {
281 | GeoHashExtensions.getAdjacent("u", (String)null);
282 | }
283 |
284 | /**
285 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String)} with geohash empty
286 | * value
287 | */
288 | @Test(expectedExceptions = IllegalArgumentException.class)
289 | public final void testGetAdjacentStringStringGeohashEmptyValue()
290 | {
291 | GeoHashExtensions.getAdjacent("", Adjacent.TOP);
292 | }
293 |
294 | /**
295 | * Test method for {@link GeoHashExtensions#getAdjacent(String, String)} with geohash null value
296 | */
297 | @Test(expectedExceptions = IllegalArgumentException.class)
298 | public final void testGetAdjacentStringStringGeohashNullValue()
299 | {
300 | GeoHashExtensions.getAdjacent(null, Adjacent.TOP);
301 | }
302 |
303 | /**
304 | * Test method for {@link GeoHashExtensions#getAllAdjacentAreasList(String)}.
305 | */
306 | @Test
307 | public void testGetAllAdjacentAreasList()
308 | {
309 | List expected;
310 | List actual;
311 | String geohash;
312 | String subGeohash;
313 |
314 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
315 | subGeohash = geohash.substring(0, 7);
316 |
317 | actual = GeoHashExtensions.getAllAdjacentAreasList(subGeohash);
318 | expected = ListFactory.newArrayList("u1x0esy", "u1x0etn", "u1x0etp", "u1x0esz", "u1x0esx",
319 | "u1x0esw", "u1x0est", "u1x0esv", "u1x0etj");
320 | for (int i = 0; i < actual.size(); i++)
321 | {
322 | assertEquals(expected.get(i), actual.get(i));
323 | }
324 | }
325 |
326 | /**
327 | * Test method for {@link GeoHashExtensions#decode(String)} with null value
328 | */
329 | @Test(expectedExceptions = IllegalArgumentException.class)
330 | public final void testGetAllAdjacentAreasListNullValue()
331 | {
332 | GeoHashExtensions.getAllAdjacentAreasList(null);
333 | }
334 |
335 | /**
336 | * Test method for {@link GeoHashExtensions#decode(String)} with empty value
337 | */
338 | @Test(expectedExceptions = IllegalArgumentException.class)
339 | public final void testGetAllAdjacentAreasListWithEmptyValue()
340 | {
341 | GeoHashExtensions.getAllAdjacentAreasList("");
342 | }
343 |
344 | /**
345 | * Test method for {@link GeoHashExtensions#getAllAdjacentAreasMap(String)}.
346 | */
347 | @Test
348 | public void testGetAllAdjacentAreasMap()
349 | {
350 | Map expected;
351 | Map actual;
352 | String geohash;
353 | String subGeohash;
354 |
355 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
356 | subGeohash = geohash.substring(0, 7);
357 | actual = GeoHashExtensions.getAllAdjacentAreasMap(subGeohash);
358 |
359 | expected = MapFactory.newHashMap(9);
360 | expected.put("center", "u1x0esy");
361 | expected.put("top", "u1x0etn");
362 | expected.put("bottom", "u1x0esw");
363 | expected.put("right", "u1x0esz");
364 | expected.put("left", "u1x0esv");
365 | expected.put("topleft", "u1x0etj");
366 | expected.put("topright", "u1x0etp");
367 | expected.put("bottomright", "u1x0esx");
368 | expected.put("bottomleft", "u1x0est");
369 | for (Entry entry : actual.entrySet())
370 | {
371 | assertEquals(expected.get(entry.getKey()), actual.get(entry.getKey()));
372 | }
373 | }
374 |
375 | /**
376 | * Test method for {@link GeoHashExtensions#decode(String)} with null value
377 | */
378 | @Test(expectedExceptions = IllegalArgumentException.class)
379 | public final void testGetAllAdjacentAreasMapNullValue()
380 | {
381 | GeoHashExtensions.getAllAdjacentAreasMap(null);
382 | }
383 |
384 | /**
385 | * Test method for {@link GeoHashExtensions#decode(String)} with empty value
386 | */
387 | @Test(expectedExceptions = IllegalArgumentException.class)
388 | public final void testGetAllAdjacentAreasMapWithEmptyValue()
389 | {
390 | GeoHashExtensions.getAllAdjacentAreasMap("");
391 | }
392 |
393 | /**
394 | * Test method for {@link GeoHashExtensions#getFirstAndSecondRingRegion(String)}.
395 | */
396 | @Test
397 | public void testGetFirstAndSecondRingRegion()
398 | {
399 | FirstAndSecondRingRegion actual;
400 | FirstAndSecondRingRegion expected;
401 | String geohash;
402 |
403 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
404 | actual = GeoHashExtensions.getFirstAndSecondRingRegion(geohash);
405 | assertNotNull(actual);
406 | expected = new FirstAndSecondRingRegion(geohash);
407 | assertEquals(expected, actual);
408 | }
409 |
410 | /**
411 | * Test method for {@link GeoHashExtensions#getFirstRingRegion(String)}.
412 | */
413 | @Test
414 | public void testGetFirstRingRegion()
415 | {
416 | FirstRingRegion actual;
417 | FirstRingRegion expected;
418 | String geohash;
419 |
420 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
421 | actual = GeoHashExtensions.getFirstRingRegion(geohash);
422 | assertNotNull(actual);
423 | expected = new FirstRingRegion(geohash);
424 | assertEquals(expected, actual);
425 | }
426 |
427 | /**
428 | * Test method for {@link GeoHashExtensions#getLatitude(String)}.
429 | */
430 | @Test
431 | public void testGetLatitude()
432 | {
433 | double actual;
434 | double expected;
435 | String geohash;
436 |
437 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
438 |
439 | actual = GeoHashExtensions.getLatitude(geohash);
440 | expected = 53.552639;
441 | assertEquals(expected, actual);
442 | }
443 |
444 | /**
445 | * Test method for {@link GeoHashExtensions#getLongitude(String)}.
446 | */
447 | @Test
448 | public void testGetLongitude()
449 | {
450 | double actual;
451 | double expected;
452 | String geohash;
453 |
454 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
455 |
456 | actual = GeoHashExtensions.getLongitude(geohash);
457 | expected = 10.006710;
458 | assertEquals(expected, actual);
459 | }
460 |
461 | /**
462 | * Test method for {@link GeoHashExtensions#getTwentyFiveAreasMap(String)}.
463 | */
464 | @Test
465 | public void testGetTwentyFiveAreasMap()
466 | {
467 | Map actual;
468 | Map expected;
469 | String geohash;
470 |
471 | geohash = GeoHashExtensions.encode(53.5526394, 10.0067103);
472 | actual = GeoHashExtensions.getTwentyFiveAreasMap(geohash);
473 | assertNotNull(actual);
474 | assertTrue(actual.size() == 25);
475 | expected = MapFactory.newLinkedHashMap(25);
476 | expected.put("center", "u1x0esywtr81");
477 | expected.put("top", "u1x0esywtr84");
478 | expected.put("bottom", "u1x0esywtr80");
479 | expected.put("right", "u1x0esywtr83");
480 | expected.put("left", "u1x0esywtpxc");
481 | expected.put("topleft", "u1x0esywtpxf");
482 | expected.put("topright", "u1x0esywtr86");
483 | expected.put("bottomright", "u1x0esywtr82");
484 | expected.put("bottomleft", "u1x0esywtpxb");
485 | expected.put("topleft_top", "u1x0esywtpxg");
486 | expected.put("topleft_top_left", "u1x0esywtpxe");
487 | expected.put("topleft_left", "u1x0esywtpxd");
488 | expected.put("top_top", "u1x0esywtr85");
489 | expected.put("topright_top", "u1x0esywtr87");
490 | expected.put("topright_right", "u1x0esywtr8d");
491 | expected.put("topright_top_right", "u1x0esywtr8e");
492 | expected.put("right_right", "u1x0esywtr89");
493 | expected.put("bottomright_right", "u1x0esywtr88");
494 | expected.put("bottomright_bottom", "u1x0esywtr2r");
495 | expected.put("bottomright_bottom_right", "u1x0esywtr2x");
496 | expected.put("bottom_bottom", "u1x0esywtr2p");
497 | expected.put("bottomleft_bottom", "u1x0esywtprz");
498 | expected.put("bottomleft_bottom_left", "u1x0esywtprx");
499 | expected.put("bottomleft_left", "u1x0esywtpx8");
500 | expected.put("left_left", "u1x0esywtpx9");
501 | for (Entry entry : actual.entrySet())
502 | {
503 | assertEquals(expected.get(entry.getKey()), actual.get(entry.getKey()));
504 | }
505 | }
506 |
507 | /**
508 | * Test method for {@link GeoHashExtensions}
509 | */
510 | @Test(expectedExceptions = { BeanTestException.class, ObjectCreationException.class })
511 | public void testWithBeanTester()
512 | {
513 | final BeanTester beanTester = new BeanTester();
514 | beanTester.testBean(GeoHashExtensions.class);
515 | }
516 | }
517 |
--------------------------------------------------------------------------------
/jgeohash-core/src/main/java/de/alpharogroup/jgeohash/GeoHashExtensions.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2010 Asterios Raptis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.alpharogroup.jgeohash;
17 |
18 | import java.util.ArrayList;
19 | import java.util.HashMap;
20 | import java.util.LinkedHashMap;
21 | import java.util.List;
22 | import java.util.Map;
23 |
24 | import de.alpharogroup.jgeohash.model.FirstAndSecondRingRegion;
25 | import de.alpharogroup.jgeohash.model.FirstRingRegion;
26 | import lombok.experimental.UtilityClass;
27 |
28 | /**
29 | * The class {@link GeoHashExtensions}. This class is based on http://en.wikipedia.org/wiki/Geohash.
30 | */
31 | @UtilityClass
32 | public final class GeoHashExtensions
33 | {
34 |
35 | /**
36 | * The Constant char map BASE_32.
37 | */
38 | private final static char[] BASE_32 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'b',
39 | 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v',
40 | 'w', 'x', 'y', 'z' };
41 |
42 | /** The Constant DECODE_MAP. */
43 | private final static Map DECODE_MAP = new HashMap<>();
44 | static
45 | {
46 | int counter = 0;
47 | for (final char c : BASE_32)
48 | {
49 | DECODE_MAP.put(c, counter++);
50 | }
51 | }
52 |
53 | /** The precision. */
54 | private static final int precision = 12;
55 |
56 | /** The bits. */
57 | private static final int[] bits = { 16, 8, 4, 2, 1 };
58 |
59 | /**
60 | * Decode the given geohash into a latitude and longitude.
61 | *
62 | * @param geohash
63 | * the geohash
64 | * @return the double[]
65 | */
66 | public static double[] decode(final String geohash)
67 | {
68 | if ((geohash == null) || geohash.isEmpty())
69 | {
70 | throw new IllegalArgumentException("Argument geohash should not be null.");
71 | }
72 |
73 | boolean even = true;
74 | double latitudeError = 90.0;
75 | double longitudeError = 180.0;
76 | double latitude;
77 | double longitude;
78 | final double[] latitudeInterval = { -90.0, 90.0 };
79 | final double[] longitudeInterval = { -180.0, 180.0 };
80 | for (int i = 0; i < geohash.length(); i++)
81 | {
82 |
83 | final int cd = DECODE_MAP.get(geohash.charAt(i));
84 |
85 | for (int j = 0; j < bits.length; j++)
86 | {
87 | final int mask = bits[j];
88 | if (even)
89 | {
90 | longitudeError /= 2;
91 | if ((cd & mask) != 0)
92 | {
93 | longitudeInterval[0] = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
94 | }
95 | else
96 | {
97 | longitudeInterval[1] = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
98 | }
99 |
100 | }
101 | else
102 | {
103 | latitudeError /= 2;
104 |
105 | if ((cd & mask) != 0)
106 | {
107 | latitudeInterval[0] = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
108 | }
109 | else
110 | {
111 | latitudeInterval[1] = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
112 | }
113 | }
114 |
115 | even = !even;
116 | }
117 |
118 | }
119 | latitude = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
120 | longitude = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
121 |
122 | return new double[] { latitude, longitude, latitudeError, longitudeError };
123 | }
124 |
125 | /**
126 | * Decodes the given geohash into a latitude and longitude.
127 | *
128 | * @param geohash
129 | * the geohash
130 | * @return the double[]
131 | */
132 | public static double[] decodeAndRound(final String geohash)
133 | {
134 | final double[] ge = decode(geohash);
135 | double latitude = ge[0];
136 | double longitude = ge[1];
137 | final double latitudeError = ge[2];
138 | final double longitudeError = ge[3];
139 |
140 | final double latitudePrecision = Math.max(1, Math.round(-Math.log10(latitudeError))) - 1;
141 | final double longitudePrecision = Math.max(1, Math.round(-Math.log10(longitudeError))) - 1;
142 |
143 | latitude = getPrecision(latitude, latitudePrecision);
144 | longitude = getPrecision(longitude, longitudePrecision);
145 |
146 | return new double[] { latitude, longitude };
147 | }
148 |
149 | /**
150 | * Encodes the given latitude and longitude into a geohash code.
151 | *
152 | * @param latitude
153 | * the latitude
154 | * @param longitude
155 | * the longitude
156 | * @return The generated geohash from the given latitude and longitude.
157 | */
158 | public static String encode(final double latitude, final double longitude)
159 | {
160 | final StringBuilder geohash = new StringBuilder();
161 | boolean even = true;
162 | int bit = 0;
163 | int ch = 0;
164 |
165 | final double[] latitudeInterval = { -90.0, 90.0 };
166 | final double[] longitudeInterval = { -180.0, 180.0 };
167 |
168 | while (geohash.length() < precision)
169 | {
170 | double mid = 0.0;
171 | if (even)
172 | {
173 | mid = (longitudeInterval[0] + longitudeInterval[1]) / 2D;
174 | if (longitude > mid)
175 | {
176 | ch |= bits[bit];
177 | longitudeInterval[0] = mid;
178 | }
179 | else
180 | {
181 | longitudeInterval[1] = mid;
182 | }
183 |
184 | }
185 | else
186 | {
187 | mid = (latitudeInterval[0] + latitudeInterval[1]) / 2D;
188 | if (latitude > mid)
189 | {
190 | ch |= bits[bit];
191 | latitudeInterval[0] = mid;
192 | }
193 | else
194 | {
195 | latitudeInterval[1] = mid;
196 | }
197 | }
198 |
199 | even = !even;
200 |
201 | if (bit < 4)
202 | {
203 | bit++;
204 | }
205 | else
206 | {
207 | geohash.append(BASE_32[ch]);
208 | bit = 0;
209 | ch = 0;
210 | }
211 | }
212 |
213 | return geohash.toString();
214 | }
215 |
216 | /**
217 | * Gets the adjacent from the given direction. For instance if direction is 'top' then the top
218 | * adjacent geohash code will be returned.
219 | *
220 | * @param geohash
221 | * the geohash
222 | * @param direction
223 | * the direction
224 | * @return the geohash code for the adjacent from the given direction.
225 | */
226 | public static String getAdjacent(final String geohash, final String direction)
227 | {
228 | if ((geohash == null) || geohash.isEmpty())
229 | {
230 | throw new IllegalArgumentException("Argument geohash should not be null or empty.");
231 | }
232 | if ((direction == null) || direction.isEmpty())
233 | {
234 | throw new IllegalArgumentException("Argument direction should not be null or empty.");
235 | }
236 | final String lowerCaseGeohash = geohash.toLowerCase();
237 | final char lastChar = lowerCaseGeohash.charAt(lowerCaseGeohash.length() - 1);
238 | final int modulo = lowerCaseGeohash.length() % 2;
239 | final String type = modulo == 0 ? Adjacent.ODD : Adjacent.EVEN;
240 | String base = lowerCaseGeohash.substring(0, lowerCaseGeohash.length() - 1);
241 | final Map borderDirection = Adjacent.Borders.borders.get(direction);
242 | final String borderDirectionType = borderDirection.get(type);
243 | final int indexOfLastChar = borderDirectionType.indexOf(lastChar);
244 | if ((indexOfLastChar != -1) && !base.isEmpty())
245 | {
246 | base = getAdjacent(base, direction);
247 | }
248 | final Map neighborsDirection = Adjacent.Neighbors.neighbors.get(direction);
249 | final String neighborsDirectionType = neighborsDirection.get(type);
250 | final int i = neighborsDirectionType.indexOf(lastChar);
251 | final char r = BASE_32[i];
252 | return base + r;
253 | }
254 |
255 | /**
256 | * Gets the adjacent from the given directions. For instance if directions is 'top' and 'feft'
257 | * then the topleft adjacent geohash code will be returned.
258 | *
259 | * @param geohash
260 | * the geohash
261 | * @param directions
262 | * the directions
263 | * @return the geohash code for the adjacent from the given directions.
264 | */
265 | public static String getAdjacent(final String geohash, final String... directions)
266 | {
267 | String geohashresult = geohash;
268 | for (final String direction : directions)
269 | {
270 | geohashresult = getAdjacent(geohashresult, direction);
271 | }
272 | return geohashresult;
273 | }
274 |
275 | /**
276 | * Gets the all adjacent areas list.
277 | *
278 | * @param geohash
279 | * the geohash
280 | * @return the all adjacent areas list
281 | */
282 | public static List getAllAdjacentAreasList(final String geohash)
283 | {
284 | if ((geohash == null) || geohash.isEmpty())
285 | {
286 | throw new IllegalArgumentException("Argument geohash should not be null.");
287 | }
288 |
289 | final List adjacentAreas = new ArrayList<>();
290 | final String top = GeoHashExtensions.getAdjacent(geohash, Adjacent.TOP);
291 | final String bottom = GeoHashExtensions.getAdjacent(geohash, Adjacent.BOTTOM);
292 | final String right = GeoHashExtensions.getAdjacent(geohash, Adjacent.RIGHT);
293 | final String left = GeoHashExtensions.getAdjacent(geohash, Adjacent.LEFT);
294 | final String topleft = GeoHashExtensions.getAdjacent(left, Adjacent.TOP);
295 | final String topright = GeoHashExtensions.getAdjacent(right, Adjacent.TOP);
296 | final String bottomright = GeoHashExtensions.getAdjacent(right, Adjacent.BOTTOM);
297 | final String bottomleft = GeoHashExtensions.getAdjacent(left, Adjacent.BOTTOM);
298 | adjacentAreas.add(geohash);
299 | adjacentAreas.add(top);
300 | adjacentAreas.add(topright);
301 | adjacentAreas.add(right);
302 | adjacentAreas.add(bottomright);
303 | adjacentAreas.add(bottom);
304 | adjacentAreas.add(bottomleft);
305 | adjacentAreas.add(left);
306 | adjacentAreas.add(topleft);
307 | return adjacentAreas;
308 | }
309 |
310 | /**
311 | * Gets the geohash cells around the given geohash cell. With other words it gets eight cells
312 | * around the given geohash cell so the first ring inclusive the given geohash cell.
313 | *
314 | * @param geohash
315 | * the geohash
316 | * @return all geohash cells around the given geohash cell.
317 | */
318 | public static Map getAllAdjacentAreasMap(final String geohash)
319 | {
320 | if ((geohash == null) || geohash.isEmpty())
321 | {
322 | throw new IllegalArgumentException("Argument geohash should not be null.");
323 | }
324 |
325 | final String top = GeoHashExtensions.getAdjacent(geohash, Adjacent.TOP);
326 | final String bottom = GeoHashExtensions.getAdjacent(geohash, Adjacent.BOTTOM);
327 | final String right = GeoHashExtensions.getAdjacent(geohash, Adjacent.RIGHT);
328 | final String left = GeoHashExtensions.getAdjacent(geohash, Adjacent.LEFT);
329 | final String topleft = GeoHashExtensions.getAdjacent(left, Adjacent.TOP);
330 | final String topright = GeoHashExtensions.getAdjacent(right, Adjacent.TOP);
331 | final String bottomright = GeoHashExtensions.getAdjacent(right, Adjacent.BOTTOM);
332 | final String bottomleft = GeoHashExtensions.getAdjacent(left, Adjacent.BOTTOM);
333 |
334 | final Map adjacentAreas = new LinkedHashMap<>();
335 | adjacentAreas.put(Adjacent.CENTER, geohash);
336 | adjacentAreas.put(Adjacent.TOP, top);
337 | adjacentAreas.put(Adjacent.BOTTOM, bottom);
338 | adjacentAreas.put(Adjacent.RIGHT, right);
339 | adjacentAreas.put(Adjacent.LEFT, left);
340 | adjacentAreas.put(Adjacent.TOP_LEFT, topleft);
341 | adjacentAreas.put(Adjacent.TOP_RIGHT, topright);
342 | adjacentAreas.put(Adjacent.BOTTOM_RIGHT, bottomright);
343 | adjacentAreas.put(Adjacent.BOTTOM_LEFT, bottomleft);
344 |
345 | return adjacentAreas;
346 | }
347 |
348 | /**
349 | * Gets the geohash cells of the first and second ring region around the given geohash cell as a
350 | * {@link FirstAndSecondRingRegion} object.
351 | *
352 | * @param geohash
353 | * the geohash cell.
354 | * @return the {@link FirstAndSecondRingRegion} that encapsulates the cells of the first and
355 | * second ring region around the given geohash cell.
356 | */
357 | public static FirstAndSecondRingRegion getFirstAndSecondRingRegion(final String geohash)
358 | {
359 | return new FirstAndSecondRingRegion(geohash);
360 | }
361 |
362 | /**
363 | * Gets the geohash cells around the given geohash cell as a {@link FirstRingRegion} object.
364 | *
365 | * @param geohash
366 | * the geohash cell.
367 | * @return the {@link FirstRingRegion} object calculated from the given geohash value.
368 | */
369 | public static FirstRingRegion getFirstRingRegion(final String geohash)
370 | {
371 | return new FirstRingRegion(geohash);
372 | }
373 |
374 | /**
375 | * Gets the latitude from the given geohash value.
376 | *
377 | * @param geohash
378 | * the geohash
379 | * @return the latitude
380 | */
381 | public static double getLatitude(final String geohash)
382 | {
383 | return decodeAndRound(geohash)[0];
384 | }
385 |
386 | /**
387 | * Gets the longitude from the given geohash value.
388 | *
389 | * @param geohash
390 | * the geohash
391 | * @return the longitude
392 | */
393 | public static double getLongitude(final String geohash)
394 | {
395 | return decodeAndRound(geohash)[1];
396 | }
397 |
398 | /**
399 | * Gets the precision.
400 | *
401 | * @param x
402 | * the x
403 | * @param precision
404 | * the precision
405 | * @return the precision
406 | */
407 | private static double getPrecision(final double x, final double precision)
408 | {
409 | final double base = Math.pow(10, -precision);
410 | final double diff = x % base;
411 | return x - diff;
412 | }
413 |
414 | /**
415 | * Gets the eight cells around the given geohash cell so the first ring inclusive the given
416 | * geohash cell and cells from the second ring. The result is 24 cells plus the given geohash
417 | * cell.
418 | *
419 | * @param geohash
420 | * the geohash
421 | * @return the eight cells around the given geohash cell so the first ring inclusive the given
422 | * geohash cell and cells from the second ring.
423 | */
424 | public static Map getTwentyFiveAreasMap(final String geohash)
425 | {
426 | final Map adjacentAreas = getAllAdjacentAreasMap(geohash);
427 |
428 | final String topTop = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.TOP),
429 | Adjacent.TOP);
430 | final String topLeftTop = GeoHashExtensions
431 | .getAdjacent(adjacentAreas.get(Adjacent.TOP_LEFT), Adjacent.TOP);
432 | final String topLeftTopLeft = GeoHashExtensions.getAdjacent(topLeftTop, Adjacent.LEFT);
433 | final String topLeftLeft = GeoHashExtensions
434 | .getAdjacent(adjacentAreas.get(Adjacent.TOP_LEFT), Adjacent.LEFT);
435 | final String topRightTop = GeoHashExtensions
436 | .getAdjacent(adjacentAreas.get(Adjacent.TOP_RIGHT), Adjacent.TOP);
437 | final String topRightTopRight = GeoHashExtensions.getAdjacent(topRightTop, Adjacent.RIGHT);
438 | final String topRightRight = GeoHashExtensions
439 | .getAdjacent(adjacentAreas.get(Adjacent.TOP_RIGHT), Adjacent.RIGHT);
440 | final String rightRight = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.RIGHT),
441 | Adjacent.RIGHT);
442 | final String bottomRightRight = GeoHashExtensions
443 | .getAdjacent(adjacentAreas.get(Adjacent.BOTTOM_RIGHT), Adjacent.RIGHT);
444 | final String bottomRightBottom = GeoHashExtensions
445 | .getAdjacent(adjacentAreas.get(Adjacent.BOTTOM_RIGHT), Adjacent.BOTTOM);
446 | final String bottomRightBottomRight = GeoHashExtensions.getAdjacent(bottomRightBottom,
447 | Adjacent.RIGHT);
448 | final String bottomBottom = GeoHashExtensions
449 | .getAdjacent(adjacentAreas.get(Adjacent.BOTTOM), Adjacent.BOTTOM);
450 | final String bottomLeftBottom = GeoHashExtensions
451 | .getAdjacent(adjacentAreas.get(Adjacent.BOTTOM_LEFT), Adjacent.BOTTOM);
452 | final String bottomLeftBottomLeft = GeoHashExtensions.getAdjacent(bottomLeftBottom,
453 | Adjacent.LEFT);
454 | final String bottomLeftLeft = GeoHashExtensions
455 | .getAdjacent(adjacentAreas.get(Adjacent.BOTTOM_LEFT), Adjacent.LEFT);
456 | final String leftLeft = GeoHashExtensions.getAdjacent(adjacentAreas.get(Adjacent.LEFT),
457 | Adjacent.LEFT);
458 |
459 | adjacentAreas.put(Adjacent.TOP_LEFT_TOP, topLeftTop);
460 | adjacentAreas.put(Adjacent.TOP_LEFT_TOP_LEFT, topLeftTopLeft);
461 | adjacentAreas.put(Adjacent.TOP_LEFT_LEFT, topLeftLeft);
462 | adjacentAreas.put(Adjacent.TOP_TOP, topTop);
463 | adjacentAreas.put(Adjacent.TOP_RIGHT_TOP, topRightTop);
464 | adjacentAreas.put(Adjacent.TOP_RIGHT_RIGHT, topRightRight);
465 | adjacentAreas.put(Adjacent.TOP_RIGHT_TOP_RIGHT, topRightTopRight);
466 | adjacentAreas.put(Adjacent.RIGHT_RIGHT, rightRight);
467 | adjacentAreas.put(Adjacent.BOTTOM_RIGHT_RIGHT, bottomRightRight);
468 | adjacentAreas.put(Adjacent.BOTTOM_RIGHT_BOTTOM, bottomRightBottom);
469 | adjacentAreas.put(Adjacent.BOTTOM_RIGHT_BOTTOM_RIGHT, bottomRightBottomRight);
470 | adjacentAreas.put(Adjacent.BOTTOM_BOTTOM, bottomBottom);
471 | adjacentAreas.put(Adjacent.BOTTOM_LEFT_BOTTOM, bottomLeftBottom);
472 | adjacentAreas.put(Adjacent.BOTTOM_LEFT_BOTTOM_LEFT, bottomLeftBottomLeft);
473 | adjacentAreas.put(Adjacent.BOTTOM_LEFT_LEFT, bottomLeftLeft);
474 | adjacentAreas.put(Adjacent.LEFT_LEFT, leftLeft);
475 |
476 | return adjacentAreas;
477 | }
478 |
479 | }
480 |
--------------------------------------------------------------------------------