amap_map_fluttify/ios/Classes/SubHandler/Custom/PathSmooth/MASmoothPathTool.m

298 lines
9.7 KiB
Mathematica
Raw Normal View History

2024-11-17 15:45:43 +08:00
//
// MASmoothPathTool.m
// iOS-path-smooth
//
// Created by shaobin on 2017/10/12.
// Copyright © 2017 autonavi. All rights reserved.
//
#import "MASmoothPathTool.h"
#import <MAMapKit/MAMapKit.h>
@implementation MALonLatPoint
@end
@implementation MASmoothPathTool
{
double lastLocation_x; //
double currentLocation_x;//
double lastLocation_y; //
double currentLocation_y;//
double estimate_x; //
double estimate_y; //
double pdelt_x; //
double pdelt_y; //
double mdelt_x; //
double mdelt_y; //
double gauss_x; //
double gauss_y; //
double kalmanGain_x; //
double kalmanGain_y; //
double m_R;
double m_Q;
}
- (id)init {
self = [super init];
if(self) {
self.intensity = 3;
self.threshHold = 0.3f;
self.noiseThreshhold = 10;
}
return self;
}
/**
*
* @param originlist list,list.size2
* @return list
*/
- (NSArray<MALonLatPoint*>*)pathOptimize:(NSArray<MALonLatPoint*>*)originlist {
NSArray<MALonLatPoint*>* list = [self removeNoisePoint:originlist];//
NSArray<MALonLatPoint*>* afterList = [self kalmanFilterPath:list intensity:self.intensity];//
NSArray<MALonLatPoint*>* pathoptimizeList = [self reducerVerticalThreshold:afterList threshHold:self.threshHold];//
return pathoptimizeList;
}
/**
* 线
* @param originlist list,list.size2
* @return list
*/
- (NSArray<MALonLatPoint*>*)kalmanFilterPath:(NSArray<MALonLatPoint*>*)originlist {
return [self kalmanFilterPath:originlist intensity:self.intensity];
}
/**
* 20m
* @param originlist list,list.size2
* @return list
*/
- (NSArray<MALonLatPoint*>*)removeNoisePoint:(NSArray<MALonLatPoint*>*)originlist{
return [self reduceNoisePoint:originlist threshHold:self.noiseThreshhold];
}
/**
*
* @param lastLoc
* @param curLoc
* @return
*/
- (MALonLatPoint*)kalmanFilterPoint:(MALonLatPoint*)lastLoc curLoc:(MALonLatPoint*)curLoc {
return [self kalmanFilterPoint:lastLoc curLoc:curLoc intensity:self.intensity];
}
/**
*
* @param inPoints listmThreshhold
* @return list
*/
- (NSArray<MALonLatPoint*>*)reducerVerticalThreshold:(NSArray<MALonLatPoint*>*)inPoints {
return [self reducerVerticalThreshold:inPoints threshHold:self.threshHold];
}
/********************************************************************************************************/
/**
* 线
* @param originlist list,list.size2
* @param intensity 15
* @return list
*/
- (NSArray<MALonLatPoint*>*)kalmanFilterPath:(NSArray<MALonLatPoint*>*)originlist intensity:(int)intensity {
if (!originlist || originlist.count <= 2) {
return nil;
}
NSMutableArray<MALonLatPoint*>* kalmanFilterList = [NSMutableArray array];
[self initial];//
MALonLatPoint* point = nil;
MALonLatPoint* lastLoc = [[MALonLatPoint alloc] init];
lastLoc.lat = [originlist objectAtIndex:0].lat;
lastLoc.lon = [originlist objectAtIndex:0].lon;
[kalmanFilterList addObject:lastLoc];
for (int i = 1; i < originlist.count; i++) {
MALonLatPoint* curLoc = [originlist objectAtIndex:i];
point = [self kalmanFilterPoint:lastLoc curLoc:curLoc intensity:intensity];
if (point) {
[kalmanFilterList addObject:point];
lastLoc = point;
}
}
return kalmanFilterList;
}
/**
*
* @param lastLoc
* @param curLoc
* @param intensity 15
* @return
*/
- (MALonLatPoint*)kalmanFilterPoint:(MALonLatPoint*)lastLoc curLoc:(MALonLatPoint*)curLoc intensity:(int)intensity {
if (!lastLoc || !curLoc){
return nil;
}
if (pdelt_x == 0 || pdelt_y == 0 ){
[self initial];
}
MALonLatPoint* point = nil;
if (intensity < 1){
intensity = 1;
} else if (intensity > 5){
intensity = 5;
}
for (int j = 0; j < intensity; j++){
point = [self kalmanFilter:lastLoc.lon value_x:curLoc.lon oldValue_y:lastLoc.lat value_y:curLoc.lat];
curLoc = point;
}
return point;
}
/***********************************************************/
//
- (void)initial {
pdelt_x = 0.001;
pdelt_y = 0.001;
// mdelt_x = 0;
// mdelt_y = 0;
mdelt_x = 5.698402909980532E-4;
mdelt_y = 5.698402909980532E-4;
}
- (MALonLatPoint*)kalmanFilter:(double)oldValue_x value_x:(double)value_x oldValue_y:(double)oldValue_y value_y:(double)value_y{
lastLocation_x = oldValue_x;
currentLocation_x= value_x;
gauss_x = sqrt(pdelt_x * pdelt_x + mdelt_x * mdelt_x)+m_Q; //
kalmanGain_x = sqrt((gauss_x * gauss_x)/(gauss_x * gauss_x + pdelt_x * pdelt_x)) +m_R; //
estimate_x = kalmanGain_x * (currentLocation_x - lastLocation_x) + lastLocation_x; //
mdelt_x = sqrt((1-kalmanGain_x) * gauss_x *gauss_x); //
lastLocation_y = oldValue_y;
currentLocation_y = value_y;
gauss_y = sqrt(pdelt_y * pdelt_y + mdelt_y * mdelt_y)+m_Q; //
kalmanGain_y = sqrt((gauss_y * gauss_y)/(gauss_y * gauss_y + pdelt_y * pdelt_y)) +m_R; //
estimate_y = kalmanGain_y * (currentLocation_y - lastLocation_y) + lastLocation_y; //
mdelt_y = sqrt((1-kalmanGain_y) * gauss_y * gauss_y); //
MALonLatPoint *point = [[MALonLatPoint alloc] init];
point.lon = estimate_x;
point.lat = estimate_y;
return point;
}
/*************************************************************/
/****************************************************************/
- (NSArray<MALonLatPoint*>*)reducerVerticalThreshold:(NSArray<MALonLatPoint*>*)inPoints threshHold:(float)threshHold {
if(inPoints.count < 2) {
return inPoints;
}
NSMutableArray *ret = [NSMutableArray arrayWithCapacity:inPoints.count];
for(int i = 0; i < inPoints.count; ++i) {
MALonLatPoint *pre = ret.lastObject;
MALonLatPoint *cur = [inPoints objectAtIndex:i];
if (!pre || i == inPoints.count - 1) {
[ret addObject:[inPoints objectAtIndex:i]];
continue;
}
MALonLatPoint *next = [inPoints objectAtIndex:(i + 1)];
MAMapPoint curP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(cur.lat, cur.lon));
MAMapPoint prevP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(pre.lat, pre.lon));
MAMapPoint nextP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(next.lat, next.lon));
double distance = [self calculateDistanceFromPoint:curP lineBegin:prevP lineEnd:nextP];
if (distance >= threshHold) {
[ret addObject:cur];
}
}
return ret;
}
- (MALonLatPoint*)getLastLocation:(NSArray<MALonLatPoint*>*)oneGraspList {
if (!oneGraspList || oneGraspList.count == 0) {
return nil;
}
NSInteger locListSize = oneGraspList.count;
MALonLatPoint* lastLocation = [oneGraspList objectAtIndex:(locListSize - 1)];
return lastLocation;
}
/**
* 线线
* @param pt
* @param begin 线
* @param end 线
*
*/
- (double)calculateDistanceFromPoint:(MAMapPoint)pt
lineBegin:(MAMapPoint)begin
lineEnd:(MAMapPoint)end {
MAMapPoint mappedPoint;
double dx = begin.x - end.x;
double dy = begin.y - end.y;
if(fabs(dx) < 0.00000001 && fabs(dy) < 0.00000001 ) {
mappedPoint = begin;
} else {
double u = (pt.x - begin.x)*(begin.x - end.x) +
(pt.y - begin.y)*(begin.y - end.y);
u = u/((dx*dx)+(dy*dy));
mappedPoint.x = begin.x + u*dx;
mappedPoint.y = begin.y + u*dy;
}
return MAMetersBetweenMapPoints(pt, mappedPoint);
}
/************************************************************/
- (NSArray<MALonLatPoint*>*)reduceNoisePoint:(NSArray<MALonLatPoint*>*)inPoints threshHold:(float)threshHold {
if (!inPoints) {
return nil;
}
if (inPoints.count <= 2) {
return inPoints;
}
NSMutableArray<MALonLatPoint*>* ret = [NSMutableArray array];
for (int i = 0; i < inPoints.count; i++) {
MALonLatPoint* pre = [self getLastLocation:ret];
MALonLatPoint* cur = [inPoints objectAtIndex:i];
if (!pre || i == inPoints.count - 1) {
[ret addObject:cur];
continue;
}
MALonLatPoint* next = [inPoints objectAtIndex:(i + 1)];
MAMapPoint curP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(cur.lat, cur.lon));
MAMapPoint prevP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(pre.lat, pre.lon));
MAMapPoint nextP = MAMapPointForCoordinate(CLLocationCoordinate2DMake(next.lat, next.lon));
double distance = [self calculateDistanceFromPoint:curP lineBegin:prevP lineEnd:nextP];
if (distance < threshHold){
[ret addObject:cur];
}
}
return ret;
}
@end