315 lines
10 KiB
Go
315 lines
10 KiB
Go
package tencent_map
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"git.rosy.net.cn/baseapi/utils"
|
|
"git.rosy.net.cn/jx-callback/globals"
|
|
"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()
|
|
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, 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
|
|
}
|