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,
  5. bool swapXY = false,
})

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.

If swapXY is true, then swaps x and y for the result.

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,
  bool swapXY = false,
}) {
  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[swapXY ? offset + 1 : offset].toDouble(),
      y: coords[swapXY ? offset : offset + 1].toDouble(),
      z: coordsType.is3D
          ? (len > 2 ? coords[offset + 2] : 0.0).toDouble()
          : null,
      m: mIndex != null
          ? (len > mIndex ? coords[offset + mIndex] : 0.0).toDouble()
          : 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 num x;
    final num y;
    if (swapXY) {
      y = iter.moveNext() ? iter.current : throw invalidCoordinates;
      x = iter.moveNext() ? iter.current : throw invalidCoordinates;
    } else {
      x = iter.moveNext() ? iter.current : throw invalidCoordinates;
      y = iter.moveNext() ? iter.current : throw invalidCoordinates;
    }

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

    // 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.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.0 : null;
      }
    } else {
      optM = null;
    }

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