MAGeometry.h 15.9 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
//
//  MAGeometry.h
//  MAMapKit
//
//  Created by AutoNavi.
//  Copyright (c) 2013年 Amap. All rights reserved.
//

#import "MAConfig.h"
#import <CoreGraphics/CoreGraphics.h>
#import <CoreLocation/CoreLocation.h>
#import <UIKit/UIKit.h>


#ifdef __cplusplus
extern "C" {
#endif
    
    ///东北、西南两个点定义的四边形经纬度范围
    typedef struct MACoordinateBounds{
        CLLocationCoordinate2D northEast; ///< 东北角经纬度
        CLLocationCoordinate2D southWest; ///< 西南角经纬度
    } MACoordinateBounds;
    
    ///经度、纬度定义的经纬度跨度范围
    typedef struct MACoordinateSpan{
        CLLocationDegrees latitudeDelta;  ///< 纬度跨度
        CLLocationDegrees longitudeDelta; ///< 经度跨度
    } MACoordinateSpan;
    
    ///中心点、跨度范围定义的四边形经纬度范围
    typedef struct MACoordinateRegion{
        CLLocationCoordinate2D center;  ///< 中心点经纬度
        MACoordinateSpan span;          ///< 跨度范围
    } MACoordinateRegion;
    
    ///平面投影坐标结构定义
    typedef struct MAMapPoint{
        double x; ///<x坐标
        double y; ///<y坐标
    } MAMapPoint;
    
    ///平面投影大小结构定义
    typedef struct MAMapSize{
        double width;   ///<宽度
        double height;  ///<高度
    } MAMapSize;
    
    ///平面投影矩形结构定义
    typedef struct MAMapRect{
        MAMapPoint origin;  ///<左上角坐标
        MAMapSize size;     ///<大小
    } MAMapRect;
    
    typedef NS_OPTIONS(NSUInteger, MAMapRectCorner) {
        MAMapRectCornerTopLeft     = 1 << 0,
        MAMapRectCornerTopRight    = 1 << 1,
        MAMapRectCornerBottomLeft  = 1 << 2,
        MAMapRectCornerBottomRight = 1 << 3,
        MAMapRectCornerAllCorners  = ~0UL
    };
    
    ///比例关系:MAZoomScale = Screen Point / MAMapPoint, 当MAZoomScale = 1时, 1 screen point = 1 MAMapPoint, 当MAZoomScale = 0.5时, 1 screen point = 2 MAMapPoints
    typedef double MAZoomScale;
    
    ///世界范围大小
    extern const MAMapSize MAMapSizeWorld;
    ///世界范围四边形
    extern const MAMapRect MAMapRectWorld;
    ///(MAMapRect){{INFINITY, INFINITY}, {0, 0}};
    extern const MAMapRect MAMapRectNull;
    ///(MAMapRect){{0, 0}, {0, 0}}
    extern const MAMapRect MAMapRectZero;
    
    static inline MACoordinateBounds MACoordinateBoundsMake(CLLocationCoordinate2D northEast,CLLocationCoordinate2D southWest)
    {
        return (MACoordinateBounds){northEast, southWest};
    }
    
    static inline MACoordinateSpan MACoordinateSpanMake(CLLocationDegrees latitudeDelta, CLLocationDegrees longitudeDelta)
    {
        return (MACoordinateSpan){latitudeDelta, longitudeDelta};
    }
    
    static inline MACoordinateRegion MACoordinateRegionMake(CLLocationCoordinate2D centerCoordinate, MACoordinateSpan span)
    {
        return (MACoordinateRegion){centerCoordinate, span};
    }

    /**
     * @brief 生成一个新的MACoordinateRegion
     * @param centerCoordinate   中心点坐标
     * @param latitudinalMeters  垂直跨度(单位 米)
     * @param longitudinalMeters 水平跨度(单位 米)
     * @return 新的MACoordinateRegion
     */
    extern MACoordinateRegion MACoordinateRegionMakeWithDistance(CLLocationCoordinate2D centerCoordinate, CLLocationDistance latitudinalMeters, CLLocationDistance longitudinalMeters);
    
    /**
     * @brief 经纬度坐标转平面投影坐标
     * @param coordinate 要转化的经纬度坐标
     * @return 平面投影坐标
     */
    extern MAMapPoint MAMapPointForCoordinate(CLLocationCoordinate2D coordinate);
    
    /**
     * @brief 平面投影坐标转经纬度坐标
     * @param mapPoint 要转化的平面投影坐标
     * @return 经纬度坐标
     */
    extern CLLocationCoordinate2D MACoordinateForMapPoint(MAMapPoint mapPoint);
    
    /**
     * @brief 平面投影矩形转region
     * @param rect 要转化的平面投影矩形
     * @return region
     */
    extern MACoordinateRegion MACoordinateRegionForMapRect(MAMapRect rect);
    
    /**
     * @brief region转平面投影矩形
     * @param region region 要转化的region
     * @return 平面投影矩形
     */
    extern MAMapRect MAMapRectForCoordinateRegion(MACoordinateRegion region);
    
    /**
     * @brief 单位投影的距离
     * @param latitude 经纬度
     * @return 距离
     */
    extern CLLocationDistance MAMetersPerMapPointAtLatitude(CLLocationDegrees latitude);
    
    /**
     * @brief 1米对应的投影
     * @param latitude 经纬度
     * @return 1米对应的投影
     */
    extern double MAMapPointsPerMeterAtLatitude(CLLocationDegrees latitude);

    /**
     * @brief 投影两点之间的距离
     * @param a a点
     * @param b b点
     * @return 距离
     */
    extern CLLocationDistance MAMetersBetweenMapPoints(MAMapPoint a, MAMapPoint b);
    
    /**
     * @brief 经纬度间的面积(单位 平方米)
     * @param northEast 东北经纬度
     * @param southWest 西南经纬度
     * @return 面积
     */
    extern double MAAreaBetweenCoordinates(CLLocationCoordinate2D northEast, CLLocationCoordinate2D southWest);
    
    /**
     * @brief 获取Inset后的MAMapRect
     * @param rect rect
     * @param dx   x点
     * @param dy   y点
     * @return MAMapRect
     */
    extern MAMapRect MAMapRectInset(MAMapRect rect, double dx, double dy);
    
    /**
     * @brief 合并两个MAMapRect
     * @param rect1 rect1
     * @param rect2 rect2
     * @return 合并后的rect
     */
    extern MAMapRect MAMapRectUnion(MAMapRect rect1, MAMapRect rect2);
    
    /**
     * @brief 判断size1是否包含size2
     * @param size1 size1
     * @param size2 size2
     * @return 判断结果
     */
    extern BOOL MAMapSizeContainsSize(MAMapSize size1, MAMapSize size2);
    
    /**
     * @brief 判断点是否在矩形内
     * @param rect  矩形rect
     * @param point 点
     * @return 判断结果
     */
    extern BOOL MAMapRectContainsPoint(MAMapRect rect, MAMapPoint point);
    
    /**
     * @brief 判断两矩形是否相交
     * @param rect1 rect1
     * @param rect2 rect2
     * @return 判断结果
     */
    extern BOOL MAMapRectIntersectsRect(MAMapRect rect1, MAMapRect rect2);
    
    /**
     * @brief 判断矩形rect1是否包含矩形rect2
     * @param rect1 rect1
     * @param rect2 rect2
     * @return 判断结果
     */
    extern BOOL MAMapRectContainsRect(MAMapRect rect1, MAMapRect rect2);
    
    /**
     * @brief 判断点是否在圆内
     * @param point  点
     * @param center 圆的中心点
     * @param radius 圆的半径,单位米
     * @return 判断结果
     */
    extern BOOL MACircleContainsPoint(MAMapPoint point, MAMapPoint center, double radius);
    
    /**
     * @brief 判断经纬度点是否在圆内
     * @param point  经纬度
     * @param center 圆的中心经纬度
     * @param radius 圆的半径,单位米
     * @return 判断结果
     */
    extern BOOL MACircleContainsCoordinate(CLLocationCoordinate2D point, CLLocationCoordinate2D center, double radius);
    
    /**
     * @brief 获取某坐标点距线上最近的坐标点
     * @param point     点
     * @param polyline  线
     * @param count     线里点的数量
     * @return 某点到线上最近的点
     */
    extern MAMapPoint MAGetNearestMapPointFromPolyline(MAMapPoint point, MAMapPoint *polyline, NSUInteger count);

    /**
     * @brief 判断点是否在多边形内
     * @param point   点
     * @param polygon 多边形
     * @param count   多边形点的数量
     * @return 判断结果
     */
    extern BOOL MAPolygonContainsPoint(MAMapPoint point, MAMapPoint *polygon, NSUInteger count);

    /**
     * @brief 判断经纬度点是否在多边形内
     * @param point   经纬度点
     * @param polygon 多边形
     * @param count   多边形点的数量
     * @return 判断结果
     */
    extern BOOL MAPolygonContainsCoordinate(CLLocationCoordinate2D point, CLLocationCoordinate2D *polygon, NSUInteger count);
    
    /**
     * @brief 取在lineStart和lineEnd组成的线段上距离point距离最近的点
     * @param lineStart 线段起点
     * @param lineEnd   线段终点
     * @param point     测试点
     * @return 距离point最近的点坐标
     */
    extern MAMapPoint MAGetNearestMapPointFromLine(MAMapPoint lineStart, MAMapPoint lineEnd, MAMapPoint point);
    
    /**
     * @brief 获取墨卡托投影切块回调block,如果是无效的映射,则返回(-1, -1, 0, 0, 0, 0)
     * @param offsetX 左上点距离所属tile的位移X, 单位像素
     * @param offsetY 左上点距离所属tile的位移Y, 单位像素
     * @param minX    覆盖tile的最小x
     * @param maxX    覆盖tile的最大x
     * @param minY    覆盖tile的最小y
     * @param maxY    覆盖tile的最大y
     */
    typedef void (^AMapTileProjectionBlock)(int offsetX, int offsetY, int minX, int maxX, int minY, int maxY);
    
    /**
     * @brief 根据所给经纬度区域获取墨卡托投影切块信息
     * @param bounds         经纬度区域
     * @param levelOfDetails 对应缩放级别, 取值0-20
     * @param tileProjection 返回的切块信息block
     */
    extern void MAGetTileProjectionFromBounds(MACoordinateBounds bounds, int levelOfDetails, AMapTileProjectionBlock tileProjection);
    
    /**
     * @brief 计算多边形面积,点与点之间按顺序尾部相连, 第一个点与最后一个点相连
     * @param coordinates 指定的经纬度坐标点数组,C数组,调用者负责内存管理
     * @param count 坐标点的个数
     * @return 多边形的面积
     */
    extern double MAAreaForPolygon(CLLocationCoordinate2D *coordinates, int count);
    
    static inline MAMapPoint MAMapPointMake(double x, double y)
    {
        return (MAMapPoint){x, y};
    }
    
    static inline MAMapSize MAMapSizeMake(double width, double height)
    {
        return (MAMapSize){width, height};
    }
    
    static inline MAMapRect MAMapRectMake(double x, double y, double width, double height)
    {
        return (MAMapRect){MAMapPointMake(x, y), MAMapSizeMake(width, height)};
    }
    
    static inline double MAMapRectGetMinX(MAMapRect rect)
    {
        return rect.origin.x;
    }
    
    static inline double MAMapRectGetMinY(MAMapRect rect)
    {
        return rect.origin.y;
    }
    
    static inline double MAMapRectGetMidX(MAMapRect rect)
    {
        return rect.origin.x + rect.size.width / 2.0;
    }
    
    static inline double MAMapRectGetMidY(MAMapRect rect)
    {
        return rect.origin.y + rect.size.height / 2.0;
    }
    
    static inline double MAMapRectGetMaxX(MAMapRect rect)
    {
        return rect.origin.x + rect.size.width;
    }
    
    static inline double MAMapRectGetMaxY(MAMapRect rect)
    {
        return rect.origin.y + rect.size.height;
    }
    
    static inline double MAMapRectGetWidth(MAMapRect rect)
    {
        return rect.size.width;
    }
    
    static inline double MAMapRectGetHeight(MAMapRect rect)
    {
        return rect.size.height;
    }
    
    static inline BOOL MAMapPointEqualToPoint(MAMapPoint point1, MAMapPoint point2) {
        return point1.x == point2.x && point1.y == point2.y;
    }
    
    static inline BOOL MAMapSizeEqualToSize(MAMapSize size1, MAMapSize size2) {
        return size1.width == size2.width && size1.height == size2.height;
    }
    
    static inline BOOL MAMapRectEqualToRect(MAMapRect rect1, MAMapRect rect2) {
        return
        MAMapPointEqualToPoint(rect1.origin, rect2.origin) &&
        MAMapSizeEqualToSize(rect1.size, rect2.size);
    }
    
    static inline BOOL MAMapRectIsNull(MAMapRect rect) {
        return isinf(rect.origin.x) || isinf(rect.origin.y);
    }
    
    static inline BOOL MAMapRectIsEmpty(MAMapRect rect) {
        return MAMapRectIsNull(rect) || (rect.size.width == 0.0 && rect.size.height == 0.0);
    }
    
    static inline NSString *MAStringFromMapPoint(MAMapPoint point) {
        return [NSString stringWithFormat:@"{%.1f, %.1f}", point.x, point.y];
    }
    
    static inline NSString *MAStringFromMapSize(MAMapSize size) {
        return [NSString stringWithFormat:@"{%.1f, %.1f}", size.width, size.height];
    }
    
    static inline NSString *MAStringFromMapRect(MAMapRect rect) {
        return [NSString stringWithFormat:@"{%@, %@}", MAStringFromMapPoint(rect.origin), MAStringFromMapSize(rect.size)];
    }
    
    ///坐标系类型枚举
    typedef NS_ENUM(NSUInteger, MACoordinateType)
    {
        MACoordinateTypeBaidu = 0,  ///< Baidu
        MACoordinateTypeMapBar,     ///< MapBar
        MACoordinateTypeMapABC,     ///< MapABC
        MACoordinateTypeSoSoMap,    ///< SoSoMap
        MACoordinateTypeAliYun,     ///< AliYun
        MACoordinateTypeGoogle,     ///< Google
        MACoordinateTypeGPS,        ///< GPS
    };
    
    /**
     * @brief 转换目标经纬度为高德坐标系
     * @param coordinate 待转换的经纬度
     * @param type       坐标系类型
     * @return 高德坐标系经纬度
     */
    extern CLLocationCoordinate2D MACoordinateConvert(CLLocationCoordinate2D coordinate, MACoordinateType type) __attribute((deprecated("已废弃,使用AMapFoundation中关于坐标转换的接口")));
    
    /**
     * @brief 获取矢量坐标方向
     * @param fromCoord 矢量坐标起点
     * @param toCoord   矢量坐标终点
     * @return 方向,详情参考系统 CLLocationDirection
     */
    extern CLLocationDirection MAGetDirectionFromCoords(CLLocationCoordinate2D fromCoord, CLLocationCoordinate2D toCoord);
    
    /**
     * @brief 获取矢量坐标方向
     * @param fromPoint 矢量坐标起点
     * @param toPoint   矢量坐标终点
     * @return 方向,详情参考系统 CLLocationDirection
     */
    extern CLLocationDirection MAGetDirectionFromPoints(MAMapPoint fromPoint, MAMapPoint toPoint);
    
    /**
     * @brief 获取点到线的垂直距离
     * @param point 起点
     * @param lineBegin 线的起点
     * @param lineEnd   线的终点
     * @return 距离,单位米
     */
    extern double MAGetDistanceFromPointToLine(MAMapPoint point, MAMapPoint lineBegin, MAMapPoint lineEnd);

    /**
     * @brief 判断线是否被点击选中
     * @param linePoints 构成线的点
     * @param count 点的个数
     * @param tappedPoint   点击点
     * @param lineWidth   线宽,单位:MAMapPoint点
     * @return 是否选中
     */
    extern BOOL MAPolylineHitTest(MAMapPoint *linePoints, NSUInteger count, MAMapPoint tappedPoint, CGFloat lineWidth);
    
#ifdef __cplusplus
}
#endif

///utils方法,方便c结构体对象和NSValue对象间相互转化
@interface NSValue (NSValueMAGeometryExtensions)

/**
 * @brief 创建 MAMapPoint 的NSValue对象
 * @param mapPoint MAMapPoint结构体对象
 * @return NSValue对象
 */
+ (NSValue *)valueWithMAMapPoint:(MAMapPoint)mapPoint;

/**
 * @brief 创建 MAMapSize 的NSValue对象
 * @param mapSize MAMapSize结构体对象
 * @return NSValue对象
 */
+ (NSValue *)valueWithMAMapSize:(MAMapSize)mapSize;

/**
 * @brief 创建 MAMapRect 的NSValue对象
 * @param mapRect MAMapRect结构体对象
 * @return NSValue对象
 */
+ (NSValue *)valueWithMAMapRect:(MAMapRect)mapRect;

/**
 * @brief 创建 CLLocationCoordinate2D 的NSValue对象
 * @param coordinate CLLocationCoordinate2D结构体对象
 * @return NSValue对象
 */
+ (NSValue *)valueWithMACoordinate:(CLLocationCoordinate2D)coordinate;

/**
 @brief 返回NSValue对象包含的MAMapPoint结构体对象
 @return 当前对象包含的MAMapPoint结构体对象
 */
- (MAMapPoint)MAMapPointValue;

/**
 @brief 返回NSValue对象包含的MAMapSize结构体对象
 @return 当前对象包含的MAMapSize结构体对象
 */
- (MAMapSize)MAMapSizeValue;

/**
 @brief 返回NSValue对象包含的MAMapRect结构体对象
 @return 当前对象包含的MAMapRect结构体对象
 */
- (MAMapRect)MAMapRectValue;

/**
 @brief 返回NSValue对象包含的CLLocationCoordinate2D结构体对象
 @return 当前对象包含的CLLocationCoordinate2D结构体对象
 */
- (CLLocationCoordinate2D)MACoordinateValue;

@end