diff --git a/pom.xml b/pom.xml index ab9f94f..d038e21 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.github.deng0515001 lnglat2Geo - 1.0.3 + 1.0.4 jar lnglat2Geo lnglat to Geo @@ -180,9 +180,9 @@ org.apache.maven.plugins maven-javadoc-plugin 3.1.1 - - true - + + + attach-javadocs diff --git a/src/main/scala/com/dengxq.lnglat2Geo/GeoTrans.scala b/src/main/scala/com/dengxq.lnglat2Geo/GeoTrans.scala index 1876dba..d10689c 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/GeoTrans.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/GeoTrans.scala @@ -5,6 +5,7 @@ import com.dengxq.lnglat2Geo.entity.CoordinateSystem.CoordinateSystem import com.dengxq.lnglat2Geo.entity.DistrictLevel.DistrictLevel import com.dengxq.lnglat2Geo.entity.{Admin, BusinessArea, BusinessAreaInfo, CoordinateSystem, _} import com.dengxq.lnglat2Geo.utils.GeoUtils +import collection.JavaConversions._ object GeoTrans { @@ -86,8 +87,8 @@ object GeoTrans { * @param adcode 地区code * @return 规范化的地区信息 */ - def normalizeName(name: String, level: DistrictLevel): Seq[AdminNode] = { - GeoTransImpl.normalizeName(name, level) + def normalizeName(name: String, level: DistrictLevel, isFullMatch: Boolean): java.util.List[AdminNode] = { + GeoTransImpl.normalizeName(name, level, isFullMatch) } /** diff --git a/src/main/scala/com/dengxq.lnglat2Geo/GeoTransImpl.scala b/src/main/scala/com/dengxq.lnglat2Geo/GeoTransImpl.scala index aa09705..9675198 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/GeoTransImpl.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/GeoTransImpl.scala @@ -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 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 .keySet .map(s => (new S2CellId(s).parent(min_level).id(), s)) @@ -71,7 +71,7 @@ private[lnglat2Geo] object GeoTransImpl { } def getCityLevel(admin: Admin): String = { - getCityLevel(admin.cityID.toString) + getCityLevel(admin.cityCode.toString) } def getCityLevel(adcode_or_name: String): String = { @@ -79,19 +79,34 @@ private[lnglat2Geo] object GeoTransImpl { } 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)) - .filter(s => s.shortName.contains(name) || s.name.contains(name)) - .toSeq + .filter(s => if (isFullMatch) s.name.equals(name) else s.shortName.contains(name) || s.name.contains(name)) + .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 city = if (cityIn == null || cityIn.equals("未知")) "" else cityIn - val district = if (districtIn == null || districtIn.equals("未知")) "" else districtIn + val city = if (cityIn == null || cityIn.equals("未知")) "" else cityNameMap.getOrElse(cityIn, cityIn) + val district = if (districtIn == null || districtIn.equals("未知")) "" else districtNameMap.getOrElse(districtIn, districtIn) 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))) @@ -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) case _ => Admin.createOversea } - }).toSeq + }).toList } private def determineAdminCode(lonIn: Double, latIn: Double, coordSys: CoordinateSystem = CoordinateSystem.GCJ02): Int = { @@ -161,7 +176,7 @@ private[lnglat2Geo] object GeoTransImpl { boundaryAdminCell.getOrElse(id2, -1) } else { var keys = List.empty[Long] - var maxLevel = 2000 //必须大于2000m,否则会出现格子半径过小选择错误问题 + var maxLevel = 2000 //必须大于2000m,否则会出现格子半径过小选择错误问题 // 最远距离 为新疆哈密市80公里 while (keys.isEmpty && maxLevel < 200000) { @@ -174,7 +189,7 @@ private[lnglat2Geo] object GeoTransImpl { .map(key => (key, new S2CellId(key).toLatLng.getEarthDistance(s2LatLng))) .sortBy(_._2) .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 => { val start = new S2CellId(line._1).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 = { - val businessAreas = determineAreaByCityId(lon, lat, admin.cityID, radius, CoordinateSystem.GCJ02) + val businessAreas = determineAreaByCityId(lon, lat, admin.cityCode, radius, CoordinateSystem.GCJ02) BusinessAreaInfo(admin, businessAreas) } diff --git a/src/main/scala/com/dengxq.lnglat2Geo/build/AdminDataProvider.scala b/src/main/scala/com/dengxq.lnglat2Geo/build/AdminDataProvider.scala index 418e0fe..509dc05 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/build/AdminDataProvider.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/build/AdminDataProvider.scala @@ -2,6 +2,8 @@ package com.dengxq.lnglat2Geo.build import com.dengxq.lnglat2Geo.entity.{AdminBoundary, AdminNode, CellAdmin} import com.dengxq.lnglat2Geo.utils.ObjectSerializer +import com.google.common.geometry._ +import scala.collection.JavaConverters._ import org.json4s.DefaultFormats import org.json4s.jackson.JsonMethods.parse @@ -11,6 +13,8 @@ import scala.util.Try object AdminDataProvider { 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 CHINA_DISTRICT_BOUNDARY_CELL = "src/main/resources/china/boundaryCell.data" @@ -43,6 +47,45 @@ object AdminDataProvider { Option(data) }.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 { @@ -59,7 +102,7 @@ object AdminDataProvider { * * @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) ObjectSerializer .deserialize[Array[AdminBoundary]](stream) @@ -69,7 +112,21 @@ object AdminDataProvider { )) .toList .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] = { diff --git a/src/main/scala/com/dengxq.lnglat2Geo/build/Upgrade.scala b/src/main/scala/com/dengxq.lnglat2Geo/build/Upgrade.scala index e8534d5..4b8d6bb 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/build/Upgrade.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/build/Upgrade.scala @@ -11,6 +11,7 @@ import com.dengxq.lnglat2Geo.utils.S2Utils.{childrenCellId, getLevel} import com.dengxq.lnglat2Geo.GeoTransImpl.min_level import AdminDataProvider._ +import scala.collection.mutable.ArrayBuffer import collection.JavaConversions._ 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] = { // 国内区县边界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 = { val data = loadBoundary() 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) } + 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 = { - Upgrade.upgradeAdminBoundary() // 生成行政区划边界数据 - Upgrade.upgradeAdminBoundaryCell() // 生成行政区划边界数据2 - Upgrade.upgradeChinaAdmin() // 生成行政区划关系数据(不含街道) - Upgrade.upgradeTownship() // 生成行政区划街道数据 - Upgrade.upgradeBusinessAreaData() // 生成商圈数据 + // upgradeAdminBoundary2() + + Upgrade.upgradeAdminBoundary() // 生成行政区划边界数据 + Upgrade.upgradeAdminBoundaryCell() // 生成行政区划边界数据2 + 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) + + } } diff --git a/src/main/scala/com/dengxq.lnglat2Geo/entity/Admin.scala b/src/main/scala/com/dengxq.lnglat2Geo/entity/Admin.scala index a1822f5..e6373aa 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/entity/Admin.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/entity/Admin.scala @@ -1,19 +1,18 @@ package com.dengxq.lnglat2Geo.entity -import com.dengxq.lnglat2Geo.entity.AdminLevel.AdminLevel import com.dengxq.lnglat2Geo.utils.AdminUtils case class Admin(country: String, province: String, city: String, district: String, - street: String, - level: AdminLevel, - countryID: String, - provinceID: Int, - cityID: Int, - districtID: Int, - streetID: Int, + town: String, + level: String, + countryCode: String, + provinceCode: Int, + cityCode: Int, + districtCode: Int, + townCode: Int, center: Location = null ) { @@ -21,21 +20,21 @@ case class Admin(country: String, def hasProvince: Boolean = province != Admin.UNKNOWN_NAME_VAL def hasCity: Boolean = city != Admin.UNKNOWN_NAME_VAL def hasDistrict: Boolean = district != Admin.UNKNOWN_NAME_VAL - def hasCityId: Boolean = cityID != Admin.UNKNOWN_ID_VAL - def hasDistrictId: Boolean = districtID != Admin.UNKNOWN_ID_VAL - def hasStreet: Boolean = street != Admin.UNKNOWN_NAME_VAL + def hasCityId: Boolean = cityCode != Admin.UNKNOWN_ID_VAL + def hasDistrictId: Boolean = districtCode != Admin.UNKNOWN_ID_VAL + def hasTown: Boolean = town != Admin.UNKNOWN_NAME_VAL def shortProvince :String = AdminUtils.shortProvince(province) def shortCity :String = AdminUtils.shortCity(city) def toShort: Admin = Admin(country, AdminUtils.shortProvince(province), AdminUtils.shortCity(city), AdminUtils.shortDistrict(district), - AdminUtils.shortStreet(street), - level, countryID, provinceID, cityID, districtID, streetID, center) - def toNameString: String = s"$country${if(hasProvince) province else ""}${if(hasCity) city else ""}${if(hasDistrict) district else ""}${if(hasStreet) street else ""}" + AdminUtils.shortStreet(town), + 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(hasTown) town else ""}" } -object Admin { +private[lnglat2Geo] object Admin { private final val CHINA_NAME = "中国" private final val CHINA_ID = "CN" private final val OVERSEA_NAME_VAL = "海外" @@ -43,109 +42,109 @@ object Admin { private final val UNKNOWN_ID_VAL = -1 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, city = OVERSEA_NAME_VAL, district = OVERSEA_NAME_VAL, - street = OVERSEA_NAME_VAL, + town = OVERSEA_NAME_VAL, level = AdminLevel.Oversea, - countryID = "", - provinceID = UNKNOWN_ID_VAL, - cityID = UNKNOWN_ID_VAL, - districtID = UNKNOWN_ID_VAL, - streetID = UNKNOWN_ID_VAL, + countryCode = "", + provinceCode = UNKNOWN_ID_VAL, + cityCode = UNKNOWN_ID_VAL, + districtCode = UNKNOWN_ID_VAL, + townCode = UNKNOWN_ID_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, province = UNKNOWN_NAME_VAL, city = UNKNOWN_NAME_VAL, district = UNKNOWN_NAME_VAL, - street = UNKNOWN_NAME_VAL, + town = UNKNOWN_NAME_VAL, level = AdminLevel.Country, - countryID = countryID, - provinceID = UNKNOWN_ID_VAL, - cityID = UNKNOWN_ID_VAL, - districtID = UNKNOWN_ID_VAL, - streetID = UNKNOWN_ID_VAL, + countryCode = countryID, + provinceCode = UNKNOWN_ID_VAL, + cityCode = UNKNOWN_ID_VAL, + districtCode = UNKNOWN_ID_VAL, + townCode = UNKNOWN_ID_VAL, 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, province = province, city = UNKNOWN_NAME_VAL, district = UNKNOWN_NAME_VAL, - street = UNKNOWN_NAME_VAL, + town = UNKNOWN_NAME_VAL, level = AdminLevel.Province, - countryID = CHINA_ID, - provinceID = provinceId, - cityID = UNKNOWN_ID_VAL, - districtID = UNKNOWN_ID_VAL, - streetID = UNKNOWN_ID_VAL, + countryCode = CHINA_ID, + provinceCode = provinceId, + cityCode = UNKNOWN_ID_VAL, + districtCode = UNKNOWN_ID_VAL, + townCode = UNKNOWN_ID_VAL, 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, province = province, city = city, district = UNKNOWN_NAME_VAL, - street = UNKNOWN_NAME_VAL, + town = UNKNOWN_NAME_VAL, level = AdminLevel.City, - countryID = CHINA_ID, - provinceID = provinceId, - cityID = cityId, - districtID = UNKNOWN_ID_VAL, - streetID = UNKNOWN_ID_VAL, + countryCode = CHINA_ID, + provinceCode = provinceId, + cityCode = cityId, + districtCode = UNKNOWN_ID_VAL, + townCode = UNKNOWN_ID_VAL, 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, province = province, city = city, district = city, - street = UNKNOWN_NAME_VAL, + town = UNKNOWN_NAME_VAL, level = AdminLevel.ProvincialCity, - countryID = CHINA_ID, - provinceID = provinceId, - cityID = cityId, - districtID = cityId, - streetID = UNKNOWN_ID_VAL, + countryCode = CHINA_ID, + provinceCode = provinceId, + cityCode = cityId, + districtCode = cityId, + townCode = UNKNOWN_ID_VAL, 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( country = CHINA_NAME, province = province, city = city, district = district, - street = UNKNOWN_NAME_VAL, + town = UNKNOWN_NAME_VAL, level = AdminLevel.District, - countryID = CHINA_ID, - provinceID = provinceId, - cityID = cityId, - districtID = districtId, - streetID = UNKNOWN_ID_VAL, + countryCode = CHINA_ID, + provinceCode = provinceId, + cityCode = cityId, + districtCode = districtId, + townCode = UNKNOWN_ID_VAL, 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( country = CHINA_NAME, province = province, city = city, district = district, - street = street, + town = town, level = AdminLevel.Street, - countryID = CHINA_ID, - provinceID = provinceId, - cityID = cityId, - districtID = districtId, - streetID = streetId, + countryCode = CHINA_ID, + provinceCode = provinceId, + cityCode = cityId, + districtCode = districtId, + townCode = streetId, center = center ) diff --git a/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminBoundary2.scala b/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminBoundary2.scala new file mode 100644 index 0000000..8ec83b0 --- /dev/null +++ b/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminBoundary2.scala @@ -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 diff --git a/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminCommonBoundary.scala b/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminCommonBoundary.scala new file mode 100644 index 0000000..d22abd1 --- /dev/null +++ b/src/main/scala/com/dengxq.lnglat2Geo/entity/AdminCommonBoundary.scala @@ -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 diff --git a/src/main/scala/com/dengxq.lnglat2Geo/entity/Enum.scala b/src/main/scala/com/dengxq.lnglat2Geo/entity/Enum.scala index edba2d0..0f80944 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/entity/Enum.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/entity/Enum.scala @@ -54,20 +54,19 @@ object DistrictLevel extends EnumFunc { } @SerialVersionUID(568714356783645678L) -object AdminLevel extends EnumFunc { - type AdminLevel = Value +object AdminLevel { /**海外**/ - 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/省直辖县级行政单位**/ - val ProvincialCity = Value("provincialcity") + val ProvincialCity = "provincialcity" /**区,县,县级市**/ - val District = Value("district") + val District = "district" /**街道**/ - val Street = Value("street") + val Street = "street" } \ No newline at end of file diff --git a/src/main/scala/com/dengxq.lnglat2Geo/entity/StreetNode.scala b/src/main/scala/com/dengxq.lnglat2Geo/entity/StreetNode.scala index 8ffb1d3..6954d63 100644 --- a/src/main/scala/com/dengxq.lnglat2Geo/entity/StreetNode.scala +++ b/src/main/scala/com/dengxq.lnglat2Geo/entity/StreetNode.scala @@ -12,7 +12,7 @@ object Func { class _sm(streetMap: StreetMap) { def findNearStreet(districtAdmin: Admin, lonlat: (Double, Double)) :Option[StreetNode] = { 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)) { val streetDistanceLs = streetMap.data(districtId) .flatMap { sn =>