processBlocks method

Future<DatastoreReadResult> processBlocks(
  1. ReadbufferSource readBufferSource,
  2. QueryParameters queryParameters,
  3. SubFileParameter subFileParameter,
  4. BoundingBox boundingBox,
  5. 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;
}