我正在处理从Google Geocoding API返回的视口和边界.当对给定坐标进行反向地理编码时,服务返回具有各种粒度(国家,行政区域,地点,子地点,路线等)的若干结果.我想在给定地图上当前可见区域的结果上选择最合适的.

我已经确定了比较位置视口,当前地图视口和它们的交点(使用MKMapRectIntersection函数)的面积比率(在MKMapPoint²中)的算法.只要位置视口不跨越180子午线,这种方法就可以很好地工作.在那种情况下,他们的交集是0.

我已经开始调查原因并作为调试辅助工具我在地图上显示MKpolygon叠加层,以便为我提供有关正在发生的事情的直观线索.为了避免我的代码在地理坐标和MKMapRect之间进行转换所引入的错误,我使用Google结果中的原始坐标构造了多边形叠加,如下所示:

CLLocationCoordinate2D sw,ne,nw,se;
sw = location.viewportSouthWest.coordinate;
ne = location.viewportnorthEast.coordinate;
nw = CLLocationCoordinate2DMake(ne.latitude,sw.longitude);
se = CLLocationCoordinate2DMake(sw.latitude,ne.longitude);
CLLocationCoordinate2D coords[] = {nw,se,sw};
MKpolygon *p = [MKpolygon polygonWithCoordinates:coords count:4];

例如,有问题的位置,这里是为美国返回的视口,类型为country的最后结果,当geocoding coordinates somewhere in Virginia时:

Southwest: 18.9110643,172.4546967  
northeast: 71.3898880,-66.9453948

请注意位于视口左下角的西南坐标是如何跨越180子午线的.当在地图上显示覆盖为多边形的此位置时,它会错误地显示在USA边框的右侧(大的棕色矩形,只有左下角可见):

类似地,显示location viewport for Russia显示矩形位于俄罗斯边界左侧不正确.

当我将位置视口转换为MKMapPoints和MKMapRect并且在地图视口(上图中的白色矩形)和位置视口之间找不到交集时,这在视觉上确认存在类似的问题.

我计算map rect的方式类似于这个SO问题中的答案:
How to fit a certain bounds consisting of NE and SW coordinates into the visible map view?
……除非坐标跨越第180个子午线,否则工作正常.使用MKMapRectSpans180thMeridian测试MKMapRect会返回false,因此构造方法不正确.

Apple文档在这方面没有帮助.我发现只有提示是在MKOverlay.h中:

// boundingMapRect should be the smallest rectangle that completely contains
// the overlay.
// For overlays that span the 180th meridian,boundingMapRect should have 
// either a negative MinX or a MaxX that is greater than MKMapSizeWorld.width.
@property (nonatomic,readonly) MKMapRect boundingMapRect;

显示跨越180度子午线的多边形叠加层的正确方法是什么?
如何正确构建跨越180度子午线的MKMapRect?

解决方法

根据MKOverlay.h中的注释,如果将nw和sw角指定为负MKMapPoint值,则应该“正确绘制”覆盖.

如果我们试试这个:

//calculation of the nw,and sw coordinates goes here

MKMapPoint points[4];
if (nw.longitude > ne.longitude)  //does it cross 180th?
{
    //Get the mappoint for equivalent distance on
    //the "positive" side of the dateline...
    points[0] = MKMapPointForCoordinate(
                  CLLocationCoordinate2DMake(nw.latitude,-nw.longitude));

    //Reset the mappoint to the correct side of the dateline,//Now it will be negative (as per Apple comments)...
    points[0].x = - points[0].x;
}
else
{
    points[0] = MKMapPointForCoordinate(nw);
}
points[1] = MKMapPointForCoordinate(ne);
points[2] = MKMapPointForCoordinate(se);
points[3] = MKMapPointForCoordinate(sw);
points[3].x = points[0].x;    //set to same as NW's whether + or -

MKpolygon *p = [MKpolygon polygonWithPoints:points count:4];

[mapView addOverlay:p];

生成的p.boundingMapRect确实为MKMapRectSpans180thMeridian返回YES(但是代码已经从坐标中找出,因为它没有以maprect开头).

不幸的是,使用负值创建maprect只能解决问题的一半.现在可以正确绘制日期线以东的多边形的一半.但是,日期线以西的另一半根本没有被绘制.

显然,内置的MKpolygonView不会调用MKMapRectSpans180thMeridian并将多边形绘制成两部分.

您可以创建自定义叠加视图并自己进行绘制(您将创建一个叠加层,但视图将绘制两个多边形).

或者,您可以创建两个MKpolygon叠加层,并让地图视图通过在上面的代码之后添加以下内容来绘制它们:

if (MKMapRectSpans180thMeridian(p.boundingMapRect))
{
    MKMapRect remainderRect = MKMapRectRemainder(p.boundingMapRect);

    MKMapPoint remPoints[4];
    remPoints[0] = remainderRect.origin;
    remPoints[1] = MKMapPointMake(remainderRect.origin.x + remainderRect.size.width,remainderRect.origin.y);
    remPoints[2] = MKMapPointMake(remainderRect.origin.x + remainderRect.size.width,remainderRect.origin.y + remainderRect.size.height);
    remPoints[3] = MKMapPointMake(remainderRect.origin.x,remainderRect.origin.y + remainderRect.size.height);

    MKpolygon *rempoly = [MKpolygon polygonWithPoints:remPoints count:4];

    [mapView addOverlay:rempoly];
}

顺便说一句,绘制跨越-180的MKpolyline叠加层也存在类似的问题(见this question).

ios – MKMapRect并显示跨越第180个子午线的地图叠加层的更多相关文章

  1. 为什么android浏览器视口比手机的实际屏幕尺寸小得多,即使使用width = device-width?

    我想问一下为什么我的HTCDesireHD浏览器报告视口的宽度为369px,即使屏幕的实际像素大小为480×800WVGA.我在我的页面中使用这个CSS样式:你能解释一下这个奇怪的行为,以及如何强制Android浏览器实际将视口的宽度设置为480px而不是奇怪的369px?

  2. Android WebView视口

    使用下面的html我预计绿色矩形只占据屏幕的一半,但实际上它占据整个屏幕宽度.我为视口宽度尝试了其他值,没有运气.任何想法为什么它不起作用?HTMLXML解决方法我有同样的问题,找到了答案!在您的情况下,您需要:

  3. 详解如何使用rem或viewport进行移动端适配

    这篇文章主要介绍了详解如何使用rem或viewport进行移动端适配,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  4. 如何利用JS检查元素是否在视口内

    这篇文章主要给大家介绍了关于如何利用JS检查元素是否在视口内的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. windows-mobile – meta“viewport”device-width:Opera Mobile 9.7(10作品)错误的宽度小

    对于我当前的移动网络项目,我使用Meta“viewport”标签来指示移动浏览器使用设备宽度为1:1的比例:这适用于IE移动,iPhoneSafari甚至Opera10测试版,但它不在Opera9.7上,默认情况下安装在HTCHD2上.HTCHD2的设备尺寸为480×800,因此视口在纵向模式下的宽度应为480.但显而易见,Operamobile9.7(也许是9.5)设置了一个错误的宽度,所以之后

  6. Angular 4 – 当div进入视口时如何触发动画?

    我一直在使用Angular4构建一个新站点,我正在尝试重新创建一个效果,当div变为可见时然后可以触发角度动画以滑动div形式双方.我以前在Angular4之外使用jQuery已经能够做到这一点,但我想尝试使用原生的Angular4动画创建相同的效果.任何人都可以向我提供有关如何在div进入视图时触发动画的建议(即,当它进入视口时向下滚动到页面的下半部分?).我已经编写了幻灯片动画但我不知道如何在以后将div显示到视口时使用滚动触发它.感谢大家!

  7. jquery – scrollTop在移动Safari中不起作用

    解决方法我想你试图以错误的方式解决事情.只需确保您的表单字段在移动视口上具有font-size:16px,这样Safari将不会放大.如果您有位置,则ScrollTop可能无法正常工作:固定在容器上.

  8. jQuery:移动窗口视口来显示新鲜的切换元素

    我有一个jQuery在doc准备好的代码片段切换一个包含textarea的div:点击链接时,切换工作正常.我遇到的问题是,如果div#addnote-area在浏览器当前的视口下方,那么它会显示出来.我想要用户的光标去文本区域,整个textarea可以在窗口中查看.Clickheretoseeanimagehttp://i50.tinypic.com/5ousuv.png解决方法看看scroll

  9. ios – MKMapRect并显示跨越第180个子午线的地图叠加层

    如何正确构建跨越180度子午线的MKMapRect?

  10. javascript – 如何将当前视图的视口从OpenLayers中获取为几何,边框或wkt?

    我试图找到一些提示,我应该搜索这个主题,但我没有找到–我花了好几个小时在这个.我也尝试从当前显示的视口从OpenLayers映射中获取当前坐标,以仅添加位于当前视口当前边界框中的这些向量.解决方法对于OpenLayers2:…将返回一个坐标数组,表示范围的边界框.

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部