vtm-app: revive / update with latest VTM, closes #90

This commit is contained in:
Emux
2016-07-21 20:22:22 +03:00
parent c67b35a277
commit 436b66be82
133 changed files with 10436 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
package org.osmdroid.utils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* Useful functions and common constants.
*
* @author M.Kergall
*/
public class BonusPackHelper {
/**
* Log tag.
*/
public static final String LOG_TAG = "BONUSPACK";
/**
* User agent sent to services by default
*/
public static final String DEFAULT_USER_AGENT = "OsmBonusPack/1";
/**
* @return true if the device is the emulator, false if actual device.
*/
public static boolean isEmulator() {
//return Build.MANUFACTURER.equals("unknown");
return ("google_sdk".equals(Build.PRODUCT) || "sdk".equals(Build.PRODUCT));
}
/**
* @param connection ...
* @return the whole content of the http request, as a string
*/
private static String readStream(HttpConnection connection) {
String result = connection.getContentAsString();
return result;
}
/**
* sends an http request, and returns the whole content result in a String.
*
* @param url ...
* @return the whole content, or null if any issue.
*/
public static String requestStringFromUrl(String url) {
HttpConnection connection = new HttpConnection();
connection.doGet(url);
String result = readStream(connection);
connection.close();
return result;
}
/**
* Loads a bitmap from a url.
*
* @param url ...
* @return the bitmap, or null if any issue.
*/
public static Bitmap loadBitmap(String url) {
Bitmap bitmap = null;
try {
InputStream is = (InputStream) new URL(url).getContent();
bitmap = BitmapFactory.decodeStream(new FlushedInputStream(is));
//Alternative providing better handling on loading errors?
/* Drawable d = Drawable.createFromStream(new
* FlushedInputStream(is), null); if (is != null) is.close(); if (d
* != null) bitmap = ((BitmapDrawable)d).getBitmap(); */
} catch (FileNotFoundException e) {
//log.debug("image not available: " + url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bitmap;
}
/**
* Workaround on Android issue see
* http://stackoverflow.com/questions/4601352
* /createfromstream-in-android-returning-null-for-certain-url
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int byteValue = read();
if (byteValue < 0)
break; // we reached EOF
bytesSkipped = 1; // we read one byte
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
}

View File

@@ -0,0 +1,141 @@
package org.osmdroid.utils;
import org.oscim.core.GeoPoint;
import java.util.ArrayList;
import java.util.List;
/**
* Reduces the number of points in a shape using the Douglas-Peucker algorithm. <br>
* From:
* http://www.phpriot.com/articles/reducing-map-path-douglas-peucker-algorithm/4<br>
* Ported from PHP to Java. "marked" array added to optimize.
*
* @author M.Kergall
*/
public class DouglasPeuckerReducer {
/**
* Reduce the number of points in a shape using the Douglas-Peucker
* algorithm
*
* @param shape The shape to reduce
* @param tolerance The tolerance to decide whether or not to keep a point, in the
* coordinate system of the points (micro-degrees here)
* @return the reduced shape
*/
public static List<GeoPoint> reduceWithTolerance(List<GeoPoint> shape,
double tolerance) {
int n = shape.size();
// if a shape has 2 or less points it cannot be reduced
if (tolerance <= 0 || n < 3) {
return shape;
}
boolean[] marked = new boolean[n]; //vertex indexes to keep will be marked as "true"
for (int i = 1; i < n - 1; i++)
marked[i] = false;
// automatically add the first and last point to the returned shape
marked[0] = marked[n - 1] = true;
// the first and last points in the original shape are
// used as the entry point to the algorithm.
douglasPeuckerReduction(
shape, // original shape
marked, // reduced shape
tolerance, // tolerance
0, // index of first point
n - 1 // index of last point
);
// all done, return the reduced shape
ArrayList<GeoPoint> newShape = new ArrayList<GeoPoint>(n); // the new shape to return
for (int i = 0; i < n; i++) {
if (marked[i])
newShape.add(shape.get(i));
}
return newShape;
}
/**
* Reduce the points in shape between the specified first and last index.
* Mark the points to keep in marked[]
*
* @param shape The original shape
* @param marked The points to keep (marked as true)
* @param tolerance The tolerance to determine if a point is kept
* @param firstIdx The index in original shape's point of the starting point for
* this line segment
* @param lastIdx The index in original shape's point of the ending point for
* this line segment
*/
private static void douglasPeuckerReduction(List<GeoPoint> 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);
}
}

View File

@@ -0,0 +1,119 @@
package org.osmdroid.utils;
import android.util.Log;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
/**
* 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.
* <p/>
* Typical usage:
* <pre>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();</pre>
*/
public class HttpConnection {
private final static int TIMEOUT_CONNECTION = 3000; //ms
private final static int TIMEOUT_SOCKET = 10000; //ms
private static OkHttpClient client;
private InputStream stream;
private String mUserAgent;
private Response response;
private static OkHttpClient getOkHttpClient() {
if (client == null) {
client = new OkHttpClient();
client.setConnectTimeout(TIMEOUT_CONNECTION, TimeUnit.MILLISECONDS);
client.setReadTimeout(TIMEOUT_SOCKET, TimeUnit.MILLISECONDS);
}
return client;
}
public HttpConnection() {
/*
client = new OkHttpClient();
client.setConnectTimeout(TIMEOUT_CONNECTION, TimeUnit.MILLISECONDS);
client.setReadTimeout(TIMEOUT_SOCKET, TimeUnit.MILLISECONDS);
*/
}
public void setUserAgent(String userAgent) {
mUserAgent = userAgent;
}
public void doGet(final String url) {
try {
Request.Builder request = new Request.Builder().url(url);
if (mUserAgent != null)
request.addHeader("User-Agent", mUserAgent);
response = getOkHttpClient().newCall(request.build()).execute();
Integer status = response.code();
if (status != 200) {
Log.e(BonusPackHelper.LOG_TAG, "Invalid response from server: " + status.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @return the opened InputStream, or null if creation failed for any reason.
*/
public InputStream getStream() {
try {
if (response == null)
return null;
stream = response.body().byteStream();
return stream;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* @return the whole content as a String, or null if creation failed for any reason.
*/
public String getContentAsString() {
try {
if (response == null)
return null;
return response.body().string();
} 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 (client != null)
client = null;
*/
}
}

View File

@@ -0,0 +1,22 @@
/*
* 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
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.osmdroid.utils;
public class MathConstants {
public static final double PI180E6 = (Math.PI / 180) / 1000000.0;
public static final double PIx4 = Math.PI * 4;
}

View File

@@ -0,0 +1,94 @@
package org.osmdroid.utils;
import org.oscim.core.GeoPoint;
import java.util.ArrayList;
/**
* 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<GeoPoint> 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<GeoPoint> decode(String encodedString, int precision) {
ArrayList<GeoPoint> polyline = new ArrayList<GeoPoint>();
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;
}
}