use of net.osmand.binary.BinaryMapDataObject in project Osmand by osmandapp.
the class DownloadResources method findIndexItemsAt.
public static List<IndexItem> findIndexItemsAt(OsmandApplication app, LatLon latLon, DownloadActivityType type) throws IOException {
List<IndexItem> res = new ArrayList<>();
OsmandRegions regions = app.getRegions();
DownloadIndexesThread downloadThread = app.getDownloadThread();
int point31x = MapUtils.get31TileNumberX(latLon.getLongitude());
int point31y = MapUtils.get31TileNumberY(latLon.getLatitude());
List<BinaryMapDataObject> mapDataObjects;
try {
mapDataObjects = regions.queryBbox(point31x, point31x, point31y, point31y);
} catch (IOException e) {
throw new IOException("Error while calling queryBbox");
}
if (mapDataObjects != null) {
Iterator<BinaryMapDataObject> it = mapDataObjects.iterator();
while (it.hasNext()) {
BinaryMapDataObject o = it.next();
if (o.getTypes() != null) {
boolean isRegion = true;
for (int i = 0; i < o.getTypes().length; i++) {
BinaryMapIndexReader.TagValuePair tp = o.getMapIndex().decodeType(o.getTypes()[i]);
if ("boundary".equals(tp.value)) {
isRegion = false;
break;
}
}
WorldRegion downloadRegion = regions.getRegionData(regions.getFullName(o));
if (downloadRegion != null && isRegion && regions.contain(o, point31x, point31y)) {
if (!isIndexItemDownloaded(downloadThread, type, downloadRegion, res)) {
addIndexItem(downloadThread, type, downloadRegion, res);
}
}
}
}
}
return res;
}
use of net.osmand.binary.BinaryMapDataObject in project Osmand by osmandapp.
the class MapRenderRepositories method readMapObjectsForRendering.
private MapIndex readMapObjectsForRendering(final int zoom, final RenderingRuleSearchRequest renderingReq, ArrayList<BinaryMapDataObject> tempResult, ArrayList<BinaryMapDataObject> basemapResult, TLongSet ids, int[] count, boolean[] ocean, boolean[] land, List<BinaryMapDataObject> coastLines, List<BinaryMapDataObject> basemapCoastLines, int leftX, int rightX, int bottomY, int topY) {
BinaryMapIndexReader.SearchFilter searchFilter = new BinaryMapIndexReader.SearchFilter() {
@Override
public boolean accept(TIntArrayList types, BinaryMapIndexReader.MapIndex root) {
for (int j = 0; j < types.size(); j++) {
int type = types.get(j);
TagValuePair pair = root.decodeType(type);
if (pair != null) {
// TODO is it fast enough ?
for (int i = 1; i <= 3; i++) {
renderingReq.setIntFilter(renderingReq.ALL.R_MINZOOM, zoom);
renderingReq.setStringFilter(renderingReq.ALL.R_TAG, pair.tag);
renderingReq.setStringFilter(renderingReq.ALL.R_VALUE, pair.value);
if (renderingReq.search(i, false)) {
return true;
}
}
renderingReq.setStringFilter(renderingReq.ALL.R_TAG, pair.tag);
renderingReq.setStringFilter(renderingReq.ALL.R_VALUE, pair.value);
if (renderingReq.search(RenderingRulesStorage.TEXT_RULES, false)) {
return true;
}
}
}
return false;
}
};
if (zoom > 16) {
searchFilter = null;
}
MapIndex mi = null;
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, searchFilter);
for (BinaryMapIndexReader c : files.values()) {
boolean basemap = c.isBasemap();
searchRequest.clearSearchResults();
List<BinaryMapDataObject> res;
try {
res = c.searchMapIndex(searchRequest);
} catch (IOException e) {
res = new ArrayList<BinaryMapDataObject>();
// $NON-NLS-1$
log.debug("Search failed " + c.getRegionNames(), e);
}
if (res.size() > 0) {
if (basemap) {
renderedState |= 1;
} else {
renderedState |= 2;
}
}
for (BinaryMapDataObject r : res) {
if (checkForDuplicateObjectIds && !basemap) {
if (ids.contains(r.getId()) && r.getId() > 0) {
// do not add object twice
continue;
}
ids.add(r.getId());
}
count[0]++;
if (r.containsType(r.getMapIndex().coastlineEncodingType)) {
if (basemap) {
basemapCoastLines.add(r);
} else {
coastLines.add(r);
}
} else {
// do not mess coastline and other types
if (basemap) {
basemapResult.add(r);
} else {
tempResult.add(r);
}
}
if (checkWhetherInterrupted()) {
return null;
}
}
if (searchRequest.isOcean()) {
mi = c.getMapIndexes().get(0);
ocean[0] = true;
}
if (searchRequest.isLand()) {
mi = c.getMapIndexes().get(0);
land[0] = true;
}
}
return mi;
}
use of net.osmand.binary.BinaryMapDataObject in project Osmand by osmandapp.
the class MapRenderRepositories method clearCache.
public synchronized void clearCache() {
cObjects = new ArrayList<BinaryMapDataObject>();
cObjectsBox = new QuadRect();
requestedBox = prevBmpLocation = null;
// Do not clear main bitmap to not cause a screen refresh
// prevBmp = null;
// bmp = null;
// bmpLocation = null;
}
use of net.osmand.binary.BinaryMapDataObject in project Osmand by osmandapp.
the class MapRenderRepositories method loadVectorData.
private boolean loadVectorData(QuadRect dataBox, final int zoom, final RenderingRuleSearchRequest renderingReq) {
double cBottomLatitude = dataBox.bottom;
double cTopLatitude = dataBox.top;
double cLeftLongitude = dataBox.left;
double cRightLongitude = dataBox.right;
long now = System.currentTimeMillis();
// to clear previous objects
System.gc();
ArrayList<BinaryMapDataObject> tempResult = new ArrayList<BinaryMapDataObject>();
ArrayList<BinaryMapDataObject> basemapResult = new ArrayList<BinaryMapDataObject>();
int[] count = new int[] { 0 };
boolean[] ocean = new boolean[] { false };
boolean[] land = new boolean[] { false };
List<BinaryMapDataObject> coastLines = new ArrayList<BinaryMapDataObject>();
List<BinaryMapDataObject> basemapCoastLines = new ArrayList<BinaryMapDataObject>();
int leftX = MapUtils.get31TileNumberX(cLeftLongitude);
int rightX = MapUtils.get31TileNumberX(cRightLongitude);
int bottomY = MapUtils.get31TileNumberY(cBottomLatitude);
int topY = MapUtils.get31TileNumberY(cTopLatitude);
TLongSet ids = new TLongHashSet();
MapIndex mi = readMapObjectsForRendering(zoom, renderingReq, tempResult, basemapResult, ids, count, ocean, land, coastLines, basemapCoastLines, leftX, rightX, bottomY, topY);
int renderRouteDataFile = 0;
if (renderingReq.searchRenderingAttribute("showRoadMapsAttribute")) {
renderRouteDataFile = renderingReq.getIntPropertyValue(renderingReq.ALL.R_ATTR_INT_VALUE);
}
if (checkWhetherInterrupted()) {
return false;
}
boolean objectsFromMapSectionRead = tempResult.size() > 0;
if (renderRouteDataFile >= 0 && zoom >= zoomOnlyForBasemaps) {
searchRequest = BinaryMapIndexReader.buildSearchRequest(leftX, rightX, topY, bottomY, zoom, null);
for (BinaryMapIndexReader c : files.values()) {
// false positive case when we have 2 sep maps Country-roads & Country
if (c.getMapIndexes().size() == 0 || renderRouteDataFile == 1) {
readRouteDataAsMapObjects(searchRequest, c, tempResult, ids);
}
}
log.info(String.format("Route objects %s", tempResult.size() + ""));
}
String coastlineTime = "";
boolean addBasemapCoastlines = true;
boolean emptyData = zoom > zoomOnlyForBasemaps && tempResult.isEmpty() && coastLines.isEmpty();
boolean basemapMissing = zoom <= zoomOnlyForBasemaps && basemapCoastLines.isEmpty() && mi == null;
boolean detailedLandData = zoom >= zoomForBaseRouteRendering && tempResult.size() > 0 && objectsFromMapSectionRead;
if (!coastLines.isEmpty()) {
long ms = System.currentTimeMillis();
boolean coastlinesWereAdded = processCoastlines(coastLines, leftX, rightX, bottomY, topY, zoom, basemapCoastLines.isEmpty(), true, tempResult);
addBasemapCoastlines = (!coastlinesWereAdded && !detailedLandData) || zoom <= zoomOnlyForBasemaps;
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
} else {
addBasemapCoastlines = !detailedLandData;
}
if (addBasemapCoastlines) {
long ms = System.currentTimeMillis();
boolean coastlinesWereAdded = processCoastlines(basemapCoastLines, leftX, rightX, bottomY, topY, zoom, true, true, tempResult);
addBasemapCoastlines = !coastlinesWereAdded;
coastlineTime = "(coastline " + (System.currentTimeMillis() - ms) + " ms )";
}
if (addBasemapCoastlines && mi != null) {
int[] coordinates = new int[] { leftX, topY, rightX, topY, rightX, bottomY, leftX, bottomY, leftX, topY };
BinaryMapDataObject o = new BinaryMapDataObject(-1, coordinates, new int[0][], RenderingRulesStorage.POLYGON_RULES, true, new int[] { ocean[0] && !land[0] ? mi.coastlineEncodingType : (mi.landEncodingType) }, null);
o.setMapIndex(mi);
tempResult.add(o);
}
if (emptyData || basemapMissing) {
// message
MapIndex mapIndex;
if (!tempResult.isEmpty()) {
mapIndex = tempResult.get(0).getMapIndex();
} else {
mapIndex = new MapIndex();
mapIndex.initMapEncodingRule(0, 1, "natural", "coastline");
mapIndex.initMapEncodingRule(0, 2, "name", "");
}
}
if (zoom <= zoomOnlyForBasemaps || emptyData) {
tempResult.addAll(basemapResult);
}
if (count[0] > 0) {
log.info(// $NON-NLS-1$
String.format(// $NON-NLS-1$
"BLat=%s, TLat=%s, LLong=%s, RLong=%s, zoom=%s", cBottomLatitude, cTopLatitude, cLeftLongitude, cRightLongitude, zoom));
// $NON-NLS-1$
log.info(String.format("Searching: %s ms %s (%s results found)", System.currentTimeMillis() - now, coastlineTime, count[0]));
}
cObjects = tempResult;
cObjectsBox = dataBox;
cObjectsZoom = zoom;
return true;
}
use of net.osmand.binary.BinaryMapDataObject in project Osmand by osmandapp.
the class MapRenderRepositories method loadMap.
public synchronized void loadMap(RotatedTileBox tileRect, MapTileDownloader mapTileDownloader) {
boolean prevInterrupted = interrupted;
interrupted = false;
// added to avoid zoomAnimation != 0 which produces wrong map position on the screen
tileRect.setZoomAndAnimation(tileRect.getZoom(), 0);
// prevent editing
requestedBox = new RotatedTileBox(tileRect);
log.info("RENDER MAP: new request " + tileRect);
if (currentRenderingContext != null) {
currentRenderingContext = null;
}
try {
// find selected rendering type
OsmandApplication app = ((OsmandApplication) context.getApplicationContext());
boolean nightMode = app.getDaynightHelper().isNightMode();
// boolean moreDetail = prefs.SHOW_MORE_MAP_DETAIL.get();
RenderingRulesStorage storage = app.getRendererRegistry().getCurrentSelectedRenderer();
RenderingRuleSearchRequest renderingReq = new RenderingRuleSearchRequest(storage);
renderingReq.setBooleanFilter(renderingReq.ALL.R_NIGHT_MODE, nightMode);
for (RenderingRuleProperty customProp : storage.PROPS.getCustomRules()) {
if (customProp.isBoolean()) {
if (customProp.getAttrName().equals(RenderingRuleStorageProperties.A_ENGINE_V1)) {
renderingReq.setBooleanFilter(customProp, true);
} else if (RenderingRuleStorageProperties.UI_CATEGORY_HIDDEN.equals(customProp.getCategory())) {
renderingReq.setBooleanFilter(customProp, false);
} else {
CommonPreference<Boolean> pref = prefs.getCustomRenderBooleanProperty(customProp.getAttrName());
renderingReq.setBooleanFilter(customProp, pref.get());
}
} else if (RenderingRuleStorageProperties.UI_CATEGORY_HIDDEN.equals(customProp.getCategory())) {
if (customProp.isString()) {
renderingReq.setStringFilter(customProp, "");
} else {
renderingReq.setIntFilter(customProp, 0);
}
} else {
CommonPreference<String> settings = prefs.getCustomRenderProperty(customProp.getAttrName());
String res = settings.get();
if (!Algorithms.isEmpty(res)) {
if (customProp.isString()) {
renderingReq.setStringFilter(customProp, res);
} else {
try {
renderingReq.setIntFilter(customProp, Integer.parseInt(res));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
} else {
if (customProp.isString()) {
renderingReq.setStringFilter(customProp, "");
}
}
}
}
renderingReq.saveState();
NativeOsmandLibrary nativeLib = !prefs.SAFE_MODE.get() ? NativeOsmandLibrary.getLibrary(storage, context) : null;
// calculate data box
QuadRect dataBox = requestedBox.getLatLonBounds();
int dataBoxZoom = requestedBox.getZoom();
long now = System.currentTimeMillis();
if (cObjectsBox.left > dataBox.left || cObjectsBox.top < dataBox.top || cObjectsBox.right < dataBox.right || cObjectsBox.bottom > dataBox.bottom || (nativeLib != null) == (cNativeObjects == null) || dataBoxZoom != cObjectsZoom || prevInterrupted) {
// increase data box in order for rotate
if ((dataBox.right - dataBox.left) > (dataBox.top - dataBox.bottom)) {
double wi = (dataBox.right - dataBox.left) * .05;
dataBox.left -= wi;
dataBox.right += wi;
} else {
double hi = (dataBox.top - dataBox.bottom) * .05;
dataBox.top += hi;
dataBox.bottom -= hi;
}
validateLatLonBox(dataBox);
renderedState = 0;
boolean loaded;
if (nativeLib != null) {
cObjects = new LinkedList<BinaryMapDataObject>();
loaded = loadVectorDataNative(dataBox, requestedBox.getZoom(), renderingReq, nativeLib);
} else {
cNativeObjects = null;
loaded = loadVectorData(dataBox, requestedBox.getZoom(), renderingReq);
}
if (!loaded || checkWhetherInterrupted()) {
return;
}
}
final long searchTime = System.currentTimeMillis() - now;
currentRenderingContext = new OsmandRenderer.RenderingContext(context);
renderingReq.clearState();
renderingReq.setIntFilter(renderingReq.ALL.R_MINZOOM, requestedBox.getZoom());
if (renderingReq.searchRenderingAttribute(RenderingRuleStorageProperties.A_DEFAULT_COLOR)) {
currentRenderingContext.defaultColor = renderingReq.getIntPropertyValue(renderingReq.ALL.R_ATTR_COLOR_VALUE);
}
renderingReq.clearState();
renderingReq.setIntFilter(renderingReq.ALL.R_MINZOOM, requestedBox.getZoom());
if (renderingReq.searchRenderingAttribute(RenderingRuleStorageProperties.A_SHADOW_RENDERING)) {
currentRenderingContext.shadowRenderingMode = renderingReq.getIntPropertyValue(renderingReq.ALL.R_ATTR_INT_VALUE);
currentRenderingContext.shadowRenderingColor = renderingReq.getIntPropertyValue(renderingReq.ALL.R_SHADOW_COLOR);
}
if (renderingReq.searchRenderingAttribute("polygonMinSizeToDisplay")) {
currentRenderingContext.polygonMinSizeToDisplay = renderingReq.getIntPropertyValue(renderingReq.ALL.R_ATTR_INT_VALUE);
}
final QuadPointDouble lt = requestedBox.getLeftTopTile(requestedBox.getZoom());
double cfd = MapUtils.getPowZoom(requestedBox.getZoomFloatPart()) * requestedBox.getMapDensity();
lt.x *= cfd;
lt.y *= cfd;
// LatLon ltn = requestedBox.getLeftTopLatLon();
final double tileDivisor = MapUtils.getPowZoom(31 - requestedBox.getZoom()) / cfd;
currentRenderingContext.leftX = lt.x;
currentRenderingContext.topY = lt.y;
currentRenderingContext.zoom = requestedBox.getZoom();
currentRenderingContext.rotate = requestedBox.getRotate();
currentRenderingContext.width = requestedBox.getPixWidth();
currentRenderingContext.height = requestedBox.getPixHeight();
currentRenderingContext.nightMode = nightMode;
if (requestedBox.getZoom() <= zoomOnlyForBasemaps && "".equals(prefs.MAP_PREFERRED_LOCALE.get())) {
currentRenderingContext.preferredLocale = app.getLanguage();
currentRenderingContext.transliterate = !"ru".equals(app.getLanguage()) && !"uk".equals(app.getLanguage()) && !"be".equals(app.getLanguage()) && !"bg".equals(app.getLanguage()) && !"mk".equals(app.getLanguage()) && !"sr".equals(app.getLanguage());
} else {
currentRenderingContext.preferredLocale = prefs.MAP_PREFERRED_LOCALE.get();
currentRenderingContext.transliterate = prefs.MAP_TRANSLITERATE_NAMES.get();
if (currentRenderingContext.preferredLocale.equals("en")) {
currentRenderingContext.transliterate = true;
}
}
final float mapDensity = (float) requestedBox.getMapDensity();
currentRenderingContext.setDensityValue(mapDensity);
// Text/icon scales according to mapDensity (so text is size of road)
// currentRenderingContext.textScale = (requestedBox.getDensity()*app.getSettings().TEXT_SCALE.get());
// Text/icon stays same for all sizes
currentRenderingContext.textScale = (requestedBox.getDensity() * app.getSettings().TEXT_SCALE.get()) / mapDensity;
currentRenderingContext.screenDensityRatio = 1 / Math.max(1, requestedBox.getDensity());
// init rendering context
currentRenderingContext.tileDivisor = tileDivisor;
if (checkWhetherInterrupted()) {
return;
}
now = System.currentTimeMillis();
Bitmap bmp;
boolean transparent = false;
RenderingRuleProperty rr = storage.PROPS.get("noPolygons");
if (rr != null) {
transparent = renderingReq.getIntPropertyValue(rr) > 0;
}
// 1. generate image step by step
Bitmap reuse = prevBmp;
this.prevBmp = this.bmp;
this.prevBmpLocation = this.bmpLocation;
// necessary for transparent, otherwise 2 times smaller
Config cfg = transparent ? Config.ARGB_8888 : Config.RGB_565;
if (reuse != null && reuse.getWidth() == currentRenderingContext.width && reuse.getHeight() == currentRenderingContext.height && cfg == reuse.getConfig()) {
bmp = reuse;
bmp.eraseColor(currentRenderingContext.defaultColor);
} else {
if (reuse != null) {
log.warn(String.format("Create new image ? %d != %d (w) %d != %d (h) ", currentRenderingContext.width, reuse.getWidth(), currentRenderingContext.height, reuse.getHeight()));
}
bmp = Bitmap.createBitmap(currentRenderingContext.width, currentRenderingContext.height, cfg);
if (reuse != null) {
reuse.recycle();
}
}
this.bmp = bmp;
this.bmpLocation = tileRect;
if (nativeLib != null) {
renderer.generateNewBitmapNative(currentRenderingContext, nativeLib, cNativeObjects, bmp, renderingReq, mapTileDownloader);
} else {
renderer.generateNewBitmap(currentRenderingContext, cObjects, bmp, renderingReq, mapTileDownloader);
}
// Force to use rendering request in order to prevent Garbage Collector when it is used in C++
if (renderingReq != null) {
log.info("Debug :" + renderingReq != null);
}
String renderingDebugInfo = currentRenderingContext.renderingDebugInfo;
currentRenderingContext.ended = true;
if (checkWhetherInterrupted()) {
// (be smart a bit do not revert if road already drawn)
if (currentRenderingContext.lastRenderedKey < OsmandRenderer.DEFAULT_LINE_MAX) {
reuse = this.bmp;
this.bmp = this.prevBmp;
this.bmpLocation = this.prevBmpLocation;
this.prevBmp = reuse;
this.prevBmpLocation = null;
}
currentRenderingContext = null;
return;
} else {
visibleRenderingContext = currentRenderingContext;
this.checkedRenderedState = renderedState;
this.checkedBox = this.bmpLocation;
}
currentRenderingContext = null;
// 2. replace whole image
// keep cache
// this.prevBmp = null;
this.prevBmpLocation = null;
if (prefs.DEBUG_RENDERING_INFO.get() && OsmandPlugin.getEnabledPlugin(OsmandDevelopmentPlugin.class) != null) {
// $NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
String timeInfo = "Searching: " + searchTime + " ms";
if (renderingDebugInfo != null) {
timeInfo += "\n" + renderingDebugInfo;
}
final String msg = timeInfo;
log.info(msg);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
});
}
} catch (RuntimeException e) {
// $NON-NLS-1$
log.error("Runtime memory exception", e);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context, R.string.rendering_exception, Toast.LENGTH_SHORT).show();
}
});
} catch (OutOfMemoryError e) {
// $NON-NLS-1$
log.error("Out of memory error", e);
cObjects = new ArrayList<BinaryMapDataObject>();
cObjectsBox = new QuadRect();
handler.post(new Runnable() {
@Override
public void run() {
// ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
// ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// activityManager.getMemoryInfo(memoryInfo);
// int avl = (int) (memoryInfo.availMem / (1 << 20));
int max = (int) (Runtime.getRuntime().maxMemory() / (1 << 20));
int avl = (int) (Runtime.getRuntime().freeMemory() / (1 << 20));
String s = " (" + avl + " MB available of " + max + ") ";
Toast.makeText(context, context.getString(R.string.rendering_out_of_memory) + s, Toast.LENGTH_SHORT).show();
}
});
} finally {
if (currentRenderingContext != null) {
currentRenderingContext.ended = true;
}
}
}
Aggregations