Skip to content

Commit c50e8f9

Browse files
committed
feat: implemented support for parsing GroundOverlay with LatLonQuad boundaries
1 parent dd85f6f commit c50e8f9

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

Diff for: library/src/main/java/com/google/maps/android/data/kml/KmlFeatureParser.java

+66
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static KmlGroundOverlay createGroundOverlay(XmlPullParser parser)
125125
LatLngBounds latLonBox;
126126
HashMap<String, String> properties = new HashMap<String, String>();
127127
HashMap<String, Double> compassPoints = new HashMap<String, Double>();
128+
ArrayList<LatLng> latLonQuad = null;
128129

129130
int eventType = parser.getEventType();
130131
while (!(eventType == END_TAG && parser.getName().equals("GroundOverlay"))) {
@@ -143,16 +144,81 @@ static KmlGroundOverlay createGroundOverlay(XmlPullParser parser)
143144
properties.put(parser.getName(), parser.nextText());
144145
} else if (parser.getName().matches(COMPASS_REGEX)) {
145146
compassPoints.put(parser.getName(), Double.parseDouble(parser.nextText()));
147+
} else if (parser.getName().equals("LatLonQuad")) {
148+
latLonQuad = getLatLonQuad(parser);
146149
}
147150
}
148151
eventType = parser.next();
149152
}
153+
154+
if (compassPoints.isEmpty() && latLonQuad != null && latLonQuad.size() >= 4) {
155+
//read coordinates from quad
156+
LatLng sw = latLonQuad.get(0);
157+
LatLng se = latLonQuad.get(1);
158+
LatLng ne = latLonQuad.get(2);
159+
LatLng nw = latLonQuad.get(3);
160+
161+
//calculate rotation from coordinates
162+
double nRot = 90 - bearing(nw, ne);
163+
double sRot = 270 - bearing(se, sw);
164+
165+
rotation = -(float)((nRot + sRot) / 2.0);
166+
167+
//this is an approximation that rectifies the quad in order to make it rectangular
168+
double n = (ne.latitude + nw.latitude) / 2.0;
169+
double s = (se.latitude + sw.latitude) / 2.0;
170+
double e = (ne.longitude + se.longitude) / 2.0;
171+
double w = (nw.longitude + sw.longitude) / 2.0;
172+
173+
compassPoints.put("north", n);
174+
compassPoints.put("south", s);
175+
compassPoints.put("east", e);
176+
compassPoints.put("west", w);
177+
}
150178
latLonBox = createLatLngBounds(compassPoints.get("north"), compassPoints.get("south"),
151179
compassPoints.get("east"), compassPoints.get("west"));
152180
return new KmlGroundOverlay(imageUrl, latLonBox, drawOrder, visibility, properties,
153181
rotation);
154182
}
155183

184+
private static ArrayList<LatLng> getLatLonQuad(XmlPullParser parser)
185+
throws XmlPullParserException, IOException {
186+
ArrayList<LatLng> latLonQuad = null;
187+
int eventType = parser.getEventType();
188+
while (!(eventType == END_TAG && parser.getName().equals("LatLonQuad"))) {
189+
if (eventType == START_TAG) {
190+
if (parser.getName().equals("coordinates")) {
191+
latLonQuad = convertToLatLngArray(parser.nextText());
192+
}
193+
}
194+
eventType = parser.next();
195+
}
196+
return latLonQuad;
197+
}
198+
199+
private static double bearing(LatLng from, LatLng to) {
200+
// formula: θ = atan2(sin(Δlong).cos(lat2), cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong))
201+
// source: http://www.movable-type.co.uk/scripts/latlong.html
202+
203+
double lat1 = Math.toRadians(from.latitude);
204+
double lon1 = Math.toRadians(from.longitude);
205+
double lat2 = Math.toRadians(to.latitude);
206+
double lon2 = Math.toRadians(to.longitude);
207+
double dLon = lon2 - lon1;
208+
double y = Math.sin(dLon) * Math.cos(lat2);
209+
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
210+
211+
double res = Math.toDegrees(Math.atan2(y, x));
212+
213+
// Since atan2 returns values in the range [-M_PI, +M_PI] (that is, [-180°, +180°]),
214+
// we need to normalise the result in the range [0°, 360°]
215+
if (res < 0) {
216+
res += 360;
217+
}
218+
219+
return res;
220+
}
221+
156222
private static float getRotation(XmlPullParser parser)
157223
throws IOException, XmlPullParserException {
158224
return -Float.parseFloat(parser.nextText());

0 commit comments

Comments
 (0)