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 net.osmand.util.MapUtils;
import java.util.Objects;
public class RotatedTileBox { public class RotatedTileBox {
/// primary fields /// 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() { public void calculateDerivedFields() {
zoomFactor = Math.pow(2, zoomAnimation + zoomFloatPart) * 256 * mapDensity; zoomFactor = Math.pow(2, zoomAnimation + zoomFloatPart) * 256 * mapDensity;
double rad = Math.toRadians(this.rotate); double rad = Math.toRadians(this.rotate);

View file

@ -1,37 +1,28 @@
package net.osmand.plus.server; package net.osmand.plus.server;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import androidx.core.util.Pair;
import com.google.gson.Gson; import com.google.gson.Gson;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import net.osmand.data.*; import net.osmand.data.FavouritePoint;
import net.osmand.map.ITileSource; import net.osmand.data.RotatedTileBox;
import net.osmand.map.TileSourceManager;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.activities.MapActivity; 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.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import java.io.*; import java.io.*;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.HashMap; import java.util.*;
import java.util.List; import java.util.concurrent.*;
import java.util.Map;
import java.util.Scanner;
import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse; import static fi.iki.elonen.NanoHTTPD.newFixedLengthResponse;
public class ApiRouter { public class ApiRouter implements OsmandMapTileView.IMapImageDrawListener {
private OsmandApplication androidContext; private OsmandApplication androidContext;
public OsmandApplication getAndroidContext() { public OsmandApplication getAndroidContext() {
return androidContext; return androidContext;
} }
@ -42,80 +33,92 @@ public class ApiRouter {
//change to weakreference //change to weakreference
public static MapActivity mapActivity; public static MapActivity mapActivity;
public ApiRouter(){ public ApiRouter() {
initRoutes(); initRoutes();
} }
private void initRoutes() { private void initRoutes() {
ApiEndpoint favorites = new ApiEndpoint(); ApiEndpoint favorites = new ApiEndpoint();
favorites.uri = "/favorites"; favorites.uri = "/favorites";
favorites.apiCall = new ApiEndpoint.ApiCall(){ favorites.apiCall = new ApiEndpoint.ApiCall() {
@Override @Override
public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) { public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) {
return newFixedLengthResponse(getFavoritesJson()); return newFixedLengthResponse(getFavoritesJson());
} }
}; };
endpoints.put(favorites.uri,favorites); endpoints.put(favorites.uri, favorites);
final ApiEndpoint tile = new ApiEndpoint(); final ApiEndpoint tile = new ApiEndpoint();
tile.uri = "/tile"; tile.uri = "/tile";
tile.apiCall = new ApiEndpoint.ApiCall(){ tile.apiCall = new ApiEndpoint.ApiCall() {
@Override @Override
public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) { public NanoHTTPD.Response call(NanoHTTPD.IHTTPSession session) {
try{ try {
int zoom = 0; return tileApiCall(session);
double lat = 0;//50.901430; } catch (Exception e) {
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){
e.printStackTrace(); e.printStackTrace();
} }
return ErrorResponses.response500; 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) { public void setAndroidContext(OsmandApplication androidContext) {
@ -132,10 +135,9 @@ public class ApiRouter {
uri.contains("/fonts/") || uri.contains("/fonts/") ||
uri.contains("/favicon.ico") uri.contains("/favicon.ico")
) return getStatic(uri); ) return getStatic(uri);
if (isApiUrl(uri)){ if (isApiUrl(uri)) {
return routeApi(session); return routeApi(session);
} } else {
else {
return routeContent(session); return routeContent(session);
} }
} }
@ -143,18 +145,18 @@ public class ApiRouter {
private NanoHTTPD.Response routeApi(NanoHTTPD.IHTTPSession session) { private NanoHTTPD.Response routeApi(NanoHTTPD.IHTTPSession session) {
String uri = session.getUri(); String uri = session.getUri();
//TODO rewrite //TODO rewrite
if (uri.contains("tile")){ if (uri.contains("tile")) {
return endpoints.get("/tile").apiCall.call(session); return endpoints.get("/tile").apiCall.call(session);
} }
ApiEndpoint endpoint = endpoints.get(uri); ApiEndpoint endpoint = endpoints.get(uri);
if (endpoint != null){ if (endpoint != null) {
return endpoint.apiCall.call(session); return endpoint.apiCall.call(session);
} }
return ErrorResponses.response404; return ErrorResponses.response404;
} }
private boolean isApiUrl(String uri) { private boolean isApiUrl(String uri) {
for (String endpoint : endpoints.keySet()){ for (String endpoint : endpoints.keySet()) {
//TODO rewrite contains //TODO rewrite contains
if (endpoint.equals(uri) || uri.contains("tile")) return true; if (endpoint.equals(uri) || uri.contains("tile")) return true;
} }
@ -240,13 +242,18 @@ public class ApiRouter {
text.append(json); text.append(json);
text.append(","); text.append(",");
} }
return "[" + text.substring(0,text.length()-1) + "]"; return "[" + text.substring(0, text.length() - 1) + "]";
} }
private String jsonFromFavorite(FavouritePoint favouritePoint) { private String jsonFromFavorite(FavouritePoint favouritePoint) {
return gson.toJson(favouritePoint); return gson.toJson(favouritePoint);
} }
@Override
public void onDraw(RotatedTileBox viewport, Bitmap bmp) {
this.map.put(viewport,bmp);
}
static class ErrorResponses { static class ErrorResponses {
static NanoHTTPD.Response response404 = static NanoHTTPD.Response response404 =
newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND, newFixedLengthResponse(NanoHTTPD.Response.Status.NOT_FOUND,

View file

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