processBlocks method
Future<DatastoreReadResult>
processBlocks(
- ReadbufferSource readBufferSource,
- QueryParameters queryParameters,
- SubFileParameter subFileParameter,
- BoundingBox boundingBox,
- MapfileSelector selector,
don't make this method private since we are using it in the example APP to analyze mapfiles
Implementation
Future<DatastoreReadResult> processBlocks(ReadbufferSource readBufferSource, QueryParameters queryParameters, SubFileParameter subFileParameter,
BoundingBox boundingBox, MapfileSelector selector) async {
bool queryIsWater = true;
bool queryReadWaterInfo = false;
DatastoreReadResult mapFileReadResult = new DatastoreReadResult(pointOfInterests: [], ways: []);
// read and process all blocks from top to bottom and from left to right
for (int row = queryParameters.fromBlockY; row <= queryParameters.toBlockY; ++row) {
for (int column = queryParameters.fromBlockX; column <= queryParameters.toBlockX; ++column) {
// calculate the actual block number of the needed block in the file
int blockNumber = row * subFileParameter.blocksWidth + column;
// String cacheKey = "$blockNumber-${queryParameters.queryZoomLevel}";
// PoiWayBundle? bundle = _blockCache.get(cacheKey);
// if (bundle != null) {
// mapFileReadResult.add(bundle);
// print(
// "from cache: $row/$column/${queryParameters.queryZoomLevel}-${subFileParameter.id} ${subFileParameter.zoomLevelMax}");
// continue;
// }
// get the current index entry
int currentBlockIndexEntry = await this._databaseIndexCache.getIndexEntry(subFileParameter, blockNumber, readBufferSource);
// 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
int currentBlockPointer = currentBlockIndexEntry & BITMASK_INDEX_OFFSET;
if (currentBlockPointer < 1 || currentBlockPointer > subFileParameter.subFileSize) {
_log.warning(
"invalid current block pointer: 0x${currentBlockPointer.toRadixString(16)} with subFileSize: 0x${subFileParameter.subFileSize.toRadixString(16)} for blocknumber $blockNumber");
return mapFileReadResult;
}
int? 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 = (await this._databaseIndexCache.getIndexEntry(subFileParameter, blockNumber + 1, readBufferSource)) & BITMASK_INDEX_OFFSET;
if (nextBlockPointer > subFileParameter.subFileSize) {
_log.warning("invalid next block pointer: $nextBlockPointer");
_log.warning("sub-file size: ${subFileParameter.subFileSize}");
return mapFileReadResult;
}
}
// calculate the size of the current block
int currentBlockSize = (nextBlockPointer - currentBlockPointer);
if (currentBlockSize < 0) {
_log.warning("current block size must not be negative: $currentBlockSize");
return mapFileReadResult;
} else if (currentBlockSize == 0) {
// the current block is empty, continue with the next block
continue;
} else if (currentBlockSize > Parameters.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 > this._fileSize) {
_log.warning("current block larger than file size: $currentBlockSize");
return mapFileReadResult;
}
String key = "${subFileParameter.startAddress + currentBlockPointer}-$currentBlockSize";
Readbuffer readbuffer = await _cache.getOrProduce(key, (key) async {
Readbuffer readBuffer = await readBufferSource.readFromFileAt(subFileParameter.startAddress + currentBlockPointer, currentBlockSize);
return readBuffer;
});
// calculate the top-left coordinates of the underlying tile
double tileLatitude = subFileParameter.projection.tileYToLatitude((subFileParameter.boundaryTileTop + row));
double tileLongitude = subFileParameter.projection.tileXToLongitude((subFileParameter.boundaryTileLeft + column));
PoiWayBundle poiWayBundle =
_processBlock(queryParameters, subFileParameter, boundingBox, tileLatitude, tileLongitude, selector, Readbuffer.from(readbuffer));
//_blockCache.set(cacheKey, poiWayBundle);
mapFileReadResult.add(poiWayBundle);
}
}
// the query is finished, was the water flag set for all blocks?
if (queryIsWater && queryReadWaterInfo) {
// Deprecate water tiles rendering
mapFileReadResult.isWater = true;
}
return mapFileReadResult;
}