Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project bounding box #96

Closed
navispatial opened this issue Feb 20, 2022 · 4 comments
Closed

Project bounding box #96

navispatial opened this issue Feb 20, 2022 · 4 comments
Labels
enhancement New feature or request 🌐 geobase Related to the code package "geobase"

Comments

@navispatial
Copy link
Member

Add method like following to Projection mixin:

 R projectBox<R extends Box>(Box source, {required CreateBox<R> to});

Plan to calculate:

  1. get distinct corners (one, two or four) in 2D for the source bbox
  2. project all corner positions
  3. calculate min and max coords in all axes from corner positions
  4. handle special case of geographic coordinates when longitude west and east coordinates span anti-meridian
  5. return the result as a new bounding box using a factory function
@navispatial navispatial added enhancement New feature or request 🌐 geobase Related to the code package "geobase" labels Feb 20, 2022
@navispatial
Copy link
Member Author

Consider also bbox factory function:

/// Creates a new bounding box from [minX], [minY], [maxX] and [maxY] values.
///
/// Optional [minZ] and [maxZ] for 3D boxes, and [minM] and [maxM] for
/// measured boxes can be provided too.
///
/// For projected or cartesian bounding boxes (`ProjBox`), coordinates axis are
/// applied as is.
///
/// For geographic bounding boxes (`GeoBox`), coordinates are applied as:
/// `minX` => `west`, `minY` => `south`, `minZ` => `minElev`, `minM` => `minM`,
/// `maxX` => `east`, `maxY` => `north`, `maxZ` => `maxElev`, `maxM` => `maxM`
typedef CreateBox<T extends Box> = T Function({
  required num minX,
  required num minY,
  num? minZ,
  num? minM,
  required num maxX,
  required num maxY,
  num? maxZ,
  num? maxM,
});

@navispatial
Copy link
Member Author

Implementatins on ProjBox and GeoBox would maybe be as follows.

ProjBox:

  /// A bounding box from parameters compatible with `CreateBox` function type.
  const ProjBox.create({
    required num minX,
    required num minY,
    num? minZ,
    num? minM,
    required num maxX,
    required num maxY,
    num? maxZ,
    num? maxM,
  })  : _minX = minX,
        _minY = minY,
        _minZ = minZ,
        _minM = minM,
        _maxX = maxX,
        _maxY = maxY,
        _maxZ = maxZ,
        _maxM = maxM;

GeoBox:

  /// A bounding box from parameters compatible with `CreateBox` function type.
  GeoBox.create({
    required num minX,
    required num minY,
    num? minZ,
    num? minM,
    required num maxX,
    required num maxY,
    num? maxZ,
    num? maxM,
  })  : _west = minX.toDouble(),
        _south = minY.toDouble(),
        _minElev = minZ?.toDouble(),
        _minM = minM?.toDouble(),
        _east = maxX.toDouble(),
        _north = maxY.toDouble(),
        _maxElev = maxZ?.toDouble(),
        _maxM = maxM?.toDouble();

@navispatial
Copy link
Member Author

Implementation not quite as previously planned.

GeoBox:

  /// Projects this geographic bounding box to a projected box using
  /// the forward [projection].
  @override
  ProjBox project(Projection projection) {
    // get distinct corners (one, two or four) in 2D for the geographic bbox
    final corners = corners2D;

    // project all corner positions (using the forward projection)
    final projected = corners.map((pos) => pos.project(projection));

    // create a projected bbox
    // (calculating min and max coords in all axes from corner positions)
    return ProjBox.from(projected);
  }

ProjBox:

  /// Projects this projected bounding box to a geographic box using
  /// the inverse [projection].
  @override
  GeoBox project(Projection projection) {
    // get distinct corners (one, two or four) in 2D for the projected bbox
    final corners = corners2D;

    // unproject all corner positions (using the inverse projection)
    final unprojected = corners.map((pos) => pos.project(projection));

    // create an unprojected (geographic) bbox
    // (calculating min and max coords in all axes from corner positions)
    return GeoBox.from(unprojected);
  }

NOT handling the special case of geographic coordinates when longitude west and east coordinates span anti-meridian, this might need a separate issue.

@navispatial
Copy link
Member Author

Implemented in geobase 0.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request 🌐 geobase Related to the code package "geobase"
Projects
None yet
Development

No branches or pull requests

1 participant