placemark / togeojson

convert KML, TCX, and GPX to GeoJSON, without the fuss
https://placemark.github.io/togeojson/
BSD 2-Clause "Simplified" License
401 stars 67 forks source link

Folder data #97

Closed mb72 closed 11 months ago

mb72 commented 1 year ago

Thank you for working to support folders. Would you consider adding another conversion option that includes the folder data in a geojson file along with the style and other data you already include? This would be very helpful. There's an approach that will do this by numbering the folder levels and making them geojson properties. The first folder encountered would be "folder0". If it has a description with it that would be "description0". The description numbers would always match the folder number they accompany in the KML. In the rare case that there is a folder with no placemarks in it, the folder name and description would be ignored.

Below is an example of what this conversion process would look like. It would help to treat the file name as the first folder entry if multiple converted KMLs are later combined, so that's what I've done. KMLs can include other KMLs which results in the tag being used. But like the tag, it can be treated as another folder. A folderpath property would also be helpful.

Point in KML

<Document>
<name>Bob's_Canada_Map.kml</name>
<Folder>
  <name>Canada_Map</name>
  <Document id="root_doc">
    <name>Alberta</name>
    <Folder>
      <name>Calgary</name>
      <description>Largest city in Alberta</description>
      <Folder>
        <name>Architecture</name>
        <Placemark>
          <name>Shops</name>
          <description>Scotia Centre</description>
          <Point>
            <coordinates>-114.0661567,51.0460943,0</coordinates>
          </Point>
        </Placemark>

Point in geojson

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -114.0661567,
                    51.0460943,
                    0
                ]
            },
            "properties": {
                "name": "Shops",
                "description": "Scotia Centre",
                "folderpath": "Bob's_Canada_Map.kml/Canada_Map/Alberta/Calgary/Architecture",
                "folder0": "Bob's_Canada_Map.kml",
                "folder1": "Canada_Map",
                "folder2": "Alberta",
                "folder3": "Calgary",
                "description3": "Largest city in Alberta",
                "folder4": " Architecture"
            }
        },
tmcw commented 1 year ago

I'm hesitant to include this in the core of this project. There's no real way to represent folders as a property in a way that's unambiguous and wouldn't clobber other properties.

At the same time, it's very possible to implement a "flattened folder scheme" outside of togeojson. You need to do a little recursion to make it work, but it's not more than 50 lines of code or so:

function toFlattenedFolders(root) {
  let features = [];
  const path = [];

  function handleChild(child, path) {
    if (child.type === "Feature") {
      features.push({
        ...child,
        properties: {
          ...(child.properties || {}),
          path
        }
      });
    } else {
      for (let x of child.children) {
        handleChild(x, path.concat(child.meta.name));
      }
    }
  }

  for (let child of root.children) {
    handleChild(child, path);
  }

  return {
    type: "FeatureCollection",
    features
  };
}

I think this living in an application or another module, if someone wants to write it, would be ideal.