Extract coordinates from KML file in Java

2019-03-29 12:49发布

I'm trying to parse a Kml file in Java. Cause I need to take the coordinates of a Placemark, to generate a poligon in java, and use it.

But my problem , is that i'm using JAK this library to parse it, and i'm not able to extract the information that i want.(I read the "help" in the official page, but I didn't found any help abut my problem)

I'm trying to do something like that:

final Kml kml = Kml.unmarshal(new File("C:/Users/A556520/Documents/Proyectos/GeoFencing/res/labasa.kml"));
final Document document = (Document)kml.getFeature();       
List<Feature> listafeatures = document.getFeature();        

But in this point I don't know how to extract the coordinates.

The file I'm trying to parse is this one: la basa

3条回答
我想做一个坏孩纸
2楼-- · 2019-03-29 13:01

Following the javadocs (unofficial) you need to check - using instanceof - each Feature whether is is a Placemark, if yes cast to it and get the Geometry which itself needs to be checked whether it is a Polygon, if yes then cast to it. After that the path to the coordinates is the following (just as it come in the kml-file):

getOuterBoundaryIs > getlinearRing > getCoordinates

Here is how it looks like in code:

@Test
public void parseKml() {
    String src = "misctests/stackoverflow/kml/labasa.kml";
    try(InputStream is = getClass().getClassLoader().getResourceAsStream(src)) {
        Assert.assertNotNull(is);
        Kml kml = Kml.unmarshal(is);
        Feature feature = kml.getFeature();
        parseFeature(feature);
    }
}

private void parseFeature(Feature feature) {
    if(feature != null) {
        if(feature instanceof Document) {
            Document document = (Document) feature;
            List<Feature> featureList = document.getFeature();
            for(Feature documentFeature : featureList) {
                if(documentFeature instanceof Placemark) {
                    Placemark placemark = (Placemark) documentFeature;
                    Geometry geometry = placemark.getGeometry();
                    parseGeometry(geometry);
                }
            }
        }
    }
}

private void parseGeometry(Geometry geometry) {
    if(geometry != null) {
        if(geometry instanceof Polygon) {
            Polygon polygon = (Polygon) geometry;
            Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
            if(outerBoundaryIs != null) {
                LinearRing linearRing = outerBoundaryIs.getLinearRing();
                if(linearRing != null) {
                    List<Coordinate> coordinates = linearRing.getCoordinates();
                    if(coordinates != null) {
                        for(Coordinate coordinate : coordinates) {
                            parseCoordinate(coordinate);
                        }
                    }
                }
            }
        }
    }
}

private void parseCoordinate(Coordinate coordinate) {
    if(coordinate != null) {
        System.out.println("Longitude: " +  coordinate.getLongitude());
        System.out.println("Latitude : " +  coordinate.getLatitude());
        System.out.println("Altitude : " +  coordinate.getAltitude());
        System.out.println("");
    }
}
查看更多
Evening l夕情丶
3楼-- · 2019-03-29 13:18

Thanks @A4L This is really an update and a more groovier way of doing the same So changed for Groovy and also attempts more types than the example given as well digs deep within a document layer:

 /**
     * This starts the process and reads in the uk file
     */
    public static void parseKml() {
        def src = ServletContextHolder.servletContext.getRealPath("/KML/doc.kml")
        InputStream is = new FileInputStream(src);
        Kml kml = Kml.unmarshal(is);
        Feature feature = kml.getFeature();
        parseFeature(feature);
    }

    /**
     * This is step 2 of the process it figures out if it has a direct placemark mapping on kml
     * or if this is part of some big folder structure
     * @param feature
     */
    public static void parseFeature(Feature feature) {
        if(feature) {
            if(feature instanceof Document) {
                feature?.feature?.each { documentFeature->
                    if(documentFeature instanceof Placemark) {
                        getPlacemark((Placemark) documentFeature)
                    } else if (documentFeature instanceof Folder) {
                        getFeatureList(documentFeature.feature)
                    }
                }
            }
        }
    }


    /**
     * This iterates over itself over and over again to gain access to placemarks within folders
     * The uk map boundary was nested folders within folders
     * @param features
     * @return
     */
    public static List<Feature> getFeatureList(List<Feature> features) {
        features?.each { Feature  f ->
            if (f instanceof Folder) {
                getFeatureList(f.getFeature())
            } else if (f instanceof Placemark) {
                getPlacemark((Placemark) f)
            }
        }
    }

    /**
     * This in short kicks off looking at a placemark it's name then parsing through each of its geometry points
     * This controls the listener content or should I say builds it up from within this helper
     * @param placemark
     */
    public static void getPlacemark(Placemark placemark) {
        Geometry geometry = placemark.getGeometry()
        List results = parseGeometry(geometry)
        GeoMapListener.update(placemark.name, results)
    }


    private static List parseGeometry(Geometry geometry) {
        List results=[]
        if(geometry != null) {
            if(geometry instanceof Polygon) {
                Polygon polygon = (Polygon) geometry;
                Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
                if(outerBoundaryIs != null) {
                    LinearRing linearRing = outerBoundaryIs.getLinearRing();
                    if(linearRing != null) {
                        List<Coordinate> coordinates = linearRing.getCoordinates();
                        if(coordinates != null) {
                            for(Coordinate coordinate : coordinates) {
                                results << parseCoordinate(coordinate);
                            }
                        }
                    }
                }
            } else  if (geometry instanceof LineString) {
                LineString lineString = (LineString) geometry;
                List<Coordinate> coordinates = lineString.getCoordinates();
                if (coordinates != null) {
                    for (Coordinate coordinate : coordinates) {
                        results <<  parseCoordinate(coordinate);
                    }
                }
            }
        }
        return results
    }

    private static Map parseCoordinate(Coordinate coordinate) {
        Map results=[:]
        if(coordinate) {
            results.longitude= coordinate.longitude
            results.latitude= coordinate.latitude
            results.altitude= coordinate.altitude
        }
        return results
    }
查看更多
家丑人穷心不美
4楼-- · 2019-03-29 13:21

Came across this post, so here is part of the code of function I have been using in my app to extract Place mark name & coordinates from a String kmlText.

    if (kmlText != null & kmlText.length() > 0) {
    // Change case of relevant tags to match our search string case
    kmlText = kmlText.replaceAll("(?i)<Placemark>", "<Placemark>")
        .replaceAll("(?i)</Placemark>", "</Placemark>")
        .replaceAll("(?i)<name>", "<name>")
        .replaceAll("(?i)</name>", "</name>")
        .replaceAll("(?i)<coordinates>", "<coordinates>")
        .replaceAll("(?i)</coordinates>", "</coordinates>");
    // Get <Placemark> tag
    String[] kmlPlacemarks = kmlText.split("</Placemark>");
    if (kmlPlacemarks.length > 0) {
        for (Integer i = 0; i < kmlPlacemarks.length; i++) {
            // Add '</Placemark>' to the end - actually not necessary
            kmlPlacemarks[i] += "</Placemark>";
            if (kmlPlacemarks[i].indexOf("<Placemark>") > -1)
                /* Trim front to start from '<Placemark>'
                Otherwise additional tags may be in between leading
                to parsing of incorrect values especially Name */
                kmlPlacemarks[i] = kmlPlacemarks[i].substring(kmlPlacemarks[i].indexOf("<Placemark>"));
        }
        String tmpPlacemarkName;
        String tmpPlacemarkCoordinates;
        for (String kmlPlacemark: kmlPlacemarks)
            if ((kmlPlacemark.indexOf("<name>") > -1 && kmlPlacemark.indexOf("</name>") > -1) &&
                    (kmlPlacemark.indexOf("<coordinates>") > -1 && kmlPlacemark.indexOf("</coordinates>") > -1)) {
                tmpPlacemarkCoordinates = kmlPlacemark.substring(kmlPlacemark.indexOf("<coordinates>") + 13, kmlPlacemark.indexOf("</coordinates>"));
                tmpPlacemarkName = kmlPlacemark.substring(kmlPlacemark.indexOf("<name>") + 6, kmlPlacemark.indexOf("</name>"));
            }
        }
}
查看更多
登录 后发表回答