3 Star 0 Fork 0

江苏岚江智能科技有限公司 / supply-point

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
help.go 4.19 KB
一键复制 编辑 原始数据 按行查看 历史
吴文凯 提交于 2023-05-05 14:30 . update
package supply_point
import (
"fmt"
"io"
"math"
"os"
"strconv"
"strings"
)
// readPathPoint 从文件中读取坐标点
// 会将坐标缩小,用于图形展示和计算
func readPathPoint(name string) []*PathPoint {
//filep, _ := filepath.Abs(name)
f, err := os.Open(name) // 打开文件 - 不用管
if err != nil {
panic("open path point error:" + err.Error() + ". name:" + name)
}
data, _ := io.ReadAll(f) // 读取文件
points := strings.Split(string(data), "\r\n") // 处理csv格式
var pathPoint []*PathPoint
for i, point := range points {
// 跳过第一行数据,第一行是列名
if i == 0 {
continue
}
// 排除掉重复的点
if point == points[i-1] {
continue
}
// 排除掉空行
if point == "" {
continue
}
xy := strings.Split(point, ",") // 处理csv格式
lat, _ := strconv.ParseFloat(xy[0], 64) // string to float64
lng, _ := strconv.ParseFloat(xy[1], 64)
// 将坐标*1000000 (相当于保留坐标的6位小数)
pathPoint = append(pathPoint, &PathPoint{X: int(lat * 1000000), Y: int(lng * 1000000)})
}
// 从坐标点集中找到边界点
// maxX, minX, maxY, minY 组成一个矩形,可以包含所有的坐标点
var (
maxX = -90000000
minX = 90000000
maxY = -180000000
minY = 180000000
)
for _, p := range pathPoint {
if p.X > maxX {
maxX = p.X
}
if p.X < minX {
minX = p.X
}
if p.Y > maxY {
maxY = p.Y
}
if p.Y < minY {
minY = p.Y
}
}
// 适配maxX, minX, maxY, minY 组成的矩形,使坐标可以包含在一个矩形中
for i := 0; i < len(pathPoint); i++ {
pathPoint[i].X = pathPoint[i].X - minX
pathPoint[i].Y = pathPoint[i].Y - minY
}
return pathPoint
}
// getCorner 从坐标点集中找到拐点
func getCorner(p []*PathPoint) ([][]*PathPoint, []*PathPoint) {
var (
lines [][]*PathPoint
line []*PathPoint
corner []*PathPoint
)
line = append(line, p[0], p[1])
// 三个点可以连成一个三角形,通过判断三角形三边的比例,来判断是否是直线
var isLine = func(p1, p2, p3 int) bool {
// 临边
d0 := getEuclideanDistance(p[p1], p[p2])
d1 := getEuclideanDistance(p[p2], p[p3])
// 斜边
d2 := getEuclideanDistance(p[p1], p[p3])
// 计算三角形三边的比例
fmt.Println(p1, p2, p3, "isline", d0, d1, d2, d2/(d0+d1), math.Acos((d0*d0+d1*d1-d2*d2)/(2*d0*d1)))
criticalValue := 0.999 // 值越大,越敏感
return d2/(d0+d1) > criticalValue
}
// 用来找拐点的方法
// p 所有的坐标集合
// needRecallCount 需要回溯的次数(需要经历多少个点才能证明这个点是真的拐点)
var recall = func(p []*PathPoint, needRecallCount int) {
var (
recallCount = 0 // 回溯次数
lineStart = 0 // 直线的起点index
prevPointIndex = 1 // 上一个点的index(遇到拐角时,这个就等于拐角的index)
)
// 从第三个点开始遍历坐标集合
for i := 2; i < len(p); i++ {
// 判断是否是直线
isline := isLine(lineStart, prevPointIndex, i)
if isline {
prevPointIndex = i // 设置当前index为prevPointIndex
recallCount = 0 // 回溯次数清零
line = append(line, p[i]) // 将当前点加入到直线中
} else {
if recallCount >= needRecallCount {
fmt.Println("corner", prevPointIndex)
lines = append(lines, line)
line = []*PathPoint{p[prevPointIndex], p[prevPointIndex+1]}
lineStart = prevPointIndex
corner = append(corner, p[prevPointIndex])
prevPointIndex, i = prevPointIndex+1, prevPointIndex+1
recallCount = -1
}
recallCount++
}
}
lines = append(lines, line)
}
recall(p, 4)
return lines, corner
}
// 计算欧式距离
func getEuclideanDistance(p1, p2 *PathPoint) float64 {
return math.Sqrt(math.Pow(float64(p1.X-p2.X), 2) + math.Pow(float64(p1.Y-p2.Y), 2))
}
// GetDistance 根据经纬度获取距离
func GetDistance(lat1, lng1, lat2, lng2 float64) float64 {
radius := 6378137.0 // 赤道半径 (单位m)
rad := float64(57.2957795130823)
lat1 = lat1 / rad
lng1 = lng1 / rad
lat2 = lat2 / rad
lng2 = lng2 / rad
s := math.Acos(math.Cos(lat1)*math.Cos(lat2)*math.Cos(lng2-lng1)+math.Sin(lat1)*math.Sin(lat2)) * radius
if math.IsNaN(s) {
return 0
}
return s
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jiangsu-lanjiang-intelligent/supply-point.git
git@gitee.com:jiangsu-lanjiang-intelligent/supply-point.git
jiangsu-lanjiang-intelligent
supply-point
supply-point
v0.1.12

搜索帮助

344bd9b3 5694891 D2dac590 5694891