优化内存
This commit is contained in:
parent
b206c870fd
commit
f60a0d5474
8
pom.xml
8
pom.xml
@ -13,7 +13,7 @@
|
|||||||
</properties>
|
</properties>
|
||||||
<groupId>com.github.deng0515001</groupId>
|
<groupId>com.github.deng0515001</groupId>
|
||||||
<artifactId>lnglat2Geo</artifactId>
|
<artifactId>lnglat2Geo</artifactId>
|
||||||
<version>1.0.3</version>
|
<version>1.0.4</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>lnglat2Geo</name>
|
<name>lnglat2Geo</name>
|
||||||
<description>lnglat to Geo</description>
|
<description>lnglat to Geo</description>
|
||||||
@ -180,9 +180,9 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
<version>3.1.1</version>
|
<version>3.1.1</version>
|
||||||
<configuration>
|
<!--<configuration>-->
|
||||||
<aggregate>true</aggregate>
|
<!--<aggregate>true</aggregate>-->
|
||||||
</configuration>
|
<!--</configuration>-->
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>attach-javadocs</id>
|
<id>attach-javadocs</id>
|
||||||
|
@ -5,6 +5,7 @@ import com.dengxq.lnglat2Geo.entity.CoordinateSystem.CoordinateSystem
|
|||||||
import com.dengxq.lnglat2Geo.entity.DistrictLevel.DistrictLevel
|
import com.dengxq.lnglat2Geo.entity.DistrictLevel.DistrictLevel
|
||||||
import com.dengxq.lnglat2Geo.entity.{Admin, BusinessArea, BusinessAreaInfo, CoordinateSystem, _}
|
import com.dengxq.lnglat2Geo.entity.{Admin, BusinessArea, BusinessAreaInfo, CoordinateSystem, _}
|
||||||
import com.dengxq.lnglat2Geo.utils.GeoUtils
|
import com.dengxq.lnglat2Geo.utils.GeoUtils
|
||||||
|
import collection.JavaConversions._
|
||||||
|
|
||||||
object GeoTrans {
|
object GeoTrans {
|
||||||
|
|
||||||
@ -86,8 +87,8 @@ object GeoTrans {
|
|||||||
* @param adcode 地区code
|
* @param adcode 地区code
|
||||||
* @return 规范化的地区信息
|
* @return 规范化的地区信息
|
||||||
*/
|
*/
|
||||||
def normalizeName(name: String, level: DistrictLevel): Seq[AdminNode] = {
|
def normalizeName(name: String, level: DistrictLevel, isFullMatch: Boolean): java.util.List[AdminNode] = {
|
||||||
GeoTransImpl.normalizeName(name, level)
|
GeoTransImpl.normalizeName(name, level, isFullMatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,7 +19,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
lazy val streetData: Map[Int, AdminNode] = AdminDataProvider.AdminLoader.loadStreetData.map(s => (s.id, s)).toMap
|
lazy val streetData: Map[Int, AdminNode] = AdminDataProvider.AdminLoader.loadStreetData.map(s => (s.id, s)).toMap
|
||||||
lazy val countryCode: Map[String, String] = AdminDataProvider.AdminLoader.loadCountryCode
|
lazy val countryCode: Map[String, String] = AdminDataProvider.AdminLoader.loadCountryCode
|
||||||
|
|
||||||
lazy val boundaryData: Map[Long, List[(Long, Int, Boolean)]] = AdminDataProvider.AdminLoader.loadBoundaryData
|
lazy val boundaryData: Map[Long, List[(Long, Int, Int)]] = AdminDataProvider.AdminLoader.loadBoundaryData
|
||||||
lazy val boundaryIndex: Map[Long, List[Long]] = boundaryData
|
lazy val boundaryIndex: Map[Long, List[Long]] = boundaryData
|
||||||
.keySet
|
.keySet
|
||||||
.map(s => (new S2CellId(s).parent(min_level).id(), s))
|
.map(s => (new S2CellId(s).parent(min_level).id(), s))
|
||||||
@ -71,7 +71,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def getCityLevel(admin: Admin): String = {
|
def getCityLevel(admin: Admin): String = {
|
||||||
getCityLevel(admin.cityID.toString)
|
getCityLevel(admin.cityCode.toString)
|
||||||
}
|
}
|
||||||
|
|
||||||
def getCityLevel(adcode_or_name: String): String = {
|
def getCityLevel(adcode_or_name: String): String = {
|
||||||
@ -79,19 +79,34 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def normalizeName(adcode: Int): AdminNode = {
|
def normalizeName(adcode: Int): AdminNode = {
|
||||||
adminData.getOrElse(adcode, null)
|
adminData.getOrElse(adcode, streetData.getOrElse(adcode, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
def normalizeName(name: String, level: DistrictLevel): Seq[AdminNode] = {
|
def normalizeName(name: String, level: DistrictLevel, isFullMatch: Boolean): List[AdminNode] = {
|
||||||
adminData.values.filter(_.level.equals(level))
|
adminData.values.filter(_.level.equals(level))
|
||||||
.filter(s => s.shortName.contains(name) || s.name.contains(name))
|
.filter(s => if (isFullMatch) s.name.equals(name) else s.shortName.contains(name) || s.name.contains(name))
|
||||||
.toSeq
|
.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
def normalizeName(provinceIn: String = "", cityIn: String = "", districtIn: String = "", streetIn: String = "", isFullMatch: Boolean = false): Seq[Admin] = {
|
private val cityNameMap: Map[String, String] = Map(("重庆市", ""), ("上海市", "上海城区"), ("北京市", "北京城区"), ("天津市", "天津城区")
|
||||||
|
,("那曲市", "那曲地区")
|
||||||
|
)
|
||||||
|
|
||||||
|
private val districtNameMap: Map[String, String] = Map(("云州区", "大同县"), ("平城区", "城区"), ("云冈区", "南郊区"),
|
||||||
|
("余江区", "余江县"), ("马龙区", "马龙县"), ("光明区", "宝安区"), ("怀仁区", "怀仁县"), ("彬州市", "彬县"), ("海安市", "海安县"),
|
||||||
|
("漠河市", "漠河县"), ("京山市", "京山县"), ("济阳区", "济阳县"), ("潞州区", "城区"), ("上党区", "长治县"), ("屯留区", "屯留县"), ("潞城区", "潞城市"),
|
||||||
|
("滦州市", "滦县"), ("潜山市", "潜山县"), ("邹平市", "邹平县"), ("荔浦市", "荔浦县"), ("兴仁市", "兴仁县"), ("水富市", "水富县"), ("华亭市", "华亭县"),
|
||||||
|
("积石山县", "积石山保安族东乡族撒拉族自治县"), ("元江县", "元江哈尼族彝族傣族自治县"), ("双江县", "双江拉祜族佤族布朗族傣族自治县"),
|
||||||
|
("孟连县", "孟连傣族拉祜族佤族自治县"), ("镇沅县", "镇沅彝族哈尼族拉祜族自治县"),
|
||||||
|
("大柴旦行政委员会", "海西蒙古族藏族自治州直辖"), ("冷湖行政委员会", "海西蒙古族藏族自治州直辖"), ("茫崖行政委员会", "海西蒙古族藏族自治州直辖"),
|
||||||
|
("上饶县", "广信区"), ("达孜区", "达孜县"),
|
||||||
|
("色尼区", "那曲县")
|
||||||
|
)
|
||||||
|
|
||||||
|
def normalizeName(provinceIn: String = "", cityIn: String = "", districtIn: String = "", streetIn: String = "", isFullMatch: Boolean = false): List[Admin] = {
|
||||||
val province = if (provinceIn == null || provinceIn.equals("未知")) "" else provinceIn
|
val province = if (provinceIn == null || provinceIn.equals("未知")) "" else provinceIn
|
||||||
val city = if (cityIn == null || cityIn.equals("未知")) "" else cityIn
|
val city = if (cityIn == null || cityIn.equals("未知")) "" else cityNameMap.getOrElse(cityIn, cityIn)
|
||||||
val district = if (districtIn == null || districtIn.equals("未知")) "" else districtIn
|
val district = if (districtIn == null || districtIn.equals("未知")) "" else districtNameMap.getOrElse(districtIn, districtIn)
|
||||||
val street = if (streetIn == null || streetIn.equals("未知")) "" else streetIn
|
val street = if (streetIn == null || streetIn.equals("未知")) "" else streetIn
|
||||||
|
|
||||||
val provinceAd = adminData.values.filter(s => s.level.equals(DistrictLevel.Province)).filter(s => StringUtils.isEmpty(province) || s.name.equals(province) || (!isFullMatch && s.shortName.equals(province)))
|
val provinceAd = adminData.values.filter(s => s.level.equals(DistrictLevel.Province)).filter(s => StringUtils.isEmpty(province) || s.name.equals(province) || (!isFullMatch && s.shortName.equals(province)))
|
||||||
@ -142,7 +157,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
Admin.createStreet(province.name, city.name, district.name, admin.name, province.id, city.id, district.id, admin.id, admin.center)
|
Admin.createStreet(province.name, city.name, district.name, admin.name, province.id, city.id, district.id, admin.id, admin.center)
|
||||||
case _ => Admin.createOversea
|
case _ => Admin.createOversea
|
||||||
}
|
}
|
||||||
}).toSeq
|
}).toList
|
||||||
}
|
}
|
||||||
|
|
||||||
private def determineAdminCode(lonIn: Double, latIn: Double, coordSys: CoordinateSystem = CoordinateSystem.GCJ02): Int = {
|
private def determineAdminCode(lonIn: Double, latIn: Double, coordSys: CoordinateSystem = CoordinateSystem.GCJ02): Int = {
|
||||||
@ -161,7 +176,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
boundaryAdminCell.getOrElse(id2, -1)
|
boundaryAdminCell.getOrElse(id2, -1)
|
||||||
} else {
|
} else {
|
||||||
var keys = List.empty[Long]
|
var keys = List.empty[Long]
|
||||||
var maxLevel = 2000 //必须大于2000m,否则会出现格子半径过小选择错误问题
|
var maxLevel = 2000 //必须大于2000m,否则会出现格子半径过小选择错误问题
|
||||||
|
|
||||||
// 最远距离 为新疆哈密市80公里
|
// 最远距离 为新疆哈密市80公里
|
||||||
while (keys.isEmpty && maxLevel < 200000) {
|
while (keys.isEmpty && maxLevel < 200000) {
|
||||||
@ -174,7 +189,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
.map(key => (key, new S2CellId(key).toLatLng.getEarthDistance(s2LatLng)))
|
.map(key => (key, new S2CellId(key).toLatLng.getEarthDistance(s2LatLng)))
|
||||||
.sortBy(_._2)
|
.sortBy(_._2)
|
||||||
.take(5)
|
.take(5)
|
||||||
.flatMap(startPoint => boundaryData.getOrElse(startPoint._1, List.empty).map(value => (startPoint._1, value._1, value._2, value._3)))
|
.flatMap(startPoint => boundaryData.getOrElse(startPoint._1, List.empty).flatMap(value => List((startPoint._1, value._1, value._2, true), (startPoint._1, value._1, value._3, false))))
|
||||||
.map(line => {
|
.map(line => {
|
||||||
val start = new S2CellId(line._1).toLatLng
|
val start = new S2CellId(line._1).toLatLng
|
||||||
val end = new S2CellId(line._2).toLatLng
|
val end = new S2CellId(line._2).toLatLng
|
||||||
@ -238,7 +253,7 @@ private[lnglat2Geo] object GeoTransImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def determineAreaByAdmin(lon: Double, lat: Double, admin: Admin, radius: Int): BusinessAreaInfo = {
|
def determineAreaByAdmin(lon: Double, lat: Double, admin: Admin, radius: Int): BusinessAreaInfo = {
|
||||||
val businessAreas = determineAreaByCityId(lon, lat, admin.cityID, radius, CoordinateSystem.GCJ02)
|
val businessAreas = determineAreaByCityId(lon, lat, admin.cityCode, radius, CoordinateSystem.GCJ02)
|
||||||
BusinessAreaInfo(admin, businessAreas)
|
BusinessAreaInfo(admin, businessAreas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ package com.dengxq.lnglat2Geo.build
|
|||||||
|
|
||||||
import com.dengxq.lnglat2Geo.entity.{AdminBoundary, AdminNode, CellAdmin}
|
import com.dengxq.lnglat2Geo.entity.{AdminBoundary, AdminNode, CellAdmin}
|
||||||
import com.dengxq.lnglat2Geo.utils.ObjectSerializer
|
import com.dengxq.lnglat2Geo.utils.ObjectSerializer
|
||||||
|
import com.google.common.geometry._
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
import org.json4s.DefaultFormats
|
import org.json4s.DefaultFormats
|
||||||
import org.json4s.jackson.JsonMethods.parse
|
import org.json4s.jackson.JsonMethods.parse
|
||||||
|
|
||||||
@ -11,6 +13,8 @@ import scala.util.Try
|
|||||||
object AdminDataProvider {
|
object AdminDataProvider {
|
||||||
|
|
||||||
final val CHINA_DISTRICT_BOUNDARY = "src/main/resources/china/boundary.data"
|
final val CHINA_DISTRICT_BOUNDARY = "src/main/resources/china/boundary.data"
|
||||||
|
final val CHINA_DISTRICT_BOUNDARY2 = "data/china/boundary.data"
|
||||||
|
final val CHINA_DISTRICT_BOUNDARY3 = "data/china/boundary3.data"
|
||||||
final val RESOURCE_CHINA_DISTRICT_BOUNDARY = "/china/boundary.data"
|
final val RESOURCE_CHINA_DISTRICT_BOUNDARY = "/china/boundary.data"
|
||||||
|
|
||||||
final val CHINA_DISTRICT_BOUNDARY_CELL = "src/main/resources/china/boundaryCell.data"
|
final val CHINA_DISTRICT_BOUNDARY_CELL = "src/main/resources/china/boundaryCell.data"
|
||||||
@ -43,6 +47,45 @@ object AdminDataProvider {
|
|||||||
Option(data)
|
Option(data)
|
||||||
}.getOrElse(None)
|
}.getOrElse(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def loadS2CellUnion(polylineString: String, minLevel: Int = -1, maxLevel: Int = -1, maxCells: Int = -1)
|
||||||
|
: S2CellUnion = {
|
||||||
|
val s2PolygonBuilder = new S2PolygonBuilder()
|
||||||
|
|
||||||
|
// polyline 中 | 分割多个polygon, 每个polygon的点用 ; 分割.
|
||||||
|
// 每个 polygon 构建 一个 S2Loop, 合并到 S2PolygonBuilder中生成 multi polygon
|
||||||
|
polylineString.split('|').foreach(loopStr => {
|
||||||
|
val points: Array[S2Point] = loopStr.split(';').map(coordStr => {
|
||||||
|
val parts = coordStr.split(',')
|
||||||
|
// (parts(0).toDouble, parts(1).toDouble)
|
||||||
|
val lng = parts(0).toDouble
|
||||||
|
val lat = parts(1).toDouble
|
||||||
|
S2LatLng.fromDegrees(lat, lng).toPoint
|
||||||
|
})
|
||||||
|
val jPoints = points.toList.asJava
|
||||||
|
|
||||||
|
s2PolygonBuilder.addLoop(new S2Loop(jPoints))
|
||||||
|
})
|
||||||
|
|
||||||
|
val polygon = s2PolygonBuilder.assemblePolygon()
|
||||||
|
|
||||||
|
// 栅格化处理区域多边形
|
||||||
|
val coverer = new S2RegionCoverer()
|
||||||
|
if (minLevel > 0) {
|
||||||
|
coverer.setMinLevel(minLevel)
|
||||||
|
}
|
||||||
|
if (maxLevel > 0) {
|
||||||
|
coverer.setMaxLevel(maxLevel)
|
||||||
|
}
|
||||||
|
if (maxCells > 0) {
|
||||||
|
coverer.setMaxCells(maxCells)
|
||||||
|
}
|
||||||
|
|
||||||
|
//val s2CellUnion = coverer.getInteriorCovering(polygon)
|
||||||
|
val s2CellUnion = coverer.getCovering(polygon)
|
||||||
|
s2CellUnion.normalize()
|
||||||
|
s2CellUnion
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object AdminLoader {
|
object AdminLoader {
|
||||||
@ -59,7 +102,7 @@ object AdminDataProvider {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def loadBoundaryData: Map[Long, List[(Long, Int, Boolean)]] = {
|
def loadBoundaryData: Map[Long, List[(Long, Int, Int)]] = {
|
||||||
val stream = this.getClass.getResourceAsStream(RESOURCE_CHINA_DISTRICT_BOUNDARY)
|
val stream = this.getClass.getResourceAsStream(RESOURCE_CHINA_DISTRICT_BOUNDARY)
|
||||||
ObjectSerializer
|
ObjectSerializer
|
||||||
.deserialize[Array[AdminBoundary]](stream)
|
.deserialize[Array[AdminBoundary]](stream)
|
||||||
@ -69,7 +112,21 @@ object AdminDataProvider {
|
|||||||
))
|
))
|
||||||
.toList
|
.toList
|
||||||
.groupBy(_._1)
|
.groupBy(_._1)
|
||||||
.map(s => (s._1, s._2.map(ss => (ss._2, ss._3, ss._4))))
|
.map(s => (s._1, s._2.map(ss => (ss._2, ss._3, ss._4)).groupBy(_._1)
|
||||||
|
.map(sss => {
|
||||||
|
val list = sss._2.map(ssss => (ssss._2, ssss._3)).sortBy(_._2)(Ordering.Boolean.reverse)
|
||||||
|
if (list.size > 2) throw new Exception
|
||||||
|
else if (list.size == 2) {
|
||||||
|
if (!list.head._2 || list.last._2) throw new Exception
|
||||||
|
val first = list.head._1
|
||||||
|
val second = list.last._1
|
||||||
|
(sss._1, first, second)
|
||||||
|
} else {
|
||||||
|
if (list.head._2) (sss._1, list.head._1, -1)
|
||||||
|
else (sss._1, -1, list.head._1)
|
||||||
|
}
|
||||||
|
}).toList
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
def loadBoundaryCellData: Map[Long, Int] = {
|
def loadBoundaryCellData: Map[Long, Int] = {
|
||||||
|
@ -11,6 +11,7 @@ import com.dengxq.lnglat2Geo.utils.S2Utils.{childrenCellId, getLevel}
|
|||||||
import com.dengxq.lnglat2Geo.GeoTransImpl.min_level
|
import com.dengxq.lnglat2Geo.GeoTransImpl.min_level
|
||||||
import AdminDataProvider._
|
import AdminDataProvider._
|
||||||
|
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
import collection.JavaConversions._
|
import collection.JavaConversions._
|
||||||
|
|
||||||
object Upgrade {
|
object Upgrade {
|
||||||
@ -76,6 +77,53 @@ object Upgrade {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def loadBoundary2(): Array[AdminBoundary2] = {
|
||||||
|
DistrictLoader.loadAMapJson("country/" + 100000 + ".json")
|
||||||
|
.get
|
||||||
|
.districts
|
||||||
|
.flatMap(province => {
|
||||||
|
val provinceData = DistrictLoader.loadAMapJson("province/" + province.adcode + ".json")
|
||||||
|
if (provinceData.nonEmpty) {
|
||||||
|
val cityDatas = provinceData.get
|
||||||
|
.districts
|
||||||
|
.flatMap(city => {
|
||||||
|
val cityData = DistrictLoader.loadAMapJson("city/" + city.adcode + ".json")
|
||||||
|
if (cityData.nonEmpty) {
|
||||||
|
val districtDatas = cityData.get.districts.map(dis => DistrictLoader.loadAMapJson("district/" + dis.adcode + ".json"))
|
||||||
|
if (districtDatas.exists(s => s.nonEmpty && s.get.polyline.nonEmpty)) districtDatas
|
||||||
|
else List(cityData)
|
||||||
|
} else {
|
||||||
|
val districtData = DistrictLoader.loadAMapJson("district/" + city.adcode + ".json")
|
||||||
|
if (districtData.nonEmpty && districtData.get.polyline.nonEmpty) List(districtData)
|
||||||
|
else List.empty
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (cityDatas.exists(s => s.nonEmpty && s.get.polyline.nonEmpty)) cityDatas
|
||||||
|
else List(provinceData)
|
||||||
|
} else List.empty
|
||||||
|
})
|
||||||
|
.filter(_.nonEmpty)
|
||||||
|
.flatMap(district => {
|
||||||
|
if (district.get.polyline.nonEmpty) {
|
||||||
|
val data = district.get.polyline.get.split('|').map(loopStr => {
|
||||||
|
loopStr.split(';')
|
||||||
|
.map(coordStr => {
|
||||||
|
val parts = coordStr.split(',')
|
||||||
|
(parts(0).toDouble, parts(1).toDouble)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
val points = data.flatMap(_.toList)
|
||||||
|
val mbr = (points.map(_._1).min, points.map(_._1).max, points.map(_._2).min, points.map(_._2).max)
|
||||||
|
|
||||||
|
val boundary = data.map(s => s.map(ss => S2CellId.fromLatLng(S2LatLng.fromDegrees(ss._2, ss._1)).id()))
|
||||||
|
|
||||||
|
List(AdminBoundary2(district.get.adcode.toInt, mbr, boundary))
|
||||||
|
}
|
||||||
|
else List.empty
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
def genCellAdmin(): Array[CellAdmin] = {
|
def genCellAdmin(): Array[CellAdmin] = {
|
||||||
|
|
||||||
// 国内区县边界S2块
|
// 国内区县边界S2块
|
||||||
@ -222,6 +270,12 @@ object Upgrade {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def upgradeAdminBoundary2(): Unit = {
|
||||||
|
val data = loadBoundary2()
|
||||||
|
ObjectSerializer.serialize(data, Paths.get(CHINA_DISTRICT_BOUNDARY2).toAbsolutePath.toString)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def upgradeAdminBoundary(): Unit = {
|
def upgradeAdminBoundary(): Unit = {
|
||||||
val data = loadBoundary()
|
val data = loadBoundary()
|
||||||
ObjectSerializer.serialize(data, Paths.get(CHINA_DISTRICT_BOUNDARY).toAbsolutePath.toString)
|
ObjectSerializer.serialize(data, Paths.get(CHINA_DISTRICT_BOUNDARY).toAbsolutePath.toString)
|
||||||
@ -247,11 +301,97 @@ object Upgrade {
|
|||||||
ObjectSerializer.serialize(obj, Paths.get(CityAreaDataProvider.BUSINESS_AREA_DATA).toAbsolutePath.toString)
|
ObjectSerializer.serialize(obj, Paths.get(CityAreaDataProvider.BUSINESS_AREA_DATA).toAbsolutePath.toString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def loadSharedLines(boundary: Array[AdminBoundary2]): Array[AdminCommonBoundary] = {
|
||||||
|
var result = ArrayBuffer.empty[AdminCommonBoundary]
|
||||||
|
for (i <- 0 until boundary.length - 1) {
|
||||||
|
val admin1 = boundary(i)
|
||||||
|
val bound1 = admin1.mbr
|
||||||
|
println(i, admin1.code)
|
||||||
|
for (j <- i + 1 until boundary.length) {
|
||||||
|
val admin2 = boundary(j)
|
||||||
|
val bound2 = admin2.mbr
|
||||||
|
|
||||||
|
val pair = if (bound1._1 > bound2._2 || bound2._1 > bound1._2 || bound1._3 > bound2._4 || bound2._3 > bound1._4) Array.empty[AdminCommonBoundary]
|
||||||
|
else admin1.boundary.flatMap(line1 => {
|
||||||
|
val line1Index = line1.zipWithIndex.toMap
|
||||||
|
|
||||||
|
val commons = admin2.boundary.flatMap(line2 =>
|
||||||
|
line2.zipWithIndex
|
||||||
|
.filter(s => line1.contains(s._1))
|
||||||
|
.map(s => {
|
||||||
|
val index1 = line1Index.getOrElse(s._1, 0)
|
||||||
|
(s._1, s._2, index1, s._2 + index1)
|
||||||
|
})
|
||||||
|
.groupBy(_._4)
|
||||||
|
.map(s => (admin2.code, admin1.code, s._2.sortBy(_._2))) // 线段方向是admin2的
|
||||||
|
)
|
||||||
|
|
||||||
|
if (commons.nonEmpty) commons.map(s => AdminCommonBoundary(s._1, s._2, s._3.map(_._1)))
|
||||||
|
else List.empty
|
||||||
|
})
|
||||||
|
result = result ++ pair
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.toArray
|
||||||
|
}
|
||||||
|
|
||||||
|
def loadOnesideLine(sharedLines: Array[AdminCommonBoundary], boundary: Array[AdminBoundary2]): Array[AdminCommonBoundary] = {
|
||||||
|
val commons = sharedLines
|
||||||
|
.flatMap(s => List((s.code, s.boundary), (s.code2, s.boundary)))
|
||||||
|
.groupBy(_._1)
|
||||||
|
.map(s => (s._1, s._2.flatMap(_._2.toList)))
|
||||||
|
|
||||||
|
boundary.flatMap(s => {
|
||||||
|
val common: Array[Long] = commons.getOrElse(s.code, Array.empty)
|
||||||
|
val result = ArrayBuffer.empty[ArrayBuffer[Long]]
|
||||||
|
|
||||||
|
s.boundary.foreach(ss => {
|
||||||
|
var temp = ArrayBuffer.empty[Long]
|
||||||
|
|
||||||
|
ss.foreach(sss => {
|
||||||
|
if (common.isEmpty || !common.contains(sss)) temp.append(sss)
|
||||||
|
else if (temp.nonEmpty) {
|
||||||
|
result.append(temp)
|
||||||
|
temp = ArrayBuffer.empty[Long]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (temp.nonEmpty) result.append(temp)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result.nonEmpty) {
|
||||||
|
println("code = " + s.code)
|
||||||
|
val sssss = result.map(s => s.map(s => {
|
||||||
|
val latlng = new S2CellId(s).toLatLng
|
||||||
|
List(latlng.lngDegrees(), latlng.latDegrees()).mkString(",")
|
||||||
|
})).mkString(";")
|
||||||
|
println(sssss)
|
||||||
|
result.map(ss => AdminCommonBoundary(s.code, -1, ss.toArray))
|
||||||
|
}
|
||||||
|
else List.empty
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
def main(args: Array[String]): Unit = {
|
def main(args: Array[String]): Unit = {
|
||||||
Upgrade.upgradeAdminBoundary() // 生成行政区划边界数据
|
// upgradeAdminBoundary2()
|
||||||
Upgrade.upgradeAdminBoundaryCell() // 生成行政区划边界数据2
|
|
||||||
Upgrade.upgradeChinaAdmin() // 生成行政区划关系数据(不含街道)
|
Upgrade.upgradeAdminBoundary() // 生成行政区划边界数据
|
||||||
Upgrade.upgradeTownship() // 生成行政区划街道数据
|
Upgrade.upgradeAdminBoundaryCell() // 生成行政区划边界数据2
|
||||||
Upgrade.upgradeBusinessAreaData() // 生成商圈数据
|
Upgrade.upgradeChinaAdmin() // 生成行政区划关系数据(不含街道)
|
||||||
|
Upgrade.upgradeTownship() // 生成行政区划街道数据
|
||||||
|
Upgrade.upgradeBusinessAreaData() // 生成商圈数据
|
||||||
|
|
||||||
|
// val data = loadBoundary2()
|
||||||
|
//
|
||||||
|
// val sharedLines = loadSharedLines(data)
|
||||||
|
// val oneSide: Array[AdminCommonBoundary] = loadOnesideLine(sharedLines, data)
|
||||||
|
|
||||||
|
// ObjectSerializer.serialize(result.toArray, Paths.get(CHINA_DISTRICT_BOUNDARY2).toAbsolutePath.toString)
|
||||||
|
// ObjectSerializer.serialize(oneSide, Paths.get(CHINA_DISTRICT_BOUNDARY3).toAbsolutePath.toString)
|
||||||
|
|
||||||
|
// val stream = this.getClass.getResourceAsStream(RESOURCE_CHINA_DISTRICT_BOUNDARY)
|
||||||
|
// ObjectSerializer
|
||||||
|
// .deserialize[Array[AdminCommonBoundary]](stream)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
package com.dengxq.lnglat2Geo.entity
|
package com.dengxq.lnglat2Geo.entity
|
||||||
|
|
||||||
import com.dengxq.lnglat2Geo.entity.AdminLevel.AdminLevel
|
|
||||||
import com.dengxq.lnglat2Geo.utils.AdminUtils
|
import com.dengxq.lnglat2Geo.utils.AdminUtils
|
||||||
|
|
||||||
case class Admin(country: String,
|
case class Admin(country: String,
|
||||||
province: String,
|
province: String,
|
||||||
city: String,
|
city: String,
|
||||||
district: String,
|
district: String,
|
||||||
street: String,
|
town: String,
|
||||||
level: AdminLevel,
|
level: String,
|
||||||
countryID: String,
|
countryCode: String,
|
||||||
provinceID: Int,
|
provinceCode: Int,
|
||||||
cityID: Int,
|
cityCode: Int,
|
||||||
districtID: Int,
|
districtCode: Int,
|
||||||
streetID: Int,
|
townCode: Int,
|
||||||
center: Location = null
|
center: Location = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -21,21 +20,21 @@ case class Admin(country: String,
|
|||||||
def hasProvince: Boolean = province != Admin.UNKNOWN_NAME_VAL
|
def hasProvince: Boolean = province != Admin.UNKNOWN_NAME_VAL
|
||||||
def hasCity: Boolean = city != Admin.UNKNOWN_NAME_VAL
|
def hasCity: Boolean = city != Admin.UNKNOWN_NAME_VAL
|
||||||
def hasDistrict: Boolean = district != Admin.UNKNOWN_NAME_VAL
|
def hasDistrict: Boolean = district != Admin.UNKNOWN_NAME_VAL
|
||||||
def hasCityId: Boolean = cityID != Admin.UNKNOWN_ID_VAL
|
def hasCityId: Boolean = cityCode != Admin.UNKNOWN_ID_VAL
|
||||||
def hasDistrictId: Boolean = districtID != Admin.UNKNOWN_ID_VAL
|
def hasDistrictId: Boolean = districtCode != Admin.UNKNOWN_ID_VAL
|
||||||
def hasStreet: Boolean = street != Admin.UNKNOWN_NAME_VAL
|
def hasTown: Boolean = town != Admin.UNKNOWN_NAME_VAL
|
||||||
def shortProvince :String = AdminUtils.shortProvince(province)
|
def shortProvince :String = AdminUtils.shortProvince(province)
|
||||||
def shortCity :String = AdminUtils.shortCity(city)
|
def shortCity :String = AdminUtils.shortCity(city)
|
||||||
def toShort: Admin = Admin(country,
|
def toShort: Admin = Admin(country,
|
||||||
AdminUtils.shortProvince(province),
|
AdminUtils.shortProvince(province),
|
||||||
AdminUtils.shortCity(city),
|
AdminUtils.shortCity(city),
|
||||||
AdminUtils.shortDistrict(district),
|
AdminUtils.shortDistrict(district),
|
||||||
AdminUtils.shortStreet(street),
|
AdminUtils.shortStreet(town),
|
||||||
level, countryID, provinceID, cityID, districtID, streetID, center)
|
level, countryCode, provinceCode, cityCode, districtCode, townCode, center)
|
||||||
def toNameString: String = s"$country${if(hasProvince) province else ""}${if(hasCity) city else ""}${if(hasDistrict) district else ""}${if(hasStreet) street else ""}"
|
def toNameString: String = s"$country${if(hasProvince) province else ""}${if(hasCity) city else ""}${if(hasDistrict) district else ""}${if(hasTown) town else ""}"
|
||||||
}
|
}
|
||||||
|
|
||||||
object Admin {
|
private[lnglat2Geo] object Admin {
|
||||||
private final val CHINA_NAME = "中国"
|
private final val CHINA_NAME = "中国"
|
||||||
private final val CHINA_ID = "CN"
|
private final val CHINA_ID = "CN"
|
||||||
private final val OVERSEA_NAME_VAL = "海外"
|
private final val OVERSEA_NAME_VAL = "海外"
|
||||||
@ -43,109 +42,109 @@ object Admin {
|
|||||||
private final val UNKNOWN_ID_VAL = -1
|
private final val UNKNOWN_ID_VAL = -1
|
||||||
private final val UNKNOWN_LOCATION_VAL = null
|
private final val UNKNOWN_LOCATION_VAL = null
|
||||||
|
|
||||||
private[lnglat2Geo] def createOversea = Admin(OVERSEA_NAME_VAL,
|
def createOversea = Admin(OVERSEA_NAME_VAL,
|
||||||
province = OVERSEA_NAME_VAL,
|
province = OVERSEA_NAME_VAL,
|
||||||
city = OVERSEA_NAME_VAL,
|
city = OVERSEA_NAME_VAL,
|
||||||
district = OVERSEA_NAME_VAL,
|
district = OVERSEA_NAME_VAL,
|
||||||
street = OVERSEA_NAME_VAL,
|
town = OVERSEA_NAME_VAL,
|
||||||
level = AdminLevel.Oversea,
|
level = AdminLevel.Oversea,
|
||||||
countryID = "",
|
countryCode = "",
|
||||||
provinceID = UNKNOWN_ID_VAL,
|
provinceCode = UNKNOWN_ID_VAL,
|
||||||
cityID = UNKNOWN_ID_VAL,
|
cityCode = UNKNOWN_ID_VAL,
|
||||||
districtID = UNKNOWN_ID_VAL,
|
districtCode = UNKNOWN_ID_VAL,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = UNKNOWN_LOCATION_VAL
|
center = UNKNOWN_LOCATION_VAL
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createCountry(country:String, countryID:String, center: Location) = Admin(
|
def createCountry(country:String, countryID:String, center: Location) = Admin(
|
||||||
country,
|
country,
|
||||||
province = UNKNOWN_NAME_VAL,
|
province = UNKNOWN_NAME_VAL,
|
||||||
city = UNKNOWN_NAME_VAL,
|
city = UNKNOWN_NAME_VAL,
|
||||||
district = UNKNOWN_NAME_VAL,
|
district = UNKNOWN_NAME_VAL,
|
||||||
street = UNKNOWN_NAME_VAL,
|
town = UNKNOWN_NAME_VAL,
|
||||||
level = AdminLevel.Country,
|
level = AdminLevel.Country,
|
||||||
countryID = countryID,
|
countryCode = countryID,
|
||||||
provinceID = UNKNOWN_ID_VAL,
|
provinceCode = UNKNOWN_ID_VAL,
|
||||||
cityID = UNKNOWN_ID_VAL,
|
cityCode = UNKNOWN_ID_VAL,
|
||||||
districtID = UNKNOWN_ID_VAL,
|
districtCode = UNKNOWN_ID_VAL,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createProvince(province: String, provinceId: Int, center: Location) = Admin(
|
def createProvince(province: String, provinceId: Int, center: Location) = Admin(
|
||||||
country = CHINA_NAME,
|
country = CHINA_NAME,
|
||||||
province = province,
|
province = province,
|
||||||
city = UNKNOWN_NAME_VAL,
|
city = UNKNOWN_NAME_VAL,
|
||||||
district = UNKNOWN_NAME_VAL,
|
district = UNKNOWN_NAME_VAL,
|
||||||
street = UNKNOWN_NAME_VAL,
|
town = UNKNOWN_NAME_VAL,
|
||||||
level = AdminLevel.Province,
|
level = AdminLevel.Province,
|
||||||
countryID = CHINA_ID,
|
countryCode = CHINA_ID,
|
||||||
provinceID = provinceId,
|
provinceCode = provinceId,
|
||||||
cityID = UNKNOWN_ID_VAL,
|
cityCode = UNKNOWN_ID_VAL,
|
||||||
districtID = UNKNOWN_ID_VAL,
|
districtCode = UNKNOWN_ID_VAL,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createCity(province: String, city: String, provinceId: Int, cityId: Int, center: Location) = Admin(
|
def createCity(province: String, city: String, provinceId: Int, cityId: Int, center: Location) = Admin(
|
||||||
country = CHINA_NAME,
|
country = CHINA_NAME,
|
||||||
province = province,
|
province = province,
|
||||||
city = city,
|
city = city,
|
||||||
district = UNKNOWN_NAME_VAL,
|
district = UNKNOWN_NAME_VAL,
|
||||||
street = UNKNOWN_NAME_VAL,
|
town = UNKNOWN_NAME_VAL,
|
||||||
level = AdminLevel.City,
|
level = AdminLevel.City,
|
||||||
countryID = CHINA_ID,
|
countryCode = CHINA_ID,
|
||||||
provinceID = provinceId,
|
provinceCode = provinceId,
|
||||||
cityID = cityId,
|
cityCode = cityId,
|
||||||
districtID = UNKNOWN_ID_VAL,
|
districtCode = UNKNOWN_ID_VAL,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createProvincialCity(province: String, city: String, provinceId: Int, cityId: Int, center: Location) = Admin(
|
def createProvincialCity(province: String, city: String, provinceId: Int, cityId: Int, center: Location) = Admin(
|
||||||
country = CHINA_NAME,
|
country = CHINA_NAME,
|
||||||
province = province,
|
province = province,
|
||||||
city = city,
|
city = city,
|
||||||
district = city,
|
district = city,
|
||||||
street = UNKNOWN_NAME_VAL,
|
town = UNKNOWN_NAME_VAL,
|
||||||
level = AdminLevel.ProvincialCity,
|
level = AdminLevel.ProvincialCity,
|
||||||
countryID = CHINA_ID,
|
countryCode = CHINA_ID,
|
||||||
provinceID = provinceId,
|
provinceCode = provinceId,
|
||||||
cityID = cityId,
|
cityCode = cityId,
|
||||||
districtID = cityId,
|
districtCode = cityId,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createDistrict(province: String, city: String, district: String,
|
def createDistrict(province: String, city: String, district: String,
|
||||||
provinceId:Int, cityId: Int, districtId: Int, center: Location) = Admin(
|
provinceId:Int, cityId: Int, districtId: Int, center: Location) = Admin(
|
||||||
country = CHINA_NAME,
|
country = CHINA_NAME,
|
||||||
province = province,
|
province = province,
|
||||||
city = city,
|
city = city,
|
||||||
district = district,
|
district = district,
|
||||||
street = UNKNOWN_NAME_VAL,
|
town = UNKNOWN_NAME_VAL,
|
||||||
level = AdminLevel.District,
|
level = AdminLevel.District,
|
||||||
countryID = CHINA_ID,
|
countryCode = CHINA_ID,
|
||||||
provinceID = provinceId,
|
provinceCode = provinceId,
|
||||||
cityID = cityId,
|
cityCode = cityId,
|
||||||
districtID = districtId,
|
districtCode = districtId,
|
||||||
streetID = UNKNOWN_ID_VAL,
|
townCode = UNKNOWN_ID_VAL,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
private[lnglat2Geo] def createStreet(province: String, city: String, district: String, street: String,
|
def createStreet(province: String, city: String, district: String, town: String,
|
||||||
provinceId:Int, cityId: Int, districtId: Int, streetId: Int, center: Location) = Admin(
|
provinceId:Int, cityId: Int, districtId: Int, streetId: Int, center: Location) = Admin(
|
||||||
country = CHINA_NAME,
|
country = CHINA_NAME,
|
||||||
province = province,
|
province = province,
|
||||||
city = city,
|
city = city,
|
||||||
district = district,
|
district = district,
|
||||||
street = street,
|
town = town,
|
||||||
level = AdminLevel.Street,
|
level = AdminLevel.Street,
|
||||||
countryID = CHINA_ID,
|
countryCode = CHINA_ID,
|
||||||
provinceID = provinceId,
|
provinceCode = provinceId,
|
||||||
cityID = cityId,
|
cityCode = cityId,
|
||||||
districtID = districtId,
|
districtCode = districtId,
|
||||||
streetID = streetId,
|
townCode = streetId,
|
||||||
center = center
|
center = center
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.dengxq.lnglat2Geo.entity
|
||||||
|
|
||||||
|
@SerialVersionUID(-1l)
|
||||||
|
case class AdminBoundary2(var code: Int, var mbr: (Double, Double, Double, Double), var boundary: Array[Array[Long]]) extends Serializable
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.dengxq.lnglat2Geo.entity
|
||||||
|
|
||||||
|
@SerialVersionUID(-1)
|
||||||
|
case class AdminCommonBoundary(var code:Int, var code2:Int, var boundary : Array[Long]) extends Serializable
|
@ -54,20 +54,19 @@ object DistrictLevel extends EnumFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SerialVersionUID(568714356783645678L)
|
@SerialVersionUID(568714356783645678L)
|
||||||
object AdminLevel extends EnumFunc {
|
object AdminLevel {
|
||||||
type AdminLevel = Value
|
|
||||||
/**海外**/
|
/**海外**/
|
||||||
val Oversea = Value("oversea")
|
val Oversea = "oversea"
|
||||||
/**国家**/
|
/**国家**/
|
||||||
val Country = Value("country")
|
val Country = "country"
|
||||||
/**省,自治区**/
|
/**省,自治区**/
|
||||||
val Province = Value("province")
|
val Province = "province"
|
||||||
/**地级市**/
|
/**地级市**/
|
||||||
val City = Value("city")
|
val City = "city"
|
||||||
/**省辖市(属县级市) see:https://baike.baidu.com/item/省直辖县级行政单位**/
|
/**省辖市(属县级市) see:https://baike.baidu.com/item/省直辖县级行政单位**/
|
||||||
val ProvincialCity = Value("provincialcity")
|
val ProvincialCity = "provincialcity"
|
||||||
/**区,县,县级市**/
|
/**区,县,县级市**/
|
||||||
val District = Value("district")
|
val District = "district"
|
||||||
/**街道**/
|
/**街道**/
|
||||||
val Street = Value("street")
|
val Street = "street"
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ object Func {
|
|||||||
class _sm(streetMap: StreetMap) {
|
class _sm(streetMap: StreetMap) {
|
||||||
def findNearStreet(districtAdmin: Admin, lonlat: (Double, Double)) :Option[StreetNode] = {
|
def findNearStreet(districtAdmin: Admin, lonlat: (Double, Double)) :Option[StreetNode] = {
|
||||||
val loc = Location(lonlat._1, lonlat._2)
|
val loc = Location(lonlat._1, lonlat._2)
|
||||||
val districtId = if(districtAdmin.districtID != -1) districtAdmin.districtID else districtAdmin.cityID
|
val districtId = if(districtAdmin.districtCode != -1) districtAdmin.districtCode else districtAdmin.cityCode
|
||||||
if(streetMap.data.contains(districtId)) {
|
if(streetMap.data.contains(districtId)) {
|
||||||
val streetDistanceLs = streetMap.data(districtId)
|
val streetDistanceLs = streetMap.data(districtId)
|
||||||
.flatMap { sn =>
|
.flatMap { sn =>
|
||||||
|
Loading…
Reference in New Issue
Block a user