/** * Processes the given number of POIs. * * @param mapDataSink the callback which handles the extracted POIs. * @param numberOfPois how many POIs should be processed. * @return true if the POIs could be processed successfully, false otherwise. */ private boolean processPOIs(ITileDataSink mapDataSink, int numberOfPois) { Tag[] poiTags = mTileSource.fileInfo.poiTags; MapElement e = mElem; int numTags = 0; for (int elementCounter = numberOfPois; elementCounter != 0; --elementCounter) { if (mDebugFile) { /* get and check the POI signature */ mSignaturePoi = mReadBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_POI); if (!mSignaturePoi.startsWith("***POIStart")) { log.warn("invalid POI signature: " + mSignaturePoi); log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock); return false; } } /* get the POI latitude offset (VBE-S) */ int latitude = mTileLatitude + mReadBuffer.readSignedInt(); /* get the POI longitude offset (VBE-S) */ int longitude = mTileLongitude + mReadBuffer.readSignedInt(); /* get the special byte which encodes multiple flags */ byte specialByte = mReadBuffer.readByte(); /* bit 1-4 represent the layer */ byte layer = (byte) ((specialByte & POI_LAYER_BITMASK) >>> POI_LAYER_SHIFT); /* bit 5-8 represent the number of tag IDs */ byte numberOfTags = (byte) (specialByte & POI_NUMBER_OF_TAGS_BITMASK); if (numberOfTags != 0) { if (!mReadBuffer.readTags(e.tags, poiTags, numberOfTags)) return false; numTags = numberOfTags; } /* reset to common tag position */ e.tags.numTags = numTags; /* get the feature bitmask (1 byte) */ byte featureByte = mReadBuffer.readByte(); /* bit 1-3 enable optional features * check if the POI has a name */ if ((featureByte & POI_FEATURE_NAME) != 0) { String str = mReadBuffer.readUTF8EncodedString(); e.tags.add(new Tag(Tag.KEY_NAME, str, false)); } /* check if the POI has a house number */ if ((featureByte & POI_FEATURE_HOUSE_NUMBER) != 0) { // mReadBuffer.getPositionAndSkip(); // String str = mReadBuffer.readUTF8EncodedString(); } /* check if the POI has an elevation */ if ((featureByte & POI_FEATURE_ELEVATION) != 0) { mReadBuffer.readSignedInt(); // mReadBuffer.getPositionAndSkip();// tags.add(new // Tag(Tag.TAG_KEY_ELE, // Integer.toString(mReadBuffer.readSignedInt()))); } mTileProjection.projectPoint(latitude, longitude, e); e.setLayer(layer); mapDataSink.process(e); } return true; }
/** * Processes the given number of ways. * * @param queryParameters the parameters of the current query. * @param mapDataSink the callback which handles the extracted ways. * @param numberOfWays how many ways should be processed. * @return true if the ways could be processed successfully, false otherwise. */ private boolean processWays( QueryParameters queryParameters, ITileDataSink mapDataSink, int numberOfWays) { Tag[] wayTags = mTileSource.fileInfo.wayTags; MapElement e = mElem; int numTags = 0; int wayDataBlocks; // skip string block int stringsSize = 0; stringOffset = 0; if (mTileSource.experimental) { stringsSize = mReadBuffer.readUnsignedInt(); stringOffset = mReadBuffer.getBufferPosition(); mReadBuffer.skipBytes(stringsSize); } // setTileClipping(queryParameters); for (int elementCounter = numberOfWays; elementCounter != 0; --elementCounter) { if (mDebugFile) { // get and check the way signature mSignatureWay = mReadBuffer.readUTF8EncodedString(SIGNATURE_LENGTH_WAY); if (!mSignatureWay.startsWith("---WayStart")) { log.warn("invalid way signature: " + mSignatureWay); log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock); return false; } } if (queryParameters.useTileBitmask) { elementCounter = mReadBuffer.skipWays(queryParameters.queryTileBitmask, elementCounter); if (elementCounter == 0) return true; if (elementCounter < 0) return false; if (mTileSource.experimental && mReadBuffer.lastTagPosition > 0) { int pos = mReadBuffer.getBufferPosition(); mReadBuffer.setBufferPosition(mReadBuffer.lastTagPosition); byte numberOfTags = (byte) (mReadBuffer.readByte() & WAY_NUMBER_OF_TAGS_BITMASK); if (!mReadBuffer.readTags(e.tags, wayTags, numberOfTags)) return false; numTags = numberOfTags; mReadBuffer.setBufferPosition(pos); } } else { int wayDataSize = mReadBuffer.readUnsignedInt(); if (wayDataSize < 0) { log.warn("invalid way data size: " + wayDataSize); if (mDebugFile) { log.warn(DEBUG_SIGNATURE_BLOCK + mSignatureBlock); } log.error("BUG way 2"); return false; } /* ignore the way tile bitmask (2 bytes) */ mReadBuffer.skipBytes(2); } /* get the special byte which encodes multiple flags */ byte specialByte = mReadBuffer.readByte(); /* bit 1-4 represent the layer */ byte layer = (byte) ((specialByte & WAY_LAYER_BITMASK) >>> WAY_LAYER_SHIFT); /* bit 5-8 represent the number of tag IDs */ byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK); if (numberOfTags != 0) { if (!mReadBuffer.readTags(e.tags, wayTags, numberOfTags)) return false; numTags = numberOfTags; } /* get the feature bitmask (1 byte) */ byte featureByte = mReadBuffer.readByte(); /* bit 1-6 enable optional features */ boolean featureWayDoubleDeltaEncoding = (featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0; boolean hasName = (featureByte & WAY_FEATURE_NAME) != 0; boolean hasHouseNr = (featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0; boolean hasRef = (featureByte & WAY_FEATURE_REF) != 0; e.tags.numTags = numTags; if (mTileSource.experimental) { if (hasName) { int textPos = mReadBuffer.readUnsignedInt(); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); e.tags.add(new Tag(Tag.KEY_NAME, str, false)); } if (hasHouseNr) { int textPos = mReadBuffer.readUnsignedInt(); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); e.tags.add(new Tag(Tag.KEY_HOUSE_NUMBER, str, false)); } if (hasRef) { int textPos = mReadBuffer.readUnsignedInt(); String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos); e.tags.add(new Tag(Tag.KEY_REF, str, false)); } } else { if (hasName) { String str = mReadBuffer.readUTF8EncodedString(); e.tags.add(new Tag(Tag.KEY_NAME, str, false)); } if (hasHouseNr) { String str = mReadBuffer.readUTF8EncodedString(); e.tags.add(new Tag(Tag.KEY_HOUSE_NUMBER, str, false)); } if (hasRef) { String str = mReadBuffer.readUTF8EncodedString(); e.tags.add(new Tag(Tag.KEY_REF, str, false)); } } if ((featureByte & WAY_FEATURE_LABEL_POSITION) != 0) // labelPosition = readOptionalLabelPosition(); if ((featureByte & WAY_FEATURE_DATA_BLOCKS_BYTE) != 0) { wayDataBlocks = mReadBuffer.readUnsignedInt(); if (wayDataBlocks < 1) { log.warn("invalid number of way data blocks: " + wayDataBlocks); logDebugSignatures(); return false; } } else { wayDataBlocks = 1; } /* some guessing if feature is a line or a polygon */ boolean linearFeature = e.tags.containsKey("highway") || e.tags.containsKey("boundary") || e.tags.containsKey("railway"); if (linearFeature) { Tag areaTag = e.tags.get("area"); if (areaTag != null && areaTag.value == Tag.VALUE_YES) linearFeature = false; } for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; wayDataBlock++) { e.clear(); if (!processWayDataBlock(e, featureWayDoubleDeltaEncoding, linearFeature)) return false; /* drop invalid outer ring */ if (e.isPoly() && e.index[0] < 6) { continue; } mTileProjection.project(e); if (!e.tags.containsKey("building")) if (!mTileClipper.clip(e)) { continue; } e.simplify(1, true); e.setLayer(layer); mapDataSink.process(e); } } return true; }
@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); }