Search in sources :

Example 1 with QuadRect

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);
        }
    }
}
Also used : Node(net.osmand.osm.edit.Node) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) QuadRect(net.osmand.data.QuadRect) Way(net.osmand.osm.edit.Way) MapRulType(net.osmand.osm.MapRenderingTypes.MapRulType) MapZoomPair(net.osmand.binary.MapZooms.MapZoomPair) Relation(net.osmand.osm.edit.Relation) RelationMember(net.osmand.osm.edit.Relation.RelationMember) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List)

Example 2 with QuadRect

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;
}
Also used : BinaryMapDataObject(net.osmand.binary.BinaryMapDataObject) QuadRect(net.osmand.data.QuadRect)

Example 3 with QuadRect

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;
        }
    }
}
Also used : OsmandApplication(net.osmand.plus.OsmandApplication) Config(android.graphics.Bitmap.Config) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) TLongArrayList(gnu.trove.list.array.TLongArrayList) QuadRect(net.osmand.data.QuadRect) Bitmap(android.graphics.Bitmap) BinaryMapDataObject(net.osmand.binary.BinaryMapDataObject) RenderingContext(net.osmand.plus.render.OsmandRenderer.RenderingContext) RotatedTileBox(net.osmand.data.RotatedTileBox) CommonPreference(net.osmand.plus.OsmandSettings.CommonPreference) RenderingRuleProperty(net.osmand.render.RenderingRuleProperty) RenderingRulesStorage(net.osmand.render.RenderingRulesStorage) RenderingRuleSearchRequest(net.osmand.render.RenderingRuleSearchRequest) QuadPointDouble(net.osmand.data.QuadPointDouble)

Example 4 with QuadRect

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);
            }
        }
    }
}
Also used : Rect(android.graphics.Rect) QuadRect(net.osmand.data.QuadRect) QuadRect(net.osmand.data.QuadRect) Paint(android.graphics.Paint)

Example 5 with QuadRect

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);
        }
    }
}
Also used : LatLon(net.osmand.data.LatLon) City(net.osmand.data.City) IOException(java.io.IOException) QuadRect(net.osmand.data.QuadRect) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

QuadRect (net.osmand.data.QuadRect)60 Paint (android.graphics.Paint)19 ArrayList (java.util.ArrayList)19 LatLon (net.osmand.data.LatLon)13 Bitmap (android.graphics.Bitmap)8 RotatedTileBox (net.osmand.data.RotatedTileBox)8 WptPt (net.osmand.plus.GPXUtilities.WptPt)8 TIntArrayList (gnu.trove.list.array.TIntArrayList)7 BinaryMapDataObject (net.osmand.binary.BinaryMapDataObject)6 Amenity (net.osmand.data.Amenity)5 PorterDuffColorFilter (android.graphics.PorterDuffColorFilter)4 Point (com.vividsolutions.jts.geom.Point)4 List (java.util.List)4 QuadPointDouble (net.osmand.data.QuadPointDouble)4 TransportStop (net.osmand.data.TransportStop)4 PoiCategory (net.osmand.osm.PoiCategory)4 GPXFile (net.osmand.plus.GPXUtilities.GPXFile)4 Rect (android.graphics.Rect)3 RectF (android.graphics.RectF)3 File (java.io.File)3