server refactoring

This commit is contained in:
simon 2020-09-02 23:31:12 +03:00
parent 6a95630076
commit e47493a229
3 changed files with 160 additions and 80 deletions

View file

@ -2,6 +2,8 @@ package net.osmand.data;
import net.osmand.util.MapUtils;
import java.util.Objects;
public class RotatedTileBox {
/// primary fields
@ -69,6 +71,47 @@ public class RotatedTileBox {
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RotatedTileBox tileBox = (RotatedTileBox) o;
return Double.compare(tileBox.lat, lat) == 0 &&
Double.compare(tileBox.lon, lon) == 0 &&
Float.compare(tileBox.rotate, rotate) == 0 &&
Float.compare(tileBox.density, density) == 0 &&
zoom == tileBox.zoom &&
Double.compare(tileBox.mapDensity, mapDensity) == 0 &&
Double.compare(tileBox.zoomAnimation, zoomAnimation) == 0 &&
Double.compare(tileBox.zoomFloatPart, zoomFloatPart) == 0 &&
cx == tileBox.cx &&
cy == tileBox.cy &&
pixWidth == tileBox.pixWidth &&
pixHeight == tileBox.pixHeight &&
Double.compare(tileBox.zoomFactor, zoomFactor) == 0 &&
Double.compare(tileBox.rotateCos, rotateCos) == 0 &&
Double.compare(tileBox.rotateSin, rotateSin) == 0 &&
Double.compare(tileBox.oxTile, oxTile) == 0 &&
Double.compare(tileBox.oyTile, oyTile) == 0;
}
@Override
public int hashCode() {
int result = 1 + (int)lat +
3* (int)lon +
5* (int)rotate +
7* (int)density +
11* (int)zoom +
13* (int)mapDensity +
17* (int)zoomAnimation +
19* (int)zoomFloatPart +
23* (int)cx +
29* (int)cy +
31* (int)pixWidth +
37* (int)pixHeight;
return result;
}
public void calculateDerivedFields() {
zoomFactor = Math.pow(2, zoomAnimation + zoomFloatPart) * 256 * mapDensity;
double rad = Math.toRadians(this.rotate);

View file

@ -1,37 +1,28 @@
package net.osmand.plus.server;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.util.Pair;
import android.webkit.MimeTypeMap;
import androidx.core.util.Pair;
import com.google.gson.Gson;
import fi.iki.elonen.NanoHTTPD;
import net.osmand.data.*;
import net.osmand.map.ITileSource;
import net.osmand.map.TileSourceManager;
import net.osmand.data.FavouritePoint;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.server.map.LayersDraw;
import net.osmand.plus.server.map.MapTileMiniLayer;
import net.osmand.plus.server.map.OsmandMapMiniLayer;
import net.osmand.plus.server.map.OsmandMapTileMiniView;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.*;
import java.util.concurrent.*;
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
public class ApiRouter {
public class ApiRouter implements OsmandMapTileView.IMapImageDrawListener {
private OsmandApplication androidContext;
public OsmandApplication getAndroidContext() {
return androidContext;
}
@ -42,80 +33,92 @@ public class ApiRouter {
//change to weakreference
public static MapActivity mapActivity;
public ApiRouter(){
public ApiRouter() {
initRoutes();
}
private void initRoutes() {
ApiEndpoint favorites = new ApiEndpoint();
favorites.uri = "/favorites";
favorites.apiCall = new ApiEndpoint.ApiCall(){
favorites.apiCall = new ApiEndpoint.ApiCall() {
@Override
public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) {
return newFixedLengthResponse(getFavoritesJson());
}
};
endpoints.put(favorites.uri,favorites);
endpoints.put(favorites.uri, favorites);
final ApiEndpoint tile = new ApiEndpoint();
tile.uri = "/tile";
tile.apiCall = new ApiEndpoint.ApiCall(){
tile.apiCall = new ApiEndpoint.ApiCall() {
@Override
public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) {
try{
int zoom = 0;
double lat = 0;//50.901430;
double lon = 0;//34.801775;
try{
String fullUri = session.getUri().replace("/tile/","");
Scanner s = new Scanner(fullUri).useDelimiter("/");
zoom = s.nextInt();
lat = s.nextDouble();//50.901430;
lon = s.nextDouble();//34.801775;
}
catch (Exception e){
e.printStackTrace();
return ErrorResponses.response500;
}
Log.d("TILE","HAVING VALUES" + zoom + " " + lat + " " + lon);
RotatedTileBox rotatedTileBox = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
rotatedTileBox.setZoom(zoom);
rotatedTileBox.setLatLonCenter(lat,lon);
rotatedTileBox.setPixelDimensions(512,512);
mapActivity.getMapView().setIntZoom(zoom);
mapActivity.getMapView().setLatLon(lat,lon);
OsmandMapLayer.DrawSettings param =
new OsmandMapLayer.DrawSettings(androidContext.getDaynightHelper().isNightMode(),
false);
mapActivity.getMapView().refreshMap();
mapActivity.getMapView().refreshMapInternal(param);
mapActivity.getMapView().refreshBaseMapInternal(rotatedTileBox, param);
Bitmap bitmap = mapActivity.getMapView().currentCanvas;
Canvas canvas = new Canvas(bitmap);
OsmandMapLayer.DrawSettings drawSettings = new OsmandMapLayer.DrawSettings(
androidContext.getDaynightHelper().isNightMode(),
true);
// mapActivity.getMapView().drawOverMap(canvas,
// rotatedTileBox,
// drawSettings);
//Bitmap bitmap = Bitmap.createBitmap(512,512,Bitmap.Config.ARGB_8888);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream str = new ByteArrayInputStream(byteArray);
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"image/png",
str,
str.available());
}
catch (Exception e){
try {
return tileApiCall(session);
} catch (Exception e) {
e.printStackTrace();
}
return ErrorResponses.response500;
}
};
endpoints.put(tile.uri,tile);
endpoints.put(tile.uri, tile);
}
ExecutorService executor = Executors.newFixedThreadPool(3);
Map<RotatedTileBox,Bitmap> hashMap = new HashMap<>();
Map<RotatedTileBox,Bitmap> map = Collections.synchronizedMap(hashMap);
private NanoHTTPD.Response tileApiCall(NanoHTTPD.IHTTPSession session) {
int zoom = 0;
double lat = 0;//50.901430;
double lon = 0;//34.801775;
try {
String fullUri = session.getUri().replace("/tile/", "");
Scanner s = new Scanner(fullUri).useDelimiter("/");
zoom = s.nextInt();
lat = s.nextDouble();
lon = s.nextDouble();
} catch (Exception e) {
e.printStackTrace();
return ErrorResponses.response500;
}
mapActivity.getMapView().setMapImageDrawListener(this);
Future<Pair<RotatedTileBox,Bitmap>> future;
final RotatedTileBox rotatedTileBox = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
rotatedTileBox.setZoom(zoom);
rotatedTileBox.setLatLonCenter(lat, lon);
rotatedTileBox.setPixelDimensions(512, 512);
future = executor.submit(new Callable<Pair<RotatedTileBox, Bitmap>>() {
@Override
public Pair<RotatedTileBox, Bitmap> call() throws Exception {
Bitmap bmp;
while((bmp = map.get(rotatedTileBox)) == null) {
Thread.sleep(1000);
}
return Pair.create(rotatedTileBox,bmp);
}
});
mapActivity.getMapView().setCurrentRotatedTileBox(rotatedTileBox);
try {
Pair<RotatedTileBox, Bitmap> pair = future.get();
Bitmap bitmap = pair.second;// mapActivity.getMapView().currentCanvas;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
ByteArrayInputStream str = new ByteArrayInputStream(byteArray);
return newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"image/png",
str,
str.available());
} catch (ExecutionException e) {
e.printStackTrace();
return ErrorResponses.response500;
} catch (InterruptedException e) {
e.printStackTrace();
return ErrorResponses.response500;
}
}
public void setAndroidContext(OsmandApplication androidContext) {
@ -132,10 +135,9 @@ public class ApiRouter {
uri.contains("/fonts/") ||
uri.contains("/favicon.ico")
) return getStatic(uri);
if (isApiUrl(uri)){
if (isApiUrl(uri)) {
return routeApi(session);
}
else {
} else {
return routeContent(session);
}
}
@ -143,18 +145,18 @@ public class ApiRouter {
private NanoHTTPD.Response routeApi(NanoHTTPD.IHTTPSession session) {
String uri = session.getUri();
//TODO rewrite
if (uri.contains("tile")){
if (uri.contains("tile")) {
return endpoints.get("/tile").apiCall.call(session);
}
ApiEndpoint endpoint = endpoints.get(uri);
if (endpoint != null){
if (endpoint != null) {
return endpoint.apiCall.call(session);
}
return ErrorResponses.response404;
}
private boolean isApiUrl(String uri) {
for (String endpoint : endpoints.keySet()){
for (String endpoint : endpoints.keySet()) {
//TODO rewrite contains
if (endpoint.equals(uri) || uri.contains("tile")) return true;
}
@ -240,13 +242,18 @@ public class ApiRouter {
text.append(json);
text.append(",");
}
return "[" + text.substring(0,text.length()-1) + "]";
return "[" + text.substring(0, text.length() - 1) + "]";
}
private String jsonFromFavorite(FavouritePoint favouritePoint) {
return gson.toJson(favouritePoint);
}
@Override
public void onDraw(RotatedTileBox viewport, Bitmap bmp) {
this.map.put(viewport,bmp);
}
static class ErrorResponses {
static NanoHTTPD.Response response404 =
newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND,

View file

@ -105,7 +105,6 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
protected static final int emptyTileDivisor = 16;
public interface OnTrackBallListener {
public boolean onTrackBallEvent(MotionEvent e);
}
@ -122,6 +121,10 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
public void onDrawOverMap();
}
public interface IMapImageDrawListener {
public void onDraw(RotatedTileBox viewport,Bitmap bmp);
}
protected static final Log LOG = PlatformUtil.getLog(OsmandMapTileView.class);
@ -145,6 +148,8 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
private OnTrackBallListener trackBallDelegate;
private IMapImageDrawListener iMapImageDrawListener;
private AccessibilityActionsProvider accessibilityActions;
private List<OsmandMapLayer> layers = new ArrayList<>();
@ -367,6 +372,14 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
return wasZoomInMultiTouch;
}
public IMapImageDrawListener getMapImageDrawListener() {
return iMapImageDrawListener;
}
public void setMapImageDrawListener(IMapImageDrawListener iMapImageDrawListener) {
this.iMapImageDrawListener = iMapImageDrawListener;
}
public boolean mapGestureAllowed(OsmandMapLayer.MapGestureType type) {
for (OsmandMapLayer layer : layers) {
if (!layer.isMapGestureAllowed(type)) {
@ -518,8 +531,8 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
public void restoreMapRatio() {
RotatedTileBox box = currentViewport.copy();
float rx = (float)box.getCenterPixelX() / box.getPixWidth();
float ry = (float)box.getCenterPixelY() / box.getPixHeight();
float rx = (float) box.getCenterPixelX() / box.getPixWidth();
float ry = (float) box.getCenterPixelY() / box.getPixHeight();
if (mapPosition == OsmandSettings.BOTTOM_CONSTANT) {
ry -= 0.35;
}
@ -616,6 +629,9 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
}
long end = SystemClock.elapsedRealtime();
additional.calculateFPS(start, end);
if (iMapImageDrawListener != null){
iMapImageDrawListener.onDraw(tileBox,bufferBitmap);
}
}
public void refreshMapInternal(DrawSettings drawSettings) {
@ -871,6 +887,20 @@ public class OsmandMapTileView implements IMapDownloaderCallback {
return currentViewport;
}
public void setCurrentRotatedTileBox(net.osmand.data.RotatedTileBox tileBox) {
float rx = (float) tileBox.getCenterPixelX() / tileBox.getPixWidth();
float ry = (float) tileBox.getCenterPixelY() / tileBox.getPixHeight();
if (mapPosition == OsmandSettings.BOTTOM_CONSTANT) {
ry -= 0.35;
}
tileBox.setCenterLocation(rx, ry);
LatLon screenCenter = tileBox.getLatLonFromPixel(tileBox.getPixWidth() / 2f, tileBox.getPixHeight() / 2f);
mapRatioX = 0;
mapRatioY = 0;
setLatLon(screenCenter.getLatitude(), screenCenter.getLongitude());
currentViewport = tileBox;
}
public float getDensity() {
return currentViewport.getDensity();
}