五、地图、谷歌地球加载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; }