shape, boolean[] marked,
+ double tolerance, int firstIdx, int lastIdx)
+ {
+ if (lastIdx <= firstIdx + 1) {
+ // overlapping indexes, just return
+ return;
+ }
+
+ // loop over the points between the first and last points
+ // and find the point that is the farthest away
+
+ double maxDistance = 0.0;
+ int indexFarthest = 0;
+
+ GeoPoint firstPoint = shape.get(firstIdx);
+ GeoPoint lastPoint = shape.get(lastIdx);
+
+ for (int idx = firstIdx + 1; idx < lastIdx; idx++) {
+ GeoPoint point = shape.get(idx);
+
+ double distance = orthogonalDistance(point, firstPoint, lastPoint);
+
+ // keep the point with the greatest distance
+ if (distance > maxDistance) {
+ maxDistance = distance;
+ indexFarthest = idx;
+ }
+ }
+
+ if (maxDistance > tolerance) {
+ //The farthest point is outside the tolerance: it is marked and the algorithm continues.
+ marked[indexFarthest] = true;
+
+ // reduce the shape between the starting point to newly found point
+ douglasPeuckerReduction(shape, marked, tolerance, firstIdx, indexFarthest);
+
+ // reduce the shape between the newly found point and the finishing point
+ douglasPeuckerReduction(shape, marked, tolerance, indexFarthest, lastIdx);
+ }
+ //else: the farthest point is within the tolerance, the whole segment is discarded.
+ }
+
+ /**
+ * Calculate the orthogonal distance from the line joining the lineStart and
+ * lineEnd points to point
+ *
+ * @param point
+ * The point the distance is being calculated for
+ * @param lineStart
+ * The point that starts the line
+ * @param lineEnd
+ * The point that ends the line
+ * @return The distance in points coordinate system
+ */
+ public static double orthogonalDistance(GeoPoint point, GeoPoint lineStart, GeoPoint lineEnd)
+ {
+ double area = Math.abs(
+ (
+ 1.0 * lineStart.latitudeE6 * lineEnd.longitudeE6
+ + 1.0 * lineEnd.latitudeE6 * point.longitudeE6
+ + 1.0 * point.latitudeE6 * lineStart.longitudeE6
+ - 1.0 * lineEnd.latitudeE6 * lineStart.longitudeE6
+ - 1.0 * point.latitudeE6 * lineEnd.longitudeE6
+ - 1.0 * lineStart.latitudeE6 * point.longitudeE6
+ ) / 2.0
+ );
+
+ double bottom = Math.hypot(
+ lineStart.latitudeE6 - lineEnd.latitudeE6,
+ lineStart.longitudeE6 - lineEnd.longitudeE6
+ );
+
+ return (area / bottom * 2.0);
+ }
+}
diff --git a/src/org/osmdroid/utils/HttpConnection.java b/src/org/osmdroid/utils/HttpConnection.java
new file mode 100644
index 00000000..5e126176
--- /dev/null
+++ b/src/org/osmdroid/utils/HttpConnection.java
@@ -0,0 +1,170 @@
+package org.osmdroid.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.util.EntityUtils;
+
+import android.util.Log;
+
+/**
+ * A "very very simple to use" class for performing http get and post requests.
+ * So many ways to do that, and potential subtle issues. If complexity should be
+ * added to handle even more issues, complexity should be put here and only
+ * here. Typical usage:
+ *
+ *
+ * HttpConnection connection = new HttpConnection();
+ * connection.doGet("http://www.google.com");
+ * InputStream stream = connection.getStream();
+ * if (stream != null) {
+ * //use this stream, for buffer reading, or XML SAX parsing, or whatever...
+ * }
+ * connection.close();
+ *
+ */
+public class HttpConnection {
+
+ private DefaultHttpClient client;
+ private InputStream stream;
+ private HttpEntity entity;
+ private String mUserAgent;
+
+ private final static int TIMEOUT_CONNECTION = 3000; //ms
+ private final static int TIMEOUT_SOCKET = 8000; //ms
+
+ /**
+ * Constructor. Opens the url with an HttpURLConnection, then opens a stream
+ * on it. param sUrl : url to open
+ */
+ public HttpConnection() {
+ stream = null;
+ entity = null;
+ HttpParams httpParameters = new BasicHttpParams();
+ /*
+ * useful? HttpProtocolParams.setContentCharset(httpParameters,
+ * "UTF-8"); HttpProtocolParams.setHttpElementCharset(httpParameters,
+ * "UTF-8");
+ */
+ // Set the timeout in milliseconds until a connection is established.
+ HttpConnectionParams.setConnectionTimeout(httpParameters, TIMEOUT_CONNECTION);
+ // Set the default socket timeout (SO_TIMEOUT)
+ // in milliseconds which is the timeout for waiting for data.
+ HttpConnectionParams.setSoTimeout(httpParameters, TIMEOUT_SOCKET);
+ client = new DefaultHttpClient(httpParameters);
+ //TODO: created here. Reuse to do for better perfs???...
+ }
+
+ public void setUserAgent(String userAgent) {
+ mUserAgent = userAgent;
+ }
+
+ public void doGet(String sUrl) {
+ HttpGet request = new HttpGet(sUrl);
+ if (mUserAgent != null)
+ request.setHeader("User-Agent", mUserAgent);
+ try {
+ HttpResponse response = client.execute(request);
+ StatusLine status = response.getStatusLine();
+ if (status.getStatusCode() != 200) {
+ Log.e(BonusPackHelper.LOG_TAG, "Invalid response from server: " + status.toString());
+ } else {
+ entity = response.getEntity();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void doPost(String sUrl, List nameValuePairs) {
+ HttpPost request = new HttpPost(sUrl);
+ if (mUserAgent != null)
+ request.setHeader("User-Agent", mUserAgent);
+ try {
+ request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
+ HttpResponse response = client.execute(request);
+ StatusLine status = response.getStatusLine();
+ if (status.getStatusCode() != 200) {
+ Log.e(BonusPackHelper.LOG_TAG, "Invalid response from server: " + status.toString());
+ } else {
+ entity = response.getEntity();
+ }
+ } catch (ClientProtocolException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @return the opened InputStream, or null if creation failed for any
+ * reason.
+ */
+ public InputStream getStream() {
+ try {
+ if (entity != null)
+ stream = entity.getContent();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return stream;
+ }
+
+ /**
+ * @return the whole content as a String, or null if creation failed for any
+ * reason.
+ */
+ public String getContentAsString() {
+ try {
+ if (entity != null) {
+ return EntityUtils.toString(entity, "UTF-8");
+ //setting the charset is important if none found in the entity.
+ }
+ return null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Calling close once is mandatory.
+ */
+ public void close() {
+ if (stream != null) {
+ try {
+ stream.close();
+ stream = null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (entity != null) {
+ try {
+ entity.consumeContent();
+ //"finish". Important if we want to reuse the client object one day...
+ entity = null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ if (client != null) {
+ client.getConnectionManager().shutdown();
+ client = null;
+ }
+ }
+
+}
diff --git a/src/org/oscim/view/OverlayManager.java b/src/org/osmdroid/utils/MathConstants.java
similarity index 75%
rename from src/org/oscim/view/OverlayManager.java
rename to src/org/osmdroid/utils/MathConstants.java
index a2fecf77..b4e5b95e 100644
--- a/src/org/oscim/view/OverlayManager.java
+++ b/src/org/osmdroid/utils/MathConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Hannes Janetzek
+ * Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -12,8 +12,11 @@
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
-package org.oscim.view;
+package org.osmdroid.utils;
-public class OverlayManager {
+public class MathConstants {
+
+ public static final double PI180E6 = (Math.PI / 180) / 1000000.0;
+ public static final double PIx4 = Math.PI * 4;
}
diff --git a/src/org/osmdroid/utils/PolylineEncoder.java b/src/org/osmdroid/utils/PolylineEncoder.java
new file mode 100644
index 00000000..5eefaa07
--- /dev/null
+++ b/src/org/osmdroid/utils/PolylineEncoder.java
@@ -0,0 +1,98 @@
+package org.osmdroid.utils;
+
+import java.util.ArrayList;
+
+import org.oscim.core.GeoPoint;
+
+/**
+ * Methods to encode and decode a polyline with Google polyline
+ * encoding/decoding scheme. See
+ * https://developers.google.com/maps/documentation/utilities/polylinealgorithm
+ */
+public class PolylineEncoder {
+
+ private static StringBuffer encodeSignedNumber(int num) {
+ int sgn_num = num << 1;
+ if (num < 0) {
+ sgn_num = ~(sgn_num);
+ }
+ return (encodeNumber(sgn_num));
+ }
+
+ private static StringBuffer encodeNumber(int num) {
+ StringBuffer encodeString = new StringBuffer();
+ while (num >= 0x20) {
+ int nextValue = (0x20 | (num & 0x1f)) + 63;
+ encodeString.append((char) (nextValue));
+ num >>= 5;
+ }
+ num += 63;
+ encodeString.append((char) (num));
+ return encodeString;
+ }
+
+ /**
+ * Encode a polyline with Google polyline encoding method
+ *
+ * @param polyline
+ * the polyline
+ * @param precision
+ * 1 for a 6 digits encoding, 10 for a 5 digits encoding.
+ * @return the encoded polyline, as a String
+ */
+ public static String encode(ArrayList polyline, int precision) {
+ StringBuffer encodedPoints = new StringBuffer();
+ int prev_lat = 0, prev_lng = 0;
+ for (GeoPoint trackpoint : polyline) {
+ int lat = trackpoint.latitudeE6 / precision;
+ int lng = trackpoint.longitudeE6 / precision;
+ encodedPoints.append(encodeSignedNumber(lat - prev_lat));
+ encodedPoints.append(encodeSignedNumber(lng - prev_lng));
+ prev_lat = lat;
+ prev_lng = lng;
+ }
+ return encodedPoints.toString();
+ }
+
+ /**
+ * Decode a "Google-encoded" polyline
+ *
+ * @param encodedString
+ * ...
+ * @param precision
+ * 1 for a 6 digits encoding, 10 for a 5 digits encoding.
+ * @return the polyline.
+ */
+ public static ArrayList decode(String encodedString, int precision) {
+ ArrayList polyline = new ArrayList();
+ int index = 0;
+ int len = encodedString.length();
+ int lat = 0, lng = 0;
+
+ while (index < len) {
+ int b, shift = 0, result = 0;
+ do {
+ b = encodedString.charAt(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lat += dlat;
+
+ shift = 0;
+ result = 0;
+ do {
+ b = encodedString.charAt(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lng += dlng;
+
+ GeoPoint p = new GeoPoint(lat * precision, lng * precision);
+ polyline.add(p);
+ }
+
+ return polyline;
+ }
+}