https://lbsyun.baidu.com/jsdemo.htm#TranslateggTobd
计算经纬度之间的距离
/*!
@brief 计算经纬度之间的距离
@param a a点
@param b b点
@return 距离,单位:米
*/
CLLocationDistance MAMetersBetweenMapPoints(CLLocationCoordinate2D a, CLLocationCoordinate2D b)
{
CLLocation *curLocation = [[CLLocation alloc] initWithLatitude:a.latitude longitude:a.longitude];
CLLocation *otherLocation = [[CLLocation alloc] initWithLatitude:b.latitude longitude:b.longitude];
return [curLocation distanceFromLocation:otherLocation];
}
static const double a = 6378245.0;
static const double ee = 0.00669342162296594323;
static const double pi = M_PI;
static const double xPi = M_PI * 3000.0 / 180.0;
GPS转高德
- (CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc {
CLLocationCoordinate2D adjustLoc;
if([self isLocationOutOfChina:wgsLoc]) {
}adjustLoc = wgsLoc;
else {
}double adjustLat = [self transformLatWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0]; double adjustLon = [self transformLonWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0]; long double radLat = wgsLoc.latitude / 180.0 * pi; long double magic = sin(radLat); magic = 1 - ee * magic * magic; long double sqrtMagic = sqrt(magic); adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi); adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * cos(radLat) * pi); adjustLoc.latitude = wgsLoc.latitude + adjustLat; adjustLoc.longitude = wgsLoc.longitude + adjustLon;
return adjustLoc;
}GPS转百度
- (CLLocationCoordinate2D)transformFromWGSToBaidu:(CLLocationCoordinate2D)p {
CLLocationCoordinate2D coo =[NSValue transformFromWGSToGCJ:p];
return [NSValue transformFromGCJToBaidu:coo];
}百度转GPS
- (CLLocationCoordinate2D)transformFromBaiduToWGS:(CLLocationCoordinate2D)p {
CLLocationCoordinate2D start_coor = [NSValue transformFromBaiduToGCJ:p];
return [NSValue transformFromGCJToWGS:start_coor];
}百度转高德
- (CLLocationCoordinate2D)transformFromBaiduToGCJ:(CLLocationCoordinate2D)p {
double x = p.longitude - 0.0065, y = p.latitude - 0.006;
double z = sqrt(x * x + y * y) - 0.00002 * sin(y * xPi);
double theta = atan2(y, x) - 0.000003 * cos(x * xPi);
CLLocationCoordinate2D geoPoint;
geoPoint.latitude = z * sin(theta);
geoPoint.longitude = z * cos(theta);
return geoPoint;
}高德转百度
- (CLLocationCoordinate2D)transformFromGCJToBaidu:(CLLocationCoordinate2D)p {
long double z = sqrt(p.longitude * p.longitude + p.latitude * p.latitude) + 0.00002 * sqrt(p.latitude * pi);
long double theta = atan2(p.latitude, p.longitude) + 0.000003 * cos(p.longitude * pi);
CLLocationCoordinate2D geoPoint;
geoPoint.latitude = (z * sin(theta) + 0.006);
geoPoint.longitude = (z * cos(theta) + 0.0065);
return geoPoint;
}高德转GPS
- (CLLocationCoordinate2D)transformFromGCJToWGS:(CLLocationCoordinate2D)p {
double threshold = 0.00001; // The boundary
double minLat = p.latitude - 0.5;
double maxLat = p.latitude + 0.5;
double minLng = p.longitude - 0.5;
double maxLng = p.longitude + 0.5; double delta = 1;
int maxIteration = 30;
// Binary search
while(true) {
}CLLocationCoordinate2D leftBottom = [[self class] transformFromWGSToGCJ:(CLLocationCoordinate2D){.latitude = minLat,.longitude = minLng}]; CLLocationCoordinate2D rightBottom = [[self class] transformFromWGSToGCJ:(CLLocationCoordinate2D){.latitude = minLat,.longitude = maxLng}]; CLLocationCoordinate2D leftUp = [[self class] transformFromWGSToGCJ:(CLLocationCoordinate2D){.latitude = maxLat,.longitude = minLng}]; CLLocationCoordinate2D midPoint = [[self class] transformFromWGSToGCJ:(CLLocationCoordinate2D){.latitude = ((minLat + maxLat) / 2),.longitude = ((minLng + maxLng) / 2)}]; delta = fabs(midPoint.latitude - p.latitude) + fabs(midPoint.longitude - p.longitude); if(maxIteration-- <= 0 || delta <= threshold) { return (CLLocationCoordinate2D){.latitude = ((minLat + maxLat) / 2),.longitude = ((minLng + maxLng) / 2)}; } if(isContains(p, leftBottom, midPoint)) { maxLat = (minLat + maxLat) / 2; maxLng = (minLng + maxLng) / 2; } else if(isContains(p, rightBottom, midPoint)) { maxLat = (minLat + maxLat) / 2; minLng = (minLng + maxLng) / 2; } else if(isContains(p, leftUp, midPoint)) { minLat = (minLat + maxLat) / 2; maxLng = (minLng + maxLng) / 2; } else { minLat = (minLat + maxLat) / 2; minLng = (minLng + maxLng) / 2; }
}
- (double)transformLatWithX:(double)x withY:(double)y {
double lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x));
lat += (20.0 * sin(6.0 * x * pi) + 20.0 *sin(2.0 * x * pi)) * 2.0 / 3.0;
lat += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
lat += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;
return lat;
} - (double)transformLonWithX:(double)x withY:(double)y {
double lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
lon += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
lon += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
lon += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;
return lon;
}判断某个点point是否在p1和p2之间
static bool isContains(CLLocationCoordinate2D point, CLLocationCoordinate2D p1, CLLocationCoordinate2D p2) {
return (point.latitude >= MIN(p1.latitude, p2.latitude) && point.latitude <= MAX(p1.latitude, p2.latitude)) && (point.longitude >= MIN(p1.longitude,p2.longitude) && point.longitude <= MAX(p1.longitude, p2.longitude));
}
粗略判断是不是在中国
- (BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location {
if (location.longitude < 72.004 || location.longitude > 137.8347 || location.latitude < 0.8293 || location.latitude > 55.8271)
return NO;return YES;
}弧线计算
double x1 = pArc.startCoordinate.longitude;
double y1 = pArc.startCoordinate.latitude;
double x2 = pArc.passedCoordinate.longitude;
double y2 = pArc.passedCoordinate.latitude;
double x3 = pArc.endCoordinate.longitude;
double y3 = pArc.endCoordinate.latitude;
double a = 2 * (x2 - x1);
double b = 2 * (y2 - y1);
double c = x2 * x2 + y2 * y2 - x1 * x1 - y1 * y1;
double d = 2 * (x3 - x2);
double e = 2 * (y3 - y2);
double f = x3 * x3 + y3 * y3 - x2 * x2 - y2 * y2;
double x = (b * f - e * c) / (b * d - e * a);
double y = (d * c - a * f) / (b * d - e * a);
double r = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
double angle1 = acos((x1 - x) / r);
if (y1 - y < 0)
angle1 = -angle1;
double angle2 = acos((x2 - x) / r);
if (y2 - y < 0)
angle2 = -angle2;
double angle3 = acos((x3 - x) / r);
if (y3 - y < 0)
angle3 = -angle3;
double deltaAngle1 = angle1 - angle2;
while (deltaAngle1 > M_PI)
deltaAngle1 -= M_PI * 2;
while (deltaAngle1 <= -M_PI)
deltaAngle1 += M_PI * 2;
int numPoints1 = (int) (128 * fabs(deltaAngle1) / M_PI);
double phase1 = deltaAngle1 / numPoints1;
double deltaAngle2 = angle2 - angle3;
while (deltaAngle2 > M_PI)
deltaAngle2 -= M_PI * 2;
while (deltaAngle2 <= -M_PI)
deltaAngle2 += M_PI * 2;
int numPoints2 = (int) (128 * fabs(deltaAngle2) / M_PI);
double phase2 = deltaAngle2 / numPoints2;
int pointCnt = numPoints1 + numPoints2 + 1;
CLLocationCoordinate2D coos[pointCnt];
pointCnt = 0;
coos[pointCnt] = CLLocationCoordinate2DMake(y1, x1);
pointCnt++;
for (int i = 1; i < numPoints1; i++) {
coos[pointCnt] = CLLocationCoordinate2DMake((y + r * sin(angle1 - phase1 * i)),(x + r * cos(angle1 - phase1 * i)));
pointCnt++;
}
coos[pointCnt] = CLLocationCoordinate2DMake(y2, x2);
pointCnt++;
for (int i = 1; i < numPoints2; i++) {
coos[pointCnt] = CLLocationCoordinate2DMake((y + r * sin(angle2 - phase2 * i)),(x + r * cos(angle2 - phase2 * i)));
pointCnt++;
}
coos[pointCnt] = CLLocationCoordinate2DMake(y3, x3);
pointCnt++;
图片截图
- (UIImage *)takeSnapshotInRect:(CGRect)rect {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (CGRectEqualToRect(rect, self.bounds)) {
}return image;
CGFloat scale = image.scale;
CGRect scaledRect = CGRectMake(rect.origin.x * scale, rect.origin.y * scale, rect.size.width * scale, rect.size.height * scale);
CGImageRef rectImage = CGImageCreateWithImageInRect(image.CGImage,scaledRect);
return [UIImage imageWithCGImage:rectImage];
}地图手势
// 单击
UITapGestureRecognizer * singletapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSingleTap:)];
[singletapGesture setNumberOfTapsRequired:1];
[singletapGesture setNumberOfTouchesRequired:1];
[self addGestureRecognizer:singletapGesture];
双击
UITapGestureRecognizer * doubletapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onDoubleTap:)];
[doubletapGesture setNumberOfTapsRequired: 2];
[doubletapGesture setNumberOfTouchesRequired: 1];
[self addGestureRecognizer:doubletapGesture];
[singletapGesture requireGestureRecognizerToFail:doubletapGesture];
长按
UILongPressGestureRecognizer* longPressGr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self addGestureRecognizer:longPressGr];
缩放
UITapGestureRecognizer *m_pZoomoutGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onZoomOut:)];
[m_pZoomoutGesture setNumberOfTapsRequired:1];
[m_pZoomoutGesture setNumberOfTouchesRequired:2];
[self addGestureRecognizer:m_pZoomoutGesture];
拖拽
m_pSinglePanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onScroll:)];
[m_pSinglePanGesture setMaximumNumberOfTouches:1];
[self addGestureRecognizer:m_pSinglePanGesture];
旋转
UIPanGestureRecognizer * doublePanGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onOverlook:)];
[doublePanGesture setMinimumNumberOfTouches:2];
[self addGestureRecognizer:doublePanGesture];
m_pPinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinch:)];
m_pPinchGesture.delegate = self;
[self addGestureRecognizer:m_pPinchGesture];
缩放
m_pRotateGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(onRotate:)];
m_pRotateGesture.delegate = self;
[self addGestureRecognizer:m_pRotateGesture];
比例尺绘制
(void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 0.0f, 0.0f, 0.0f, 1.0f); //画笔颜色
CGContextSetLineWidth(context, 1.0); //线宽CGFloat scale = [UIScreen mainScreen].scale;
int zoomLevel = self.zoomLevel;int iLength = (MASCALE_DISTANCES[zoomLevel] /([self.mapView metersPerPointForZoomLevel:zoomLevel] * scale));
if (iLength >200) {iLength = 200;
}
int iStartX = rect.origin.x;
int iStartY = rect.size.height - 12;
int iEndY = rect.size.height - 9;
NSString *name = MASCALE_DISTANCESNAME[zoomLevel];
[name drawInRect:CGRectMake(iStartX + SCALE_NAME_STARTX, iStartY - 13, rect.size.width, rect.size.height) withFont:[UIFont systemFontOfSize:10.0]];CGPoint points[2];//坐标点
points[0] = CGPointMake(iStartX, iEndY);//坐标1
points[1] = CGPointMake(iStartX + iLength, iEndY);//坐标2
CGContextAddLines(context, points, 2);//添加线
CGContextDrawPath(context, kCGPathStroke);points[0] = CGPointMake(iStartX, iStartY); //坐标1
points[1] = CGPointMake(iStartX, iEndY); //坐标2
CGContextAddLines(context, points, 2); //添加线
CGContextDrawPath(context, kCGPathStroke);points[0] = CGPointMake(iStartX + iLength, iStartY);//坐标1
points[1] = CGPointMake(iStartX + iLength, iEndY);//坐标2
CGContextAddLines(context, points, 2);//添加线
CGContextDrawPath(context, kCGPathStroke);
}
点到直线的距离
- (CGFloat)lineDistance:(CGPoint)point linePoint1:(CGPoint)line1 linePoint2:(CGPoint)line2
{
CGFloat se = (line1.x-line2.x)(line1.x-line2.x)+(line1.y-line2.y)(line1.y-line2.y);//线段两点距离平方
CGFloat p = ((point.x-line1.x)(line2.x-line1.x)+(point.y-line1.y)(line2.y-line1.y)); //向量点乘=|a||b|cosA
CGFloat r = p / se; //r即点到线段的投影长度与线段长度比
CGFloat outx = line1.x + r * (line2.x-line1.x);
CGFloat outy = line1.y+r(line2.y-line1.y);
CGFloat des =(point.x-outx)(point.x-outx)+(point.y-outy)*(point.y-outy);
return sqrt(des);
}
检查某点是否包含在多边形的范围内(判断多边形是否被点击
- (BOOL)PointInPoly:(CGPoint *)poly count:(int)count point:(CGPoint)pt {
BOOL c = false;
int i = -1, l = count;
for (int j = l - 1; ++i < l; j = i){
}((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) && (c = !c);
return c;
}判断折线是否被点击
原理:点到线的距离是否大与线的宽度
MAPolylineRenderer *line = (MAPolylineRenderer *)ovlay;
CLLocationCoordinate2D *coo = line.polyline.points;
long count = line.polyline.pointCount;
for (int i = 0; i < count - 1; i++) {
}CLLocationCoordinate2D item = coo[i]; CLLocationCoordinate2D item1 = coo[i + 1]; CGPoint point1 = [m_pSkMap lonlat2Pixel:item]; CGPoint point2 = [m_pSkMap lonlat2Pixel:item1]; CGFloat dis = [self lineDistance:point linePoint1:point1 linePoint2:point2]; if (dis < line.lineWidth * 3) { // 为了防止点不上,给进行了加大处理 return line.polyline; }
判断是否在弧形上
原理:同线的点击
MAArcRenderer *arcRenderer = (MAArcRenderer *)ovlay;
MAArc *arc = arcRenderer.arc;
int count = arc.pointCount;
CLLocationCoordinate2D *coo = arc.points;
for (int i = 0; i < count - 1; i++) {
}CLLocationCoordinate2D item = coo[i]; CLLocationCoordinate2D pointCoo = [m_pSkMap pixel2LonLat:point]; CLLocationDistance dis = MAMetersBetweenMapPoints(item,pointCoo); CGFloat zoom = [m_pSkMap getZoom]; if (dis < arcRenderer.lineWidth * 500 / zoom) { // 为了防止点不上,给进行了加大处理 return arc; }
判断是否在圆内
原理:点到圆心的距离小于半径
MACircleRenderer *circle = (MACircleRenderer *)ovlay;
CLLocationCoordinate2D coo = circle.circle.coordinate;
CLLocationCoordinate2D sele = [m_pSkMap pixel2LonLat:point];
double dis = MAMetersBetweenMapPoints(coo,sele);
if (dis < circle.circle.radius) {
}return circle.circle;
判断矩形画图标是否被点击
判断点击是否在矩形图标rect内
MAMarkerRenderer *mark = (MAMarkerRenderer *)ovlay;
CGPoint markPoint = [m_pSkMap lonlat2Pixel:mark.marker.coordinate];
CGSize imageSize = mark.imageSize;
CGFloat scale = 1;
if (mark.image) { // 不规则图形处理
}scale = mark.imageSize.height / mark.imageSize.width; if (scale > 1) { imageSize.width = mark.imageSize.width / scale; imageSize.height = mark.imageSize.height / scale; markPoint.x = markPoint.x + imageSize.width / scale; }else{ imageSize.width = mark.imageSize.width * scale; imageSize.height = mark.imageSize.height * scale; }
CGRect rect = CGRectMake(markPoint.x, markPoint.y, imageSize.width,imageSize.height);
if (CGRectContainsPoint(rect,point)) {
}return mark.marker;
覆盖物的拖拽:
1.通过长按手势触发拖拽
2.通过判断是否点击了多边形,判断是否在拖拽覆盖物
3.计算移动的坐标数量,获取覆盖物新的坐标位置
4.修改覆盖物坐标位置