You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据经纬度、方位角生成±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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 01:36:04