Skip to content

Commit

Permalink
Use function overloads to be specific about returned geometry types.
Browse files Browse the repository at this point in the history
  • Loading branch information
stevage committed Jan 22, 2025
1 parent f4490cc commit 6a05a9f
Showing 1 changed file with 44 additions and 18 deletions.
62 changes: 44 additions & 18 deletions packages/turf-bbox-clip/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ import {
import { getGeom } from "@turf/invariant";
import { lineclip, polygonclip } from "./lib/lineclip.js";

type OneGeometry =
| Point
| MultiPoint
| LineString
| MultiLineString
| Polygon
| MultiPolygon;

/**
* Takes a {@link Feature}, {@link Geometry} or {@link FeatureCollection} and a bbox and clips the object to the bbox using
* [lineclip](https://github.com/mapbox/lineclip).
Expand All @@ -54,36 +46,70 @@ type OneGeometry =
* //addToMap
* var addToMap = [bbox, poly, clipped]
*/
// pass a specific geometry type or FeatureCollection, get the same type back
function bboxClip<
G extends Point | MultiPoint,
P extends GeoJsonProperties = GeoJsonProperties,
>(feature: Feature<G, P> | G, bbox: BBox): Feature<Point | MultiPoint, P>;
function bboxClip<
G extends LineString | MultiLineString,
P extends GeoJsonProperties = GeoJsonProperties,
>(
feature: Feature<G, P> | G,
bbox: BBox
): Feature<LineString | MultiLineString, P>;
function bboxClip<
G extends Polygon | MultiPolygon,
P extends GeoJsonProperties = GeoJsonProperties,
>(feature: Feature<G, P> | G, bbox: BBox): Feature<Polygon | MultiPolygon, P>;

function bboxClip<
G extends GeometryCollection,
P extends GeoJsonProperties = GeoJsonProperties,
>(feature: Feature<G, P> | G, bbox: BBox): Feature<G, P>;
function bboxClip<
G extends FeatureCollection,
P extends GeoJsonProperties = GeoJsonProperties,
>(feature: G, bbox: BBox): FeatureCollection<Geometry, P>;

// pass a non-specific geometry type, get a generic feature back
function bboxClip<P extends GeoJsonProperties = GeoJsonProperties>(
feature: Feature<Geometry, P>,
bbox: BBox
): Feature<Geometry, P>;
function bboxClip(feature: Geometry, bbox: BBox): Feature<Geometry>;

// "implementation signature", can't be called directly
function bboxClip<
G extends Geometry,
P extends GeoJsonProperties = GeoJsonProperties,
>(
feature: Feature<G, P> | G | FeatureCollection,
bbox: BBox
): Feature | FeatureCollection {
): Feature<Geometry> | FeatureCollection {
if (feature.type === "FeatureCollection") {
return featureCollection(
feature.features.map((f: Feature) => bboxClip(f, bbox) as Feature)
);
}

const geom = getGeom(feature);
const type = geom.type;
const properties = feature.type === "Feature" ? feature.properties : {};
const properties: GeoJsonProperties =
feature.type === "Feature" ? feature.properties : {};

if (type === "GeometryCollection") {
const gs = geom.geometries as OneGeometry[];
const outGs: OneGeometry[] = gs.map(
(g: OneGeometry) =>
(bboxClip(g as OneGeometry, bbox) as Feature<OneGeometry>).geometry
);
const gs = geom.geometries;
const outGs = gs.map(
(g: Geometry) => (bboxClip(g, bbox) as Feature<Geometry>).geometry
) as Exclude<Geometry, GeometryCollection>[];
return geometryCollection(outGs, properties) as Feature<
GeometryCollection,
P
>;
}

let coords: any[] = geom.coordinates;

switch (type) {
case "LineString":
case "MultiLineString": {
Expand Down Expand Up @@ -137,8 +163,8 @@ function checkCoord(coord: Position, bbox: BBox) {
);
}

function clipPolygon(rings: number[][][], bbox: BBox) {
const outRings = [];
function clipPolygon(rings: Position[][], bbox: BBox) {
const outRings: Position[][] = [];
for (const ring of rings) {
const clipped = polygonclip(ring, bbox);
if (clipped.length > 0) {
Expand Down

0 comments on commit 6a05a9f

Please sign in to comment.