简体   繁体   English

从 Java 中的 KML 文件中提取坐标

[英]Extract coordinates from KML file in Java

I'm trying to parse a Kml file in Java.我正在尝试用 Java 解析 Kml 文件。 Cause I need to take the coordinates of a Placemark, to generate a poligon in java, and use it.因为我需要获取地标的坐标,在 java 中生成一个 poligon 并使用它。

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)但我的问题是,我使用JAK这个库来解析它,我无法提取我想要的信息。(我阅读了官方页面中的“帮助”,但我没有找到任何帮助解决我的问题)

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我试图解析的文件是这个: la basa

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.遵循javadocs非官方),您需要检查 - 使用instanceof - 每个Feature是否是Placemark ,如果是,则转换为它并获取Geometry本身需要检查它是否为Polygon ,如果是,则转换为它。 After that the path to the coordinates is the following (just as it come in the kml-file):之后,坐标路径如下(就像在 kml 文件中一样):

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("");
    }
}

With respect to A4L answer , thank you so much while i have added some more extraction methods which will get data from folder and document with point line and polygon extraction with spring MVC using javaapi4kml using package关于 A4L 答案,非常感谢您,同时我添加了更多提取方法,这些方法将使用 javaapi4kml 使用包从带有点线和多边形提取的 Spring MVC 文件夹和文档中获取数据

<dependency>
<groupId>de.micromata.jak</groupId>
<artifactId>JavaAPIforKml</artifactId>
<version>2.2.0</version>
</dependency> 

@RequestMapping(value = "/testKml", method = RequestMethod.POST)
public Map<String, Object> parseKml(@RequestBody Map<String, Object> data){
    Map<String, Object> response = new HashMap<String, Object>();
    List<Map<String, Object>> wktObjrow = new ArrayList<Map<String, Object>>();
    String src = data.get("kmlfile").toString();
    try {
        URL url;
        url = new URL(src);
        URLConnection conn = url.openConnection();
        InputStream is = url.openStream();
        Assert.notNull(is);
        Kml kml = Kml.unmarshal(is);
        Feature feature = kml.getFeature();
        Map<String, Object> geodata = new HashMap<String, Object>();

        if(feature != null) {
            if(feature instanceof Document) {
                Document document = (Document) feature;
                List<Feature> featureList = document.getFeature();
                for(Feature documentFeature : featureList) {
                    if(documentFeature instanceof Placemark) {
                        geodata = new HashMap<String, Object>();
                        Placemark placemark = (Placemark) documentFeature;
                        Geometry geometry = placemark.getGeometry();
                        geodata = parseGeometry(geometry, documentFeature.getName().toString());
                        if(!geodata.isEmpty())
                        {
                            wktObjrow.add(geodata);
                        }
                    }
                    else if(documentFeature instanceof Folder) 
                    {
                        Folder folder = (Folder) documentFeature;
                        List<Feature> folderfeaturList = folder.getFeature();
                        for(Feature folderfeature : folderfeaturList) 
                        {
                            geodata = new HashMap<String, Object>();
                            if(folderfeature instanceof Placemark) {
                                Placemark placemark = (Placemark) folderfeature;
                                Geometry geometry = placemark.getGeometry();
                                //push each of return store in list
                                geodata = parseGeometry(geometry, placemark.getName().toString());
                                if(!geodata.isEmpty())
                                {
                                    wktObjrow.add(geodata);
                                }
                            }
                            else
                            {
                                System.err.println("folderfeatures was not of type Placemark"); 
                            }
                        }
                    }
                    else
                    {
                        System.err.println("Was not instance of Placemark or Folder");
                    }
                }
                System.out.println("wktObjrow : "+wktObjrow);
            }
            else
            {
                System.err.println("instance of feature was Not Document");
                if(feature instanceof Folder) {
                    Folder folder = (Folder) feature;
                    List<Feature> featureList = folder.getFeature();

                    geodata = new HashMap<String, Object>();

                    for(Feature documentFeature : featureList) {

                        if(documentFeature instanceof Placemark) {
                            Placemark placemark = (Placemark) documentFeature;
                            Geometry geometry = placemark.getGeometry();
                            if(documentFeature.getName().toString().length() > 0)
                            {
                                geodata =  parseGeometry(geometry, documentFeature.getName().toString());
                                if(!geodata.isEmpty())
                                {
                                    wktObjrow.add(geodata);
                                }
                            }
                            else 
                            {
                                geodata = parseGeometry(geometry, placemark.getName().toString());
                                if(!geodata.isEmpty())
                                {
                                    wktObjrow.add(geodata);
                                }
                            }

                        }else
                        {
                            System.err.println("Was not instance of Placemark");
                        }
                    }
                    System.out.println("wktObjrow : "+wktObjrow);

                }
            }
        }
        else
        {
            System.err.println("Feature was null");
            response.put("Null", "Feature was null");
        }
    }
    catch (Exception e) {
        // TODO: handle exception
        System.err.println("Exception @ : "+ e);
    }

    if(!wktObjrow.isEmpty() && wktObjrow != null)
    {
        response.put("data", wktObjrow);
    }

    return response;
}

public Map<String, Object> parseGeometry(Geometry geometry,String name) {
    // <Point> <LinearRing> <Geometry> <Model> <LineString> <Polygon> <MultiGeometry>

    Map<String, Object> response = new HashMap<String, Object>();
    List<Map<String, Object>> wktObjrow = new ArrayList<Map<String, Object>>();

    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) {
                        Map<String, Object> map = new HashMap<String, Object>();
                        ArrayList<String> wkt_lonlat = new ArrayList<String>();
                        for(Coordinate coordinate : coordinates) {
                            wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
                        }
                        response.put("name",name);
                        response.put("category","POLYGON");
                        response.put("row","POLYGON(("+String.join(",", wkt_lonlat)+"))");
                    }
                    else
                    {
                        System.err.println("coordinate was null");
                    }
                }
            }
        }
        else if(geometry instanceof Point)
        {
            Point point = (Point) geometry;
            List<Coordinate> coordinates = point.getCoordinates();
            if(coordinates != null  && !coordinates.isEmpty())
            {
                if(coordinates != null) {

                    for(Coordinate coordinate : coordinates) {
                        Map<String, Object> map = new HashMap<String, Object>();
                        response.put("lon",coordinate.getLongitude());
                        response.put("lat",coordinate.getLatitude());
                        response.put("name",name);
                        response.put("category","POINT");
                    }
                }
            }
        }
        else if(geometry instanceof LineString)
        {
            LineString line = (LineString) geometry;
            List<Coordinate> coordinates = line.getCoordinates();
            if(coordinates != null  && !coordinates.isEmpty())
            {
                if(coordinates != null) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    ArrayList<String> wkt_lonlat = new ArrayList<String>();
                    for(Coordinate coordinate : coordinates) {
                        wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
                    }
                    response.put("name",name);
                    response.put("category","LINESTRING");
                    response.put("row","LINESTRING("+String.join(",", wkt_lonlat)+")");
                }
            }
       }
       else if(geometry instanceof MultiGeometry)
       {

            MultiGeometry multigeometry = (MultiGeometry) geometry;
               for (int j = 0; j < multigeometry.getGeometry().size(); j++) {
                    if(multigeometry.getGeometry().get(j) instanceof LineString)
                    {
                        LineString line = (LineString) multigeometry.getGeometry().get(j);
                        List<Coordinate> coordinates = line.getCoordinates();
                        if(coordinates != null  && !coordinates.isEmpty())
                        {
                            if(coordinates != null) {
                                Map<String, Object> map = new HashMap<String, Object>();

                                ArrayList<String> wkt_lonlat = new ArrayList<String>();

                                for(Coordinate coordinate : coordinates) {
                                    wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
                                }
                                response.put("name",name);
                                response.put("category","LINESTRING");
                                response.put("row","LINESTRING("+String.join(",", wkt_lonlat)+")");
                            }
                        }
                    }
                    else if(multigeometry.getGeometry().get(j) instanceof Point)
                    {
                        Point point = (Point) multigeometry.getGeometry().get(j);
                        List<Coordinate> coordinates = point.getCoordinates();
                           if(coordinates != null  && !coordinates.isEmpty())
                           {
                               if(coordinates != null) {
                                   for(Coordinate coordinate : coordinates) {
                                    Map<String, Object> map = new HashMap<String, Object>();
                                    response.put("lon",coordinate.getLongitude());
                                    response.put("lat",coordinate.getLatitude());
                                    response.put("name",name);
                                    response.put("category","POINT");
                                   }
                               }
                           }
                    }
                    else if(multigeometry.getGeometry().get(j) instanceof Polygon)
                    {
                        Polygon polygon = (Polygon) multigeometry.getGeometry().get(j);
                        Boundary outerBoundaryIs = polygon.getOuterBoundaryIs();
                        if(outerBoundaryIs != null) {
                            LinearRing linearRing = outerBoundaryIs.getLinearRing();
                            if(linearRing != null) {
                                List<Coordinate> coordinates = linearRing.getCoordinates();
                                if(coordinates != null) {

                                    Map<String, Object> map = new HashMap<String, Object>();

                                    ArrayList<String> wkt_lonlat = new ArrayList<String>();

                                    for(Coordinate coordinate : coordinates) {
                                        wkt_lonlat.add(coordinate.getLongitude()+" "+coordinate.getLatitude());
                                    }
                                    response.put("name",name);
                                    response.put("category","POLYGON");
                                    response.put("row","POLYGON(("+String.join(",", wkt_lonlat)+"))");
                                }
                                else
                                {
                                    System.err.println("coordinate was null");
                                }
                            }
                        }
                    }
               }

       }
    }
    else
    {
        System.err.println("geometry was null");
        response.put("Null", "geometry was null");
    }
    return response;
}

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.看到这篇文章,所以这里是我在我的应用程序中使用的函数代码的一部分,用于从字符串 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>"));
            }
        }
}

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:谢谢@A4L 这真的是一个更新,也是一种更时髦的方法,所以对 Groovy 进行了更改,并且还尝试了比给出的示例更多的类型,并在文档层中深入挖掘:

 /**
     * 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
    }

The answers above make use of the library de.micromata.opengis.kml which appears to be unsupported now.上面的答案使用了de.micromata.opengis.kml库,该库现在似乎不受支持。 There is a newer library, OSM Bonus Pack which has a good KmlDocument class.有一个更新的库, OSM Bonus Pack ,它有一个很好的 KmlDocument 类。 I have used this to extract the coords as below.我用它来提取坐标如下。 It only extracts lines (roads), not polygons, but it should be modifiable.它只提取线(道路),而不是多边形,但它应该是可修改的。

List<List<GeoPoint>> roads = new ArrayList<List<GeoPoint>>();

public void parseKmlDocument(KmlDocument doc) {
    int index = 0;
    for (KmlFeature kmlf: doc.mKmlRoot.mItems) {
        if ((kmlf instanceof KmlPlacemark))
        {
            KmlPlacemark placemark = (KmlPlacemark)kmlf;
            KmlGeometry kmlg = placemark.mGeometry;
            if (kmlg instanceof KmlMultiGeometry)
            {
                KmlMultiGeometry kmlmg = (KmlMultiGeometry)kmlg;
                for (KmlGeometry thisKmlg: kmlmg.mItems)
                {
                    ArrayList<GeoPoint> mCoordinates = thisKmlg.mCoordinates;
                    roads.add(index++, mCoordinates);

                }
            }
        }
        else {
                // kmlg is a LineString
                    ArrayList<GeoPoint> mCoordinates = kmlg.mCoordinates;
                    Road road = new Road(mCoordinates);
                    roads.add(road);
                    ++rIndex;
             
            }
    }
    // checking the result
    int road = 0 ;
    int gpoint = 0;
    for (List<GeoPoint> listGp: roads) {
        Log.d("road ", String.valueOf(road++));
        for (GeoPoint gp: listGp) {
            gpoint++;
            Log.d("    coords ",gp.getLatitude() + " " + gp.getLongitude());
        }
    }
    Log.d("Summary ",road + " roads containing " + gpoint + " geopoints");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM