Skip to content

Commit

Permalink
feat(geobase): simple geometry data structures #133
Browse files Browse the repository at this point in the history
  • Loading branch information
navispatial committed Aug 4, 2022
1 parent fb3a5e4 commit c512dff
Show file tree
Hide file tree
Showing 16 changed files with 865 additions and 2 deletions.
2 changes: 2 additions & 0 deletions dart/geobase/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ binary data formats, encodings and content interfaces also redesigned.
- [Coordinate order on box and position consistently #134](https://github.com/navibyte/geospatial/issues/134)
- [Positions as iterable of coordinate values on geobase #136](https://github.com/navibyte/geospatial/issues/136)
- [PositionData access (on lists or buffers) #137](https://github.com/navibyte/geospatial/issues/137)
- new mini library "transforms" and "projections"
- [Simple geometry data structures on geobase #133](https://github.com/navibyte/geospatial/issues/133)

🛠 Refactoring:
- [Optimize reading from iterable of coordinate values #131](https://github.com/navibyte/geospatial/issues/131)
Expand Down
1 change: 1 addition & 0 deletions dart/geobase/lib/geobase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ export 'src/vector/encoding.dart';
export 'src/vector/formats.dart';
export 'src/vector_data/array.dart';
export 'src/vector_data/coords.dart';
export 'src/vector_data/model.dart';
2 changes: 2 additions & 0 deletions dart/geobase/lib/src/vector_data/model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'model/bounded.dart';
export 'model/geometry.dart';
1 change: 1 addition & 0 deletions dart/geobase/lib/src/vector_data/model/bounded.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'bounded/bounded.dart';
27 changes: 27 additions & 0 deletions dart/geobase/lib/src/vector_data/model/bounded/bounded.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) 2020-2022 Navibyte (https://navibyte.com). All rights reserved.
// Use of this source code is governed by a “BSD-3-Clause”-style license that is
// specified in the LICENSE file.
//
// Docs: https://github.com/navibyte/geospatial

//import '/src/coordinates/base.dart';

/// A base interface for classes that know their bounding boxes.
abstract class Bounded {
/// Default `const` constructor to allow extending this abstract class.
const Bounded();

/*
/// The [bounds] for this object (could be calculated if not explicitely set).
///
/// Please note that in some cases bounds could be pre-calculated but it's
/// possible that accessing this property may cause extensive calculations.
Box get bounds;
/// The explicit [bounds] for this object when available.
///
/// Accessing this should never trigger extensive calculations. That is, if
/// bounds is not known, then returns the null value.
Box? get boundsExplicit;
*/
}
9 changes: 9 additions & 0 deletions dart/geobase/lib/src/vector_data/model/geometry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export 'geometry/geometry.dart';
export 'geometry/geometry_builder.dart';
export 'geometry/geometry_collection.dart';
export 'geometry/linestring.dart';
export 'geometry/multi_linestring.dart';
export 'geometry/multi_point.dart';
export 'geometry/multi_polygon.dart';
export 'geometry/point.dart';
export 'geometry/polygon.dart';
22 changes: 22 additions & 0 deletions dart/geobase/lib/src/vector_data/model/geometry/geometry.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2020-2022 Navibyte (https://navibyte.com). All rights reserved.
// Use of this source code is governed by a “BSD-3-Clause”-style license that is
// specified in the LICENSE file.
//
// Docs: https://github.com/navibyte/geospatial

//import '/src/codes/geom.dart';

import 'package:meta/meta.dart';

import '/src/codes/geom.dart';
import '/src/vector_data/model/bounded.dart';

/// A base interface for geometry classes.
@immutable
abstract class Geometry extends Bounded {
/// Default `const` constructor to allow extending this abstract class.
const Geometry();

/// The geometry type.
Geom get type;
}
181 changes: 181 additions & 0 deletions dart/geobase/lib/src/vector_data/model/geometry/geometry_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// Copyright (c) 2020-2022 Navibyte (https://navibyte.com). All rights reserved.
// Use of this source code is governed by a “BSD-3-Clause”-style license that is
// specified in the LICENSE file.
//
// Docs: https://github.com/navibyte/geospatial

import '/src/codes/coords.dart';
import '/src/codes/geom.dart';
import '/src/coordinates/base.dart';
import '/src/vector/content.dart';

import 'geometry.dart';
import 'geometry_collection.dart';
import 'linestring.dart';
import 'multi_linestring.dart';
import 'multi_point.dart';
import 'multi_polygon.dart';
import 'point.dart';
import 'polygon.dart';

/// A builder to create geometry instances from [GeometryContent] stream.
class GeometryBuilder with GeometryContent {
final void Function(Geometry geom, {required int index, String? name})
_addGeometry;

int _index = 0;

GeometryBuilder._(this._addGeometry);

void _add(Geometry geom, {String? name}) {
_addGeometry.call(geom, index: _index++, name: name);
}

/// Builds a geometry list from the content stream provided by [geometries].
///
/// Only geometry objects of [T] are built, any other geometries are ignored.
///
/// An optional expected [count], when given, specifies the number of geometry
/// objects in a content stream. Note that when given the count MUST be exact.
static List<T> buildList<T extends Geometry>(
WriteGeometries geometries, {
int? count,
}) {
final list = <T>[];
final builder =
GeometryBuilder._((Geometry geom, {required int index, String? name}) {
if (geom is T) {
list.add(geom);
}
});
geometries.call(builder);
return list;
}

/// Builds a geometry map from the content stream provided by [geometries].
///
/// Only geometry objects of [T] are built, any other geometries are ignored.
///
/// A content stream on [GeometryContent] should provide also the `name`
/// attribute for each geometry object. When `name` is not available, then
/// an index as String is used a key.
///
/// An optional expected [count], when given, specifies the number of geometry
/// objects in a content stream. Note that when given the count MUST be exact.
static Map<String, T> buildMap<T extends Geometry>(
WriteGeometries geometries, {
int? count,
}) {
final map = <String, T>{};
final builder =
GeometryBuilder._((Geometry geom, {required int index, String? name}) {
if (geom is T) {
map[name ?? index.toString()] = geom;
}
});
geometries.call(builder);
return map;
}

@override
void point(
Iterable<double> position, {
Coords? type,
String? name,
}) {
_add(
Point.build(position, type: type),
name: name,
);
}

@override
void lineString(
Iterable<double> chain, {
required Coords type,
String? name,
Box? bbox,
}) {
if (chain.length < 2) {
// note: ignore empty geometries for this implementation
}
_add(
LineString.build(chain, type: type),
name: name,
);
}

@override
void polygon(
Iterable<Iterable<double>> rings, {
required Coords type,
String? name,
Box? bbox,
}) {
if (rings.isEmpty) {
// note: ignore empty geometries for this implementation
}
_add(
Polygon.build(rings, type: type),
name: name,
);
}

@override
void multiPoint(
Iterable<Iterable<double>> points, {
required Coords type,
String? name,
Box? bbox,
}) {
_add(
MultiPoint.build(points, type: type),
name: name,
);
}

@override
void multiLineString(
Iterable<Iterable<double>> lineStrings, {
required Coords type,
String? name,
Box? bbox,
}) {
_add(
MultiLineString.build(lineStrings, type: type),
name: name,
);
}

@override
void multiPolygon(
Iterable<Iterable<Iterable<double>>> polygons, {
required Coords type,
String? name,
Box? bbox,
}) {
_add(
MultiPolygon.build(polygons, type: type),
name: name,
);
}

@override
void geometryCollection(
WriteSimpleGeometries geometries, {
Coords? type,
int? count,
String? name,
Box? bbox,
}) {
_add(
GeometryCollection.build(geometries, count: count),
name: name,
);
}

@override
void emptyGeometry(Geom type, {String? name}) {
// note: ignore empty geometries for this implementation
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2020-2022 Navibyte (https://navibyte.com). All rights reserved.
// Use of this source code is governed by a “BSD-3-Clause”-style license that is
// specified in the LICENSE file.
//
// Docs: https://github.com/navibyte/geospatial

import '/src/codes/geom.dart';
import '/src/vector/content.dart';

import 'geometry.dart';
import 'geometry_builder.dart';

/// A geometry collection with geometries.
class GeometryCollection<E extends Geometry> extends Geometry {
final List<E> _geometries;

/// A geometry collection with [geometries].
const GeometryCollection(List<E> geometries) : _geometries = geometries;

/// A geometry collection from the content stream provided by [geometries].
///
/// Only geometry objects of [E] are built, any other geometries are ignored.
///
/// An optional expected [count], when given, specifies the number of geometry
/// objects in a content stream. Note that when given the count MUST be exact.
///
/// An example to build a geometry collection with two child geometries:
/// ```dart
/// GeometryCollection.build(
/// count: 2,
/// (geom) => geom
/// ..point([10.123, 20.25])
/// ..polygon(
/// [
/// [
/// 10.1, 10.1,
/// 5.0, 9.0,
/// 12.0, 4.0,
/// 10.1, 10.1,
/// ],
/// ],
/// type: Coords.xy,
/// ),
/// );
/// ```
///
/// An example to build a type geometry collection with points only:
/// ```dart
/// GeometryCollection<Point>.build(
/// count: 3,
/// (geom) => geom
/// ..point([-1.1, -1.1])
/// ..point([2.1, -2.5])
/// ..point([3.5, -3.49]),
/// );
/// ```
factory GeometryCollection.build(
WriteGeometries geometries, {
int? count,
}) =>
GeometryCollection<E>(
GeometryBuilder.buildList<E>(geometries, count: count),
);

@override
Geom get type => Geom.geometryCollection;

/// All geometry items in this geometry collection.
List<E> get items => _geometries;

// todo: ==, hashCode, toString
}
Loading

0 comments on commit c512dff

Please sign in to comment.