buildPosition<R extends Position> static method

R buildPosition<R extends Position>(
  1. Iterable<num> coords, {
  2. required CreatePosition<R> to,
  3. int offset = 0,
  4. Coords? type,
})

Builds a position of R from coords starting from offset.

A position instance is created using the factory function to.

Supported coordinate value combinations for coords are: (x, y), (x, y, z), (x, y, m) and (x, y, z, m).

Use an optional type to explicitely set the coordinate type. If not provided and coords has 3 items, then xyz coordinates are assumed.

Throws FormatException if coordinates are invalid.

Implementation

static R buildPosition<R extends Position>(
  Iterable<num> coords, {
  required CreatePosition<R> to,
  int offset = 0,
  Coords? type,
}) {
  if (coords is List<num>) {
    final len = coords.length - offset;
    final coordsType = type ?? Coords.fromDimension(math.min(4, len));
    final mIndex = coordsType.indexForM;
    if (len < 2) {
      throw invalidCoordinates;
    }
    return to.call(
      x: coords[offset],
      y: coords[offset + 1],
      z: coordsType.is3D ? (len > 2 ? coords[offset + 2] : 0) : null,
      m: mIndex != null ? (len > mIndex ? coords[offset + mIndex] : 0) : null,
    );
  } else {
    // resolve iterator for source coordinates
    final Iterator<num> iter;
    if (offset == 0) {
      iter = coords.iterator;
    } else if (coords.length >= offset + 2) {
      iter = coords.skip(offset).iterator;
    } else {
      throw invalidCoordinates;
    }

    // iterate at least to x and y
    final x = iter.moveNext() ? iter.current : throw invalidCoordinates;
    final y = iter.moveNext() ? iter.current : throw invalidCoordinates;

    // XY was asked
    if (type == Coords.xy) {
      return to.call(x: x, y: y);
    }

    // iterate optional z and m
    final num? optZ;
    if (type == null || type.is3D) {
      if (iter.moveNext()) {
        optZ = iter.current;
      } else {
        optZ = type?.is3D ?? false ? 0 : null;
      }
    } else {
      optZ = null;
    }
    final num? optM;
    if (type == null || type.isMeasured) {
      if (iter.moveNext()) {
        optM = iter.current;
      } else {
        optM = type?.isMeasured ?? false ? 0 : null;
      }
    } else {
      optM = null;
    }

    // finally create a position object
    return to.call(x: x, y: y, z: optZ, m: optM);
  }
}