基于Java的度分秒坐標(biāo)轉(zhuǎn)純經(jīng)緯度坐標(biāo)的漂亮國(guó)基地信息管理的方法
前言
眾所周知,漂亮國(guó)在全球范圍內(nèi)部署了大量的基地,用以維持其打擊能力。這里無(wú)意于討論這些部署的事情。只是作為一個(gè)GIS開(kāi)發(fā)者,使用地理信息的視角來(lái)看看其到底分布在全球的哪些地方,在之前的博客中,我們?cè)?jīng)介紹了使用Java去解析KMZ和KML數(shù)據(jù),這份數(shù)據(jù)就是其它博主分享的漂亮國(guó)海外基地的分布情況。這是一份數(shù)據(jù)源,同時(shí)我們?cè)谀扯劝倏粕弦材苷业揭恍┕_(kāi)的資料,上面公布了一些國(guó)內(nèi)或者海外基地的坐標(biāo)信息。
要想實(shí)現(xiàn)在WebGIS中直觀(guān)的顯示這些位置,首先要解決數(shù)據(jù)的管理問(wèn)題。之前我們?cè)谑褂肎DAL的KMZ數(shù)據(jù)解析中,通過(guò)在數(shù)據(jù)中查看具體的數(shù)據(jù)可以看到。其提供的數(shù)據(jù)中,應(yīng)該是有重復(fù)的。我們采用基地名稱(chēng)和位置wkt字符串作為分組查詢(xún),可以發(fā)現(xiàn)有很多的數(shù)據(jù)的條數(shù)是大于2的。因此可以判定出是有數(shù)據(jù)的重復(fù),因此要求我們對(duì)入庫(kù)的數(shù)據(jù)進(jìn)行去重。同時(shí)由于在互聯(lián)網(wǎng)上公開(kāi)的數(shù)據(jù)中,有一些位置信息是以度分秒的形式給出的。對(duì)于常見(jiàn)的坐標(biāo),我們都是采用純數(shù)字的經(jīng)緯度來(lái)展示的。那么怎么將度分秒的位置信息轉(zhuǎn)換成常見(jiàn)的經(jīng)緯度信息呢?
這就是本文的由來(lái),本文將以java語(yǔ)言為例,詳細(xì)介紹如何管理漂亮國(guó)的基地信息。為下一步全球的空間可視化打下堅(jiān)實(shí)的基礎(chǔ),首先介紹如何對(duì)數(shù)據(jù)進(jìn)行去重處理,然后介紹在java當(dāng)中如何進(jìn)行度分秒位置的轉(zhuǎn)換,最后結(jié)合實(shí)現(xiàn)原型進(jìn)行詳細(xì)的說(shuō)明。通過(guò)本文,您可以掌握如何管理這些矢量數(shù)據(jù),同時(shí)知道如何進(jìn)行空間數(shù)據(jù)的去重,還可以掌握如何進(jìn)行度分秒數(shù)據(jù)的轉(zhuǎn)換,歡迎品鑒。
一、空間表設(shè)計(jì)
這里著重介紹空間表的設(shè)計(jì)與實(shí)現(xiàn),讓大家了解空間表的設(shè)計(jì)。這里直接分享表的物理結(jié)構(gòu),通過(guò)SQL語(yǔ)句直接分享給大家,如果大家感興趣也可以進(jìn)行實(shí)踐。
1、物理表結(jié)構(gòu)
閑言少敘,這里將設(shè)計(jì)的表字段信息以sql語(yǔ)句的形式提供出來(lái),供大家參考,表中的字段,大家可以根據(jù)實(shí)際情況進(jìn)行增減。
物理表結(jié)構(gòu)的sql語(yǔ)句如下(如果您想在本地記性測(cè)試,請(qǐng)一定要安裝postgis擴(kuò)展,否則空間數(shù)據(jù)類(lèi)型將無(wú)法創(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 '英文名稱(chēng)'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_desc" IS '英文描述'; COMMENT ON COLUMN "public"."biz_usa_military_base"."cn_name" IS '英文名稱(chēng)'; 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)建時(shí)間'; COMMENT ON COLUMN "public"."biz_usa_military_base"."update_by" IS '更新人'; COMMENT ON COLUMN "public"."biz_usa_military_base"."update_time" IS '更新時(shí)間'; COMMENT ON COLUMN "public"."biz_usa_military_base"."type" IS '基地類(lèi)型,1海外 0 本土'; COMMENT ON COLUMN "public"."biz_usa_military_base"."en_country" IS '部署國(guó)家英文名'; COMMENT ON COLUMN "public"."biz_usa_military_base"."cn_country" IS '部署國(guó)家中文名'; 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 '美軍軍事基地信息表';
在設(shè)計(jì)好上述的空間數(shù)據(jù)表之后,我們就將表在PostGIS數(shù)據(jù)庫(kù)中進(jìn)行新建,確保沒(méi)有報(bào)錯(cuò)。下面再來(lái)進(jìn)行后臺(tái)去重識(shí)別和信息轉(zhuǎn)換的工作。
二、后臺(tái)數(shù)據(jù)管理
后臺(tái)數(shù)據(jù)的管理比較簡(jiǎn)單,這里不涉及復(fù)雜的邏輯,首先解析KMZ的數(shù)據(jù),這部分的內(nèi)容不再贅述,僅提供如何進(jìn)行數(shù)據(jù)去重的處理。然后如何進(jìn)行經(jīng)緯度不同數(shù)據(jù)格式的轉(zhuǎn)換,因此將數(shù)據(jù)同步成同一個(gè)標(biāo)準(zhǔn)。
1、數(shù)據(jù)去重
在之前的數(shù)據(jù)處理過(guò)程當(dāng)中,我們將所有的基地信息都讀取出來(lái),然后統(tǒng)一放到一個(gè)List集合當(dāng)中,最后調(diào)用MP的批量插入接口實(shí)現(xiàn)數(shù)據(jù)的批量插入。但是這樣的數(shù)據(jù)是很容易重復(fù)的。查詢(xún)數(shù)據(jù)是否重復(fù)的sql語(yǔ)句如下,我們采用的機(jī)制就是根據(jù)英文名稱(chēng)來(lái)進(jìn)行檢索,我們?cè)诤Y選數(shù)據(jù)時(shí),著重檢查基地的英文名和位置信息是否一致,如果這兩個(gè)完全一致,那么我們認(rèn)為就是同一個(gè)基地,是需要將數(shù)據(jù)進(jìn)行去除的。
select id,en_name,cn_name,st_asgeojson(geom) from biz_usa_military_base order by st_asgeojson(geom);
上面的數(shù)據(jù)由于我已經(jīng)處理過(guò)了,因此已經(jīng)將重復(fù)的數(shù)據(jù)都已經(jīng)全部去掉了。默認(rèn)情況下,是有蠻多重復(fù)的數(shù)據(jù)。在實(shí)際項(xiàng)目中,我們?cè)趺唇鉀Q這種重復(fù)數(shù)據(jù)呢?一般可以有兩種思路。第一種就是循環(huán)插入,這樣在插入前做一次重復(fù)查詢(xún),如果數(shù)據(jù)已經(jīng)存在了就不再插入。這樣做的效率是比較低的,因?yàn)闆](méi)插一次還要去數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù)是否存在,消耗的時(shí)間是比較大。既然這種方式不太好,那么第二種方式就是在批量插入,但是要求是必須要在批量的集合中進(jìn)行去重,這樣從源頭上就解決了重復(fù)插入的問(wèn)題。
2、去重的具體實(shí)現(xiàn)
為了實(shí)現(xiàn)去重,我們這里選用LinkedHashMap來(lái)進(jìn)行處理,選這個(gè)數(shù)據(jù)結(jié)構(gòu)是因?yàn)長(zhǎng)inkedHashMap可以實(shí)現(xiàn)有序性,數(shù)據(jù)會(huì)按照讀取的順序添加到集合當(dāng)中。同時(shí)基于HashMap的特性可以實(shí)現(xiàn)重復(fù)數(shù)據(jù)的處理,map的key我們選用字符串來(lái)處理,由基地的名稱(chēng)+空間的WKT字符串,這樣子雖然長(zhǎng)點(diǎn),但是可以進(jìn)行重復(fù)的校驗(yàn)。在map的結(jié)構(gòu)當(dāng)中,如果key是重復(fù)的話(huà),會(huì)以最后的一次put為準(zhǔn),這樣就實(shí)現(xiàn)我們的去重。代碼實(shí)現(xiàn)就更加簡(jiǎn)單了:
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,實(shí)現(xiàn)動(dòng)態(tài)寫(xiě)入 linkedHashMap.put(enName + wkt, base); }
然后通過(guò)這種方式得到的map就是實(shí)現(xiàn)了去重之后的數(shù)據(jù)集合。當(dāng)然,如果想實(shí)現(xiàn)批量插入,就需要循環(huán)map,將map的value取出來(lái),然后添加到List中,再調(diào)用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條提交一次事務(wù) }
3、度分秒數(shù)據(jù)格式轉(zhuǎn)換
在空間數(shù)據(jù)展示中,度分秒也是一種非常常見(jiàn)的格式,因此很多地方也是以度分秒的形式來(lái)進(jìn)行展示的。其中,我們?cè)谀扯壬峡吹降钠羾?guó)基地信息都是以度分秒的形式展示的,如下所示:
其數(shù)據(jù)的表達(dá)方式都是:
華盛頓州:
序號(hào) 基地名稱(chēng)、經(jīng)緯度
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、 普吉海峽海軍造船廠(chǎng) 47°33'41.32"N 122°37'56.17"W
像這些數(shù)據(jù)怎么保存到數(shù)據(jù)庫(kù)中,怎么進(jìn)行wkt類(lèi)型的轉(zhuǎn)換呢?這里分享java的實(shí)現(xiàn)方式。
4、具體的轉(zhuǎn)換方法
關(guān)于如何將度分秒的數(shù)據(jù)進(jìn)行轉(zhuǎn)換,網(wǎng)上有很多例子。我也是參考了別人的代碼,但是很多代碼其實(shí)沒(méi)有將清楚,比如南緯和西經(jīng)的數(shù)據(jù)處理方法,也就是會(huì)有負(fù)數(shù)的情況出現(xiàn)。如果按照正常的計(jì)算邏輯,則會(huì)出現(xiàn)位置錯(cuò)誤。下面分享在網(wǎng)友的基礎(chǔ)之上改造的可以帶符號(hào)的經(jīng)緯度轉(zhuǎn)換方法。在后臺(tái)的控制器中增加以下代碼:
@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; //構(gòu)造wkt,默認(rèn)參考為4326 String geom = "SRID=" + 4326 + ";POINT (" + newLon + " " + newLat + ")"; militaraBase.setGeom(geom); } return toAjax(mbaseService.insertEntity(militaraBase)); }
需要注意的是,在數(shù)據(jù)中,要解析出數(shù)據(jù)中的南緯和西經(jīng),也就是S和W,如果位置后面是這兩個(gè)字符,需要將結(jié)果轉(zhuǎn)換成負(fù)數(shù)即可。處理具體轉(zhuǎn)換的代碼如下,我整理成了一個(gè)工具類(lèi):
/** * 度分秒轉(zhuǎn)經(jīng)緯度 * * @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、新增界面的實(shí)現(xiàn)
這里簡(jiǎn)單分享新增界面的實(shí)現(xiàn),界面實(shí)現(xiàn)采用Thymeleaf,并不是流行的vue,喜歡vue的可以自己自行改造哈。將度分秒信息一次性傳給后臺(tái),后臺(tái)使用上面展示的add方法接收參數(shù),然后調(diào)用轉(zhuǎn)換邏輯。
<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>
三、數(shù)據(jù)管理界面
本節(jié)將重點(diǎn)講解數(shù)據(jù)管理界面以及功能介紹。
列表管理界面實(shí)現(xiàn)數(shù)據(jù)的查詢(xún)展示,展示基地的英文名稱(chēng)、中文名稱(chēng),數(shù)據(jù)的創(chuàng)建時(shí)間,支持按照基地的中英文名稱(chēng)進(jìn)行查詢(xún)。
新增基地信息頁(yè)面,請(qǐng)注意在位置這里,輸入度分秒格式的數(shù)據(jù),同時(shí)輸入基地的中英文名稱(chēng)、所在國(guó)家的中英文名稱(chēng),所在城市的中英文名稱(chēng)。輸入完畢后,點(diǎn)擊確定即可。
信息編輯頁(yè)面,與新建的窗口界面不同的是,新增界面可以輸入位置坐標(biāo)信息,而修改暫時(shí)不提供這個(gè)功能(技術(shù)上沒(méi)有問(wèn)題,只是從業(yè)務(wù)上禁止修改)。
總結(jié)
以上就是本文的主要內(nèi)容,本文將以java語(yǔ)言為例,詳細(xì)介紹如何管理漂亮國(guó)的基地信息。為下一步全球的空間可視化打下堅(jiān)實(shí)的基礎(chǔ),首先介紹如何對(duì)數(shù)據(jù)進(jìn)行去重處理,然后介紹在java當(dāng)中如何進(jìn)行度分秒位置的轉(zhuǎn)換,最后結(jié)合實(shí)現(xiàn)原型進(jìn)行詳細(xì)的說(shuō)明。通過(guò)本文,您可以掌握如何管理這些矢量數(shù)據(jù),同時(shí)知道如何進(jìn)行空間數(shù)據(jù)的去重,還可以掌握如何進(jìn)行度分秒數(shù)據(jù)的轉(zhuǎn)換,歡迎感興趣的朋友互相交流。行文倉(cāng)促,難免有不足之處,歡迎朋友們?cè)谠u(píng)論區(qū)批評(píng)指正,不慎感謝。
到此這篇關(guān)于基于Java的度分秒坐標(biāo)轉(zhuǎn)純經(jīng)緯度坐標(biāo)的漂亮國(guó)基地信息管理的文章就介紹到這了,更多相關(guān)Java度分秒坐標(biāo)轉(zhuǎn)純經(jīng)緯度內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)粒子跟隨效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)鼠標(biāo)移動(dòng)粒子跟隨效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08完整B樹(shù)算法Java實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了完整的B樹(shù)算法Java實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09深入淺出講解Spring框架中AOP及動(dòng)態(tài)代理的應(yīng)用
在軟件業(yè),AOP為Aspect?Oriented?Programming的縮寫(xiě),意為:面向切面編程,通過(guò)預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)程序功能的統(tǒng)一維護(hù)的一種技術(shù)2022-03-03SpringBoot整合阿里云OSS對(duì)象存儲(chǔ)服務(wù)實(shí)現(xiàn)文件上傳
這篇文章主要介紹了SpringBoot整合阿里云OSS對(duì)象存儲(chǔ)實(shí)現(xiàn)文件上傳,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot,感興趣的朋友可以了解下2021-04-04java實(shí)現(xiàn)消息隊(duì)列的兩種方式(小結(jié))
本文主要介紹了兩種java實(shí)現(xiàn)消息隊(duì)列的方式,利用Spring消息模板發(fā)送消息和Apache ActiveMQ官方實(shí)例發(fā)送消息,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12jpa異常No entity found for query問(wèn)題解決
這篇文章主要為大家介紹了jpa異常之No entity found for query的異常問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03