Skip to content

Commit

Permalink
feat: Add geometry-type property
Browse files Browse the repository at this point in the history
  • Loading branch information
tmcw committed Oct 28, 2022
1 parent 59df17e commit 14be7ce
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 39 deletions.
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ also encodes parts of KML, GPX, and TCX files that otherwise would be lost.
This also emits the [geojson-coordinate-properties](https://github.com/mapbox/geojson-coordinate-properties) format
to include time and other attributes that apply to each coordinate of a LineString.

## Ground overlays

KML GroundOverlays are now supported, and transformed into Features
with Polygon geometries. They have two defined properties:

```json
{
"@geometry-type": "groundoverlay",
"icon": "https://url.to.image…"
}
```

## CLI

Use [@tmcw/togeojson-cli](https://github.com/tmcw/togeojson-cli) to use this
Expand Down Expand Up @@ -100,8 +112,8 @@ import { kml } from "@tmcw/togeojson";
- [x] [TimeSpan](https://developers.google.com/kml/documentation/kmlreference#timespan)
- [x] [TimeStamp](https://developers.google.com/kml/documentation/kmlreference#timestamp)
- [x] Folders (with kmlWithFolders)
- [x] GroundOverlays
- [ ] NetworkLinks
- [ ] GroundOverlays

### GPX Feature Support

Expand Down Expand Up @@ -146,15 +158,6 @@ step if desired.
This module should support converting all KML and GPX features that have commonplace
equivalents in GeoJSON.

KML is a very complex format with many features. Some of these features, like NetworkLinks,
folders, and GroundOverlays, don't have a GeoJSON equivalent. In these cases,
toGeoJSON doesn't convert the features. It also doesn't crash on these constructs:
toGeoJSON should be able to run on all valid KML and GPX files without crashing:
but for some files it may have no output.

We encourage other libraries to look into supporting these features, but
support for them is out of scope for toGeoJSON.

## Protips:

Have a string of XML and need an XML DOM? There are two main options:
Expand Down
40 changes: 20 additions & 20 deletions lib/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12773,24 +12773,24 @@ Object {
"coordinates": Array [
Array [
Array [
14.60128369746704,
37.46543388598137,
14.60190128636069,
37.464406338104496,
],
Array [
14.60128369746704,
37.91904192681665,
14.600668902543442,
37.91801270483731,
],
Array [
15.35832653742206,
37.91904192681665,
15.35770894852841,
37.92006947469352,
],
Array [
14.60128369746704,
37.91904192681665,
14.600668902543442,
37.91801270483731,
],
Array [
14.60128369746704,
37.46543388598137,
14.60190128636069,
37.464406338104496,
],
],
],
Expand Down Expand Up @@ -12820,24 +12820,24 @@ Object {
"coordinates": Array [
Array [
Array [
14.60128369746704,
37.46543388598137,
14.60190128636069,
37.464406338104496,
],
Array [
14.60128369746704,
37.91904192681665,
14.600668902543442,
37.91801270483731,
],
Array [
15.35832653742206,
37.91904192681665,
15.35770894852841,
37.92006947469352,
],
Array [
14.60128369746704,
37.91904192681665,
14.600668902543442,
37.91801270483731,
],
Array [
14.60128369746704,
37.46543388598137,
14.60190128636069,
37.464406338104496,
],
],
],
Expand Down
50 changes: 41 additions & 9 deletions lib/kml/ground_overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,32 @@ function getGroundOverlayBox(node: Element): Polygon | null {
return getLatLonBox(node);
}

type BBox = [number, number, number, number];

const DEGREES_TO_RADIANS = Math.PI / 180;

function rotateBox(
bbox: BBox,
coordinates: Polygon["coordinates"],
rotation: number
): Polygon["coordinates"] {
const center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];

return [
coordinates[0].map((coordinate) => {
const dy = coordinate[1] - center[1];
const dx = coordinate[0] - center[0];
const distance = Math.sqrt(Math.pow(dy, 2) + Math.pow(dx, 2));
const angle = Math.atan2(dy, dx) - rotation * DEGREES_TO_RADIANS;

return [
center[0] + Math.cos(angle) * distance,
center[1] + Math.sin(angle) * distance,
];
}),
];
}

function getLatLonBox(node: Element): Polygon | null {
const latLonBox = get1(node, "LatLonBox");

Expand All @@ -32,24 +58,30 @@ function getLatLonBox(node: Element): Polygon | null {
const west = num1(latLonBox, "west");
const east = num1(latLonBox, "east");
const south = num1(latLonBox, "south");
const rotation = num1(latLonBox, "rotation");

if (
typeof north === "number" &&
typeof south === "number" &&
typeof west === "number" &&
typeof east === "number"
) {
const bbox: BBox = [west, south, east, north];
let coordinates = [
[
[west, south], // bottom left
[west, north], // top left
[east, north], // top right
[west, north], // bottom right
[west, south], // bottom left (again)
],
];
if (typeof rotation === "number") {
coordinates = rotateBox(bbox, coordinates, rotation);
}
return {
type: "Polygon",
coordinates: [
[
[west, south], // bottom left
[west, north], // top left
[east, north], // top right
[west, north], // bottom right
[west, south], // bottom left (again)
],
],
coordinates,
};
}
}
Expand Down

0 comments on commit 14be7ce

Please sign in to comment.