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;
Projection projection =
MercatorProjection.fromZoomlevel(subFileParameter.baseZoomLevel);
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: $currentBlockPointer");
_log.warning("subFileSize: ${subFileParameter.subFileSize}");
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;
}
// _log.info(
// "Processing block $row/$column from currentBlockPointer ${subFileParameter.startAddress + currentBlockPointer} to nextBlockPointer ${subFileParameter.startAddress + nextBlockPointer} ($currentBlockSize byte)");
// seek to the current block in the map file
// read the current block into the buffer
//ReadBuffer readBuffer = new ReadBuffer(inputChannel);
Readbuffer readBuffer = await readBufferSource.readFromFileAt(
subFileParameter.startAddress + currentBlockPointer,
currentBlockSize);
// calculate the top-left coordinates of the underlying tile
double tileLatitude = projection
.tileYToLatitude((subFileParameter.boundaryTileTop + row));
double tileLongitude = projection
.tileXToLongitude((subFileParameter.boundaryTileLeft + column));
PoiWayBundle poiWayBundle = _processBlock(
queryParameters,
subFileParameter,
boundingBox,
tileLatitude,
tileLongitude,
selector,
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;
}