GIS经纬度转桩号工具

需求

现有一条公路,有公里桩和百米桩对应的经纬度数据;需要根据这个数据得到,输入一个经纬度得到对应的桩号,或者输入一个桩号得到对应的经纬度

实现思路

  1. 根据原始数据的公里桩和百米桩对应的经纬度数据,打断获取到一米对应一个经纬度,即每米的桩号对应的经纬度
  2. 根据第一步得到的结果值,编写查询服务接口,输入经纬度得到桩号、输入桩号得到经纬度。

具体实现

go 复制代码
var stepNum int32 = 1

func main() {
   fileName := "./zh_data_02.csv"
   // 读取csv文件
   zhDataList := readCSV(fileName)
   // 按照一米打断
   resultDataList := insertPoint(zhDataList)
   //保存成csv文件
   saveToFile(resultDataList)

}
  • 读取原桩号CSV文件
go 复制代码
func readCSV(fileName string) []bean.CsvZHData {
   zhDataList := make([]bean.CsvZHData, 0)
   fs, err := os.Open(fileName)
   if err != nil {
      log.Fatalf("can not open the file, err is %+v", err)
   }
   defer fs.Close()
   r := csv.NewReader(fs)
   //针对大文件,一行一行的读取文件
   for {
      row, err := r.Read()
      if err != nil && err != io.EOF {
         log.Fatalf("can not read, err is %+v", err)
      }
      if err == io.EOF {
         break
      }
      zhStr := row[0]
      lonStr := row[1]
      latStr := row[2]
      eleStr := row[3]
      zh, err := strconv.ParseFloat(zhStr, 64)
      lon, err := strconv.ParseFloat(lonStr, 64)
      lat, err := strconv.ParseFloat(latStr, 64)
      ele, err := strconv.ParseFloat(eleStr, 64)

      zhDataList = append(zhDataList, bean.CsvZHData{ZHStr: zhStr, LonStr: lonStr, LatStr: latStr, EleStr: eleStr,
         ZH: zh, Lon: lon, Lat: lat, Ele: ele})
   }

   return zhDataList
}
  • 按1米打断
go 复制代码
func insertPoint(zhDataList []bean.CsvZHData) []bean.CsvZHData {
   resultZHList := make([]bean.CsvZHData, 0)
   size := len(zhDataList)
   for i := 0; i < size; i++ {
      zhPoint := zhDataList[i]
      endPoint := bean.CsvZHData{}
      if i == (size - 1) {
         endPoint = zhDataList[i]
      } else {
         resultZHList = append(resultZHList, zhPoint)
         endPoint = zhDataList[i+1]
      }

      startLon := zhPoint.Lon
      startLat := zhPoint.Lat
      startZH := zhPoint.ZH
      endLon := endPoint.Lon
      endLat := endPoint.Lat
      endZH := endPoint.ZH

      distance := endZH - startZH
      azimuth := mytools.ComputeAzimuth(startLon, startLat, endLon, endLat)

      if distance <= 1000 { // 只有百米桩在计算,其他超过1百米情况不计算
         for addLen := 0.0; addLen < distance-1; {
            addLen = addLen + 1
            stepLenKM := addLen / 1000
            lonlat := mytools.ConvertDistanceToLogLat(startLon, startLat, stepLenKM, azimuth)
            lonlatArr := strings.Split(lonlat, ",")
            lon, _ := strconv.ParseFloat(lonlatArr[0], 64)
            lat, _ := strconv.ParseFloat(lonlatArr[1], 64)
            zh := startZH + addLen
            //startLon = lon
            //startLat = lat

            resultZHList = append(resultZHList, bean.CsvZHData{Lon: lon, Lat: lat, Ele: 0, ZH: zh})

         }
      } else {

      }

      //resultZHList = append(resultZHList, endPoint)

   }
   resultZHList = append(resultZHList, zhDataList[len(zhDataList)-1])
   return resultZHList
}
  • 保存成CSV
go 复制代码
func saveToFile(zhList []bean.CsvZHData) {
   OUT_FILE_NAME := "over_zh_data_02.csv"
   fileCSV, err := os.OpenFile(OUT_FILE_NAME, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
   if err != nil {
      log.Fatal(err)
   }
   // 关闭文件
   defer fileCSV.Close()

   for _, zhBean := range zhList {
      //fileCSV.WriteString(string(result) + "," + "\r\n")
      zhStr := strconv.FormatFloat(zhBean.ZH, 'f', -1, 32)
      lonStr := strconv.FormatFloat(zhBean.Lon, 'f', -1, 64)
      latStr := strconv.FormatFloat(zhBean.Lat, 'f', -1, 64)
      eleStr := strconv.FormatFloat(zhBean.Ele, 'f', -1, 64)
      fileCSV.WriteString(zhStr + "," + lonStr + "," + latStr + "," + eleStr + "\r\n")

   }
}
  • 经纬度转桩号服务
go 复制代码
router.GET("/tozh", func(c *gin.Context) {
   lonStr := c.Query("lon")
   latStr := c.Query("lat")
   precisionStr := c.Query("precision")

   fmt.Println("lon=", lonStr, "  lat=", latStr)
   resultObj := make(map[string]interface{})

   if lonStr == "" || latStr == "" {
      resultObj["msg"] = "请传入正确的经纬度!"
      resultObj["code"] = 401
      c.JSON(200, resultObj)
   } else {
      lon, err := strconv.ParseFloat(lonStr, 64)
      lat, err := strconv.ParseFloat(latStr, 64)
      if err != nil {
         fmt.Println(err)
      }
      var precision float64
      if precisionStr == "" {
         precision = 50
      }
      zhGJD02 := myConfig.ZH_GJD_02
      zhList, _ := myUtils.ReadGJDZH(zhGJD02)
      zhBean := myUtils.LonlatToZH(bean.LonLatToZHParamBean{Lon: lon, Lat: lat, Precision: precision}, zhList)
      c.JSON(200, zhBean)
   }

})
  • 桩号转经纬度服务
go 复制代码
router.GET("/zhto", func(c *gin.Context) {
   zhStr := c.Query("zh")
   roadCode := c.Query("roadCode")
   resultObj := make(map[string]interface{})
   if zhStr == "" {
      resultObj["msg"] = "请传入正确的经纬度!"
      resultObj["code"] = 401
      c.JSON(200, resultObj)
   } else {
      if roadCode == "" {
         roadCode = "G320"
      }
      zhGJD02 := myConfig.ZH_GJD_02
      _, zhMap := myUtils.ReadGJDZH(zhGJD02)

      zhint, err := strconv.ParseInt(zhStr, 10, 64)
      if err != nil {
         fmt.Println(err)
      }
      lonlatBean := myUtils.ZhToLonLat(bean.ZHToLonLatParamBean{
         RoadCode: roadCode,
         ZHInt:    zhint,
      }, zhMap)

      c.JSON(200, lonlatBean)
   }

})

最终编译成的工具

工具下载

相关推荐
明月_清风3 分钟前
FastAPI 从入门到实战:3 分钟构建高性能异步 API
后端·python·fastapi
小村儿4 分钟前
连载10-Sub-agents 深度解析:从源码理解 Claude Code 的分身术
前端·后端·ai编程
他们叫我阿冠6 分钟前
Day5学习--SpringBoot详解
spring boot·后端·学习
枕星而眠33 分钟前
Linux 四大进程/线程同步锁详解:互斥锁、读写锁、条件变量、文件锁
linux·c语言·后端·ubuntu·学习方法
IT_陈寒38 分钟前
Vite动态导入把我坑惨了,原来要这样用才对
前端·人工智能·后端
审判长烧鸡2 小时前
【Go i18n】TOML语言包
go·i18n·语言包
计算机魔术师2 小时前
【AI面试八股文 Vol.3.4:训练微调部署选型】从预训练到量化部署:LLM 工程落地如何做模型选择
人工智能·后端·面试·架构·moe·vol.3.3·vol.3.4
明月_清风2 小时前
从零到一构建生产级 AI Agent:架构拆解 × Python 高并发实战 × 技术选型方法论
后端·agent
金銀銅鐵3 小时前
[Java] 如何理解 class 文件中字段的 access flags?
java·后端
不懒不懒4 小时前
基于 Flask —— 异步任务处理接口服务
后端·python·flask