read method

  1. @override
dynamic read(
  1. LByteBuffer buffer,
  2. ShapeType? type,
  3. bool flatGeometry
)
override

Read a geometry from the ByteBuffer. The buffer's position, byteOrder, and limit are set to that which is needed. The record has been read as well as the shape type integer. The handler need not worry about reading unused information as the ShapefileReader will correctly adjust the buffer position after this call.

@param buffer The ByteBuffer to read from. @return A geometry object.

Implementation

@override
dynamic read(LByteBuffer buffer, ShapeType? type, bool flatGeometry) {
  if (type == ShapeType.NULL) {
    return createNull();
  }
  int dimensions =
      ((shapeType == ShapeType.ARCZ || shapeType == ShapeType.ARCM) &&
              !flatGeometry)
          ? 3
          : 2;
  // read bounding box (not needed)
  buffer.position = buffer.position + 4 * 8;

  int numParts = buffer.getInt32();
  int numPoints = buffer.getInt32(); // total number of points

  List<int> partOffsets = List.filled(numParts, 0);

  // points = new Coordinate[numPoints];
  for (int i = 0; i < numParts; i++) {
    partOffsets[i] = buffer.getInt32();
  }
  // read the first two coordinates and start building the coordinate
  // sequences
  List<CoordinateSequence> lines = []; //List(numParts);
  int finish, start = 0;
  int length = 0;
  bool clonePoint = false;
  // final DoubleBuffer doubleBuffer = buffer.asDoubleBuffer();
  for (int part = 0; part < numParts; part++) {
    start = partOffsets[part];

    if (part == (numParts - 1)) {
      finish = numPoints;
    } else {
      finish = partOffsets[part + 1];
    }

    length = finish - start;
    int xyLength = length;
    if (length == 1) {
      length = 2;
      clonePoint = true;
    } else {
      clonePoint = false;
    }

    CoordinateSequence cs;
    int measure = flatGeometry ? 0 : 1;
    if (shapeType == ShapeType.ARCM) {
      cs = Shapeutils.createCSMeas(
          geometryFactory.getCoordinateSequenceFactory(),
          length,
          dimensions + measure,
          measure);
    } else if (shapeType == ShapeType.ARCZ) {
      cs = Shapeutils.createCSMeas(
          geometryFactory.getCoordinateSequenceFactory(),
          length,
          dimensions + measure,
          measure);
    } else {
      cs = Shapeutils.createCS(
          geometryFactory.getCoordinateSequenceFactory(), length, dimensions);
    }
    // List<double> xy = new double[xyLength * 2];
    // doubleBuffer.get(xy);
    List<double> xy = List.filled(xyLength * 2, 0.0);
    for (var i = 0; i < xy.length; i++) {
      xy[i] = buffer.getDouble64();
    }

    for (int i = 0; i < xyLength; i++) {
      cs.setOrdinate(i, CoordinateSequence.X, xy[i * 2]);
      cs.setOrdinate(i, CoordinateSequence.Y, xy[i * 2 + 1]);
    }

    if (clonePoint) {
      cs.setOrdinate(
          1, CoordinateSequence.X, cs.getOrdinate(0, CoordinateSequence.X));
      cs.setOrdinate(
          1, CoordinateSequence.Y, cs.getOrdinate(0, CoordinateSequence.Y));
    }

    lines.add(cs);
    // lines[part] = cs;
  }

  // if we have another coordinate, read and add to the coordinate
  // sequences
  if (shapeType == ShapeType.ARCZ && !flatGeometry) {
    // z min, max
    // buffer.position(buffer.position() + 2 * 8);
    // doubleBuffer.position(doubleBuffer.position() + 2);
    buffer.position = buffer.position + 2 * 8;
    for (int part = 0; part < numParts; part++) {
      start = partOffsets[part];

      if (part == (numParts - 1)) {
        finish = numPoints;
      } else {
        finish = partOffsets[part + 1];
      }

      length = finish - start;
      if (length == 1) {
        length = 2;
        clonePoint = true;
      } else {
        clonePoint = false;
      }

      // List<double> z = new double[length];
      // doubleBuffer.get(z);
      List<double> z = List.filled(length, 0.0);
      for (var i = 0; i < z.length; i++) {
        z[i] = buffer.getDouble64();
      }

      for (int i = 0; i < length; i++) {
        lines[part].setOrdinate(i, CoordinateSequence.Z, z[i]);
      }
    }
  }
  if ((shapeType == ShapeType.ARCZ || shapeType == ShapeType.ARCM) &&
      !flatGeometry) {
    // M min, max
    // buffer.position(buffer.position() + 2 * 8);
    // doubleBuffer.position(doubleBuffer.position() + 2);
    buffer.position = buffer.position + 2 * 8;
    for (int part = 0; part < numParts; part++) {
      start = partOffsets[part];

      if (part == (numParts - 1)) {
        finish = numPoints;
      } else {
        finish = partOffsets[part + 1];
      }

      length = finish - start;
      if (length == 1) {
        length = 2;
        clonePoint = true;
      } else {
        clonePoint = false;
      }

      // List<double> m = new double[length];
      // doubleBuffer.get(m);
      List<double> m = List.filled(length, 0.0);
      for (var i = 0; i < m.length; i++) {
        m[i] = buffer.getDouble64();
      }
      for (int i = 0; i < length; i++) {
        lines[part].setOrdinate(i, CoordinateSequence.M, m[i]);
      }
    }
  }

  // Prepare line strings and return the multilinestring
  List<LineString> lineStrings = []; // List(numParts);
  for (int part = 0; part < numParts; part++) {
    lineStrings.add(geometryFactory.createLineStringSeq(lines[part]));
    // lineStrings[part] = geometryFactory.createLineStringSeq(lines[part]);
  }

  return geometryFactory.createMultiLineString(lineStrings);
}