基于Java的度分秒坐標轉純經緯度坐標的漂亮國基地信息管理的方法
前言
眾所周知,漂亮國在全球范圍內部署了大量的基地,用以維持其打擊能力。這里無意于討論這些部署的事情。只是作為一個GIS開發(fā)者,使用地理信息的視角來看看其到底分布在全球的哪些地方,在之前的博客中,我們曾經介紹了使用Java去解析KMZ和KML數據,這份數據就是其它博主分享的漂亮國海外基地的分布情況。這是一份數據源,同時我們在某度百科上也能找到一些公開的資料,上面公布了一些國內或者海外基地的坐標信息。
要想實現在WebGIS中直觀的顯示這些位置,首先要解決數據的管理問題。之前我們在使用GDAL的KMZ數據解析中,通過在數據中查看具體的數據可以看到。其提供的數據中,應該是有重復的。我們采用基地名稱和位置wkt字符串作為分組查詢,可以發(fā)現有很多的數據的條數是大于2的。因此可以判定出是有數據的重復,因此要求我們對入庫的數據進行去重。同時由于在互聯(lián)網上公開的數據中,有一些位置信息是以度分秒的形式給出的。對于常見的坐標,我們都是采用純數字的經緯度來展示的。那么怎么將度分秒的位置信息轉換成常見的經緯度信息呢?
這就是本文的由來,本文將以java語言為例,詳細介紹如何管理漂亮國的基地信息。為下一步全球的空間可視化打下堅實的基礎,首先介紹如何對數據進行去重處理,然后介紹在java當中如何進行度分秒位置的轉換,最后結合實現原型進行詳細的說明。通過本文,您可以掌握如何管理這些矢量數據,同時知道如何進行空間數據的去重,還可以掌握如何進行度分秒數據的轉換,歡迎品鑒。
一、空間表設計
這里著重介紹空間表的設計與實現,讓大家了解空間表的設計。這里直接分享表的物理結構,通過SQL語句直接分享給大家,如果大家感興趣也可以進行實踐。
1、物理表結構
閑言少敘,這里將設計的表字段信息以sql語句的形式提供出來,供大家參考,表中的字段,大家可以根據實際情況進行增減。
物理表結構的sql語句如下(如果您想在本地記性測試,請一定要安裝postgis擴展,否則空間數據類型將無法創(chuàng)建):
CREATE TABLE "public"."biz_usa_military_base" ( "id" int8 NOT NULL, "en_name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "en_desc" varchar(1024) COLLATE "pg_catalog"."default", "cn_name" varchar(255) COLLATE "pg_catalog"."default", "remark" varchar(255) COLLATE "pg_catalog"."default", "geom" "public"."geometry", "create_by" varchar(64) COLLATE "pg_catalog"."default", "create_time" timestamp(6), "update_by" varchar(64) COLLATE "pg_catalog"."default", "update_time" timestamp(6), "type" int4, "en_country" varchar(255) COLLATE "pg_catalog"."default", "cn_country" varchar(255) COLLATE "pg_catalog"."default", "en_city" varchar(255) COLLATE "pg_catalog"."default", "cn_city" varchar(255) COLLATE "pg_catalog"."default", CONSTRAINT "pk_biz_usa_military_topics" PRIMARY KEY ("id") ); CREATE INDEX "idx_biz_usa_military_base_geom" ON "public"."biz_usa_military_base" USING gist ( "geom" "public"."gist_geometry_ops_2d" ); COMMENT ON COLUMN "public"."biz_usa_military_base"."id" IS '主鍵'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_name" IS '英文名稱'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_desc" IS '英文描述'; COMMENT ON COLUMN "public"."biz_usa_military_base"."cn_name" IS '英文名稱'; COMMENT ON COLUMN "public"."biz_usa_military_base"."remark" IS '備注'; COMMENT ON COLUMN "public"."biz_usa_military_base"."geom" IS '空間信息'; COMMENT ON COLUMN "public"."biz_usa_military_base"."create_by" IS '創(chuàng)建人'; COMMENT ON COLUMN "public"."biz_usa_military_base"."create_time" IS '創(chuàng)建時間'; COMMENT ON COLUMN "public"."biz_usa_military_base"."update_by" IS '更新人'; COMMENT ON COLUMN "public"."biz_usa_military_base"."update_time" IS '更新時間'; COMMENT ON COLUMN "public"."biz_usa_military_base"."type" IS '基地類型,1海外 0 本土'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_country" IS '部署國家英文名'; COMMENT ON COLUMN "public"."biz_usa_military_base"."cn_country" IS '部署國家中文名'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_city" IS '部署城市英文名'; COMMENT ON COLUMN "public"."biz_usa_military_base"."cn_city" IS '部署城市中文名'; COMMENT ON TABLE "public"."biz_usa_military_base" IS '美軍軍事基地信息表';
在設計好上述的空間數據表之后,我們就將表在PostGIS數據庫中進行新建,確保沒有報錯。下面再來進行后臺去重識別和信息轉換的工作。
二、后臺數據管理
后臺數據的管理比較簡單,這里不涉及復雜的邏輯,首先解析KMZ的數據,這部分的內容不再贅述,僅提供如何進行數據去重的處理。然后如何進行經緯度不同數據格式的轉換,因此將數據同步成同一個標準。
1、數據去重
在之前的數據處理過程當中,我們將所有的基地信息都讀取出來,然后統(tǒng)一放到一個List集合當中,最后調用MP的批量插入接口實現數據的批量插入。但是這樣的數據是很容易重復的。查詢數據是否重復的sql語句如下,我們采用的機制就是根據英文名稱來進行檢索,我們在篩選數據時,著重檢查基地的英文名和位置信息是否一致,如果這兩個完全一致,那么我們認為就是同一個基地,是需要將數據進行去除的。
select id,en_name,cn_name,st_asgeojson(geom) from biz_usa_military_base order by st_asgeojson(geom);
上面的數據由于我已經處理過了,因此已經將重復的數據都已經全部去掉了。默認情況下,是有蠻多重復的數據。在實際項目中,我們怎么解決這種重復數據呢?一般可以有兩種思路。第一種就是循環(huán)插入,這樣在插入前做一次重復查詢,如果數據已經存在了就不再插入。這樣做的效率是比較低的,因為沒插一次還要去數據庫中查詢數據是否存在,消耗的時間是比較大。既然這種方式不太好,那么第二種方式就是在批量插入,但是要求是必須要在批量的集合中進行去重,這樣從源頭上就解決了重復插入的問題。
2、去重的具體實現
為了實現去重,我們這里選用LinkedHashMap來進行處理,選這個數據結構是因為LinkedHashMap可以實現有序性,數據會按照讀取的順序添加到集合當中。同時基于HashMap的特性可以實現重復數據的處理,map的key我們選用字符串來處理,由基地的名稱+空間的WKT字符串,這樣子雖然長點,但是可以進行重復的校驗。在map的結構當中,如果key是重復的話,會以最后的一次put為準,這樣就實現我們的去重。代碼實現就更加簡單了:
Map<String,UsaMilitaryBase> linkedHashMap = new LinkedHashMap<String, UsaMilitaryBase>(); for(int i=0; i<featureCount; i++){ Feature feature = layer.GetFeature(i); if(null == feature) continue; String enName = feature.GetFieldAsString("Name"); UsaMilitaryBase base = new UsaMilitaryBase(); Geometry geom = feature.GetGeometryRef(); //step 1、生成原始wkt String wkt = geom.ExportToWkt(); wkt = "SRID=" + srid +";" + wkt;//拼接srid,實現動態(tài)寫入 linkedHashMap.put(enName + wkt, base); }
然后通過這種方式得到的map就是實現了去重之后的數據集合。當然,如果想實現批量插入,就需要循環(huán)map,將map的value取出來,然后添加到List中,再調用MP的批量插入的接口。
if(linkedHashMap.size() >0) { // 使用for-each循環(huán)遍歷HashMap for (Map.Entry<String, UsaMilitaryBase> entry : linkedHashMap.entrySet()) { dataList.add(entry.getValue()); } usaMilitaryBaseService.saveBatch(dataList, 300);//批量插入,每300條提交一次事務 }
3、度分秒數據格式轉換
在空間數據展示中,度分秒也是一種非常常見的格式,因此很多地方也是以度分秒的形式來進行展示的。其中,我們在某度上看到的漂亮國基地信息都是以度分秒的形式展示的,如下所示:
其數據的表達方式都是:
華盛頓州:
序號 基地名稱、經緯度
1、 陸軍劉易斯堡 47° 4'57.21"N 122°35'2.78"W
2、 惠德貝島海軍航空站 48°20'42.49"N 122°39'51.71"W
3、 埃弗雷特海軍基地 47°59'20.32"N 122°13'12.91"W
4、 普吉海峽海軍造船廠 47°33'41.32"N 122°37'56.17"W
像這些數據怎么保存到數據庫中,怎么進行wkt類型的轉換呢?這里分享java的實現方式。
4、具體的轉換方法
關于如何將度分秒的數據進行轉換,網上有很多例子。我也是參考了別人的代碼,但是很多代碼其實沒有將清楚,比如南緯和西經的數據處理方法,也就是會有負數的情況出現。如果按照正常的計算邏輯,則會出現位置錯誤。下面分享在網友的基礎之上改造的可以帶符號的經緯度轉換方法。在后臺的控制器中增加以下代碼:
@RequiresPermissions("mt:usabase:add") @Log(title = "美軍軍事基地", businessType = BusinessType.INSERT) @PostMapping("/add") @ResponseBody public AjaxResult addSave(UsaMilitaryBase militaraBase,String latLonStr){ if(StringUtils.isNotEmpty(latLonStr)) { //String lat1 = "34°49'36.28\"N 95°57'33.18\"W"; String lat = latLonStr.split(" ")[0]; String lon = latLonStr.split(" ")[1]; String latSuffix = lat.substring(lat.length() -1 );//取出緯度后綴N,S String lonSuffix = lon.substring(lon.length() -1 );//取出緯度后綴W,E String newLat = String.valueOf(LatLngUtil.dfm2LatLng(lat.substring(0,lat.length() -1 ))); String newLon = String.valueOf(LatLngUtil.dfm2LatLng(lon.substring(0,lon.length() -1 ))); newLat = latSuffix.equalsIgnoreCase("S") ? "-" + newLat : newLat; newLon = lonSuffix.equalsIgnoreCase("W") ? "-" + newLon : newLon; //構造wkt,默認參考為4326 String geom = "SRID=" + 4326 + ";POINT (" + newLon + " " + newLat + ")"; militaraBase.setGeom(geom); } return toAjax(mbaseService.insertEntity(militaraBase)); }
需要注意的是,在數據中,要解析出數據中的南緯和西經,也就是S和W,如果位置后面是這兩個字符,需要將結果轉換成負數即可。處理具體轉換的代碼如下,我整理成了一個工具類:
/** * 度分秒轉經緯度 * * @param dms 116°25'7.85" * @return 116.418847 */ public static double dfm2LatLng(String dms) { if (dms == null) return 0; try { dms = dms.replace(" ", ""); String[] str2 = dms.split("°"); if (str2.length < 2) return 0; int d = Integer.parseInt(str2[0]); String[] str3 = str2[1].split("\'"); if (str3.length < 2) return 0; int f = Integer.parseInt(str3[0]); String str4 = str3[1].substring(0, str3[1].length() - 1); double m = Double.parseDouble(str4); double fen = f + (m / 60); double du = (fen / 60) + Math.abs(d); if (d < 0) du = -du; return Double.parseDouble(String.format("%.7f", du)); } catch (Exception e) { e.printStackTrace(); } return 0; }
5、新增界面的實現
這里簡單分享新增界面的實現,界面實現采用Thymeleaf,并不是流行的vue,喜歡vue的可以自己自行改造哈。將度分秒信息一次性傳給后臺,后臺使用上面展示的add方法接收參數,然后調用轉換邏輯。
<div class="form-group"> <label class="col-sm-3 control-label">位置(度分秒):</label> <div class="col-sm-8"> <input name="latLonStr" class="form-control" type="text" required> </div> </div>
三、數據管理界面
本節(jié)將重點講解數據管理界面以及功能介紹。
列表管理界面實現數據的查詢展示,展示基地的英文名稱、中文名稱,數據的創(chuàng)建時間,支持按照基地的中英文名稱進行查詢。
新增基地信息頁面,請注意在位置這里,輸入度分秒格式的數據,同時輸入基地的中英文名稱、所在國家的中英文名稱,所在城市的中英文名稱。輸入完畢后,點擊確定即可。
信息編輯頁面,與新建的窗口界面不同的是,新增界面可以輸入位置坐標信息,而修改暫時不提供這個功能(技術上沒有問題,只是從業(yè)務上禁止修改)。
總結
以上就是本文的主要內容,本文將以java語言為例,詳細介紹如何管理漂亮國的基地信息。為下一步全球的空間可視化打下堅實的基礎,首先介紹如何對數據進行去重處理,然后介紹在java當中如何進行度分秒位置的轉換,最后結合實現原型進行詳細的說明。通過本文,您可以掌握如何管理這些矢量數據,同時知道如何進行空間數據的去重,還可以掌握如何進行度分秒數據的轉換,歡迎感興趣的朋友互相交流。行文倉促,難免有不足之處,歡迎朋友們在評論區(qū)批評指正,不慎感謝。
到此這篇關于基于Java的度分秒坐標轉純經緯度坐標的漂亮國基地信息管理的文章就介紹到這了,更多相關Java度分秒坐標轉純經緯度內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
深入淺出講解Spring框架中AOP及動態(tài)代理的應用
在軟件業(yè),AOP為Aspect?Oriented?Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期間動態(tài)代理實現程序功能的統(tǒng)一維護的一種技術2022-03-03SpringBoot整合阿里云OSS對象存儲服務實現文件上傳
這篇文章主要介紹了SpringBoot整合阿里云OSS對象存儲實現文件上傳,幫助大家更好的理解和學習使用SpringBoot,感興趣的朋友可以了解下2021-04-04jpa異常No entity found for query問題解決
這篇文章主要為大家介紹了jpa異常之No entity found for query的異常問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-03-03