read1Way method

List<Way> read1Way(
  1. Readbuffer readBuffer,
  2. QueryParameters queryParameters,
  3. double tileLatitude,
  4. double tileLongitude,
  5. MapDatastore mapDataStore,
  6. List<Tag> wayTags,
  7. bool filterRequired,
  8. BoundingBox wayFilterBbox,
  9. MapfileSelector selector,
)

Reads a single way from the given readBuffer and returns it as a list containing one or more Way objects.

A single way entry in the map file can result in multiple Way objects if it consists of multiple data blocks (e.g., for multipolygons).

Implementation

List<Way> read1Way(
  Readbuffer readBuffer,
  QueryParameters queryParameters,
  double tileLatitude,
  double tileLongitude,
  MapDatastore mapDataStore,
  List<Tag> wayTags,
  bool filterRequired,
  BoundingBox wayFilterBbox,
  MapfileSelector selector,
) {
  List<Way> ways = [];
  if (_mapFileHeader.getMapHeaderInfo().debugFile) {
    // get and check the way signature
    String signatureWay = readBuffer.readUTF8EncodedString2(SIGNATURE_LENGTH_WAY);
    if (!signatureWay.startsWith("---WayStart")) {
      throw MapFileException("invalid way signature: $signatureWay");
    }
  }

  // get the size of the way (VBE-U)
  int wayDataSize = readBuffer.readUnsignedInt();
  if (wayDataSize < 0) {
    throw MapFileException("invalid way data size: $wayDataSize");
  }

  /*int pos =*/
  readBuffer.getBufferPosition();
  if (queryParameters.useTileBitmask) {
    // get the way tile bitmask (2 bytes)
    int tileBitmask = readBuffer.readShort();
    // check if the way is inside the requested tile

    if ((queryParameters.queryTileBitmask! & tileBitmask) == 0) {
      // skip the rest of the way and continue with the next way
      readBuffer.skipBytes(wayDataSize - 2);
      return ways;
    }
  } else {
    // ignore the way tile bitmask (2 bytes)
    readBuffer.skipBytes(2);
  }

  // get the special int which encodes multiple flags
  int specialByte = readBuffer.readByte();

  // bit 1-4 represent the layer
  int layer = ((specialByte & WAY_LAYER_BITMASK) >> WAY_LAYER_SHIFT);
  // bit 5-8 represent the number of tag IDs
  int numberOfTags = (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);

  // get the tags from IDs (VBE-U)
  List<Tag> tags = readBuffer.readTags(wayTags, numberOfTags);
  //_log.info("processWays for ${wayTags.toString()} and numberofTags: $numberOfTags returned ${tags.length} items");

  // get the feature bitmask (1 byte)
  int featureByte = readBuffer.readByte();

  // bit 1-6 enable optional features
  bool featureName = (featureByte & WAY_FEATURE_NAME) != 0;
  bool featureHouseNumber = (featureByte & WAY_FEATURE_HOUSE_NUMBER) != 0;
  bool featureRef = (featureByte & WAY_FEATURE_REF) != 0;
  bool featureLabelPosition = (featureByte & WAY_FEATURE_LABEL_POSITION) != 0;
  bool featureWayDataBlocksByte = (featureByte & WAY_FEATURE_DATA_BLOCKS_BYTE) != 0;
  bool featureWayDoubleDeltaEncoding = (featureByte & WAY_FEATURE_DOUBLE_DELTA_ENCODING) != 0;

  // check if the way has a name
  if (featureName) {
    try {
      tags.add(Tag(TAG_KEY_NAME, mapDataStore.extractLocalized(readBuffer.readUTF8EncodedString())!));
    } catch (e) {
      _log.warning(e.toString());
      //tags.add(Tag(TAG_KEY_NAME, "unknown"));
    }
  }

  // check if the way has a house number
  if (featureHouseNumber) {
    try {
      tags.add(Tag(TAG_KEY_HOUSE_NUMBER, readBuffer.readUTF8EncodedString()));
    } catch (e) {
      _log.warning(e.toString());
      //tags.add(Tag(TAG_KEY_NAME, "unknown"));
    }
  }

  // check if the way has a reference
  if (featureRef) {
    try {
      tags.add(Tag(TAG_KEY_REF, readBuffer.readUTF8EncodedString()));
    } catch (e) {
      _log.warning(e.toString());
      //tags.add(Tag(TAG_KEY_NAME, "unknown"));
    }
  }

  List<int>? labelPosition;
  if (featureLabelPosition) {
    labelPosition = _readOptionalLabelPosition(readBuffer);
  }

  int wayDataBlocks = _readOptionalWayDataBlocksByte(featureWayDataBlocksByte, readBuffer);
  if (wayDataBlocks < 1) {
    throw MapFileException("invalid number of way data blocks: $wayDataBlocks");
  }

  for (int wayDataBlock = 0; wayDataBlock < wayDataBlocks; ++wayDataBlock) {
    List<List<LatLong>> wayNodes = _processWayDataBlock(tileLatitude, tileLongitude, featureWayDoubleDeltaEncoding, readBuffer);
    if (filterRequired && wayFilterEnabled && !wayFilterBbox.intersectsArea(wayNodes)) {
      continue;
    }
    if (MapfileSelector.ALL == selector || featureName || featureHouseNumber || featureRef || wayAsLabelTagFilter(tags)) {
      LatLong? labelLatLong;
      if (labelPosition != null) {
        labelLatLong = LatLong(
          wayNodes[0][0].latitude + LatLongUtils.microdegreesToDegrees(labelPosition[1]),
          wayNodes[0][0].longitude + LatLongUtils.microdegreesToDegrees(labelPosition[0]),
        );
      }
      ways.add(Way(layer, tags, wayNodes, labelLatLong));
    }
  }
  return ways;
}