Files
baseapi/platformapi/tencent_map/tencent_api.go
邹宗楠 757573973f 1
2024-07-31 15:53:13 +08:00

316 lines
10 KiB
Go

package tencent_map
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
// TencentCoordinateChange 腾讯坐标转换(其他坐标转换为腾讯坐标)
func (a *API) TencentCoordinateChange(param *TencentCoordinateChangeReq) ([]*LocationsCoordinateObj, error) {
requestParam := utils.Struct2Map(param, "", false)
requestParam["sig"] = a.signParams(requestParam, TencentCoordinateApi)
result, err := a.AccessAPI(BaseUrl, TencentCoordinateApi, http.MethodGet, requestParam)
if err != nil {
return nil, err
}
resultByte, err := json.Marshal(result)
if err != nil {
return nil, err
}
data := &TencentCoordinateChangeRes{}
if err = json.Unmarshal(resultByte, data); err != nil {
return nil, err
}
if data.Status != 0 {
return nil, fmt.Errorf("%s", data.Message)
}
locations := make([]*LocationsCoordinateObj, 0, 0)
for _, v := range data.Locations {
locations = append(locations, &LocationsCoordinateObj{
Lat: v.Lat.String(),
Lng: v.Lng.String(),
})
}
return locations, nil
}
// TencentCyclingPlanning 腾讯电动车骑行规划
func (a *API) TencentCyclingPlanning(param *TencentCyclingPlanningReq) (distance int64, duration int64, coordinatePoint []string, err error) {
requestParam := utils.Struct2Map(param, "", false)
requestParam["sig"] = a.signParams(requestParam, TencentCyclingPlanning)
result, err := a.AccessAPI(BaseUrl, TencentCyclingPlanning, http.MethodGet, requestParam)
if err != nil {
return 0, 0, nil, err
}
resultByte, err := json.Marshal(result)
if err != nil {
return 0, 0, nil, err
}
data := &TencentCyclingPlanningRes{}
if err = json.Unmarshal(resultByte, data); err != nil {
return 0, 0, nil, err
}
if data.Status != 0 {
return 0, 0, nil, err
}
for _, v := range data.Result["routes"] {
distance = v.Distance
duration = v.Duration
pointList := make([]string, 0, len(v.Polyline))
pointList = append(pointList, v.Polyline[0].String())
pointList = append(pointList, v.Polyline[1].String())
for i := 2; i < len(v.Polyline); i++ {
point1 := utils.Str2Float64(pointList[i-2])
point2, _ := v.Polyline[i].Float64()
point3 := point1 + point2/float64(1000000)
point4 := fmt.Sprintf("%.6f", point3)
pointList = append(pointList, point4)
}
for i := 0; i < len(pointList); i += 2 {
coordinatePoint = append(coordinatePoint, fmt.Sprintf("%s,%s", pointList[i+1], pointList[i]))
}
return distance, duration, coordinatePoint, nil
}
return 0, 0, nil, fmt.Errorf("骑行计划获取异常")
}
// WalkingDistance 获取两点之间的步行距离
func (a *API) WalkingDistance(param *TencentCyclingPlanningReq) (distance int64, err error) {
requestParam := utils.Struct2Map(param, "", false)
requestParam["sig"] = a.signParams(requestParam, TencentWalkingPlanning)
result, err := a.AccessAPI(BaseUrl, TencentWalkingPlanning, http.MethodGet, requestParam)
if err != nil {
return 0, err
}
resultByte, err := json.Marshal(result)
if err != nil {
return 0, err
}
data := &TencentCyclingPlanningRes{}
if err = json.Unmarshal(resultByte, data); err != nil {
return 0, err
}
if data.Status != 0 {
return 0, err
}
for _, v := range data.Result["routes"] {
return v.Distance, nil
//duration = v.Duration
//
//pointList := make([]string, 0, len(v.Polyline))
//pointList = append(pointList, v.Polyline[0].String())
//pointList = append(pointList, v.Polyline[1].String())
//for i := 2; i < len(v.Polyline); i++ {
// point1 := utils.Str2Float64(pointList[i-2])
// point2, _ := v.Polyline[i].Float64()
// pointList = append(pointList, fmt.Sprintf("%.6f", point1+point2/float64(1000000)))
//}
//
//for i := 0; i < len(pointList); i += 2 {
// coordinatePoint = append(coordinatePoint, fmt.Sprintf("%s,%s", pointList[i+1], pointList[i]))
//}
//globals.SugarLogger.Debugf("调换后 : %s", utils.Format4Output(coordinatePoint, false))
//
//return distance, duration, coordinatePoint, nil
}
return 0, fmt.Errorf("步行计划获取异常")
}
// GetCoordinateFromAddress 根据地址或者城市code获取坐标已经城市编码
func (a *API) GetCoordinateFromAddress(address string, cityInfo string) (lng, lat float64, districtCode int, districtName string, err error) {
if address == "" {
return 0, 0, 0, "", fmt.Errorf("地址信息不能为空")
}
requestParam := map[string]interface{}{
"address": address,
"key": a.key,
}
requestParam["sig"] = a.signParams(requestParam, TencentGeoAddress2Code)
result, err := a.AccessAPI(BaseUrl, TencentGeoAddress2Code, http.MethodGet, requestParam)
if err != nil {
return 0, 0, 0, "", err
}
data := &AddressGeoCoderChangeRes{}
if err := utils.Map2StructByJson(result, data, false); err != nil {
return 0, 0, 0, "", err
}
lng, _ = data.Result.Location.Lng.Float64()
lat, _ = data.Result.Location.Lat.Float64()
return lng, lat, utils.Str2Int(data.Result.AdInfo.AdCode), data.Result.AddressComponents.District, nil
}
// GeoCodeRegeoSingle 根据坐标获取地址信息
func (a *API) GeoCodeRegeoSingle(lng, lat float64, radius int, isExt bool, poiTypes []string, roadLevel, homeOrCorp int) (coordInfo *Codes2AddressRes, err error) {
param := map[string]interface{}{
"location": utils.Float64ToStr(lat) + "," + utils.Float64ToStr(lng),
"key": a.key,
}
param["sig"] = a.signParams(param, TencentCoder2Address)
result, err := a.AccessAPI(BaseUrl, TencentCoder2Address, http.MethodGet, param)
resultByte, err := json.Marshal(result)
if err != nil {
return nil, err
}
if err = json.Unmarshal(resultByte, &coordInfo); err != nil {
return nil, err
}
return coordInfo, err
}
// GetDistricts 行政区划查询 subdistrict子级行政区 keywords 关键字
func (a *API) GetDistricts(subDistrict int, keywords string, level int) (districtList []*District, err error) {
// 之前是使用的高德地图更新的,高德更新的地图在直辖市的时候,比腾讯地图多了一行数据
// 行政区划长时间不会改变,所以不在更新本地存储的行政区划直接跳过
// 110000 北京市 0 1 010 100001 131 1 0 1 0
// 110100 北京市 110000 2 010 1 0 1 730 0 0
if subDistrict == 3 && keywords == "" {
return nil, fmt.Errorf("高德转腾讯,暂时不做修改")
/*param := map[string]interface{}{
"struct_type": 1,
"key": a.key,
}
param["sig"] = a.signParams(param, TencentGetDistrictList)
result, err := a.AccessAPI(BaseUrl, TencentGetDistrictList, http.MethodGet, param)
resultByte, err := json.Marshal(result)
if err != nil {
return nil, err
}
administrativeDivision := &AdministrativeDivision{}
if err = json.Unmarshal(resultByte, administrativeDivision); err != nil {
return nil, err
}
return administrativeDivision.Result, err*/
}
if keywords != "" {
return a.GetSecondaryDivision(subDistrict, keywords, level)
}
return nil, fmt.Errorf("参数异常")
}
// GetSecondaryDivision 获取二级行政区划 keywords 是父级code
func (a *API) GetSecondaryDivision(number int, keywords string, level int) ([]*District, error) {
param := map[string]interface{}{
"key": a.key,
"id": keywords,
}
param["sig"] = a.signParams(param, TencentGetChildrenList)
result, err := a.AccessAPI(BaseUrl, TencentGetChildrenList, http.MethodGet, param)
if err != nil {
return nil, err
}
resultByte, err := json.Marshal(result)
if err != nil {
return nil, err
}
districtGetChildren := &DistrictGetChildren{}
if err = json.Unmarshal(resultByte, districtGetChildren); err != nil {
return nil, err
}
if districtGetChildren.Status != 0 {
return nil, fmt.Errorf("%s", districtGetChildren.Message)
}
resultData := make([]*District, 0, 0)
for _, v := range districtGetChildren.Result[0] {
parentCode := &District{
Adcode: v.Id,
Lng: 0.0,
Lat: 0.0,
CityCode: "",
Level: level,
Name: v.Fullname,
Districts: nil,
}
parentCode.Lng, _ = v.Location.Lng.Float64()
parentCode.Lat, _ = v.Location.Lat.Float64()
if number == 2 {
parentCode.Districts, _ = a.GetSecondaryDivision(1, v.Id, level+1)
}
resultData = append(resultData, parentCode)
}
return resultData, nil
}
// BatchWalkingDistance 批量获取两点之间的步行距离
func (a *API) BatchWalkingDistance(srcLng, srcLat float64, destCoords []*Coordinate) (distanceList []float64, err error) {
for _, v := range destCoords {
distance, err := a.WalkingDistance(&TencentCyclingPlanningReq{
Key: a.key,
From: fmt.Sprintf("%f,%f", srcLat, srcLng),
To: fmt.Sprintf("%f,%f", v.Lat, v.Lng),
})
if err != nil {
return nil, err
}
distanceList = append(distanceList, utils.Int64ToFloat64(distance))
}
return distanceList, err
}
// GetCoordinateDistrictCode 获取坐标点所在行政区划
func (a *API) GetCoordinateDistrictCode(lng, lat float64) (districtCode int) {
result, err := a.GeoCodeRegeoSingle(lng, lat, 0, false, nil, 0, 0)
if err == nil {
districtCode = utils.Str2Int(result.Result.AdInfo.Adcode)
// 这个是因为老代码使用搞的地图获取这两个市的时候没有分区,place表做了一个假的分区,这边为了统一
if result.Result.AdInfo.District == "东莞市" || result.Result.AdInfo.District == "中山市" {
districtCode += 9000000 // FakeDistrictPadding
}
return
}
return 0
}
// GetCoordinateTownInfo 根据坐标获取城市名称和坐标
func (a *API) GetCoordinateTownInfo(lng, lat float64) (townName, townCode string) {
result, err := a.GeoCodeRegeoSingle(lng, lat, 0, false, nil, 0, 0)
if err == nil {
if name, ok := result.Result.AddressReference.(map[string]interface{})["town"].(map[string]interface{})["title"]; ok {
townName = name.(string)
}
if name, ok := result.Result.AddressReference.(map[string]interface{})["town"].(map[string]interface{})["id"]; ok {
townCode = name.(string) + "000"
}
}
return
}
// GetCoordinateCityInfo 根据坐标获取
func (a *API) GetCoordinateCityInfo(lng, lat float64) (cityName, cityCode string) {
result, err := a.GeoCodeRegeoSingle(lng, lat, 0, false, nil, 0, 0)
if err == nil {
cityName = result.Result.AdInfo.City
// cityCode 老版本高德地图获取到的是电话的区号,但是这个返回值没有使用,暂时不做处理
cityCode = result.Result.AdInfo.CityCode
}
return
}