This commit is contained in:
DDIsFriend
2023-08-18 17:28:57 +08:00
commit f0e8a1709d
4282 changed files with 192396 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,42 @@
//
// DDMALocationManager.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/24.
#import <Foundation/Foundation.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <AMapLocationKit/AMapLocationKit.h>
NS_ASSUME_NONNULL_BEGIN
@protocol DDMALocationManagerDelegate <NSObject>
@optional
- (void)ddMALocationManager:(AMapLocationManager *)manager doRequireLocationAuth:(CLLocationManager*)locationManager;
- (void)ddMALocationManager:(AMapLocationManager *)manager locationManager:(CLLocationManager *_Nullable)locationManager didChangeAuthorization:(CLAuthorizationStatus)authorizationStatus accuracyAuthorization:(CLAccuracyAuthorization)accuracyAuthorization;
- (void)ddMALocationManager:(AMapLocationManager *)manager didFailWithError:(NSError *)error;
- (void)ddMALocationManager:(AMapLocationManager *)manager didUpdateHeading:(CLHeading *)heading;
- (void)ddMALocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode;
@end
@interface DDMALocationManager : NSObject
// 请在使用该类前先设置appkey
+ (void)startWithAppKey:(nullable NSString *)appKey;
// 在创建该类实例前调用
+ (void)agreePrivacy;
@property (nonatomic, strong)AMapLocationManager *maLocationManager;
@property (nonatomic, weak)id<DDMALocationManagerDelegate> delegate;
@property (nonatomic, assign)BOOL forceFullAccuracy;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,135 @@
//
// DDMALocationManager.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/24.
#import "DDMALocationManager.h"
#import <DDLogKit_Private/DDOCLog.h>
@interface DDMALocationManager ()<AMapLocationManagerDelegate>
@end
@implementation DDMALocationManager
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
[[AMapServices sharedServices] setEnableHTTPS:YES];
[AMapServices sharedServices].apiKey = appKey;
}
+ (void)agreePrivacy{
[AMapLocationManager updatePrivacyShow:AMapPrivacyShowStatusDidShow privacyInfo:AMapPrivacyInfoStatusDidContain];
[AMapLocationManager updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
}
- (AMapLocationManager *)maLocationManager{
if (_maLocationManager == nil) {
_maLocationManager = [AMapLocationManager new];
_maLocationManager.delegate = self;
}
return _maLocationManager;
}
// MARK: <AMapLocationManagerDelegate>
- (void)amapLocationManager:(AMapLocationManager *)manager doRequireLocationAuth:(CLLocationManager*)locationManager{
if ([self.delegate respondsToSelector:@selector(ddMALocationManager:doRequireLocationAuth:)]) {
[self.delegate ddMALocationManager:manager doRequireLocationAuth:locationManager];
}else{
[locationManager requestWhenInUseAuthorization];
}
}
- (void)amapLocationManager:(AMapLocationManager *)manager doRequireTemporaryFullAccuracyAuth:(CLLocationManager *)locationManager completion:(void (^)(NSError *))completion API_AVAILABLE(ios(14.0)){
if (locationManager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy) {
/// Every time you open the app and detect that the positioning accuracy is reduce, you need to apply for a temporary full accuracy.
[self ddMALocationManager:locationManager requestTemporaryFullAccuracyAuthorizationWithCompletion:^(NSError * _Nullable error) {
}];
}
}
- (void)amapLocationManager:(AMapLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status API_DEPRECATED("",ios(11.0 , 13.0)){
[self ddMACombineManager:manager locationManager:nil didChangeAuthorization:[CLLocationManager authorizationStatus] accuracyAuthorization:CLAccuracyAuthorizationFullAccuracy];
}
- (void)amapLocationManager:(AMapLocationManager *)manager locationManagerDidChangeAuthorization:(CLLocationManager*)locationManager API_AVAILABLE(ios(14.0)){
CLAccuracyAuthorization accuracyAuthorization = CLAccuracyAuthorizationFullAccuracy;
if (locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy) {
accuracyAuthorization = CLAccuracyAuthorizationFullAccuracy;
}else if (locationManager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy){
accuracyAuthorization = CLAccuracyAuthorizationReducedAccuracy;
/// When opening the app authorization location for the first time, a temporary promt is also required.
[self ddMALocationManager:locationManager requestTemporaryFullAccuracyAuthorizationWithCompletion:^(NSError * _Nullable error) {
}];
}
[self ddMACombineManager:manager locationManager:locationManager didChangeAuthorization:[locationManager authorizationStatus] accuracyAuthorization:accuracyAuthorization];
}
- (void)ddMALocationManager:(CLLocationManager *_Nullable)locationManager requestTemporaryFullAccuracyAuthorizationWithCompletion:(void(^)(NSError *_Nullable error))completion API_AVAILABLE(ios(14.0)) {
/// This is async.
[locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:@"FORCE_FULL_ACCURACY" completion:^(NSError * _Nullable error) {
//
BOOL canBeLocated = (locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedAlways || locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse);
if (canBeLocated && locationManager.accuracyAuthorization == CLAccuracyAuthorizationReducedAccuracy && self.forceFullAccuracy) {
[self ddMALocationManager:locationManager requestTemporaryFullAccuracyAuthorizationWithCompletion:nil];
}
}];
}
- (void)ddMACombineManager:(AMapLocationManager *)manager locationManager:(CLLocationManager *_Nullable)locationManager didChangeAuthorization:(CLAuthorizationStatus)authorizationStatus accuracyAuthorization:(CLAccuracyAuthorization)accuracyAuthorization{
switch (authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
DDLog("当前定位权限 - kCLAuthorizationStatusNotDetermined");
break;
case kCLAuthorizationStatusDenied:
DDLog("当前定位权限 - kCLAuthorizationStatusDenied");
break;
case kCLAuthorizationStatusRestricted:
DDLog("当前定位权限 - kCLAuthorizationStatusRestricted");
break;
case kCLAuthorizationStatusAuthorizedAlways:
DDLog("当前定位权限 - kCLAuthorizationStatusAuthorizedAlways");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
DDLog("当前定位权限 - kCLAuthorizationStatusAuthorizedWhenInUse");
break;
default:
break;
}
switch (accuracyAuthorization) {
case CLAccuracyAuthorizationFullAccuracy:
DDLog("当前精度 - CLAccuracyAuthorizationFullAccuracy");
break;
case CLAccuracyAuthorizationReducedAccuracy:
DDLog("当前精度 - CLAccuracyAuthorizationReducedAccuracy");
break;
default:
break;
}
if ([self.delegate respondsToSelector:@selector(ddMALocationManager:locationManager:didChangeAuthorization:accuracyAuthorization:)]){
[self.delegate ddMALocationManager:manager locationManager:locationManager didChangeAuthorization:authorizationStatus accuracyAuthorization:accuracyAuthorization];
}
}
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode{
if ([self.delegate respondsToSelector:@selector(ddMALocationManager:didUpdateLocation:reGeocode:)]) {
[self.delegate ddMALocationManager:manager didUpdateLocation:location reGeocode:reGeocode];
}
}
- (void)amapLocationManager:(AMapLocationManager *)manager didFailWithError:(NSError *)error{
if ([self.delegate respondsToSelector:@selector(ddMALocationManager:didFailWithError:)]) {
[self.delegate ddMALocationManager:manager didFailWithError:error];
}
}
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateHeading:(CLHeading *)heading{
if ([self.delegate respondsToSelector:@selector(ddMALocationManager:didUpdateHeading:)]) {
[self.delegate ddMALocationManager:manager didUpdateHeading:heading];
}
}
@end

View File

@@ -0,0 +1,15 @@
//
// DriveRouteCustomAnnotation.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/3.
#import <AMapNaviKit/MAMapKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface DriveRouteCustomAnnotation : MAPointAnnotation
@property (nonatomic, copy)NSAttributedString *customAttributedText;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,11 @@
//
// DriveRouteCustomAnnotation.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/3.
#import "DriveRouteCustomAnnotation.h"
@implementation DriveRouteCustomAnnotation
@end

View File

@@ -0,0 +1,25 @@
//
// MAPointAnnotation+DDCategory.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/31.
#import <AMapNaviKit/MAMapKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface MAPointAnnotation (DDCategory)
// 自定义图片
@property (nonatomic, strong, nullable)UIImage *dd_image;
// 自定义气泡的view
@property (nonatomic, strong, nullable)UIView *customCalloutView;
// 类型字符
@property (nonatomic, strong)Class annotationClass;
// tag
@property (nonatomic, assign)long tag;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,42 @@
//
// MAPointAnnotation+DDCategory.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/31.
#import "MAPointAnnotation+DDCategory.h"
#import <objc/runtime.h>
@implementation MAPointAnnotation (DDCategory)
- (void)setDd_image:(UIImage *)dd_image{
objc_setAssociatedObject(self, @selector(dd_image), dd_image, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (nullable UIImage *)dd_image{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setCustomCalloutView:(UIView *)customCalloutView{
objc_setAssociatedObject(self, @selector(customCalloutView), customCalloutView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (nullable UIView *)customCalloutView{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setAnnotationClass:(Class)annotationClass{
objc_setAssociatedObject(self, @selector(annotationClass), annotationClass, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (Class)annotationClass{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setTag:(int)tag{
objc_setAssociatedObject(self, @selector(tag), @(tag), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (int)tag{
return [objc_getAssociatedObject(self, _cmd) intValue];
}
@end

View File

@@ -0,0 +1,15 @@
//
// DriveRouteCustomAnnotationView.h
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/3.
#import <AMapNaviKit/MAMapKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface DriveRouteCustomAnnotationView : MAAnnotationView
@property (nonatomic, strong)UILabel *customTextLabel;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,37 @@
//
// DriveRouteCustomAnnotationView.m
// DDCategoryKit_Private
// Created by DDIsFriend on 2023/2/3.
#import "DriveRouteCustomAnnotationView.h"
@interface DriveRouteCustomAnnotationView ()
@end
@implementation DriveRouteCustomAnnotationView
- (id)initWithAnnotation:(id <MAAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self) {
[self addSubview:self.customTextLabel];
self.customTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.customTextLabel.heightAnchor constraintEqualToConstant:30],
[self.customTextLabel.bottomAnchor constraintEqualToAnchor:self.topAnchor constant:0],
[self.customTextLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
]];
}
return self;
}
// MARK: <Lazy>
- (UILabel *)customTextLabel{
if (_customTextLabel == nil) {
_customTextLabel = [[UILabel alloc] init];
}
return _customTextLabel;
}
@end

View File

@@ -0,0 +1,154 @@
//
// DDMAMapView.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/30.
#import <UIKit/UIKit.h>
#import <AMapNaviKit/MAMapKit.h>
#import <DDMAMapKit_Private/MATraceReplayOverlay.h>
#import <DDMAMapKit_Private/MATraceReplayOverlayRender.h>
NS_ASSUME_NONNULL_BEGIN
@protocol DDMAMapViewDelegate;
@class DDAnnotationView;
@class DDAnnotation;
@interface DDMAMapView : UIView
@property (nonatomic, strong, nonnull)MAMapView *maMapView;
@property (nonatomic, weak)id<DDMAMapViewDelegate> delegate;
// 请在使用该类前先设置appkey
+ (void)startWithAppKey:(nullable NSString *)appKey;
// 在创建该类实例前调用
+ (void)agreePrivacy;
- (MAOverlayRenderer *)dd_rendererForOverlay:(id <MAOverlay>)overlay;
@end
@interface DDMAMapView (Location)
/// @brief 用户当前位置的属性
@property (nonatomic, readonly)MAUserLocation *maUserLocation;
/// @brief 调用此方法来自定义当前位置小蓝点
- (void)updateLocationViewWithParam:(MAUserLocationRepresentation *)representation;
@end
@interface DDMAMapView (Trace)
@property (nonatomic, strong)MATraceReplayOverlay *traceReplayOverlay;
@property (nonatomic, strong)MATraceReplayOverlayRenderer *traceReplayOverlayRenderer;
@end
@protocol DDMAMapViewDelegate <NSObject>
@optional
/**
* @brief 地图开始加载
* @param mapView 地图View
*/
- (void)dd_mapViewWillStartLoadingMap:(MAMapView *)mapView;
/**
* @brief 地图加载成功
* @param mapView 地图View
*/
- (void)dd_mapViewDidFinishLoadingMap:(MAMapView *)mapView;
/**
* @brief 地图加载失败
* @param mapView 地图View
* @param error 错误信息
*/
- (void)dd_mapViewDidFailLoadingMap:(MAMapView *)mapView withError:(NSError *)error;
/**
* @brief 地形图加载失败
* @param mapView 地图View
* @param error 错误信息
*/
- (void)dd_mapView:(MAMapView *)mapView didFailLoadTerrainWithError:(NSError *)error;
/**
* @brief 在地图View将要启动定位时会调用此函数
* @param mapView 地图View
*/
- (void)dd_mapViewWillStartLocatingUser:(MAMapView *)mapView;
/**
* @brief 在地图View停止定位后会调用此函数
* @param mapView 地图View
*/
- (void)dd_mapViewDidStopLocatingUser:(MAMapView *)mapView;
/**
* @brief 位置或者设备方向更新后,会调用此函数
* @param mapView 地图View
* @param userLocation 用户定位信息(包括位置与设备方向等数据)
* @param updatingLocation 标示是否是location数据更新, YES:location数据更新 NO:heading数据更新
*/
- (void)dd_mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation;
/**
* @brief 当plist配置NSLocationAlwaysUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription并且[CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined会调用代理的此方法。
此方法实现调用后台权限API即可 该回调必须实现 [locationManager requestAlwaysAuthorization] ; since 6.8.0
* @param locationManager 地图的CLLocationManager。
*/
- (void)dd_mapViewRequireLocationAuth:(CLLocationManager *)locationManager;
/**
* @brief 定位失败后,会调用此函数
* @param mapView 地图View
* @param error 错误号参考CLError.h中定义的错误号
*/
- (void)dd_mapView:(MAMapView *)mapView didFailToLocateUserWithError:(NSError *)error;
/**
* @brief 根据anntation生成对应的View。
注意:
1、5.1.0后由于定位蓝点增加了平滑移动功能如果在开启定位的情况先添加annotation需要在此回调方法中判断annotation是否为MAUserLocation从而返回正确的View。
if ([annotation isKindOfClass:[MAUserLocation class]]) {
return nil;
}
2、请不要在此回调中对annotation进行select和deselect操作此时annotationView还未添加到mapview。
* @param mapView 地图View
* @param annotation 指定的标注
* @return 生成的标注View
*/
- (MAAnnotationView *)dd_mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation;
/**
* @brief 根据overlay生成对应的Renderer
* @param mapView 地图View
* @param overlay 指定的overlay
* @return 生成的覆盖物Renderer
*/
- (MAOverlayRenderer *)dd_mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay;
/**
* @brief 标注view被点击时触发该回调。since 5.7.0
* @param mapView 地图的view
* @param view annotationView
*/
- (void)dd_mapView:(MAMapView *)mapView didAnnotationViewTapped:(MAAnnotationView *)view;
/**
* @brief 当mapView新添加overlay renderers时调用此接口
* @param mapView 地图View
* @param overlayRenderers 新添加的overlay renderers
*/
- (void)dd_mapView:(MAMapView *)mapView didAddOverlayRenderers:(NSArray *)overlayRenderers;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,245 @@
//
// DDMAMapView.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/30.
#import "DDMAMapView.h"
#import <objc/runtime.h>
#import <DDCategoryKit_Private/UIImage+DDCategory.h>
#import <DDMAMapKit_Private/MAPointAnnotation+DDCategory.h>
#import <DDMAMapKit_Private/MABaseOverlay+DDCategory.h>
#import <DDMAMapKit_Private/DriveRouteCustomAnnotationView.h>
#import <DDMAMapKit_Private/DriveRouteCustomAnnotation.h>
@interface DDMAMapView () <MAMapViewDelegate>
@end
@implementation DDMAMapView
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
[[AMapServices sharedServices] setEnableHTTPS:YES];
[AMapServices sharedServices].apiKey = appKey;
}
+ (void)agreePrivacy{
[MAMapView updatePrivacyShow:AMapPrivacyShowStatusDidShow privacyInfo:AMapPrivacyInfoStatusDidContain];
[MAMapView updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
}
// MARK: <Init Function>
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (!self) return nil;
[self configMapView];
return self;
}
- (void)configMapView{
// MAMapView.metalEnabled = YES;
self.maMapView = [[MAMapView alloc] init];
self.maMapView.delegate = self;
[self addSubview:self.maMapView];
self.maMapView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[self.maMapView.leftAnchor constraintEqualToAnchor:self.leftAnchor],
[self.maMapView.topAnchor constraintEqualToAnchor:self.topAnchor],
[self.maMapView.rightAnchor constraintEqualToAnchor:self.rightAnchor],
[self.maMapView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
]];
self.maMapView.showsIndoorMap = NO;
self.maMapView.zoomLevel = 16;
self.maMapView.mapType = MAMapTypeStandard;
self.maMapView.showsCompass = NO;
self.maMapView.showsScale = NO;
}
- (MAOverlayRenderer *)dd_rendererForOverlay:(id <MAOverlay>)overlay{
return [self.maMapView rendererForOverlay:overlay];
}
// MARK: <MAMapViewDelegate>
- (void)mapViewWillStartLoadingMap:(MAMapView *)mapView{
if ([self.delegate respondsToSelector:@selector(dd_mapViewWillStartLoadingMap:)]) {
[self.delegate dd_mapViewWillStartLoadingMap:mapView];
}
}
- (void)mapViewDidFinishLoadingMap:(MAMapView *)mapView{
if ([self.delegate respondsToSelector:@selector(dd_mapViewDidFinishLoadingMap:)]) {
[self.delegate dd_mapViewDidFinishLoadingMap:mapView];
}
}
- (void)mapViewDidFailLoadingMap:(MAMapView *)mapView withError:(NSError *)error{
if ([self.delegate respondsToSelector:@selector(dd_mapViewDidFailLoadingMap:withError:)]) {
[self.delegate dd_mapViewDidFailLoadingMap:mapView withError:error];
}
}
- (void)mapView:(MAMapView *)mapView didFailLoadTerrainWithError:(NSError *)error{
if ([self.delegate respondsToSelector:@selector(dd_mapView:didFailLoadTerrainWithError:)]) {
[self.delegate dd_mapView:mapView didFailLoadTerrainWithError:error];
}
}
// MARK: <Locate>
- (void)mapViewWillStartLocatingUser:(MAMapView *)mapView{
if ([self.delegate respondsToSelector:@selector(dd_mapViewWillStartLocatingUser:)]) {
[self.delegate dd_mapViewWillStartLocatingUser:mapView];
}
}
- (void)mapViewDidStopLocatingUser:(MAMapView *)mapView{
if ([self.delegate respondsToSelector:@selector(dd_mapViewDidStopLocatingUser:)]) {
[self.delegate dd_mapViewDidStopLocatingUser:mapView];
}
}
- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation{
if ([self.delegate respondsToSelector:@selector(dd_mapView:didUpdateUserLocation:updatingLocation:)]) {
[self.delegate dd_mapView:mapView didUpdateUserLocation:userLocation updatingLocation:updatingLocation];
}
}
- (void)mapViewRequireLocationAuth:(CLLocationManager *)locationManager {
if ([self.delegate respondsToSelector:@selector(dd_mapViewRequireLocationAuth:)]) {
[self.delegate dd_mapViewRequireLocationAuth:locationManager];
}
}
- (void)mapView:(MAMapView *)mapView didFailToLocateUserWithError:(NSError *)error{
if ([self.delegate respondsToSelector:@selector(dd_mapView:didFailToLocateUserWithError:)]) {
[self.delegate dd_mapView:mapView didFailToLocateUserWithError:error];
}
}
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation{
if ([self.delegate respondsToSelector:@selector(dd_mapView:viewForAnnotation:)]) {
return [self.delegate dd_mapView:mapView viewForAnnotation:annotation];
}
if ([annotation isMemberOfClass:[MAPointAnnotation class]]){
MAPointAnnotation *pointAnnotation = (MAPointAnnotation *)annotation;
static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
if (annotationView == nil)
{
annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
}
annotationView.annotation = pointAnnotation;
annotationView.image = pointAnnotation.dd_image;
if (pointAnnotation.customCalloutView != nil) {
annotationView.customCalloutView = [[MACustomCalloutView alloc] initWithCustomView:pointAnnotation.customCalloutView];
annotationView.canShowCallout = YES;
annotationView.selected = YES;
}
return annotationView;
}
if ([annotation isMemberOfClass:[MAAnimatedAnnotation class]]) {
MAAnimatedAnnotation *animatedAnnotation = (MAAnimatedAnnotation *)annotation;
static NSString *pointReuseIndentifier = @"AnimatedAnnotationPointReuseIndentifier";
MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
if (annotationView == nil)
{
annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
}
annotationView.annotation = animatedAnnotation;
annotationView.image = animatedAnnotation.dd_image;
return annotationView;
}
if ([annotation isMemberOfClass:[DriveRouteCustomAnnotation class]]){
DriveRouteCustomAnnotation *pointAnnotation = (DriveRouteCustomAnnotation *)annotation;
static NSString *pointReuseIndentifier = @"DriveRouteCustomAnnotationPointReuseIndentifier";
DriveRouteCustomAnnotationView *annotationView = (DriveRouteCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
if (annotationView == nil)
{
annotationView = [[DriveRouteCustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
}
annotationView.annotation = pointAnnotation;
annotationView.image = pointAnnotation.dd_image;
annotationView.customTextLabel.attributedText = pointAnnotation.customAttributedText;
return annotationView;
}
return nil;
}
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay{
if ([self.delegate respondsToSelector:@selector(dd_mapView:rendererForOverlay:)]) {
return [self.delegate dd_mapView:mapView rendererForOverlay:overlay];
}
if ([overlay isMemberOfClass:[MAPolyline class]]){
MAPolyline *polyline = (MAPolyline *)overlay;
MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:polyline];
polylineRenderer.lineWidth = polyline.dd_lineWidth;
polylineRenderer.strokeColor = polyline.dd_strokeColor;
polylineRenderer.lineJoinType = polyline.dd_lineJoinType;
polylineRenderer.lineCapType = polyline.dd_lineCapType;
return polylineRenderer;
}
if ([overlay isMemberOfClass:[MATraceReplayOverlay class]]) {
MATraceReplayOverlay *traceReplayOverlay = (MATraceReplayOverlay *)overlay;
MATraceReplayOverlayRenderer *traceReplayOverlayRenderer = [[MATraceReplayOverlayRenderer alloc] initWithOverlay:traceReplayOverlay];
traceReplayOverlayRenderer.lineWidth = traceReplayOverlay.dd_lineWidth;
traceReplayOverlayRenderer.strokeColors = traceReplayOverlay.dd_strokeColors;
traceReplayOverlayRenderer.lineJoinType = traceReplayOverlay.dd_lineJoinType;
traceReplayOverlayRenderer.lineCapType = traceReplayOverlay.dd_lineCapType;
self.traceReplayOverlay = traceReplayOverlay;
self.traceReplayOverlayRenderer = traceReplayOverlayRenderer;
return traceReplayOverlayRenderer;
}
return nil;
}
- (void)mapView:(MAMapView *)mapView didAnnotationViewTapped:(MAAnnotationView *)view{
if ([self.delegate respondsToSelector:@selector(dd_mapView:didAnnotationViewTapped:)]) {
[self.delegate dd_mapView:mapView didAnnotationViewTapped:view];
}
}
- (void)mapView:(MAMapView *)mapView didAddOverlayRenderers:(NSArray *)overlayRenderers{
if ([self.delegate respondsToSelector:@selector(dd_mapView:didAddOverlayRenderers:)]) {
[self.delegate dd_mapView:mapView didAddOverlayRenderers:overlayRenderers];
}
}
@end
@implementation DDMAMapView (Location)
- (MAUserLocation *)maUserLocation{
return self.maMapView.userLocation;
}
- (void)updateLocationViewWithParam:(MAUserLocationRepresentation *)representation{
[self.maMapView updateUserLocationRepresentation:representation];
}
@end
@implementation DDMAMapView (Trace)
- (void)setTraceReplayOverlay:(MATraceReplayOverlay *)traceReplayOverlay{
objc_setAssociatedObject(self, @selector(traceReplayOverlay), traceReplayOverlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MATraceReplayOverlay *)traceReplayOverlay{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setTraceReplayOverlayRenderer:(MATraceReplayOverlayRenderer *)traceReplayOverlayRenderer{
objc_setAssociatedObject(self, @selector(traceReplayOverlayRenderer), traceReplayOverlayRenderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MATraceReplayOverlayRenderer *)traceReplayOverlayRenderer{
return objc_getAssociatedObject(self, _cmd);
}
@end

View File

@@ -0,0 +1,26 @@
//
// MABaseOverlay+DDCategory.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/1.
#import <AMapNaviKit/MAMapKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface MABaseOverlay (DDCategory)
@property (nonatomic, assign)CGFloat dd_lineWidth;
@property (nonatomic, strong)UIColor *dd_strokeColor;
@property (nonatomic, strong)NSArray *dd_strokeColors;
@property (nonatomic, assign)MALineJoinType dd_lineJoinType;
@property (nonatomic, assign)MALineCapType dd_lineCapType;
@property (nonatomic, assign)int tag;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,58 @@
//
// MABaseOverlay+DDCategory.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/1.
#import "MABaseOverlay+DDCategory.h"
#import <objc/runtime.h>
@implementation MABaseOverlay (DDCategory)
- (void)setDd_lineWidth:(CGFloat)dd_lineWidth{
objc_setAssociatedObject(self, @selector(dd_lineWidth), @(dd_lineWidth), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CGFloat)dd_lineWidth{
return [objc_getAssociatedObject(self, _cmd) floatValue];
}
- (void)setDd_strokeColor:(UIColor *)dd_strokeColor{
objc_setAssociatedObject(self, @selector(dd_strokeColor), dd_strokeColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)dd_strokeColor{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setDd_strokeColors:(NSArray *)dd_strokeColors{
objc_setAssociatedObject(self, @selector(dd_strokeColors), dd_strokeColors, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSArray *)dd_strokeColors{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setDd_lineJoinType:(MALineJoinType)dd_lineJoinType{
objc_setAssociatedObject(self, @selector(dd_lineJoinType), @(dd_lineJoinType), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MALineJoinType)dd_lineJoinType{
return (MALineJoinType)[objc_getAssociatedObject(self, _cmd) intValue];
}
- (void)setDd_lineCapType:(MALineCapType)dd_lineCapType{
objc_setAssociatedObject(self, @selector(dd_lineCapType), @(dd_lineCapType), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (MALineCapType)dd_lineCapType{
return (MALineCapType)[objc_getAssociatedObject(self, _cmd) intValue];
}
- (void)setTag:(int)tag{
objc_setAssociatedObject(self, @selector(tag), @(tag), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (int)tag{
return [objc_getAssociatedObject(self, _cmd) intValue];
}
@end

View File

@@ -0,0 +1,30 @@
//
// MATraceReplayOverlay+Addition.h
// MAMapKit
//
// Created by shaobin on 2017/4/20.
// Copyright © 2017年 Amap. All rights reserved.
//
#import "MATraceReplayOverlay.h"
@interface MATraceReplayOverlay (Addition)
/**
* @brief 每次帧绘制时调用
* @param timeDelta 时间
* @param zoomLevel 地图zoom
*/
- (void)drawStepWithTime:(NSTimeInterval)timeDelta zoomLevel:(CGFloat)zoomLevel;
/**
* @brief 获取内部mutlipolyine
*/
- (MAMultiPolyline *)getMultiPolyline;
/**
* @brief 获取内部patchLine
*/
- (MAPolyline *)getPatchPolyline;
@end

View File

@@ -0,0 +1,82 @@
//
// MATraceReplayOverlay.h
// MAMapKit
//
// Created by shaobin on 2017/4/20.
// Copyright © 2017年 Amap. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AMapNaviKit/MAMapKit.h>
///轨迹回放overlaysince 5.1.0
@interface MATraceReplayOverlay : MABaseOverlay
///是否启动点抽稀默认YES
@property (nonatomic, assign) BOOL enablePointsReduce;
///小汽车移动速度默认80 km/h, 单位米每秒
@property (nonatomic, assign) CGFloat speed;
///是否自动调整车头方向默认NO
@property (nonatomic, assign) BOOL enableAutoCarDirection;
///是否暂停, 初始为YES
@property (nonatomic, assign) BOOL isPaused;
///各个点权重设置取值1-55最大。权重为5则不对此点做抽稀。格式为{weight:indices}
@property (nonatomic, strong) NSDictionary<NSNumber*, NSArray*> *pointsWeight;
/**
* @brief 重置为初始状态
*/
- (void)reset;
/**
* @brief 根据map point设置轨迹点
* @param points map point数据,points对应的内存会拷贝,调用者负责该内存的释放
* @param count map point个数
* @return 返回是否成功
*/
- (BOOL)setWithPoints:(MAMapPoint *)points count:(NSInteger)count;
/**
* @brief 根据经纬度坐标设置轨迹点
* @param coords 经纬度坐标数据,coords对应的内存会拷贝,调用者负责该内存的释放
* @param count 经纬度坐标个数
* @return 返回是否成功
*/
- (BOOL)setWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSInteger)count;
/**
* @brief 获取当前car所在位置点索引
*/
- (NSInteger)getOrigPointIndexOfCar;
/**
* @brief 获取抽稀后当前car所在位置点索引
*/
- (NSInteger)getReducedPointIndexOfCar;
/**
* @brief 获取行进方向,in radian
*/
- (CGFloat)getRunningDirection;
/**
* @brief 获取索引index对应的mapPoint
*/
- (MAMapPoint)getMapPointOfIndex:(NSInteger)origIndex;
/**
* @brief 获取小车位置
*/
- (MAMapPoint)getCarPosition;
/**
* @brief 预处理,加快后面的操作流畅度. 调用前不要把overlay加到mapview在callback中再把overlay加到mapview
*/
- (void)prepareAsync:(void(^)())callback;
@end

View File

@@ -0,0 +1,523 @@
//
// MATraceReplayOverlay.m
// MAMapKit
//
// Created by shaobin on 2017/4/20.
// Copyright © 2017 Amap. All rights reserved.
//
#import "MATraceReplayOverlay.h"
#import "MATraceReplayOverlay+Addition.h"
struct MATraceReplayPoint{
double x; ///<x
double y; ///<y
int weight; ///<
int flag; ///<, 10
double distance; ///<
};
typedef struct MATraceReplayPoint MATraceReplayPoint;
@interface MATraceReplayOverlay () {
MAMultiPolyline *_multiPolyline;
MAPolyline *_patchLine; //线
MAMapPoint _patchLinePoints[2];
MATraceReplayPoint *_origMapPoints;
NSInteger _origPointCount;
NSInteger _carIndexInOrigArray;
NSInteger _reducedPointIndexOfCar;
BOOL _needRecalculateMapPoints;
CGFloat _zoomLevel;
CGFloat _accumulatedDistance;
MAMapPoint _carMapPoint;
CGFloat _runningDirection;
BOOL _readyForDrawing;
NSMutableDictionary *_reducedPointsCache; //{zoomLevel:IndexArray}
}
@end
@implementation MATraceReplayOverlay
- (id)init {
self = [super init];
if(self) {
self.isPaused = YES;
_multiPolyline = [MAMultiPolyline polylineWithCoordinates:NULL count:0 drawStyleIndexes:nil];
_patchLine = [MAPolyline polylineWithPoints:NULL count:0];
_enablePointsReduce = YES;
_zoomLevel = 0;
_speed = 80.0*1000/3600;
_reducedPointsCache = [NSMutableDictionary dictionaryWithCapacity:20];
}
return self;
}
- (void)dealloc {
if(_origMapPoints) {
free(_origMapPoints);
}
}
- (void)setEnablePointsReduce:(BOOL)enablePointsReduce {
if(_enablePointsReduce != enablePointsReduce) {
_enablePointsReduce = enablePointsReduce;
_needRecalculateMapPoints = YES;
}
}
- (void)reset {
self.isPaused = YES;
_carIndexInOrigArray = 0;
_multiPolyline.drawStyleIndexes = nil;
_readyForDrawing = NO;
}
- (BOOL)setWithPoints:(MAMapPoint *)points count:(NSInteger)count {
if(points == NULL || count <= 0) {
if (_origMapPoints != NULL) {
free(_origMapPoints), _origMapPoints = NULL;
}
_origPointCount = 0;
[_reducedPointsCache removeAllObjects];
_needRecalculateMapPoints = YES;
[self recalculateMapPoints];
return YES;
}
MATraceReplayPoint *oldPoints = _origMapPoints;
_origMapPoints = (MATraceReplayPoint*)calloc(count, sizeof(MATraceReplayPoint));
if(_origMapPoints == NULL) {
_origMapPoints = oldPoints;
return NO;
}
_origPointCount = count;
MATraceReplayPoint *curP1 = _origMapPoints;
MAMapPoint *curP2 = points;
for(int i = 0; i < count; ++i) {
curP1->x = curP2->x;
curP1->y = curP2->y;
curP1->weight = 1;
curP1->flag = 1;
curP1++;
curP2++;
}
for(int i = 0; i < count - 1; ++i) {
MAMapPoint p1 = MAMapPointMake(_origMapPoints[i].x, _origMapPoints[i].y);
MAMapPoint p2 = MAMapPointMake(_origMapPoints[i+1].x, _origMapPoints[i+1].y);
_origMapPoints[i].distance = MAMetersBetweenMapPoints(p1, p2);
}
if(oldPoints != NULL) {
free(oldPoints);
}
[_reducedPointsCache removeAllObjects];
_needRecalculateMapPoints = YES;
[self recalculateMapPoints];
return YES;
}
- (BOOL)setWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSInteger)count {
if(coords == NULL || count <= 0) {
if (_origMapPoints != NULL) {
free(_origMapPoints), _origMapPoints = NULL;
}
_origPointCount = 0;
[_reducedPointsCache removeAllObjects];
_needRecalculateMapPoints = YES;
[self recalculateMapPoints];
return YES;
}
MATraceReplayPoint *oldPoints = _origMapPoints;
_origMapPoints = (MATraceReplayPoint*)calloc(count, sizeof(MATraceReplayPoint));
if(_origMapPoints == NULL) {
_origMapPoints = oldPoints;
return NO;
}
_origPointCount = count;
MATraceReplayPoint *curP1 = _origMapPoints;
for(int i = 0; i < count; ++i) {
MAMapPoint p = MAMapPointForCoordinate(coords[i]);
curP1->x = p.x;
curP1->y = p.y;
curP1->weight = 1;
curP1->flag = 1;
curP1++;
}
for(int i = 0; i < count - 1; ++i) {
MAMapPoint p1 = MAMapPointMake(_origMapPoints[i].x, _origMapPoints[i].y);
MAMapPoint p2 = MAMapPointMake(_origMapPoints[i+1].x, _origMapPoints[i+1].y);
_origMapPoints[i].distance = MAMetersBetweenMapPoints(p1, p2);
}
if(oldPoints != NULL) {
free(oldPoints);
}
[_reducedPointsCache removeAllObjects];
_needRecalculateMapPoints = YES;
[self recalculateMapPoints];
return YES;
}
- (void)setPointsWeight:(NSDictionary<NSNumber *,NSArray *> *)pointsWeight {
_pointsWeight = pointsWeight;
for(NSNumber *key in [pointsWeight allKeys]) {
int weight = key.intValue;
if(weight > 5 || weight < 1) {
continue;
}
NSArray *indices = [pointsWeight objectForKey:key];
for(NSNumber *index in indices) {
int i = index.intValue;
if(i < _origPointCount) {
_origMapPoints[i].weight = weight;
}
}
}
[_reducedPointsCache removeAllObjects];
_needRecalculateMapPoints = YES;
[self recalculateMapPoints];
}
- (NSInteger)getOrigPointIndexOfCar {
return _carIndexInOrigArray;
}
- (NSInteger)getReducedPointIndexOfCar {
if(!_enablePointsReduce) {
return [self getOrigPointIndexOfCar];
}
return _reducedPointIndexOfCar;
}
- (CGFloat)getRunningDirection {
return _runningDirection;
}
- (MAMapPoint)getMapPointOfIndex:(NSInteger)origIndex {
if(origIndex >= _origPointCount) {
return MAMapPointMake(0, 0);
}
return MAMapPointMake(_origMapPoints[origIndex].x, _origMapPoints[origIndex].y);
}
- (MAMapPoint)getCarPosition {
return _carMapPoint;
}
#pragma mark - overlay
- (MAMapRect)boundingMapRect {
if(_needRecalculateMapPoints) {
return MAMapRectWorld;
}
return _multiPolyline.boundingMapRect;
}
- (CLLocationCoordinate2D)coordinate {
MAMapRect boundimgMapRect = [self boundingMapRect];
return MACoordinateForMapPoint(MAMapPointMake(MAMapRectGetMidX(boundimgMapRect), MAMapRectGetMidY(boundimgMapRect)));
}
#pragma mark - addition
- (MAMultiPolyline *)getMultiPolyline {
return _multiPolyline;
}
- (MAPolyline *)getPatchPolyline {
return _patchLine;
}
- (void)drawStepWithTime:(NSTimeInterval)timeDelta zoomLevel:(CGFloat)zoomLevel {
[self setZoomLevel:zoomLevel];
BOOL hasRecalculated = [self recalculateMapPoints];
//
if(!_isPaused || !_readyForDrawing || hasRecalculated) {
if(_isPaused) {
timeDelta = 0;
}
//flag=1
NSInteger theLastIndex = _origPointCount - 1;
while(theLastIndex > 0 && _origMapPoints[theLastIndex].flag != 1) {
theLastIndex--;
}
NSInteger curIndex = _carIndexInOrigArray;
if(curIndex >= (_origPointCount - 1)) {
_carMapPoint = MAMapPointMake(_origMapPoints[theLastIndex].x, _origMapPoints[theLastIndex].y);
[_patchLine setPolylineWithPoints:NULL count:0];
_multiPolyline.drawStyleIndexes = @[@(_multiPolyline.pointCount - 1)];
_runningDirection = MAGetDirectionFromPoints(_multiPolyline.points[_multiPolyline.pointCount - 2], _multiPolyline.points[_multiPolyline.pointCount - 1]) * M_PI / 180;
self.isPaused = YES;
return;
}
double deltaDistance = _speed * timeDelta;
_accumulatedDistance += deltaDistance;
while(curIndex < _origPointCount) {
double distance = _origMapPoints[curIndex].distance;
if(_accumulatedDistance > distance) {
curIndex++;
_accumulatedDistance -= distance;
} else {
break;
}
}
_carIndexInOrigArray = curIndex;
if(curIndex >= (_origPointCount - 1)) {
_carMapPoint = MAMapPointMake(_origMapPoints[theLastIndex].x, _origMapPoints[theLastIndex].y);
[_patchLine setPolylineWithPoints:NULL count:0];
_multiPolyline.drawStyleIndexes = @[@(_multiPolyline.pointCount - 1)];
_runningDirection = MAGetDirectionFromPoints(_multiPolyline.points[_multiPolyline.pointCount - 2], _multiPolyline.points[_multiPolyline.pointCount - 1]) * M_PI / 180;
self.isPaused = YES;
return;
}
//polyline线
NSInteger prevIndex = curIndex;
NSInteger nextIndex = curIndex + 1;
while(prevIndex > 0 && _origMapPoints[prevIndex].flag != 1) {
prevIndex--;
}
while(nextIndex <= theLastIndex && _origMapPoints[nextIndex].flag != 1) {
nextIndex++;
}
//
double passedDistance = 0;
for(NSInteger i = prevIndex; i < curIndex; ++i) {
passedDistance += _origMapPoints[i].distance;
}
double totalDistance = passedDistance;
for(NSInteger i = curIndex; i < nextIndex; ++i) {
totalDistance += _origMapPoints[i].distance;
}
float ratio = (passedDistance + _accumulatedDistance) / totalDistance;
MAMapPoint p1 = MAMapPointMake(_origMapPoints[prevIndex].x, _origMapPoints[prevIndex].y);
MAMapPoint p2 = MAMapPointMake(_origMapPoints[nextIndex].x, _origMapPoints[nextIndex].y);
_carMapPoint.x = p1.x + ratio * (p2.x - p1.x);
_carMapPoint.y = p1.y + ratio * (p2.y - p1.y);
//
_runningDirection = MAGetDirectionFromPoints(MAMapPointMake(p1.x, p1.y), MAMapPointMake(p2.x, p2.y)) * M_PI / 180;
//polyline
NSInteger ret = 0;
for(int i = 0; i < prevIndex; ++i) {
if(_origMapPoints[i].flag == 1) {
ret++;
}
}
_reducedPointIndexOfCar = ret;
//polylinedrawIndex
if(_carIndexInOrigArray == 0) {
_multiPolyline.drawStyleIndexes = nil;
//patchline
[_patchLine setPolylineWithPoints:NULL count:0];
} else {
_multiPolyline.drawStyleIndexes = @[@(_reducedPointIndexOfCar + 1)];
//patchline
_patchLinePoints[0] = _carMapPoint;
_patchLinePoints[1] = p2;
[_patchLine setPolylineWithPoints:_patchLinePoints count:2];
}
}
if(!_readyForDrawing) {
_readyForDrawing = YES;
}
}
#pragma mark - private
- (void)setZoomLevel:(CGFloat)zoomLevel {
int prevZoomLevel = floor(_zoomLevel);
int currentoomLevel = floor(zoomLevel);
if(prevZoomLevel != currentoomLevel) {
_needRecalculateMapPoints = YES;
}
_zoomLevel = zoomLevel;
}
- (void)reducer_RDP:(MATraceReplayPoint *)inPoints
fromIndex:(NSInteger)fromIndex
toIndex:(NSInteger)toIndex
threshHold:(float)threshHold {
NSInteger count = toIndex - fromIndex + 1;
if(count <= 2) {
for(NSInteger i = 0; i < count; ++i) {
inPoints[i].flag = 1;
}
return;
}
double max = 0;
NSInteger index = 0;
MAMapPoint firstPoint = MAMapPointMake(inPoints[fromIndex].x, inPoints[fromIndex].y);
MAMapPoint lastPoint = MAMapPointMake(inPoints[toIndex].x, inPoints[toIndex].y);
for(NSInteger i = fromIndex; i <= toIndex; ++i) {
MAMapPoint curP = MAMapPointMake(inPoints[i].x, inPoints[i].y);
double d = MAGetDistanceFromPointToLine(curP, firstPoint, lastPoint);
if(d > max) {
index = i;
max = d;
}
}
if(max < threshHold) {
inPoints[fromIndex].flag = 1;
inPoints[toIndex].flag = 1;
} else {
[self reducer_RDP:inPoints fromIndex:fromIndex toIndex:index threshHold:threshHold];
[self reducer_RDP:inPoints fromIndex:index toIndex:toIndex threshHold:threshHold];
}
}
- (BOOL)recalculateMapPoints {
if(!_needRecalculateMapPoints) {
return NO;
}
///
if(_enablePointsReduce) {
int zoomLevel = floor(_zoomLevel);
NSNumber *key = @(zoomLevel);
NSArray *indexArray = [_reducedPointsCache objectForKey:key];
for(NSInteger i = 0; i < _origPointCount; ++i) {
_origMapPoints[i].flag = 0;
}
if(!indexArray) {
CGFloat metersPerPixel = exp2(19 - zoomLevel);
metersPerPixel = fmax(1, metersPerPixel);
[self reducer_RDP:_origMapPoints fromIndex:0 toIndex:_origPointCount - 1 threshHold:metersPerPixel];
NSMutableArray<NSNumber*> *tempArr = [NSMutableArray array];
for(NSInteger i = 0; i < _origPointCount; ++i) {
if(_origMapPoints[i].flag == 1 || _origMapPoints[i].weight == 5) {
[tempArr addObject:@(i)];
}
}
indexArray = tempArr;
[_reducedPointsCache setObject:indexArray forKey:key];
}
if (indexArray.count > 0) {
for(NSNumber *indexObj in indexArray) {
int index = indexObj.intValue;
_origMapPoints[index].flag = 1;
}
NSInteger count = indexArray.count;
MAMapPoint *p = (MAMapPoint *)malloc(sizeof(MAMapPoint) * count);
if(p) {
for(int i = 0; i < count; ++i) {
NSNumber *indexObj = [indexArray objectAtIndex:i];
int index = indexObj.intValue;
p[i].x = _origMapPoints[index].x;
p[i].y = _origMapPoints[index].y;
}
[_multiPolyline setPolylineWithPoints:p count:count drawStyleIndexes:nil];
free(p);
}
}
} else {
MAMapPoint *p = (MAMapPoint *)malloc(sizeof(MAMapPoint) * _origPointCount);
if(p) {
for(int i = 0; i < _origPointCount; ++i) {
p[i].x = _origMapPoints[i].x;
p[i].y = _origMapPoints[i].y;
}
[_multiPolyline setPolylineWithPoints:p count:_origPointCount drawStyleIndexes:nil];
free(p);
}
}
_needRecalculateMapPoints = NO;
return YES;
}
- (void)prepareAsync:(void(^)())callback {
if([NSThread isMainThread]) {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[weakSelf prepareAsync:callback];
});
} else {
for(NSInteger i = 0; i < _origPointCount; ++i) {
_origMapPoints[i].flag = 0;
}
for(int zoomLevel = 3; zoomLevel <= 20; ++zoomLevel) {
CGFloat metersPerPixel = exp2(19 - zoomLevel);
metersPerPixel = fmax(1, metersPerPixel);
[self reducer_RDP:_origMapPoints fromIndex:0 toIndex:_origPointCount - 1 threshHold:metersPerPixel];
NSMutableArray<NSNumber*> *tempArr = [NSMutableArray array];
for(NSInteger i = 0; i < _origPointCount; ++i) {
if(_origMapPoints[i].flag == 1 || _origMapPoints[i].weight == 5) {
[tempArr addObject:@(i)];
}
}
[_reducedPointsCache setObject:tempArr forKey:@(zoomLevel)];
}
dispatch_async(dispatch_get_main_queue(), ^{
if(callback) {
callback();
}
});
}
}
@end

View File

@@ -0,0 +1,22 @@
//
// MATraceReplayOverlayRender.h
// MAMapKit
//
// Created by shaobin on 2017/4/20.
// Copyright © 2017年 Amap. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AMapNaviKit/MAMapKit.h>
///轨迹回放overlay渲染器since 5.1.0
@interface MATraceReplayOverlayRenderer : MAOverlayPathRenderer
///轨迹回放图标,会沿轨迹平滑移动
@property (nonatomic, strong) UIImage *carImage;
///分段绘制的颜色,需要分段颜色绘制时数组大小必须是2第一个颜色是走过轨迹的颜色第二个颜色是未走过的
@property (nonatomic, strong) NSArray *strokeColors;
- (void)reset;
@end

View File

@@ -0,0 +1,327 @@
//
// MATraceReplayOverlayRender.m
// MAMapKit
//
// Created by shaobin on 2017/4/20.
// Copyright © 2017 Amap. All rights reserved.
//
#import "MATraceReplayOverlayRender.h"
#import "MATraceReplayOverlay.h"
#import "MATraceReplayOverlay+Addition.h"
#import <GLKit/GLKit.h>
#import <OpenGLES/ES2/gl.h>
#import <DDCategoryKit_Private/UIImage+DDCategory.h>
typedef struct _MADrawPoint {
float x;
float y;
} MADrawPoint;
@interface MATraceReplayOverlayRenderer () {
MAMultiColoredPolylineRenderer *_proxyRender;
NSTimeInterval _prevTime;
MAPolylineRenderer *_patchLineRender;
CGPoint _imageMapPoints[4];
GLuint _textureName;
GLuint _programe;
GLuint _uniform_viewMatrix_location;
GLuint _uniform_projMatrix_location;
GLuint _attribute_position_location;
GLuint _attribute_texCoord_location;
}
@end
@implementation MATraceReplayOverlayRenderer
- (id)initWithOverlay:(id<MAOverlay>)overlay {
if(![overlay isKindOfClass:[MATraceReplayOverlay class]]) {
return nil;
}
self = [super initWithOverlay:overlay];
if(self) {
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)overlay;
_proxyRender = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:[traceOverlay getMultiPolyline]];
_proxyRender.gradient = NO;
_proxyRender.strokeColors = @[[UIColor grayColor], [UIColor greenColor]];
_proxyRender.strokeColor = _proxyRender.strokeColors.lastObject;
_patchLineRender = [[MAPolylineRenderer alloc] initWithPolyline:[traceOverlay getPatchPolyline]];
_patchLineRender.strokeColor = _proxyRender.strokeColors.lastObject;
_carImage = [UIImage dd_imageNamed:@"DDMAMap/my_location" bundleName:@"DDMAMapKit_Private" aClass:[self class]];
}
return self;
}
- (void)dealloc
{
if(_textureName) {
glDeleteTextures(1, &_textureName);
_textureName = 0;
}
}
- (void)glRender
{
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)self.overlay;
CGFloat zoomLevel = [self getMapZoomLevel];
if(_prevTime == 0) {
_prevTime = CFAbsoluteTimeGetCurrent();
[traceOverlay drawStepWithTime:0 zoomLevel:zoomLevel];
} else {
NSTimeInterval curTime = CFAbsoluteTimeGetCurrent();
[traceOverlay drawStepWithTime:curTime - _prevTime zoomLevel:zoomLevel];
_prevTime = curTime;
}
if(self.carImage && [traceOverlay getMultiPolyline].pointCount > 0) {
[_proxyRender glRender];
[_patchLineRender glRender];
[self renderCarImage];
} else {
[_proxyRender glRender];
}
}
- (void)setRendererDelegate:(id<MAOverlayRenderDelegate>)rendererDelegate {
[super setRendererDelegate:rendererDelegate];
_proxyRender.rendererDelegate = rendererDelegate;
_patchLineRender.rendererDelegate = rendererDelegate;
}
- (void)setLineWidth:(CGFloat)lineWidth {
[super setLineWidth:lineWidth];
_proxyRender.lineWidth = lineWidth;
_patchLineRender.lineWidth = lineWidth;
}
- (void)setStrokeColors:(NSArray *)strokeColors {
if(strokeColors.count != 2) {
return;
}
_proxyRender.strokeColors = strokeColors;
if(strokeColors.count > 0) {
_proxyRender.strokeColor = strokeColors.lastObject;
_patchLineRender.strokeColor = strokeColors.lastObject;
}
}
- (NSArray *)strokeColors {
return _proxyRender.strokeColors;
}
- (void)setStrokeColor:(UIColor *)strokeColor {
[super setStrokeColor:strokeColor];
[_proxyRender setStrokeColor:strokeColor];
[_patchLineRender setStrokeColor:strokeColor];
}
- (UIColor *)strokeColor {
return _proxyRender.strokeColor;
}
- (void)reset {
_prevTime = 0;
}
- (void)renderCarImage {
if(_textureName == 0) {
NSError *error = nil;
GLKTextureInfo *texInfo = [GLKTextureLoader textureWithCGImage:self.carImage.CGImage options:nil error:&error];
_textureName = texInfo.name;
}
if(_programe == 0) {
_programe = [self loadGLESPrograme];
}
if(_textureName == 0 || _programe == 0) {
return;
}
MATraceReplayOverlay *traceOverlay = (MATraceReplayOverlay*)self.overlay;
MAMapPoint carPoint = [traceOverlay getCarPosition];
CLLocationDirection rotate = [traceOverlay getRunningDirection];
double zoomLevel = [self getMapZoomLevel];
double zoomScale = pow(2, zoomLevel);
CGSize imageSize = self.carImage.size;
double halfWidth = imageSize.width * (1 << 20) / zoomScale/2;
double halfHeight = imageSize.height * (1 << 20) / zoomScale/2;
_imageMapPoints[0].x = -halfWidth;
_imageMapPoints[0].y = halfHeight;
_imageMapPoints[1].x = halfWidth;
_imageMapPoints[1].y = halfHeight;
_imageMapPoints[2].x = halfWidth;
_imageMapPoints[2].y = -halfHeight;
_imageMapPoints[3].x = -halfWidth;
_imageMapPoints[3].y = -halfHeight;
MADrawPoint points[4] = { 0 };
for(int i = 0; i < 4; ++i) {
CGPoint tempPoint = _imageMapPoints[i];
if(traceOverlay.enableAutoCarDirection) {
tempPoint = CGPointApplyAffineTransform(_imageMapPoints[i], CGAffineTransformMakeRotation(rotate));
}
tempPoint.x += carPoint.x;
tempPoint.y += carPoint.y;
CGPoint p = [self glPointForMapPoint:MAMapPointMake(tempPoint.x, tempPoint.y)];
points[i].x = p.x;
points[i].y = p.y;
}
float *viewMatrix = [self getViewMatrix];
float *projectionMatrix = [self getProjectionMatrix];
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);//alpha
glUseProgram(_programe);
glBindTexture(GL_TEXTURE_2D, _textureName);
//glUseProgram(shaderToUse.programName);
glEnableVertexAttribArray(_attribute_position_location);
glEnableVertexAttribArray(_attribute_texCoord_location);
glUniformMatrix4fv(_uniform_viewMatrix_location, 1, false, viewMatrix);
glUniformMatrix4fv(_uniform_projMatrix_location, 1, false, projectionMatrix);
MADrawPoint textureCoords[4] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};
glVertexAttribPointer(_attribute_position_location, 2, GL_FLOAT, false, sizeof(MADrawPoint), &(points[0]));
glVertexAttribPointer(_attribute_texCoord_location, 2, GL_FLOAT, false, sizeof(MADrawPoint), &(textureCoords[0]));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(_attribute_position_location);
glDisableVertexAttribArray(_attribute_texCoord_location);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glUseProgram(0);
}
- (GLuint)loadGLESPrograme {
NSString *vertexShaderSrc = @"precision highp float;\n\
attribute vec2 attrVertex;\n\
attribute vec2 attrTextureCoord;\n\
uniform mat4 inViewMatrix;\n\
uniform mat4 inProjMatrix;\n\
varying vec2 textureCoord;\n\
void main(){\n\
gl_Position = inProjMatrix * inViewMatrix * (vec4(attrVertex, 1.0, 1.0));\n\
textureCoord = attrTextureCoord;\n\
}";
NSString *fragShaderSrc = @"precision highp float;\n\
varying vec2 textureCoord;\n\
uniform sampler2D inTextureUnit;\n\
void main(){\n\
gl_FragColor = texture2D(inTextureUnit, textureCoord);\n\
}";
GLuint prgName = 0;
prgName = glCreateProgram();
if(prgName <= 0) {
return 0;
}
GLint logLength = 0, status = 0;
//////////////////////////////////////
// Specify and compile VertexShader //
//////////////////////////////////////
const GLchar* vertexShaderSrcStr = (const GLchar*)[vertexShaderSrc UTF8String];
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const GLchar **)&(vertexShaderSrcStr), NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*) malloc(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, log);
NSLog(@"Vtx Shader compile log:%s\n", log);
free(log);
}
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if (status == 0) {
NSLog(@"Failed to compile vtx shader:\n%s\n", vertexShaderSrcStr);
return 0;
}
glAttachShader(prgName, vertexShader);
glDeleteShader(vertexShader);
/////////////////////////////////////////
// Specify and compile Fragment Shader //
/////////////////////////////////////////
const GLchar* fragmentShaderSrcStr = (const GLchar*)[fragShaderSrc UTF8String];
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, (const GLchar **)&(fragmentShaderSrcStr), NULL);
glCompileShader(fragShader);
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetShaderInfoLog(fragShader, logLength, &logLength, log);
NSLog(@"Frag Shader compile log:\n%s\n", log);
free(log);
}
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &status);
if (status == 0) {
NSLog(@"Failed to compile frag shader:\n%s\n", fragmentShaderSrcStr);
return 0;
}
glAttachShader(prgName, fragShader);
glDeleteShader(fragShader);
//////////////////////
// Link the program //
//////////////////////
glLinkProgram(prgName);
glGetProgramiv(prgName, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar*)malloc(logLength);
glGetProgramInfoLog(prgName, logLength, &logLength, log);
NSLog(@"Program link log:\n%s\n", log);
free(log);
}
glGetProgramiv(prgName, GL_LINK_STATUS, &status);
if (status == 0) {
NSLog(@"Failed to link program");
return 0;
}
_uniform_viewMatrix_location = glGetUniformLocation(prgName, "inViewMatrix");
_uniform_projMatrix_location = glGetUniformLocation(prgName, "inProjMatrix");
_attribute_position_location = glGetAttribLocation(prgName, "attrVertex");
_attribute_texCoord_location = glGetAttribLocation(prgName, "attrTextureCoord");
return prgName;
}
@end

View File

@@ -0,0 +1,26 @@
//
// DDMANaviManager.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/3/16.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
struct CLLocationCoordinate2D;
@interface DDMANaviManager : NSObject
+ (instancetype)shareManager;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
// 请在使用该类前先设置appkey
+ (void)startWithAppKey:(nullable NSString *)appKey;
// 在创建该类实例前调用
+ (void)agreePrivacy;
- (void)presentRoutePlanViewControllerFromCoordinate:(CLLocationCoordinate2D)fromCoordinate fromName:(nullable NSString *)fromName fromPOIId:(nullable NSString *)fromPOIId toCoordinate:(CLLocationCoordinate2D)toCoordinate toName:(nullable NSString *)toName toPOIId:(nullable NSString *)toPOIId;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,69 @@
//
// DDMANaviManager.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/3/16.
#import "DDMANaviManager.h"
#import <AMapNaviKit/AMapNaviKit.h>
@interface DDMANaviManager ()
@property (nonatomic, strong)AMapNaviCompositeManager *compositeManager;
@end
@implementation DDMANaviManager
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
[[AMapServices sharedServices] setEnableHTTPS:YES];
[AMapServices sharedServices].apiKey = appKey;
}
+ (void)agreePrivacy{
[MAMapView updatePrivacyShow:AMapPrivacyShowStatusDidShow privacyInfo:AMapPrivacyInfoStatusDidContain];
[MAMapView updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
}
+ (instancetype)shareManager{
static DDMANaviManager *_Nullable _manager = nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
_manager = [[self alloc] initWithSuper];
});
return _manager;
}
- (instancetype)initWithSuper{
self = [super init];
if (self == nil) return nil;
return self;
}
- (instancetype)init{
@throw [[NSException alloc] initWithName:NSGenericException reason:@"'init' is unavailable,please use 'shareManager' instead." userInfo:nil];
}
// MARK: <Func>
- (AMapNaviCompositeManager *)compositeManager{
if (!_compositeManager) {
_compositeManager = [[AMapNaviCompositeManager alloc] init];
}
return _compositeManager;
}
- (void)presentRoutePlanViewControllerFromCoordinate:(CLLocationCoordinate2D)fromCoordinate fromName:(nullable NSString *)fromName fromPOIId:(nullable NSString *)fromPOIId toCoordinate:(CLLocationCoordinate2D)toCoordinate toName:(nullable NSString *)toName toPOIId:(nullable NSString *)toPOIId {
// since 5.2.0
AMapNaviCompositeUserConfig *config = [[AMapNaviCompositeUserConfig alloc] init];
//POIId
[config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeStart location:[AMapNaviPoint locationWithLatitude:fromCoordinate.latitude longitude:fromCoordinate.longitude] name:fromName POIId:fromPOIId];
//POIId
[config setRoutePlanPOIType:AMapNaviRoutePlanPOITypeEnd location:[AMapNaviPoint locationWithLatitude:toCoordinate.latitude longitude:toCoordinate.longitude] name:toName POIId:toPOIId];
//
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf.compositeManager presentRoutePlanViewControllerWithOptions:config];
});
}
@end

View File

@@ -0,0 +1,63 @@
//
// DDMASearch.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/30.
#import <Foundation/Foundation.h>
#import <AMapSearchKit/AMapSearchKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, MASearchType) {
kMASearchNone = 1 << 0,
kMASearchPOIKeywords = 1 << 1,
kMASearchPOIAround = 1 << 2,
kMASearchInputTips = 1 << 3,
kMASearchGeocode = 1 << 4,
kMASearchReGeocode = 1 << 5,
kMASearchDrivingCalRoute = 1 << 6,
kMASearchRidingRoute = 1 << 7,
};
@class AMapSearchObject;
@interface DDMASearch : NSObject
// 申请高德appKey,先设置appKey才能使用search功能
+ (void)startWithAppKey:(nullable NSString *)appKey;
// 创建该类实例前先同意
+ (void)agreePrivacy;
@property (nonatomic, strong)AMapSearchObject *searchOption;
@property (nonatomic, copy)void(^onRequestFailed)(id request,NSError *error);
@property (nonatomic, copy)void(^onResponseDone)(id request,id response);
- (void)refresh;
- (void)loadMore;
@end
typedef NS_ENUM(NSUInteger, MADriveSearchType) {
kMADriveSearchPolyline,
kMADriveSearchCost
};
@interface DDMASearch (Route)
typedef NSDictionary *DDMACoordinate NS_TYPED_EXTENSIBLE_ENUM;
typedef NSString *DDMACoordinateKey NS_TYPED_EXTENSIBLE_ENUM;
FOUNDATION_EXTERN DDMACoordinateKey const DDMACoords;// DDMACoordinate[DDMACoords] get coords
FOUNDATION_EXTERN DDMACoordinateKey const DDMACoordsCount; // DDMACoordinate[DDMACoordsCount] get count
FOUNDATION_EXTERN DDMACoordinateKey const DDMALocations;// DDMACoordinate[DDMACoords] get coords
// 返回驾驶的route
+ (AMapSearchObject *)drivingCalRouteSearchRequestWithOrigin:(CLLocationCoordinate2D)origin destination:(CLLocationCoordinate2D)destination strategy:(NSInteger)strategy type:(MADriveSearchType)type;
// 返回骑行的route
+ (AMapSearchObject *)ridingRouteSearchRequestWithOrigin:(CLLocationCoordinate2D)origin destination:(CLLocationCoordinate2D)destination;
// 返回一个包含DDMACoordinate的数组DDMACoordinate里有coordinates数据和count利用DDMACoordinateKey去取
+ (NSArray<DDMACoordinate> *)coordsArrayWithRouteSearchResponse:(AMapRouteSearchResponse *)routeSearchResponse;
+ (NSMutableArray<NSMutableArray<CLLocation *> *> *)locationsArrayWithRouteSearchResponse:(AMapRouteSearchResponse *)routeSearchResponse;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,270 @@
//
// DDMASearch.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/1/30.
#import "DDMASearch.h"
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <CoreLocation/CoreLocation.h>
@interface DDMASearch ()<AMapSearchDelegate>
@property (nonatomic, strong)AMapSearchAPI *search;
@property (nonatomic, assign)MASearchType searchType;
@end
@implementation DDMASearch
static NSString *const requestKey = @"request";
static NSString *const responseKey = @"response";
static NSString *const errorKey = @"error";
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
[[AMapServices sharedServices] setEnableHTTPS:YES];
[AMapServices sharedServices].apiKey = appKey;
}
+ (void)agreePrivacy{
[AMapSearchAPI updatePrivacyShow:AMapPrivacyShowStatusDidShow privacyInfo:AMapPrivacyInfoStatusDidContain];
[AMapSearchAPI updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
}
// MARK: <Init>
- (instancetype)init{
self = [super init];
if (self == nil) return nil;
return self;
}
// MARK: <Function>
- (void)setSearchOption:(AMapSearchObject *)searchOption{
_searchOption = searchOption;
MASearchType currentSearchType = kMASearchNone;
if ([searchOption isMemberOfClass:[AMapPOIKeywordsSearchRequest class]]) {
currentSearchType = kMASearchPOIKeywords;
}else if ([searchOption isMemberOfClass:[AMapPOIAroundSearchRequest class]]){
currentSearchType = kMASearchPOIAround;
}else if ([searchOption isMemberOfClass:[AMapInputTipsSearchRequest class]]){
currentSearchType = kMASearchInputTips;
}else if ([searchOption isMemberOfClass:[AMapGeocodeSearchRequest class]]){
currentSearchType = kMASearchGeocode;
}else if ([searchOption isMemberOfClass:[AMapReGeocodeSearchRequest class]]){
currentSearchType = kMASearchReGeocode;
}else if ([searchOption isMemberOfClass:[AMapDrivingCalRouteSearchRequest class]]){
currentSearchType = kMASearchDrivingCalRoute;
}else if ([searchOption isMemberOfClass:[AMapRidingRouteSearchRequest class]]){
currentSearchType = kMASearchRidingRoute;
}
self.searchType = currentSearchType;
}
- (void)refresh{
if (self.searchOption == nil) {
return;
}
// [self performSelector:@selector(refreshInSearchThread:) onThread:self.searchThread withObject:self.searchOption waitUntilDone:NO];
[self refreshInSearchThread:self.searchOption];
}
- (void)refreshInSearchThread:(AMapSearchObject *)searchOption{
// bool isUnlock = os_unfair_lock_trylock(&_requestLock);
// if (!isUnlock) return;
if (self.searchType & kMASearchPOIKeywords) {
AMapPOIKeywordsSearchRequest *POIKeywordsSearchRequest = (AMapPOIKeywordsSearchRequest *)self.searchOption;
POIKeywordsSearchRequest.page = 1;
[self.search AMapPOIKeywordsSearch:POIKeywordsSearchRequest];
}else if (self.searchType & kMASearchPOIAround){
AMapPOIAroundSearchRequest *POIAroundSearchRequest = (AMapPOIAroundSearchRequest *)self.searchOption;
POIAroundSearchRequest.page = 1;
[self.search AMapPOIAroundSearch:POIAroundSearchRequest];
}else if (self.searchType & kMASearchInputTips){
[self.search AMapInputTipsSearch:(AMapInputTipsSearchRequest *)self.searchOption];
}else if (self.searchType & kMASearchGeocode){
[self.search AMapGeocodeSearch:(AMapGeocodeSearchRequest *)self.searchOption];
}else if (self.searchType & kMASearchReGeocode){
[self.search AMapReGoecodeSearch:(AMapReGeocodeSearchRequest *)self.searchOption];
}else if (self.searchType & kMASearchDrivingCalRoute){
[self.search AMapDrivingV2RouteSearch:(AMapDrivingCalRouteSearchRequest *)self.searchOption];
}else if (self.searchType & kMASearchRidingRoute){
[self.search AMapRidingRouteSearch:(AMapRidingRouteSearchRequest *)self.searchOption];
}
}
- (void)loadMore{
if (self.searchOption == nil) {
return;
}
// [self performSelector:@selector(loadMoreInSearchThread:) onThread:self.searchThread withObject:self.searchOption waitUntilDone:NO];
[self loadMoreInSearchThread:self.searchOption];
}
- (void)loadMoreInSearchThread:(AMapSearchObject *)searchOption{
// bool isUnlock = os_unfair_lock_trylock(&_requestLock);
// if (!isUnlock) return;
if (self.searchType & kMASearchPOIKeywords) {
AMapPOIKeywordsSearchRequest *POIKeywordsSearchRequest = (AMapPOIKeywordsSearchRequest *)self.searchOption;
POIKeywordsSearchRequest.page++;
[self.search AMapPOIKeywordsSearch:POIKeywordsSearchRequest];
}else if (self.searchType & kMASearchPOIAround){
AMapPOIAroundSearchRequest *POIAroundSearchRequest = (AMapPOIAroundSearchRequest *)self.searchOption;
POIAroundSearchRequest.page++;
[self.search AMapPOIAroundSearch:POIAroundSearchRequest];
}else{
return;
}
}
- (void)onRequestFailedInSearchThread:(NSDictionary *)dict{
if (self.onRequestFailed) {
self.onRequestFailed(dict[requestKey], dict[errorKey]);
}
// os_unfair_lock_unlock(&_requestLock);
}
- (void)onResponseInSearchThread:(NSDictionary *)dict{
if (self.onResponseDone) {
self.onResponseDone(dict[requestKey], dict[responseKey]);
}
// os_unfair_lock_unlock(&_requestLock);
}
// MARK: <AMapSearchDelegate>
- (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[errorKey] = error;
// [self performSelector:@selector(onRequestFailedInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onRequestFailedInSearchThread:dict];
}
- (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[responseKey] = response;
// [self performSelector:@selector(onResponseInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onResponseInSearchThread:dict];
}
- (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[responseKey] = response;
// [self performSelector:@selector(onResponseInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onResponseInSearchThread:dict];
}
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[responseKey] = response;
// [self performSelector:@selector(onResponseInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onResponseInSearchThread:dict];
}
- (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[responseKey] = response;
// [self performSelector:@selector(onResponseInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onResponseInSearchThread:dict];
}
- (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[requestKey] = request;
dict[responseKey] = response;
// [self performSelector:@selector(onResponseInSearchThread:) onThread:self.searchThread withObject:dict waitUntilDone:NO];
[self onResponseInSearchThread:dict];
}
// MARK: <Lazy>
- (AMapSearchAPI *)search{
if (_search == nil) {
_search = [[AMapSearchAPI alloc] init];
_search.delegate = self;
}
return _search;
}
@end
@implementation DDMASearch (Route)
DDMACoordinateKey const DDMACoords = @"coords";
DDMACoordinateKey const DDMACoordsCount = @"coordsCount";
DDMACoordinateKey const DDMALocations = @"locations";
+ (AMapSearchObject *)drivingCalRouteSearchRequestWithOrigin:(CLLocationCoordinate2D)origin destination:(CLLocationCoordinate2D)destination strategy:(NSInteger)strategy type:(MADriveSearchType)type {
AMapDrivingCalRouteSearchRequest *request = [[AMapDrivingCalRouteSearchRequest alloc] init];
if (type == kMADriveSearchPolyline) {
request.showFieldType = AMapDrivingRouteShowFieldTypePolyline;
}else if (type == kMADriveSearchCost){
request.showFieldType = AMapDrivingRouteShowFieldTypeCost;
}
request.strategy = strategy;
request.origin = [AMapGeoPoint locationWithLatitude:origin.latitude
longitude:origin.longitude];
request.destination = [AMapGeoPoint locationWithLatitude:destination.latitude
longitude:destination.longitude];
return request;
}
+ (AMapSearchObject *)ridingRouteSearchRequestWithOrigin:(CLLocationCoordinate2D)origin destination:(CLLocationCoordinate2D)destination{
AMapRidingRouteSearchRequest *request = [[AMapRidingRouteSearchRequest alloc] init];
request.showFieldsType = AMapRidingRouteShowFieldsTypeAll;
request.origin = [AMapGeoPoint locationWithLatitude:origin.latitude
longitude:origin.longitude];
request.destination = [AMapGeoPoint locationWithLatitude:destination.latitude
longitude:destination.longitude];
return request;
}
+ (NSMutableArray<DDMACoordinate> *)coordsArrayWithRouteSearchResponse:(AMapRouteSearchResponse *)routeSearchResponse{
NSMutableArray<NSDictionary *> *coordinateArr = [NSMutableArray array];
[routeSearchResponse.route.paths enumerateObjectsUsingBlock:^(AMapPath * _Nonnull aMapPath, NSUInteger idx, BOOL * _Nonnull stop) {
NSMutableArray *coorArray = [NSMutableArray array];
[aMapPath.steps enumerateObjectsUsingBlock:^(AMapStep * _Nonnull step, NSUInteger idx, BOOL * _Nonnull stop) {
[coorArray addObjectsFromArray:[step.polyline componentsSeparatedByString:@";"]];
}];
CLLocationCoordinate2D *coords = new CLLocationCoordinate2D[coorArray.count];
[coorArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSArray *coordinate = [obj componentsSeparatedByString:@","];
coords[idx].latitude = [coordinate.lastObject floatValue];
coords[idx].longitude = [coordinate.firstObject floatValue];
}];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[DDMACoordsCount] = @(coorArray.count);
dict[DDMACoords] = [NSValue valueWithPointer:coords];
[coordinateArr addObject:dict];
}];
return coordinateArr;
}
+ (NSMutableArray<NSMutableArray<CLLocation *> *> *)locationsArrayWithRouteSearchResponse:(AMapRouteSearchResponse *)routeSearchResponse{
NSMutableArray<NSMutableArray<CLLocation *> *> *coordinateArr = [NSMutableArray array];
[routeSearchResponse.route.paths enumerateObjectsUsingBlock:^(AMapPath * _Nonnull aMapPath, NSUInteger idx, BOOL * _Nonnull stop) {
NSMutableArray *coorArray = [NSMutableArray array];
[aMapPath.steps enumerateObjectsUsingBlock:^(AMapStep * _Nonnull step, NSUInteger idx, BOOL * _Nonnull stop) {
[coorArray addObjectsFromArray:[step.polyline componentsSeparatedByString:@";"]];
}];
NSMutableArray<CLLocation *> *locations = [NSMutableArray array];
[coorArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSArray *coordinate = [obj componentsSeparatedByString:@","];
[locations addObject:[[CLLocation alloc] initWithLatitude:[coordinate.lastObject floatValue] longitude:[coordinate.firstObject floatValue]]];
}];
[coordinateArr addObject:locations];
}];
return coordinateArr;
}
@end

View File

@@ -0,0 +1,92 @@
//
// DDMATrackManager.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/3/5.
#import <Foundation/Foundation.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <AMapTrackKit/AMapTrackKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface DDMATrackManager : NSObject
+ (instancetype)shareManager;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
+ (void)startWithAppKey:(nullable NSString *)appKey;
@property (nonatomic, copy)NSString *serviceID; // 初始化猎鹰服务前必须设置服务id
@property (nonatomic, copy)NSString *fullAccuracyPurpose; // 初始化猎鹰服务前必须设置
@property (nonatomic, copy)NSString *terminalID; // 启动服务前必须设置设备id
@property (nonatomic, copy)NSString *terminalName; // 这应该是一个唯一的名字利用它来获取terminalID
@property (nonatomic, copy,nullable)NSString *trackID; // 当轨迹id存在时上报服务回保存在trackID中否则将以散点形式上报
@property (nonatomic, assign)BOOL isServing; // 是否已开启服务
@property (nonatomic, assign)BOOL isGathering; // 是否已开启采集
// 初始化猎鹰服务
- (void)initTraceService;
/**
* @brief 设定定位信息的采集周期和上传周期,注意:上传周期必须为采集周期的整数倍
* @param gatherTimeInterval 定位信息的采集周期,单位秒,有效值范围[1, 60]
* @param packTimeInterval 定位信息的上传周期,单位秒,有效值范围[5, 3000]
*/
- (void)changeGatherAndPackTimeInterval:(NSInteger)gatherTimeInterval packTimeInterval:(NSInteger)packTimeInterval;
/**
* @brief 设定允许的本地缓存最大值
* @param cacheMaxSize 本地缓存最大值单位MB默认+∞,有效值范围[50,+∞)。
* @return 是否设定成功
*/
- (BOOL)setLocalCacheMaxSize:(NSInteger)cacheMaxSize;
//查询终端是否存在
/// @warning 开始上报前先创建terminal可以拿到terminalID
- (void)queryTerminal:(NSString *)terminalName;
// 创建轨迹
/// @warning 开始上报到指定轨迹前先创建track可以拿到trackID
- (void)addTrackID;
/// 启动猎鹰服务,不建议直接开启服务,应该使'- (void)queryTerminal:(NSString *)terminalName'方法来开启服务
/// @warning serviceID,terminalID必不可少而trackID是指定轨迹时才需要
- (void)startService;
// 关闭猎鹰服务
- (void)stopService;
// 开启采集服务
- (void)startGatherAndPack;
// 关闭采集服务
- (void)stopGatherAndPack;
// 创建轨迹成功的回调
@property (nonatomic, copy,nullable)void(^addTrackOnDone)(AMapTrackAddTrackRequest *request,AMapTrackAddTrackResponse *response);
// 开始服务的回调
@property (nonatomic, copy,nullable)void(^startServiceOnDone)(AMapTrackErrorCode error);
// 关闭服务的回调
@property (nonatomic, copy,nullable)void(^stopServiceOnDone)(AMapTrackErrorCode error);
// 开始采集的回调
@property (nonatomic, copy,nullable)void(^startGatherAndPackOnDone)(AMapTrackErrorCode error);
// 关闭采集的回调
@property (nonatomic, copy,nullable)void(^stopGatherAndPackOnDone)(AMapTrackErrorCode error);
// query失败回调
@property (nonatomic, copy,nullable)void(^queryFailWithErrorOnDone)(NSError *error,id request);
// 查询设备位置,queryLastPointOnDone回调
- (void)queryLastPointWith:(nullable NSString *)trackID;
@property (nonatomic, copy,nullable)void(^queryLastPointOnDone)(AMapTrackQueryLastPointRequest *request,AMapTrackQueryLastPointResponse *response);
// 查询设备一段时间内的行驶里程,queryTrackDistanceOnDone回调
- (void)queryTrackDistanceWith:(long long)startTime endTime:(long long)endTime trackID:(nullable NSString *)trackID;
@property (nonatomic, copy,nullable)void(^queryTrackDistanceOnDone)(AMapTrackQueryTrackDistanceRequest *request,AMapTrackQueryTrackDistanceResponse *response);
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,315 @@
//
// DDMATrackManager.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/3/5.
#import "DDMATrackManager.h"
#import <DDLogKit_Private/DDOCLog.h>
@interface DDMATrackManager ()<AMapTrackManagerDelegate>
@property (nonatomic, strong)AMapTrackManager *trackManager;
@end
@implementation DDMATrackManager
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
[[AMapServices sharedServices] setEnableHTTPS:YES];
[AMapServices sharedServices].apiKey = appKey;
}
+ (instancetype)shareManager{
static DDMATrackManager *_Nullable _manager = nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
_manager = [[self alloc] initWithSuper];
});
return _manager;
}
- (instancetype)initWithSuper{
self = [super init];
if (self == nil) return nil;
return self;
}
- (instancetype)init{
@throw [[NSException alloc] initWithName:NSGenericException reason:@"'init' is unavailable,please use 'shareManager' instead." userInfo:nil];
}
// MARK: <Start Service>
- (void)initTraceService{
NSAssert(self.serviceID != nil, @"猎鹰serviceID = nil");
NSAssert(self.fullAccuracyPurpose != nil, @"请设置fullAccuracyPurpose的值");
if (self.serviceID == nil) {
return;
}
if (self.fullAccuracyPurpose == nil) {
return;
}
AMapTrackManagerOptions *option = [[AMapTrackManagerOptions alloc] init];
option.serviceID = self.serviceID; //Service ID
//AMapTrackManager
self.trackManager = [[AMapTrackManager alloc] initWithOptions:option];
self.trackManager.delegate = self;
[self.trackManager setPausesLocationUpdatesAutomatically:NO];
}
//
- (void)queryTerminal:(NSString *)terminalName{
AMapTrackQueryTerminalRequest *request = [[AMapTrackQueryTerminalRequest alloc] init];
request.serviceID = self.serviceID;
request.terminalName = terminalName;
[self.trackManager AMapTrackQueryTerminal:request];
}
//
- (void)onQueryTerminalDone:(AMapTrackQueryTerminalRequest *)request response:(AMapTrackQueryTerminalResponse *)response
{
//
if ([[response terminals] count] > 0) {
//使 Terminal ID
NSString *terminalID = [[[response terminals] firstObject] tid];
DDLog(@"--------------------------------LBS查询终端成功,terminalID = %@--------------------------------\n--------------------------------准备启动服务--------------------------------",terminalID);
//(service id)
self.terminalID = terminalID;
[self startService];
}
else {
DDLog(@"--------------------------------LBS查询终端为空--------------------------------\n--------------------------------准备创建终端--------------------------------");
//terminal
[self addTerminal:request.terminalName];
}
}
//
- (void)addTerminal:(NSString *)terminalName{
AMapTrackAddTerminalRequest *addRequest = [[AMapTrackAddTerminalRequest alloc] init];
addRequest.serviceID = self.trackManager.serviceID;
addRequest.terminalName = terminalName;
[self.trackManager AMapTrackAddTerminal:addRequest];
}
//
- (void)onAddTerminalDone:(AMapTrackAddTerminalRequest *)request response:(AMapTrackAddTerminalResponse *)response {
DDLog(@"--------------------------------LBS创建终端成功--------------------------------\n--------------------------------准备开启服务--------------------------------");
//terminal
NSString *terminalID = [response terminalID];
//(service id)
self.terminalID = terminalID;
[self startService];
}
//
- (void)didFailWithError:(NSError *)error associatedRequest:(id)request {
if ([request isKindOfClass:[AMapTrackQueryTerminalRequest class]]) {
//
DDLog(@"--------------------------------LBS查询终端失败--------------------------------");
}
if ([request isKindOfClass:[AMapTrackAddTerminalRequest class]]) {
//terminal
DDLog(@"--------------------------------LBS创建终端失败--------------------------------");
}
if ([request isKindOfClass:[AMapTrackAddTrackRequest class]]) {
//
DDLog(@"--------------------------------LBS创建轨迹失败--------------------------------");
}
if ([request isKindOfClass:[AMapTrackQueryLastPointRequest class]]) {
//
DDLog(@"--------------------------------LBS查询最后位置失败--------------------------------");
}
if ([request isKindOfClass:[AMapTrackQueryTrackDistanceRequest class]]) {
//
DDLog(@"--------------------------------LBS查询距离失败--------------------------------");
}
if (self.queryFailWithErrorOnDone) {
self.queryFailWithErrorOnDone(error, request);
}
}
//
- (void)addTrackID{
AMapTrackAddTrackRequest *request = [[AMapTrackAddTrackRequest alloc] init];
request.serviceID = self.trackManager.serviceID;
request.terminalID = self.trackManager.terminalID;
[self.trackManager AMapTrackAddTrack:request];
}
- (void)onAddTrackDone:(AMapTrackAddTrackRequest *)request response:(AMapTrackAddTrackResponse *)response
{
//
self.trackID = response.trackID;
DDLog(@"---------------------------------创建轨迹成功----------------------------------")
if (self.addTrackOnDone != nil) {
self.addTrackOnDone(request, response);
}
}
- (void)startService{
if (self.isServing == false) {
//
[self.trackManager setAllowsBackgroundLocationUpdates:YES];
AMapTrackManagerServiceOption *serviceOption = [[AMapTrackManagerServiceOption alloc] init];
serviceOption.terminalID = self.terminalID;//Terminal ID
[self.trackManager startServiceWithOptions:serviceOption];
}
}
- (void)stopService{
if (self.isServing == true) {
[self.trackManager stopService];
}
}
- (void)startGatherAndPack{
if (self.trackID != nil) {
self.trackManager.trackID = self.trackID;
NSLog(@"轨迹id---------------%@",self.trackID);
DDLog(@"---------------------------------设置轨迹成功----------------------------------")
}
[self.trackManager startGatherAndPack];
}
- (void)stopGatherAndPack{
[self.trackManager stopGaterAndPack];
}
//service
- (void)onStartService:(AMapTrackErrorCode)errorCode {
if (errorCode == AMapTrackErrorOK) {
DDLog("--------------------------------开启猎鹰服务成功--------------------------------\n--------------------------------准备采集--------------------------------");
//
self.isServing = YES;
} else {
//
DDLog("--------------------------------开启猎鹰服务失败--%ld",errorCode);
}
if (self.startServiceOnDone) {
self.startServiceOnDone(errorCode);
}
}
//
- (void)onStopService:(AMapTrackErrorCode)errorCode {
if (errorCode == AMapTrackErrorOK) {
//
self.isServing = false;
DDLog(@"--------------------------------关闭猎鹰服务成功--------------------------------");
} else {
//
DDLog(@"--------------------------------关闭猎鹰服务失败--------------------------------");
}
if (self.stopServiceOnDone) {
self.stopServiceOnDone(errorCode);
}
}
//gather
- (void)onStartGatherAndPack:(AMapTrackErrorCode)errorCode {
if (errorCode == AMapTrackErrorOK) {
//
self.isGathering = YES;
DDLog(@"--------------------------------开始猎鹰采集成功--------------------------------");
} else {
//
DDLog(@"--------------------------------开始猎鹰采集失败--------------------------------");
}
if (self.startGatherAndPackOnDone) {
self.startGatherAndPackOnDone(errorCode);
}
}
//
- (void)onStopGatherAndPack:(AMapTrackErrorCode)errorCode {
if (errorCode == AMapTrackErrorOK) {
//
self.isGathering = NO;
DDLog(@"--------------------------------关闭猎鹰采集成功--------------------------------");
} else {
//
DDLog(@"--------------------------------关闭猎鹰采集失败--------------------------------");
}
if (self.stopGatherAndPackOnDone) {
self.stopGatherAndPackOnDone(errorCode);
}
}
//
- (void)queryLastPointWith:(nullable NSString *)trackID{
AMapTrackQueryLastPointRequest *request = [[AMapTrackQueryLastPointRequest alloc] init];
request.serviceID = self.trackManager.serviceID;
request.terminalID = self.trackManager.terminalID;
if (trackID != nil) {
request.trackID = trackID;
}
[self.trackManager AMapTrackQueryLastPoint:request];
}
//
- (void)onQueryLastPointDone:(AMapTrackQueryLastPointRequest *)request response:(AMapTrackQueryLastPointResponse *)response
{
if (self.queryLastPointOnDone != nil) {
self.queryLastPointOnDone(request,response);
}
}
- (void)queryTrackDistanceWith:(long long)startTime endTime:(long long)endTime trackID:(nullable NSString *)trackID{
AMapTrackQueryTrackDistanceRequest *request = [[AMapTrackQueryTrackDistanceRequest alloc] init];
request.serviceID = self.trackManager.serviceID;
request.terminalID = self.trackManager.terminalID;
request.startTime = startTime;
request.endTime = endTime;
request.correctionMode = @"driving";
if (trackID != nil) {
request.trackID = self.trackManager.trackID;
}
DDLog(@"--------------------------------当前猎鹰查询distance:\n起始时间:%lld\n结束时间:%lld--------------------------------",startTime,endTime);
[self.trackManager AMapTrackQueryTrackDistance:request];
}
- (void)onQueryTrackDistanceDone:(AMapTrackQueryTrackDistanceRequest *)request response:(AMapTrackQueryTrackDistanceResponse *)response
{
//
NSLog(@"--------------------------------onQueryTrackDistanceDone%@--------------------------------", response.formattedDescription);
if (self.queryTrackDistanceOnDone != nil) {
DDLog(@"--------------------------------当前猎鹰查询distance:%lu--------------------------------",(unsigned long)response.distance);
self.queryTrackDistanceOnDone(request, response);
}
}
- (void)changeGatherAndPackTimeInterval:(NSInteger)gatherTimeInterval packTimeInterval:(NSInteger)packTimeInterval{
[self.trackManager changeGatherAndPackTimeInterval:gatherTimeInterval packTimeInterval:packTimeInterval];
}
- (BOOL)setLocalCacheMaxSize:(NSInteger)cacheMaxSize{
return [self.trackManager setLocalCacheMaxSize:50];
}
//
- (void)amapTrackManager:(nonnull AMapTrackManager *)manager doRequireTemporaryFullAccuracyAuth:(nonnull CLLocationManager *)locationManager completion:(nonnull void (^)(NSError * _Nonnull))completion API_AVAILABLE(ios(14.0)){
[locationManager requestTemporaryFullAccuracyAuthorizationWithPurposeKey:self.fullAccuracyPurpose completion:^(NSError *error){
if(completion){
completion(error);
}
}];
}
@end

View File

@@ -0,0 +1,23 @@
//
// DDMAGeometry.h
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/2.
#import <Foundation/Foundation.h>
#import <AMapNaviKit/MAGeometry.h>
NS_ASSUME_NONNULL_BEGIN
@interface DDMAGeometry : NSObject
// 获取一个合适的地图展示范围
+ (MAMapRect)getVisibleMapRectWithCoordinates:(CLLocationCoordinate2D *_Nullable)coords coordinateCount:(NSUInteger)coordinateCount;
// 获取一个合适的地图展示范围
+ (MAMapRect)getVisibleMapRectWithMapPoints:(MAMapPoint *_Nullable)mapPoints mapPointCount:(NSUInteger)mapPointCount;
// 获取一个合适的地图展示范围
+ (MAMapRect)getVisibleMapRectWithCLLocations:(NSArray<CLLocation *> *_Nullable)locations;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,87 @@
//
// DDMAGeometry.m
// DDMAMapKit_Private
// Created by DDIsFriend on 2023/2/2.
#import "DDMAGeometry.h"
//#import <MAMapKit/MAPolyline.h>
//#import <AMapSearchKit/AMapSearchKit.h>
//#import <DDMAMapKit_Private/DDMASearch.h>
@implementation DDMAGeometry
+ (MAMapRect)getVisibleMapRectWithCoordinates:(CLLocationCoordinate2D *_Nullable)coords coordinateCount:(NSUInteger)coordinateCount{
if (coords == NULL) return MAMapRectMake(0,0,0,0);
MAMapPoint *mapPoints = new MAMapPoint[coordinateCount];
for (NSUInteger i = 0; i < coordinateCount; i++) {
mapPoints[i] = MAMapPointForCoordinate(coords[i]);
}
if (coordinateCount < 2) return MAMapRectMake(mapPoints[0].x,mapPoints[0].y,0,0);
return [self getVisibleMapRectWithMapPoints:mapPoints mapPointCount:coordinateCount];
}
+ (MAMapRect)getVisibleMapRectWithMapPoints:(MAMapPoint *_Nullable)mapPoints mapPointCount:(NSUInteger)mapPointCount{
if (mapPoints == NULL) return MAMapRectMake(0,0,0,0);
if (mapPointCount < 2) return MAMapRectMake(mapPoints[0].x,mapPoints[0].y,0,0);
double xMin = 0.0;
double yMin = 0.0;
double xMax = 0.0;
double yMax = 0.0;
MAMapPoint mapPoint = mapPoints[0];
xMin = mapPoint.x;
yMin = mapPoint.y;
xMax = mapPoint.x;
yMax = mapPoint.y;
for (NSUInteger i = 1; i < mapPointCount; i++) {
MAMapPoint point = mapPoints[i];
if (xMin > point.x) {
xMin = point.x;
}
if (yMin > point.y) {
yMin = point.y;
}
if (xMax < point.x) {
xMax = point.x;
}
if (yMax < point.y) {
yMax = point.y;
}
}
return MAMapRectMake(xMin, yMin, xMax - xMin, yMax - yMin);
}
+ (MAMapRect)getVisibleMapRectWithCLLocations:(NSArray<CLLocation *> *_Nullable)locations{
if (locations == nil) return MAMapRectMake(0,0,0,0);
if (locations.count == 0) return MAMapRectMake(0,0,0,0);
CLLocationCoordinate2D *coords = new CLLocationCoordinate2D[locations.count];
[locations enumerateObjectsUsingBlock:^(CLLocation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
coords[idx].latitude = obj.coordinate.latitude;
coords[idx].longitude = obj.coordinate.longitude;
}];
return [self getVisibleMapRectWithCoordinates:coords coordinateCount:locations.count];
}
//+ (MAPolyline *)getPolylineWithRouteSearchResponse:(AMapRouteSearchResponse *)routeSearchResponse{
// NSArray *array = [DDMASearch coordsArrayWithRouteSearchResponse:routeSearchResponse];
// [array enumerateObjectsUsingBlock:^(DDMACoordinate _Nonnull coordinate, NSUInteger idx, BOOL * _Nonnull stop) {
// if (idx == 0) {
// CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)[(NSValue *)coordinate[DDMACoords] pointerValue];
// NSUInteger count = [coordinate[DDMACoordsCount] integerValue];
// MAPolyline *polyline = [MAPolyline polylineWithCoordinates:coords count:count];
//
// dispatch_async(dispatch_get_main_queue(), ^{
// [mapView.maMapView setVisibleMapRect:[DDMAGeometry getVisibleMapRectWithCoordinates:coords coordinateCount:count] edgePadding:UIEdgeInsetsMake(50, 30, 50, 30) animated:YES];
// });
//
// }
//
// }];
//}
@end

19
Pods/DDMAMapKit_Private/LICENSE generated Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2023 DDIsFriend <DDIsFriend@163.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

56
Pods/DDMAMapKit_Private/README.md generated Normal file
View File

@@ -0,0 +1,56 @@
# DDMAMapKit_Private
[![CI Status](https://img.shields.io/travis/DDIsFriend/DDMAMapKit_Private.svg?style=flat)](https://travis-ci.org/DDIsFriend/DDMAMapKit_Private)
[![Version](https://img.shields.io/cocoapods/v/DDMAMapKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDMAMapKit_Private)
[![License](https://img.shields.io/cocoapods/l/DDMAMapKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDMAMapKit_Private)
[![Platform](https://img.shields.io/cocoapods/p/DDMAMapKit_Private.svg?style=flat)](https://cocoapods.org/pods/DDMAMapKit_Private)
## Example
To run the example project, clone the repo, and run `pod install` from the Example directory first.
## Requirements
### Info.plist
```Objective-C
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>获取你的位置</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>获取你的位置</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>FORCE_FULL_ACCURACY</key>
<string>当前功能必须要获取您的精准定位才能提供服务</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>获取你的位置</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>remote-notification</string>
</array>
```
### 其余的见Demo和高德的api
## Installation
DDMAMapKit_Private is available through [CocoaPods](https://cocoapods.org). To install
it, simply add the following line to your Podfile:
```ruby
pod 'DDMAMapKit_Private'
```
## Author
DDIsFriend, DDIsFriend@163.com
## License
DDMAMapKit_Private is available under the MIT license. See the LICENSE file for more info.