@@ -125,6 +125,7 @@ static KmlGroundOverlay createGroundOverlay(XmlPullParser parser)
125
125
LatLngBounds latLonBox ;
126
126
HashMap <String , String > properties = new HashMap <String , String >();
127
127
HashMap <String , Double > compassPoints = new HashMap <String , Double >();
128
+ ArrayList <LatLng > latLonQuad = null ;
128
129
129
130
int eventType = parser .getEventType ();
130
131
while (!(eventType == END_TAG && parser .getName ().equals ("GroundOverlay" ))) {
@@ -143,16 +144,81 @@ static KmlGroundOverlay createGroundOverlay(XmlPullParser parser)
143
144
properties .put (parser .getName (), parser .nextText ());
144
145
} else if (parser .getName ().matches (COMPASS_REGEX )) {
145
146
compassPoints .put (parser .getName (), Double .parseDouble (parser .nextText ()));
147
+ } else if (parser .getName ().equals ("LatLonQuad" )) {
148
+ latLonQuad = getLatLonQuad (parser );
146
149
}
147
150
}
148
151
eventType = parser .next ();
149
152
}
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
+ }
150
178
latLonBox = createLatLngBounds (compassPoints .get ("north" ), compassPoints .get ("south" ),
151
179
compassPoints .get ("east" ), compassPoints .get ("west" ));
152
180
return new KmlGroundOverlay (imageUrl , latLonBox , drawOrder , visibility , properties ,
153
181
rotation );
154
182
}
155
183
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
+
156
222
private static float getRotation (XmlPullParser parser )
157
223
throws IOException , XmlPullParserException {
158
224
return -Float .parseFloat (parser .nextText ());
0 commit comments