use of net.osmand.data.QuadRect in project OsmAnd-tools by osmandapp.
the class BasemapProcessor method processEntity.
public void processEntity(Entity e) {
if (e instanceof Way) {
if ("reverse_coastline".equals(((Way) e).getModifiableTags().get("natural"))) {
((Way) e).putTag("natural", "coastline");
Collections.reverse(((Way) e).getNodes());
((Way) e).getNodeIds().reverse();
}
}
long refId = -Math.abs(e.getId());
for (int level = 0; level < mapZooms.getLevels().size(); level++) {
boolean mostDetailed = level == 0;
MapZoomPair zoomPair = mapZooms.getLevel(level);
int zoomToEncode = mostDetailed ? Math.max(MOST_DETAILED_APPROXIMATION, zoomPair.getMinZoom() + 1) : zoomPair.getMaxZoom();
if (mostDetailed && zoomPair.getMaxZoom() < 10) {
throw new IllegalStateException("Zoom pair is not detailed " + zoomPair);
}
renderingTypes.encodeEntityWithType(e, zoomToEncode, typeUse, addtypeUse, namesUse, tempNameUse);
if (typeUse.isEmpty()) {
continue;
}
if (e instanceof Relation) {
Relation r = (Relation) e;
Iterator<RelationMember> it = r.getMembers().iterator();
List<Node> outer = null;
List<List<Node>> inner = new ArrayList<List<Node>>();
while (it.hasNext()) {
RelationMember n = it.next();
if (n.getRole().equals("outer")) {
if (outer != null) {
throw new IllegalStateException("2 outer lines for relation = " + e.getId());
}
outer = ((Way) n.getEntity()).getNodes();
} else if (n.getRole().equals("inner")) {
inner.add(((Way) n.getEntity()).getNodes());
}
}
if (OsmMapUtils.polygonAreaPixels(outer, zoomToEncode) < PIXELS_THRESHOLD_AREA) {
continue;
}
addObject(refId, level, zoomPair, zoomToEncode, outer, inner);
} else if (e instanceof Way) {
if (((Way) e).getNodes().size() < 2) {
continue;
}
double dist = OsmMapUtils.getDistance(((Way) e).getFirstNode(), ((Way) e).getLastNode());
boolean polygon = dist < 100;
if ("coastline".equals(e.getTag("natural"))) {
if (polygon && !mostDetailed) {
if (OsmMapUtils.polygonAreaPixels(((Way) e).getNodes(), zoomToEncode) < PIXELS_THRESHOLD_AREA) {
continue;
}
}
splitContinuousWay(((Way) e).getNodes(), typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair, zoomToEncode, quadTrees[level], refId);
} else {
List<Node> ns = ((Way) e).getNodes();
if (!polygon) {
QuadRect qr = ((Way) e).getLatLonBBox();
if (qr == null) {
continue;
}
double mult = 1 / MapUtils.getPowZoom(Math.max(31 - (zoomToEncode + 8), 0));
int rx = MapUtils.get31TileNumberX(qr.right);
int lx = MapUtils.get31TileNumberX(qr.left);
int by = MapUtils.get31TileNumberY(qr.bottom);
int ty = MapUtils.get31TileNumberY(qr.top);
if (mult * (rx - lx) < PIXELS_THRESHOLD_AREA && mult * (by - ty) < PIXELS_THRESHOLD_AREA) {
continue;
}
} else {
if (OsmMapUtils.polygonAreaPixels(ns, zoomToEncode) < PIXELS_THRESHOLD_AREA) {
continue;
}
}
addObject(refId, level, zoomPair, zoomToEncode, ns, null);
}
} else {
int z = getViewZoom(zoomPair.getMinZoom(), zoomToEncode);
int tilex = (int) MapUtils.getTileNumberX(z, ((Node) e).getLongitude());
int tiley = (int) MapUtils.getTileNumberY(z, ((Node) e).getLatitude());
addRawData(Collections.singletonList((Node) e), null, typeUse.toArray(), !addtypeUse.isEmpty() ? addtypeUse.toArray() : null, zoomPair, quadTrees[level], z, tilex, tiley, namesUse.isEmpty() ? null : new LinkedHashMap<MapRulType, String>(namesUse), refId);
}
}
}
use of net.osmand.data.QuadRect 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.data.QuadRect 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;
}
}
}
use of net.osmand.data.QuadRect in project Osmand by osmandapp.
the class TextRenderer method createTextDrawInfo.
private void createTextDrawInfo(final BinaryMapDataObject o, RenderingRuleSearchRequest render, RenderingContext rc, TagValuePair pair, final float xMid, float yMid, Path path, final PointF[] points, String name, String tagName) {
render.setInitialTagValueZoom(pair.tag, pair.value, rc.zoom, o);
render.setIntFilter(render.ALL.R_TEXT_LENGTH, name.length());
render.setStringFilter(render.ALL.R_NAME_TAG, tagName);
if (render.search(RenderingRulesStorage.TEXT_RULES)) {
if (render.getFloatPropertyValue(render.ALL.R_TEXT_SIZE) > 0) {
final TextDrawInfo text = new TextDrawInfo(name);
text.fillProperties(rc, render, xMid, yMid);
final String tagName2 = render.getStringPropertyValue(render.ALL.R_NAME_TAG2);
if (!Algorithms.isEmpty(tagName2)) {
o.getObjectNames().forEachEntry(new TIntObjectProcedure<String>() {
@Override
public boolean execute(int tagid, String nname) {
String tagNameN2 = o.getMapIndex().decodeType(tagid).tag;
if (tagName2.equals(tagNameN2)) {
if (nname != null && nname.trim().length() > 0) {
text.text += " (" + nname + ")";
}
return false;
}
return true;
}
});
}
paintText.setTextSize(text.textSize);
Rect bs = new Rect();
paintText.getTextBounds(name, 0, name.length(), bs);
text.bounds = new QuadRect(bs.left, bs.top, bs.right, bs.bottom);
text.bounds.inset(-rc.getDensityValue(3), -rc.getDensityValue(10));
boolean display = true;
if (path != null) {
text.drawOnPath = path;
display = calculatePathToRotate(rc, text, points, render.getIntPropertyValue(render.ALL.R_TEXT_ON_PATH, 0) != 0);
}
if (text.drawOnPath == null) {
text.bounds.offset(text.centerX, text.centerY);
// shift to match alignment
text.bounds.offset(-text.bounds.width() / 2, 0);
} else {
text.bounds.offset(text.centerX - text.bounds.width() / 2, text.centerY - text.bounds.height() / 2);
}
if (display) {
rc.textToDraw.add(text);
}
}
}
}
use of net.osmand.data.QuadRect in project Osmand by osmandapp.
the class RegionAddressRepositoryBinary method preloadCities.
@Override
public synchronized void preloadCities(ResultMatcher<City> resultMatcher) {
if (cities.isEmpty()) {
try {
List<City> cs = getOpenFile().getCities(BinaryMapIndexReader.buildAddressRequest(resultMatcher), BinaryMapAddressReaderAdapter.CITY_TOWN_TYPE);
LinkedHashMap<Long, City> ncities = new LinkedHashMap<Long, City>();
for (City c : cs) {
ncities.put(c.getId(), c);
LatLon loc = c.getLocation();
if (loc != null) {
int y31 = MapUtils.get31TileNumberY(loc.getLatitude());
int x31 = MapUtils.get31TileNumberX(loc.getLongitude());
int dz = (31 - ZOOM_QTREE);
citiesQtree.insert(c, new QuadRect((x31 >> dz) - 1, (y31 >> dz) - 1, (x31 >> dz) + 1, (y31 >> dz) + 1));
}
}
cities = ncities;
} catch (IOException e) {
// $NON-NLS-1$
log.error("Disk operation failed", e);
}
}
}
Aggregations