【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 1747|回复: 0

实战iPhone GPS定位系统

[复制链接]
发表于 2012-12-9 20:26:37 | 显示全部楼层 |阅读模式
如今,配备GPS功能的移动设备越来越普遍了,使用GPS定位系统,可以精确地定位你当前所在的地理位置,但由于GPS接收机需要对准天空才能工作,因此在室内环境基本无用。

  另一个找到自己所在位置的有效方法是使用手机基站,手机开机时,它会与周围的基站保持联系,如果你知道这些基站的身份,就可以使用各种数据库(包含基站的身份和它们的确切地理位置)计算出手机的物理位置。基站不需要卫星,和GPS不同,它对室内环境一样管用。但它没有GPS那样精确,它的精度取决于基站的密度,它在基站密集型区域的准确度最高。
  提示:第一代iPhone并没有配置GPS接收器,基站方式不能应用到iPod Touch上,因为它不是手机。
  第三种方法是依赖Wi-Fi,使用这种方法时,设备连接到Wi-Fi网络,通过检查服务提供商的数据确定位置,它既不依赖卫星,也不依赖基站,因此这个方法对于可以连接到Wi-Fi网络的区域有效,但它的精确度也是这三个方法中最差的。
  定位框架内核
  在iPhone上,苹果提供了定位框架内核,以帮助你确定你的物理位置,这个框架的美妙之处在于它使用了前面提到的所有三种方法,具体使用的是哪种方法对于开发者来说是透明的,开发人员只需要指定所需要的精度,定位内核将会以最佳方式确定定位结果。
  你一定感到很吃惊吧?!本文其余部分将向你展示这是如何做到的。
  获取位置坐标
  使用Xcode,创建一个新的基于视图的应用程序项目,取名为LBS,在新项目中,双击LBSViewController.xib文件,在界面设计工具中编辑它。使用下面的组件填充视图窗口,如图1所示。
  l Label
  l TextField
   
  图 1 位置视图实例:用Label和TextFiled填充这个窗口
  在Xcode中框架组上点击右键,选择“添加”*“现有框架”,选择 “Framework/CoreLocation.framework”,向LBSViewController.h文件中添加以下粗体字显示的代码:
Java代码
  1. #import <UIKit/UIKit.h>  
  2. #import <CoreLocation/CoreLocation.h>  
  3. @interface LBSViewController : UIViewController  
  4.      <CLLocationManagerDelegate> {  
  5.      IBOutlet UITextField *latitudeTextField;  
  6.      IBOutlet UITextField *longitudeTextField;  
  7.      IBOutlet UITextField *accuracyTextField;  
  8.      CLLocationManager *lm;  
  9. }  
  10. @property (retain, nonatomic) UITextField *latitudeTextField;  
  11. @property (retain, nonatomic) UITextField *longitudeTextField;  
  12. @property (retain, nonatomic) UITextField *accuracyTextField;  
  13. @end  
复制代码
若要使用CLLocationManager类,需要在你的视图控制器类中实现CLLocationManagerDelegate协议,还需要创建三个出口用于连接视图窗口中的三个TextFiled视图。

  回到界面编辑器,单击并拖动文档的所有者项目到三个TextField视图,然后分别选择latitudeTextField,longitudeTextField和accuracyTextField。
  在 LBSViewController.m文件中查询以下代码中的粗体部分:
Java代码

  • #import "LBSViewController.h"
  • @implementation LBSViewController
  • @synthesize latitudeTextField, longitudeTextField, accuracyTextField;
  • - (void) viewDidLoad {
  •     lm = [[CLLocationManager alloc] init];
  •     if ([lm locationServicesEnabled]) {
  •         lm.delegate = self;
  •         lm.desiredAccuracy = kCLLocationAccuracyBest;
  •         lm.distanceFilter = 1000.0f;
  •         [lm startUpdatingLocation];
  •     }
  • }
  • - (void) locationManager: (CLLocationManager *) manager
  •     didUpdateToLocation: (CLLocation *) newLocation
  •     fromLocation: (CLLocation *) oldLocation{
  •     NSString *lat = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.coordinate.latitude];
  •     latitudeTextField.text = lat;
  •     NSString *lng = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.coordinate.longitude];
  •     longitudeTextField.text = lng;
  •     NSString *acc = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.horizontalAccuracy];
  •     accuracyTextField.text = acc;
  •     [acc release];
  •     [lat release];
  •     [lng release];
  • }
  • - (void) locationManager: (CLLocationManager *) manager
  •     didFailWithError: (NSError *) error {
  •     NSString *msg = [[NSString alloc]
  •        initWithString:@"Error obtaining location"];
  •     UIAlertView *alert = [[UIAlertView alloc]
  •                           initWithTitle:@"Error"
  •                           message:msg
  •                           delegate:nil
  •                           cancelButtonTitle: @"Done"
  •                           otherButtonTitles:nil];
  •     [alert show];
  •     [msg release];
  •     [alert release];
  • }
  • - (void) dealloc{
  •     [lm release];
  •     [latitudeTextField release];
  •     [longitudeTextField release];
  •     [accuracyTextField release];
  •     [super dealloc];
  • }


  前面的代码创建了 CLLocationManager类的一个实例,在使用对象之前,你应该检查用户是否开启了设备的定位服务,如果开启了,你可以使用 desiredAccuracy属性指定想要的精度,使用下面的常量指定想要的精度:

  l kCLLocationAccuracyBest
  l kCLLocationAccuracyNearestTenMeters
  l kCLLocationAccuracyHundredMeters
  l kCLLocationAccuracyKilometer
  l kCLLocationAccuracyThreeKilometers
  distanceFilter属性让你指定设备必须移动多少距离位置信息才会更新,这个属性的单位是米。如果你想得到所有移动的通知,可以使用kCLDistanceFilterNone常量,最后,使用 startUpdatingLocation方法启动位置管理器。
  要获得位置信息,需处理下面两个事件:
  l locationManager:didUpdateToLocation:fromLocation:
  l locationManager:didFailWithError:
  当获得一个新的定位值时,设备触发 locationManager:didUpdateToLocation:fromLocation:事件,如果位置管理器不能确定位置信息,就会触发 locationManager:didFailWithError:事件。
  当设备可以确定位置时,你可能想显示经纬度值和精度,这时你可以使用CLLocation对象,它的horizontalAccuracy属性可以指定精度范围,单位是米。
  按Command- r在iPhone模拟器上测试该程序,图2显示了模拟器显示的位置经纬度值,同时显示了精度。
   
  图 2 定位测试:当你在iPhone模拟器上测试该示例程序时,总会显示这些固定的值


显示地图
  如果能将位置坐标定位到地图上显示将会更有趣,幸运的是,iPhone 3.0 SDK包括了Map Kit API,它可以让你在程序中显示Google Map,下面以一个例子进行说明。
  还是使用前面创建的项目,在 LBSViewController.xib文件中视图窗口上增加一个按钮,如图3所示。
   
  图 3 View Map按钮:增加按钮后的样子
  在Xcode中框架组上点击右键,增加一个新的框架MapKit.framework。在 LBSViewController.h文件中添加下列代码中的粗体部分:

Java代码

  • #import <UIKit/UIKit.h>
  • #import <CoreLocation/CoreLocation.h>
  • #import <MapKit/MapKit.h>
  • @interface LBSViewController : UIViewController
  •     <CLLocationManagerDelegate> {
  •     IBOutlet UITextField *accuracyTextField;
  •     IBOutlet UITextField *latitudeTextField;
  •     IBOutlet UITextField *longitudeTextField;
  •     CLLocationManager *lm;
  •     MKMapView *mapView;
  • }
  • @property (retain, nonatomic) UITextField *accuracyTextField;
  • @property (retain, nonatomic) UITextField *latitudeTextField;
  • @property (retain, nonatomic) UITextField *longitudeTextField;
  • -(IBAction) btnViewMap: (id) sender;
  • @end


  回到界面编辑器,拖动按钮到文件的所有者项目上,然后选择btnViewMap:。
  在LBSViewController.m文件中,添加下列代码中的粗体部分:

Java代码

  • -(IBAction) btnViewMap: (id) sender {
  •     [self.view addSubview:mapView];
  • }
  • - (void) viewDidLoad {
  •     lm = [[CLLocationManager alloc] init];
  •     lm.delegate = self;
  •     lm.desiredAccuracy = kCLLocationAccuracyBest;
  •     lm.distanceFilter = 1000.0f;
  •     [lm startUpdatingLocation];
  •     mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
  •     mapView.mapType = MKMapTypeHybrid;
  • }
  • - (void) locationManager: (CLLocationManager *) manager
  •     didUpdateToLocation: (CLLocation *) newLocation
  •     fromLocation: (CLLocation *) oldLocation{
  •     NSString *lat = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.coordinate.latitude];
  •     latitudeTextField.text = lat;
  •     NSString *lng = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.coordinate.longitude];
  •     longitudeTextField.text = lng;
  •     NSString *acc = [[NSString alloc] initWithFormat:@"%g",
  •         newLocation.horizontalAccuracy];
  •     accuracyTextField.text = acc;
  •     [acc release];
  •     [lat release];
  •     [lng release];
  •     MKCoordinateSpan span;
  •     span.latitudeDelta=.005;
  •     span.longitudeDelta=.005;
  •     MKCoordinateRegion region;
  •     region.center = newLocation.coordinate;
  •     region.span=span;
  •     [mapView setRegion:region animated:TRUE];
  • }
  • - (void) dealloc{
  •     [mapView release];
  •     [lm release];
  •     [latitudeTextField release];
  •     [longitudeTextField release];
  •     [accuracyTextField release];
  •     [super dealloc];
  • }


  代码解释:

  l 当视图载入时创建一个MKMapView类的实例,设置显示的地图类型。
  l 当用户点击View Map按钮时,在当前视图上增加mapView对象。
  l 当位置信息得到更新时,使用mapView对象的setRegion:方法放大地图。
  在iPhone模拟器中按Command-r测试该程序,点击View Map按钮将会显示一个包含位置管理器返回位置的地图。如图4所示。
   
  图 4 地图位置:通过定位内核框架显示地图位置
  因为模拟器始终显示的是相同的位置,如果你有一部iPhone手机也可以真实地感受一下,当你移动位置时,你会看到地图会自动更新。将 distanceFilter属性设置得小一点,这样可以增强跟踪体验。
http://ming-fanglin.javaeye.com/blog/703744
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-9-28 00:23

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表