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 }