五、地图、谷歌地球加载kml文件,java解析实现

使用:

<!-- https://mvnrepository.com/artifact/de.micromata.jak/JavaAPIforKml -->
<dependency>
    <groupId>de.micromata.jak</groupId>
    <artifactId>JavaAPIforKml</artifactId>
    <version>2.2.0</version>
</dependency>

这个包里封装了java实现的解析谷歌地球kml文件的方法

我使用到的地方,代码如下:

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.building.entity.BuildingKmlGeo;
import com.building.entity.vo.KmlBuilding;
import com.building.entity.vo.KmlDoc;
import com.building.entity.vo.KmlLookAt;
import com.building.entity.vo.KmlNetworkLink;
import de.micromata.opengis.kml.v_2_2_0.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * kml转geoJson文件
 * @author cheney
 */
public class KmlToGeoJsonUtils {

    public static List<BuildingKmlGeo> unzipKmzToKml(String filePath) throws Exception {
        List<BuildingKmlGeo> geos = new ArrayList<>();
        File file = new File(filePath);
        ZipFile zipFile = new ZipFile(file);
        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(file));
        InputStream inputStream;
        ZipEntry entry = zipFile.getEntry("_doc.kml");
        inputStream = zipFile.getInputStream(entry);
        Kml docKml = Kml.unmarshal(inputStream);
        Feature feature = docKml.getFeature();
        String name = zipFile.getName();
        int startIndex = name.lastIndexOf("\\");
        int endIndex = name.lastIndexOf(".");
        String kmzFileName = name.substring(startIndex + 1, endIndex);
        KmlDoc kmlDoc = new KmlDoc();
        kmlDoc.setDocName(kmzFileName);
        setKmlDoc(feature, kmlDoc);

        ZipEntry linkHrefEntry = zipFile.getEntry(kmlDoc.getLink().getLinkHref());
        inputStream = zipFile.getInputStream(linkHrefEntry);
        Kml linkHrefKml = Kml.unmarshal(inputStream);
        Feature linkHrefKmlFeature = linkHrefKml.getFeature();
        KmlBuilding kmlBuilding = new KmlBuilding();
        List<KmlNetworkLink> kmlNetworkLinks  = new ArrayList<>();
        setKmlBuilding(linkHrefKmlFeature, kmlNetworkLinks);
        kmlBuilding.setNetworkLinks(kmlNetworkLinks);

        List<String> entryNames = new ArrayList<>();
        while ((entry = zipInputStream.getNextEntry()) != null) {
            String zipEntryName = entry.getName();
            entryNames.add(zipEntryName);
        }

        kmlNetworkLinks.forEach(kmlNetworkLink -> {
            String entryName = getEntryName(kmlNetworkLink.getLinkHref(), entryNames);
            ZipEntry zipEntry = zipFile.getEntry(entryName);
            int i = entryName.lastIndexOf("/");
            int endI = entryName.lastIndexOf(".");
            String kmlFileName = entryName.substring(i + 1, endI);
            InputStream kmlInputStream = null;
            try {
                kmlInputStream = zipFile.getInputStream(zipEntry);
            } catch (IOException e) {
                e.printStackTrace();
            }
            geos.addAll(parseKml(null, kmlInputStream, kmlFileName));
            geos.forEach(geo -> geo.setKmzName(kmzFileName));
            assert kmlInputStream != null;
            try {
                kmlInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        inputStream.close();
        zipFile.close();
        zipInputStream.close();
        return geos;
    }

    private static String getEntryName(String entryName, List<String> absEntryNames){
        return absEntryNames.stream().filter(item -> item.contains(entryName)).findFirst().get();
    }

    /**
     * 设置kmlBuilding
     */
    private static void setKmlBuilding(Feature feature, List<KmlNetworkLink> kmlNetworkLinks) {
        if(feature != null){
            if (feature instanceof Document) {
                List<Feature> featureList = ((Document) feature).getFeature();
                setKmlBuildingFeature(featureList, kmlNetworkLinks);
            } else if (feature instanceof Folder) {
                List<Feature> featureList = ((Folder) feature).getFeature();
                setKmlBuildingFeature(featureList, kmlNetworkLinks);
            }
        }
    }

    private static void setKmlBuildingFeature(List<Feature> featureList, List<KmlNetworkLink> kmlNetworkLinks) {
        featureList.forEach(documentFeature -> {
                    if (documentFeature instanceof NetworkLink) {
                        kmlNetworkLinks.add(setKmlBuildingNetworkLinkData((NetworkLink) documentFeature));
                    }
                }
        );
    }

    private static KmlNetworkLink setKmlBuildingNetworkLinkData(NetworkLink networkLink) {
        String name = networkLink.getName();
        Link link = networkLink.getLink();
        String href = link.getHref();
        KmlNetworkLink kmlNetworkLink = new KmlNetworkLink();
        kmlNetworkLink.setNetworkName(name);
        kmlNetworkLink.setLinkHref(href);
        return kmlNetworkLink;
    }

    /**
     * 设置KmlDoc
     */
    private static void setKmlDoc(Feature feature, KmlDoc kmlDoc) {
        if (feature != null) {
            if (feature instanceof Document) {
                List<Feature> featureList = ((Document) feature).getFeature();
                setKmlDocFeature(feature, featureList, kmlDoc);
            } else if (feature instanceof Folder) {
                List<Feature> featureList = ((Folder) feature).getFeature();
                setKmlDocFeature(feature, featureList, kmlDoc);
            }
        }
    }

    private static void setKmlDocFeature(Feature feature, List<Feature> featureList, KmlDoc kmlDoc) {
        LookAt lookAt = (LookAt) feature.getAbstractView();
        if(lookAt != null){
            KmlLookAt kmlLookAt = new KmlLookAt();
            BeanUtil.copyProperties(lookAt,kmlLookAt);
            kmlDoc.setLook(kmlLookAt);
        }
        featureList.forEach(documentFeature -> {
                    if (documentFeature instanceof NetworkLink) {
                        NetworkLink networkLink = (NetworkLink) documentFeature;
                        String name = networkLink.getName();
                        Link link = networkLink.getLink();
                        String href = link.getHref();
                        KmlNetworkLink kmlNetworkLink = new KmlNetworkLink();
                        kmlNetworkLink.setNetworkName(name);
                        kmlNetworkLink.setLinkHref(href);
                        kmlDoc.setLink(kmlNetworkLink);
                    } else {
                        setKmlDoc(documentFeature, kmlDoc);
                    }
                }
        );
    }

    /**
     * 解析Kml文件
     */
    public static List<BuildingKmlGeo> parseKml(File file, InputStream inputStream, String kmlFileName) {
        Kml kml;
        if(file != null){
            kml = Kml.unmarshal(file);
        } else {
            kml = Kml.unmarshal(inputStream);
        }
        Feature feature = kml.getFeature();
        return parseFeature(feature, kmlFileName);
    }

    private static List<BuildingKmlGeo> parseFeature(Feature feature, String kmlFileName) {
        if (feature != null) {
            List<BuildingKmlGeo> geos = new ArrayList<>();
            //判断根节点是否为Document
            if (feature instanceof Document) {
                List<Feature> featureList = ((Document) feature).getFeature();
                //只解析folder->geo
                featureList.forEach(documentFeature -> {
                            if (documentFeature instanceof Folder) {
                                geos.add(folderToGeoJson(documentFeature, kmlFileName));
                            }
                        }
                );
            }
            return geos;
        }
        return null;
    }

    /**
     * folder -> geo
     */
    private static BuildingKmlGeo folderToGeoJson(Feature feature, String kmlFileName){
        BuildingKmlGeo kmlGeo = new BuildingKmlGeo();
        Folder folder = (Folder) feature;
        String name = feature.getName();
        List<Feature> folderFeature = folder.getFeature();
        JSONObject result = new JSONObject();
        result.put("type","FeatureCollection");
        result.put("name", name);
        JSONArray features = new JSONArray();
        result.put("features", features);
        folderFeature.forEach(item -> {
            if (item instanceof Placemark) {
                features.add(getPlaceMark((Placemark) item));
            }
        });
        kmlGeo.setContent(result.toJSONString());
        kmlGeo.setGeoName(name);
        kmlGeo.setKmlName(kmlFileName);
        return kmlGeo;
    }

    /**
     * 设置单个placeMark
     */
    private static JSONObject getPlaceMark(Placemark placemark) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type","Feature");
        JSONObject propertyJson = new JSONObject();
        propertyJson.put("Name",placemark.getName());
        propertyJson.put("description",placemark.getDescription());
        jsonObject.put("properties", propertyJson);
        JSONObject geometryJson = new JSONObject();
        jsonObject.put("geometry", geometryJson);
        Geometry geometry = placemark.getGeometry();
        if (geometry != null) {
            if (geometry instanceof Polygon) {
                geometryJson.put("type","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) {
                            setCoordinates(coordinates, geometryJson);
                        }
                    }
                }
            } else if (geometry instanceof LineString) {
                geometryJson.put("type","LineString");
                LineString lineString = (LineString) geometry;
                List<Coordinate> coordinates = lineString.getCoordinates();
                if (coordinates != null) {
                    coordinates = ((LineString) geometry).getCoordinates();
                    setCoordinates(coordinates, geometryJson);
                }
            } else if (geometry instanceof Point) {
                geometryJson.put("type","Point");
                Point point = (Point) geometry;
                List<Coordinate> coordinates = point.getCoordinates();
                if (coordinates != null) {
                    coordinates = ((Point) geometry).getCoordinates();
                    setCoordinates(coordinates, geometryJson);
                }
            }
        }
        return jsonObject;
    }

    private static void setCoordinates(List<Coordinate> coordinates, JSONObject geometryJson) {
        JSONArray array3 = new JSONArray();
        JSONArray array2 = new JSONArray();
        coordinates.forEach(coordinate -> {
            JSONArray array1 = new JSONArray();
            array1.add(coordinate.getLongitude());
            array1.add(coordinate.getLatitude());
            array1.add(coordinate.getAltitude());
            array2.add(array1);
        });
        array3.add(array2);
        geometryJson.put("coordinates", array3);
    }

}

对应的使用到的vo对象有以下几个:

1.BuildingKmlGeo

@Data
@TableName(value = "building_kml_geo")
public class BuildingKmlGeo extends Model<BuildingKmlGeo> implements Serializable {


    private static final long serialVersionUID = 4129983261567443938L;
    private String id;
    private String content;
    private String geoName;
    private String kmlName;
    private String kmzName;
    private String entryName;

    public BuildingKmlGeo() {
        this.id = UuidUtils.randomUUID();
    }

    @Override
    protected Serializable pkVal() {
        return this.id;
    }
}

2.KmlBuilding

/**
 * Kmz文件里Kml文件的href的Kml文件对应的实体
 * @author cheney
 */
@Data
public class KmlBuilding {
    private List<KmlNetworkLink> networkLinks;
}

3.KmlDoc

/**
 * _doc.kml文件对应的实体
 * @author cheney
 */
@Data
public class KmlDoc {
    private String docId;
    private String docName;
    private String folderName;
    private KmlNetworkLink link;
    private KmlLookAt look;
}

4.KmlLookAt

/**
 * kml的LookAt对应的实体
 * @author cheney
 */
@Data
public class KmlLookAt {
    private double longitude;
    private double latitude;
    private double altitude;
    private double tilt;
    private double range;
}

5.KmlNetworkLink

/**
 * kml文件的networkLink对应的实体
 * @author cheney
 */
@Data
public class KmlNetworkLink {
    private String networkName;
    private String linkHref;
}

 

上一篇:Excle无法在受保护的视图中打开该文件


下一篇:IOS基础学习-2: UIButton