A geospatial library for Dart. Designed primarily around vector features, this library provides a simple interface for working with geographic data.
It's based heavily on the geojson specification, but has been extended to add functionality directly to the feature types.
You can convert between different units with the conversions
library.
Types of conversions:
- Distance: conversions between meters, kilometers, and miles, etc.
- Area: conversions between square meters, square kilometers, and square miles, etc.
- Angle: conversions between degrees, radians, and gradians, etc.
Here's an example:
import 'package:geodart/conversions.dart';
// Ten miles to kilometers
convertDistance(10, DistanceUnits.miles, DistanceUnits.kilometers); // returns 16.09344
// Ten degrees to radians
convertAngle(10, AngleUnits.degrees, AngleUnits.radians); // returns 0.17453292519943295
// Ten acres to square miles
convertArea(10, AreaUnits.acres, AreaUnits.squareMiles); // returns 0.004046856
There are some static units that are available with the type of DistanceUnit
, AngleUnit
and AreaUnit
. There are some preset units that are available with these types:
The following are the available units for length and distance:
DistanceUnits.meters
DistanceUnits.kilometers
DistanceUnits.miles
DistanceUnits.feet
DistanceUnits.yards
DistanceUnits.nauticalMiles
DistanceUnits.millimeters
DistanceUnits.centimeters
The following are the available units for angles:
AngleUnits.degrees
AngleUnits.radians
AngleUnits.gradians
AngleUnits.turns
AngleUnits.arcSeconds
AngleUnits.arcMinutes
AngleUnits.milliradians
The following are the available units for area:
AreaUnits.squareMeters
AreaUnits.squareKilometers
AreaUnits.squareMiles
AreaUnits.acres
AreaUnits.hectares
AreaUnits.squareFeet
AreaUnits.squareYards
AreaUnits.squareInches
To use this library, you'll need to get familiar with the feature types. All other actions taken depend on using the proper feature types. These feature types are very similar to the ones used in the geojson specification.
I'll admit, the feature coordinates are a bit of a mess. I'm working on a better way to handle this.
The following features are included in this library:
The package also provides a Feature
class, which is a
abstract class that can be extended to create new feature types.
Positions are stored using Coordinate
objects, which has a variety of
convenience methods for working with coordinates.
Bounding boxes (generally used as the minimum surrounding area of a Feature
) are stored
using BoundingBox
objects, which has a variety of convenience methods
for working with bounding boxes.
A FeatureCollection
is a collection of
Feature
objects.
It functions very similarly to a List
of Feature
objects,
but might extended to include additional properties in the future.
Constructors
FeatureCollection.fromJson(Map<String, dynamic> json)
- Creates aFeatureCollection
from a JSON object. Automatically converts features from GeoJSON to their respective types.FeatureCollection.fromWKT(String wkt)
- Creates aFeatureCollection
from a Well-Known Text string.
Methods
toJson()
- Returns a JSON object representing theFeatureCollection
. Automatically converts features to GeoJSON.nearestPointTo(Point point)
- Returns the nearestPoint
in theFeatureCollection
to the given point.explode()
- Returns aFeatureCollection
ofPoint
objects, one for each coordinate in each geometry in theFeatureCollection
.isCollectionOf(String type)
- Returns true if theFeatureCollection
contains only features of the given type.
Properties
features
- AList
ofFeature
objects.type
- The type of theFeatureCollection
. Always"FeatureCollection"
.bbox
- The [BoundingBox
] of theFeatureCollection
.envelope
- APolygon
representing the envelope of theFeatureCollection
.center
- ThePoint
representing the center of theFeatureCollection
.isEmpty
- Whether or not theFeatureCollection
is empty.convexHull
- The smallestPolygon
representing the convex hull of theFeatureCollection
.
A Feature
is an abstract class that can be extended to create new feature types.
Because this class is abstract, you cannot instantiate it directly.
Methods
explode()
- Returns a [List] ofPoint
objects, one for each coordinate in theFeature
.toJson()
- Returns a JSON object representing theFeature
. Automatically converts features to GeoJSON.toWKT()
- Returns a WKT string representing theFeature
.
Properties
type
- The type of theFeature
.bbox
- The [BoundingBox
] of theFeature
.center
- ThePoint
representing the center of theFeature
.
A Point
is a single position. It is represented by a Coordinate
object.
Constructors
Point.fromJson(Map<String, dynamic> json)
- Creates aPoint
from aMap
of GeoJSON data.Point.fromLngLat(num lng, num lat)
- Creates aPoint
from anum
longitude and latitude.Point.fromWKT(String wkt)
- Creates aPoint
from a Well-Known Text string.Point.random()
- Creates aPoint
at a random location within the [-180, 180] x [-90, 90] bounding box.
Methods
explode()
- Returns aList
of itself.toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing thePoint
.isContainedIn(Feature feature)
- Returns true if thePoint
is contained within the givenPolygon
orMultiPolygon
.buffer(double distance, {DistanceUnit unit = DistanceUnits.meters, int steps = 40})
- Returns aPolygon
that is the buffer of thePoint
of the given distance.
Properties
coordinates
- TheCoordinate
of thePoint
.type
- The type of thePoint
. Always"Point"
.properties
- AMap
of properties.bbox
- aBoundingBox
of thePoint
.center
- ThePoint
representing the center of thePoint
, which is same as the point itself.lat
- The latitude of thePoint
.lng
- The longitude of thePoint
.
A MultiPoint
is a collection of Coordinate
objects, represented by individual and non-connected points.
Constructors
MultiPoint.fromJson(Map<String, dynamic> json)
- Creates aMultiPoint
from aMap
of GeoJSON data.MultiPoint.fromWKT(String wkt)
- Creates aMultiPoint
from a Well-Known Text string.
Methods
explode()
- Returns aList
ofPoint
objects.toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing theMultiPoint
.union({MultiPoint? multi, Point? point})
- Merges theMultiPoint
with anotherMultiPoint
orPoint
.flatten()
- Returns aList
ofPoint
objects.
Properties
coordinates
- AList
ofCoordinate
objects.type
- The type of theMultiPoint
. Always"MultiPoint"
.properties
- AMap
of properties.bbox
- aBoundingBox
of theMultiPoint
.center
- ThePoint
representing the center of theMultiPoint
.
A LineString
is a collection of Coordinate
objects that form a line.
Constructors
LineString.fromJson(Map<String, dynamic> json)
- Creates aLineString
from aMap
of GeoJSON data.LineString.fromWkt(String wkt)
- Creates aLineString
from a Well-Known Text string.LineString.random({int length})
- Creates aLineString
at a random location within the [-180, 180] x [-90, 90] bounding box with a given number of points (defaults to 2).
Methods
along(distance)
- Returns aPoint
at the specified distance along the line.explode()
- Returns aList
ofPoint
objects that make up the LineString.toJson()
- Returns a GeoJSONMap
of the LineString.toPolygon()
- Returns aPolygon
that is the same as the LineString. LineString must be closed, or an exception will be thrown.toWKT()
- Returns aString
of the LineString in WKT format.pointAt(double percentage)
- Returns aPoint
at the specified percentage along the line.reverse()
- Returns aLineString
that is the reverse of the original LineString.isParallelTo(LineString line)
- Returnstrue
if the LineString is parallel to the specified LineString, or all segments are parallel in order or reverse order.intersections(LineString line)
- Returns aFeatureCollection
ofPoint
objects where the LineString intersects the specified LineString.contains(Point point)
- Returnstrue
if the LineString contains the specifiedPoint
.
Properties
coordinates
- AList
ofCoordinate
objects that make up the LineString.type
- The type of the LineString. Always"LineString"
.isClosedRing
- A boolean indicating whether the LineString is a closed ring.length
- The length (in meters) of the LineString.properties
- AMap
of properties.bbox
- aBoundingBox
of theLineString
.segments
- AList
ofLineString
objects that make up the LineString.midpoint
- Returns aPoint
at the midpoint of the LineString.center
- ThePoint
representing the center of theLineString
's coordinates.bearing
- The bearing of theLineString
. If more than 2 coordinates are provided, 0.0 is returned.slope
- The slope of theLineString
. If more than 2 coordinates are provided, it uses the first and last coordinates.
A MultiLineString
is a collection of Coordinate
objects that form multiple separate LineStrings with one set of shared properties.
Constructor
MultiLineString.fromJson(Map<String, dynamic> json)
- Creates aMultiLineString
from aMap
of GeoJSON data.MultiLineString.fromWkt(String wkt)
- Creates aMultiLineString
from a Well-Known Text string.MultiLineString.random({int count, int length})
- Creates aMultiLineString
at a random location within the [-180, 180] x [-90, 90] bounding box, with a line count (count) and a number of points in each line (length).
Methods
explode()
- Returns aList
ofLineString
objects.toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing theMultiLineString
.union(MultiLineString other)
- Merges theMultiLineString
with anotherMultiLineString
.flatten()
- Returns aList
ofLineString
objects.
Properties
coordinates
- A nestedList
ofCoordinate
objects.type
- The type of theMultiLineString
. Always"MultiLineString"
.properties
- AMap
of properties.bbox
- aBoundingBox
of theMultiLineString
.
A Polygon
is a collection of [LinearRing
](#Linear Ring) objects that form a closed ring. The first LinearRing in the list is the outer ring, and any subsequent LinearRings are holes. Holes should be contained within the outer ring - if they are not, some algorithms may not work correctly. A Polygon should also not intersect itself - again, some algorithms may not work correctly if this is not the case.
Constructors
Polygon.fromJson(Map<String, dynamic> json)
- Creates aPolygon
from aMap
of GeoJSON data.Polygon.fromWkt(String wkt)
- Creates aPolygon
from a Well-Known Text string.
Methods
explode()
- Returns aList
ofPoint
objects.toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing thePolygon
.toLineString()
- Returns aLineString
that is the same geometry as thePolygon
.contains(Point point)
- Returnstrue
if thePolygon
contains the specifiedPoint
.intersects(Polygon poly)
- Returnstrue
if thePolygon
intersects the specifiedPolygon
.
Properties
coordinates
- AList
of [LinearRing
](#Linear Ring) objects.type
- The type of thePolygon
. Always"Polygon"
.area
- The are (in square meters) of the Polygon.properties
- AMap
of properties.bbox
- aBoundingBox
of thePolygon
.
A MultiPolygon
is a collection of Polygon
geometries forming one MultiPolygon with shared properties.
Constructors
MultiPolygon.fromJson(Map<String, dynamic> json)
- Creates aMultiPolygon
from aMap
of GeoJSON data.MultiPolygon.fromWkt(String wkt)
- Creates aMultiPolygon
from a Well-Known Text string.
Methods
explode()
- Returns aList
ofPoint
objects.toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing theMultiPolygon
.union({MultiPolygon? multi, Polygon? poly})
- Merges theMultiPolygon
with anotherMultiPolygon
and/orPolygon
.flatten()
- Returns aList
ofPolygon
objects.toMultiLineString()
- Returns aMultiLineString
that is the same geometry as theMultiPolygon
.contains(Point point)
- Returnstrue
if theMultiPolygon
contains thePoint
.intersects(poly: Polygon, multi: MultiPolygon)
- Returnstrue
if thisMultiPolygon
intersects the passedPolygon
orMultiPolygon
.
Properties
coordinates
- AList
ofPolygon
objects.type
- The type of theMultiPolygon
. Always"MultiPolygon"
.properties
- AMap
of properties.area
- The are (in square meters) of the MultiPolygon.bbox
- aBoundingBox
of theMultiPolygon
.hasSelfIntersections
- Returnstrue
if any of the containedLinearRing
geometries intersect.
A Coordinate
is a point in a two-dimensional Cartesian coordinate system.
Constructors
Coordinate.fromJson(Map<String, dynamic> json)
- Creates aCoordinate
from aMap
of GeoJSON data.Coordinate.fromWkt(String wkt)
- Creates aCoordinate
from a Well-Known Text string.Coordinate.random()
- Creates aCoordinate
at a random location.
Methods
toJson()
- Returns aMap
of GeoJSON data.toWKT()
- Returns a Well-Known Text string representing theCoordinate
.toENU(Coordinate origin)
- Returns the difference in 3 dimensional space (asList<double>[xEast, yNorth, zUp]
) between theCoordinate
and the passedCoordinate
origin.distanceTo(Coordinate other)
- Returns the distance (in meters) between theCoordinate
and anotherCoordinate
.bearingTo(Coordinate other)
- Returns the bearing (in degrees) between theCoordinate
and anotherCoordinate
.destination(num distance, num bearing)
- Returns aCoordinate
that is the same geometry as theCoordinate
but moved a given distance and bearing.interpolate(Coordinate other, num fraction)
- Returns aCoordinate
that is the same geometry as theCoordinate
but moved a given fraction of the distance and bearing to anotherCoordinate
.
Properties
latitude
- The latitude of theCoordinate
.longitude
- The longitude of theCoordinate
.type
- The type of theCoordinate
. Always"Coordinate"
.
A [LinearRing
](#Linear Ring) is a closed LineString
that is closed because the first and last coordinate are the same.
Constructors
LinearRing.random()
- Creates a [LinearRing
](#Linear Ring) with 3 randomCoordinates
.
Methods
toLineString()
- Returns aLineString
that is the same geometry as the [LinearRing
](#Linear Ring).reverse()
- Returns a [LinearRing
](#Linear Ring) that is the same geometry as the [LinearRing
](#Linear Ring) but in reverse order.explode()
- Returns aFeatureCollection
ofPoint
objects.
Properties
coordinates
- AList
ofCoordinate
objects.type
- The type of the [LinearRing
](#Linear Ring). Always"LinearRing"
.area
- The are (in square meters) of the [LinearRing
](#Linear Ring).centroid
- TheCoordinate
that is the centroid of the [LinearRing
](#Linear Ring).bbox
- aBoundingBox
of the [LinearRing
](#Linear Ring).
A BoundingBox
is a rectangular area of the two-dimensional Cartesian coordinate system.
Generally, it is used to represent the smallest possible bounds of a Feature
in lat/long space.
Constructors
BoundingBox.fromCoordinates(List<Coordinate> points)
- Creates aBoundingBox
from aList
ofCoordinate
objects.BoundingBox.empty()
- Creates an emptyBoundingBox
.BoundingBox.fromPoints(List<Point> points)
- Creates aBoundingBox
from aList
ofPoint
objects.
Methods
toList()
- Returns aList
of GeoJSON data.toPolygon()
- Returns aPolygon
that is the same geometry as theBoundingBox
.
Properties
minLong
- The minimum longitude of theBoundingBox
.minLat
- The minimum latitude of theBoundingBox
.maxLong
- The maximum longitude of theBoundingBox
.maxLat
- The maximum latitude of theBoundingBox
.type
- The type of theBoundingBox
. Always"BoundingBox"
.center
- TheCoordinate
center of theBoundingBox
.square
- TheBoundingBox
, but made square.
Measure the distance between two points.
import 'package:geodart/measurements.dart';
import 'package:geodart/geometries.dart';
double distanceBetween = distance(
Point.fromLngLat(1.0, 1.0),
Point.fromLngLat(2.0, 2.0),
);
Under the hood, this uses the coordinate distanceTo()
function, and could be very easily replaced with a different algorithm.
I prefer the distanceTo()
function because it is more explicit and easier to read.
import 'package:geodart/geometries.dart';
double distanceBetween = Coordinate(1.0, 1.0).distanceTo(Coordinate(2.0, 2.0));
Measure the area of a polygon.
import 'package:geodart/geometries.dart';
Polygon polygon = Polygon.fromJson(
{
'type': 'Polygon',
'coordinates': [
[
[1.0, 1.0],
[2.0, 1.0],
[2.0, 2.0],
[1.0, 1.0],
],
],
}
);
print(polygon.area);
Measure the length of a LineString.
LineString
length is calculated on the fly.
import 'package:geodart/geometries.dart';
LineString lineString = LineString.fromJson(
{
'type': 'LineString',
'coordinates': [
[1.0, 1.0],
[2.0, 2.0],
],
}
);
print(lineString.length);
This library is free software under the terms of the MIT license. See the LICENSE file for more details.
If you have any questions or comments, please open an issue on the Github repository.
If you want to make a pull request, please open a pull request on the Github repository. Please make sure to include a test suite. I make no promises that I will accept pull requests, but I will try my best to keep the code up to date.