private void processBlocks( IMapDatabaseCallback mapDatabaseCallback, QueryParameters queryParameters, SubFileParameter subFileParameter) throws IOException { boolean queryIsWater = true; // boolean queryReadWaterInfo = false; // read and process all blocks from top to bottom and from left to right for (long row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) { for (long column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) { // calculate the actual block number of the needed block in the // file long blockNumber = row * subFileParameter.blocksWidth + column; // get the current index entry long currentBlockIndexEntry = sDatabaseIndexCache.getIndexEntry(subFileParameter, blockNumber); // check if the current query would still return a water tile if (queryIsWater) { // check the water flag of the current block in its index // entry queryIsWater &= (currentBlockIndexEntry & BITMASK_INDEX_WATER) != 0; // queryReadWaterInfo = true; } // get and check the current block pointer long currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET; if (currentBlockPointer < 1 || currentBlockPointer > subFileParameter.subFileSize) { LOG.warning("invalid current block pointer: " + currentBlockPointer); LOG.warning("subFileSize: " + subFileParameter.subFileSize); return; } long nextBlockPointer; // check if the current block is the last block in the file if (blockNumber + 1 == subFileParameter.numberOfBlocks) { // set the next block pointer to the end of the file nextBlockPointer = subFileParameter.subFileSize; } else { // get and check the next block pointer nextBlockPointer = sDatabaseIndexCache.getIndexEntry(subFileParameter, blockNumber + 1) & BITMASK_INDEX_OFFSET; if (nextBlockPointer < 1 || nextBlockPointer > subFileParameter.subFileSize) { LOG.warning("invalid next block pointer: " + nextBlockPointer); LOG.warning("sub-file size: " + subFileParameter.subFileSize); return; } } // calculate the size of the current block int currentBlockSize = (int) (nextBlockPointer - currentBlockPointer); if (currentBlockSize < 0) { LOG.warning("current block size must not be negative: " + currentBlockSize); return; } else if (currentBlockSize == 0) { // the current block is empty, continue with the next block continue; } else if (currentBlockSize > ReadBuffer.MAXIMUM_BUFFER_SIZE) { // the current block is too large, continue with the next // block LOG.warning("current block size too large: " + currentBlockSize); continue; } else if (currentBlockPointer + currentBlockSize > mFileSize) { LOG.warning("current block largher than file size: " + currentBlockSize); return; } // seek to the current block in the map file mInputFile.seek(subFileParameter.startAddress + currentBlockPointer); // read the current block into the buffer if (!mReadBuffer.readFromFile(currentBlockSize)) { // skip the current block LOG.warning("reading current block has failed: " + currentBlockSize); return; } // calculate the top-left coordinates of the underlying tile double tileLatitudeDeg = MercatorProjection.tileYToLatitude( subFileParameter.boundaryTileTop + row, subFileParameter.baseZoomLevel); double tileLongitudeDeg = MercatorProjection.tileXToLongitude( subFileParameter.boundaryTileLeft + column, subFileParameter.baseZoomLevel); mTileLatitude = (int) (tileLatitudeDeg * 1000000); mTileLongitude = (int) (tileLongitudeDeg * 1000000); try { processBlock(queryParameters, subFileParameter, mapDatabaseCallback); } catch (ArrayIndexOutOfBoundsException e) { LOG.log(Level.SEVERE, null, e); } } } // the query is finished, was the water flag set for all blocks? // if (queryIsWater && queryReadWaterInfo) { // Tag[] tags = new Tag[1]; // tags[0] = TAG_NATURAL_WATER; // // System.arraycopy(WATER_TILE_COORDINATES, 0, mWayNodes, // mWayNodePosition, 8); // mWayNodePosition += 8; // mapDatabaseCallback.renderWaterBackground(tags, wayDataContainer); // } }
/** * Get the GeoPoint for x,y in screen coordinates. * * @param x screen coordinate * @param y screen coordinate * @return the corresponding GeoPoint */ public GeoPoint fromScreenPoint(float x, float y) { fromScreenPoint(x, y, mMovePoint); return new GeoPoint( MercatorProjection.toLatitude(mMovePoint.y), MercatorProjection.toLongitude(mMovePoint.x)); }
/** * Get the screen pixel for a GeoPoint * * @param geoPoint the GeoPoint * @param out Point projected to screen pixel relative to center */ public void toScreenPoint(GeoPoint geoPoint, Point out) { MercatorProjection.project(geoPoint, out); toScreenPoint(out.x, out.y, out); }
@Override public void query(MapTile tile, ITileDataSink sink) { if (mTileSource.fileHeader == null) { sink.completed(FAILED); return; } if (mIntBuffer == null) mIntBuffer = new int[MAXIMUM_WAY_NODES_SEQUENCE_LENGTH * 2]; try { mTileProjection.setTile(tile); // mTile = tile; /* size of tile in map coordinates; */ double size = 1.0 / (1 << tile.zoomLevel); /* simplification tolerance */ int pixel = (tile.zoomLevel > 11) ? 1 : 2; int simplify = Tile.SIZE / pixel; /* translate screen pixel for tile to latitude and longitude * tolerance for point reduction before projection. */ minDeltaLat = (int) (Math.abs( MercatorProjection.toLatitude(tile.y + size) - MercatorProjection.toLatitude(tile.y)) * 1e6) / simplify; minDeltaLon = (int) (Math.abs( MercatorProjection.toLongitude(tile.x + size) - MercatorProjection.toLongitude(tile.x)) * 1e6) / simplify; QueryParameters queryParameters = new QueryParameters(); queryParameters.queryZoomLevel = mTileSource.fileHeader.getQueryZoomLevel(tile.zoomLevel); /* get and check the sub-file for the query zoom level */ SubFileParameter subFileParameter = mTileSource.fileHeader.getSubFileParameter(queryParameters.queryZoomLevel); if (subFileParameter == null) { log.warn("no sub-file for zoom level: " + queryParameters.queryZoomLevel); sink.completed(FAILED); return; } QueryCalculations.calculateBaseTiles(queryParameters, tile, subFileParameter); QueryCalculations.calculateBlocks(queryParameters, subFileParameter); processBlocks(sink, queryParameters, subFileParameter); } catch (IOException e) { log.error(e.getMessage()); sink.completed(FAILED); return; } sink.completed(SUCCESS); }