如何根据经纬度、方位角生成±35度范围、2公里距离的定向矩形多边形?
核心实现方案(Scala + JTS)
你之前调用GeometricShapeFactory.createCircle()生成的是圆形,我们可以通过手动计算矩形四个顶点的坐标,直接构造JTS Polygon实现需求:
import org.locationtech.jts.geom.{Coordinate, GeometryFactory, Polygon} import scala.math._ object DirectionalRectangleGenerator { private val geometryFactory = new GeometryFactory() // 地球半径(米) private val EARTH_RADIUS = 6378137.0 /** * 给定起点经纬度、方位角、距离,计算终点经纬度 * @param lat 起点纬度(度) * @param lon 起点经度(度) * @param azimuth 方位角(正北为0,顺时针递增,单位度) * @param distance 距离(米) * @return 终点坐标 */ def calculateDestination(lat: Double, lon: Double, azimuth: Double, distance: Double): Coordinate = { val latRad = toRadians(lat) val lonRad = toRadians(lon) val azimuthRad = toRadians(azimuth) val angularDistance = distance / EARTH_RADIUS val destLatRad = asin( sin(latRad) * cos(angularDistance) + cos(latRad) * sin(angularDistance) * cos(azimuthRad) ) val destLonRad = lonRad + atan2( sin(azimuthRad) * sin(angularDistance) * cos(latRad), cos(angularDistance) - sin(latRad) * sin(destLatRad) ) // 转换回度构造坐标,x为经度、y为纬度符合JTS默认规范 new Coordinate(toDegrees(destLonRad), toDegrees(destLatRad)) } /** * 生成定向矩形 * @param lat 中心点纬度 * @param lon 中心点经度 * @param azimuth 中心方位角(度) * @param extendDistance 延伸距离(米,默认2000即2公里) * @param angleRange 左右角度范围(默认35即±35度) * @return WKT格式的多边形 */ def generateDirectionalRectangle(lat: String, lon: String, azimuth: String, extendDistance: Double = 2000, angleRange: Double =35): Option[String] = { try { val centerLat = lat.toDouble val centerLon = lon.toDouble val centerAzimuth = azimuth.toDouble // 计算四个顶点 // 1. 左边界最远点:方位角-35度,走2公里 val p1 = calculateDestination(centerLat, centerLon, centerAzimuth - angleRange, extendDistance) // 2. 右边界最远点:方位角+35度,走2公里 val p2 = calculateDestination(centerLat, centerLon, centerAzimuth + angleRange, extendDistance) // 3. 右边界近点:方位角+35度,走1米(可调整,要窄的话就更小) val p3 = calculateDestination(centerLat, centerLon, centerAzimuth + angleRange, 1) // 4. 左边界近点:方位角-35度,走1米 val p4 = calculateDestination(centerLat, centerLon, centerAzimuth - angleRange, 1) // 多边形需要闭合,最后一个点等于第一个点 val coordinates = Array(p1, p2, p3, p4, p1) val polygon = geometryFactory.createPolygon(coordinates) Some(polygon.toText) } catch { case e: Exception => None } } }
轻量化方案(PostGIS)
如果你的数据存储在PostgreSQL+PostGIS中,不需要写代码,一条SQL即可生成目标多边形:
-- 假设你的表名为site,字段为item, item_latitude, item_longitude, azimuth SELECT item, ST_AsText( ST_MakePolygon( ST_MakeLine( ARRAY[ -- 左边界最远点 ST_Project(ST_SetSRID(ST_MakePoint(item_longitude, item_latitude),4326), 2000, radians(azimuth -35)), -- 右边界最远点 ST_Project(ST_SetSRID(ST_MakePoint(item_longitude, item_latitude),4326), 2000, radians(azimuth +35)), -- 右边界近点 ST_Project(ST_SetSRID(ST_MakePoint(item_longitude, item_latitude),4326), 1, radians(azimuth +35)), -- 左边界近点 ST_Project(ST_SetSRID(ST_MakePoint(item_longitude, item_latitude),4326), 1, radians(azimuth -35)), -- 闭合多边形 ST_Project(ST_SetSRID(ST_MakePoint(item_longitude, item_latitude),4326), 2000, radians(azimuth -35)) ] ) ) ) as rectangle_polygon FROM site;
注意事项
- 上述实现默认采用WGS84坐标系(SRID=4326),符合常规经纬度数据的坐标标准
- 如果你需要的是扇形而不是矩形,只需要把近点的两个顶点替换为中心点即可,构造扇形的坐标数组为
Array(p1,p2,中心点坐标,p1) - 近点距离可根据需求调整,如果需要矩形紧贴中心点,把1米改成0即可,避免坐标重合建议保留极小值
内容的提问来源于stack exchange,提问作者Smith
相关产品推荐
相关产品推荐

