Skip to content

Commit

Permalink
Simplify GeometryCollections containing a single Polygon
Browse files Browse the repository at this point in the history
GeoJSONLint complains about these types of features:

> GeometryCollection with a single geometry should be avoided in favor
> of single part or a single object of multi-part type

This simultaneously expands (`GeometryCollection | Polygon`) and narrows
(`GeometryCollection<Polygon | LineString>`) the type of GeoJSON
features created from isolines.
  • Loading branch information
mojodna committed Nov 14, 2024
1 parent cccb802 commit 14ad080
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 10 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,13 @@ const featureCollections = calculateRoutesResponseToFeatureCollections(response)

### calculateIsolinesResponseToFeatureCollection

This converts a CalculateIsolineResponse from the standalone Routes SDK to a GeoJSON FeatureCollection which contains one Feature for each isoline
in the response. Isolines can contain both polygons for isoline regions and lines for connectors between regions
(such as ferry travel), so each Feature is a GeometryCollection that can contain a mix of Polygons and LineStrings.
The `flattenProperties` option will flatten the nested response data into a flat properties list.
This option is enabled by default, as it makes the data easier to use from within MapLibre expressions.
This converts a CalculateIsolineResponse from the standalone Routes SDK to a GeoJSON
FeatureCollection which contains one Feature for each isoline in the response. Isolines can contain
both polygons for isoline regions and lines for connectors between regions (such as ferry travel),
so each Feature contains either a GeometryCollection with a mix of Polygons and LineStrings or a
single Polygon. The `flattenProperties` option will flatten the nested response data into a flat
properties list. This option is enabled by default, as it makes the data easier to use from within
MapLibre expressions.

Any feature that is missing its geometry in the response or has invalid geometry will throw an Error().

Expand Down
24 changes: 19 additions & 5 deletions src/to-geojson/georoutes-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ const defaultCalculateIsolinesResponseOptions = defaultBaseGeoRoutesOptions;
/**
* This converts a CalculateIsolineResponse to a GeoJSON FeatureCollection which contains one Feature for each isoline
* in the response. Isolines can contain both polygons for isoline regions and lines for connectors between regions
* (such as ferry travel), so each Feature is a GeometryCollection that can contain a mix of Polygons and LineStrings.
* (such as ferry travel), so each Feature contains either a GeometryCollection with a mix of Polygons and LineStrings
* or a single Polygon.
*
* Any feature that is missing its geometry in the response or has invalid geometry will throw an Error.
*
Expand Down Expand Up @@ -405,11 +406,11 @@ const defaultCalculateIsolinesResponseOptions = defaultBaseGeoRoutesOptions;
export function calculateIsolinesResponseToFeatureCollection(
isolinesResponse: CalculateIsolinesResponse,
options?: CalculateIsolinesResponseOptions,
): FeatureCollection<GeometryCollection> {
): FeatureCollection<GeometryCollection<Polygon | LineString> | Polygon> {
// Set any options that weren't passed in to the default values.
options = { ...defaultCalculateIsolinesResponseOptions, ...options };

const isolines: FeatureCollection<GeometryCollection> = {
const isolines: FeatureCollection<GeometryCollection<Polygon | LineString> | Polygon> = {
type: "FeatureCollection",
features: [],
};
Expand All @@ -420,7 +421,7 @@ export function calculateIsolinesResponseToFeatureCollection(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { Geometries, Connections, ...properties } = isoline;

const feature: Feature<GeometryCollection> = {
const feature: Feature<GeometryCollection<Polygon | LineString>> = {
type: "Feature",
id: isolines.features.length,
properties: options.flattenProperties ? flattenProperties(properties, "") : properties,
Expand Down Expand Up @@ -448,7 +449,20 @@ export function calculateIsolinesResponseToFeatureCollection(

// As long as this feature has at least one polygon or line, add it to the result set.
if (feature.geometry.geometries.length > 0) {
isolines.features.push(feature);
if (feature.geometry.geometries.length === 1 && feature.geometry.geometries[0].type === "Polygon") {
// GeometryCollections containing single geometries trigger GeoJSONLint warnings:
// GeometryCollection with a single geometry should be avoided in favor of single part
// or a single object of multi-part type
// in practice, the geometry type for single-geometry isolines is Polygon; LineStrings are
// supplemental and appear when multiple polygons are present, representing the connection
// between those areas
isolines.features.push({
...feature,
geometry: feature.geometry.geometries[0],
});
} else {
isolines.features.push(feature);
}
}
}

Expand Down

0 comments on commit 14ad080

Please sign in to comment.