多摩美 - “iTamabi” – iPhoneアプリ開発プロジェクト 2010
openFrameworks for iPhone:MapKitを利用して地図を表示する
今日の内容
- openFrameworks for iPhoneで、地図を表示する
- 地図から緯度経度の情報をとりだしたり、地図上に図形を配置してみる
- iTamabiアプリへ応用できるかも?
ofxiPhoneMapKit
- ofxiPhoneMapKit – openFrameworksでMapKitを利用できるようにしたAddon
- MapKitは、iPhone OS 3.0から追加された、地図の表示を扱う事ができるフレームワーク
- MapKitを利用することで、iPhoneに付属の「マップ」アプリと同等の地図を利用することができる
- ofxiPhoneMapKitは、最新のopenFrameworksのiPhone版であれば、既に利用できる形でインストールされている
ofxiPhoneMapKit の使用方法
- ofxiPhoneMapKitクラスをインスタンス化する
- あとは、そのインスタンスに様々なメソッド(関数、動作)を指定するだけで、地図に関する機能を付加していくことができる
opxiPhoneMapKit で使用可能なメソッド
- open() – 地図を開く
- close() – 地図を閉じる
- void setCenter(double latitude, double longitude, bool animated = true); – 地図の中心位置を指定した緯度経度に移動する
- void setSpan(double latitudeDelta, double longitudeDelta, bool animated = true); – 地図の表示範囲を角度で指定
- void setSpanWithMeters(double metersLatitude, double metersLongitude, bool animated = true); – 地図の表示範囲を距離(メートル)で指定
- void setRegion(double latitude, double longitude, double latitudeDelta, double longitudeDelta, bool animated = true); – 地図の中心位置の緯度経度と、表示範囲の角度を同時に指定
- void setRegionWithMeters(double latitude, double longitude, double metersLatitude, double metersLongitude, bool animated = true); – 地図の中心位置の緯度経度と、表示範囲の距離を同時に指定
- void setType(ofxiPhoneMapKitType type = OFXIPHONE_MAPKIT_MAP); – 地図の表示方法を指定する
- 通常の地図:OFXIPHONE_MAPKIT_MAP
- 衛星画像:OFXIPHONE_MAPKIT_SATELLITE
- ハイブリット:OFXIPHONE_MAPKIT_HYRBID
- void setShowUserLocation(bool b); – ユーザの位置を青い点で表示する
- void setAllowUserInteraction(bool b); – 地図とのインタラクションの有効/無効の設定、有効にするとiPhoneのtouchイベント(testApp::touchXXXX)が無視される
- void setAllowZoom(bool b); – ズームの有効/無効
- void setAllowScroll(bool b); – 地図の移動の有効/無効
- bool isUserOnScreen(); – ユーザの位置の表示がされているかどうかを調べる
- ofxMapKitLocation getCenterLocation(); – 現在表示している地図の位置(緯度、経度)を調べる
- ofPoint getScreenCoordinatesForLocation(double latitude, double longitude); – 地図上の位置(緯度、経度)を、画面の座標(ピクセル)に変換
- ofxMapKitLocation getLocationForScreenCoordinates(float x, float y); – 画面の座標(ピクセル)を、地図上の位置(緯度、経度)に変換
- ofRectangle getScreenRectForRegion(double latitude, double latitudeDelta, double longitudeDelta); – 地図上の位置(緯度、経度)と角度(°)から、四角形の領域を生成
- ofRectangle getScreenRectForRegionWithMeters(double latitude, double longitude, double metersLatitude, double metersLongitude); – 地図上の位置(緯度、経度)と距離(メートル)から、四角形の領域を生成
- bool isOpen(); – 現在地図が表示されているかどうかを調べる
ステップ1:地図を表示する
- まず、ofxiPhoneMapkitを使用して、地図を表示してみる
testApp.h
#pragma once #include "ofMain.h" #include "ofxiPhoneExtras.h" class testApp : public ofxiPhoneApp, ofxiPhoneMapKitListener { public: void setup(); void update(); void draw(); void exit(); void touchDown(ofTouchEventArgs &touch); void touchMoved(ofTouchEventArgs &touch); void touchUp(ofTouchEventArgs &touch); void touchDoubleTap(ofTouchEventArgs &touch); void lostFocus(); void gotFocus(); void gotMemoryWarning(); void deviceOrientationChanged(int newOrientation); //ofxiPhoneMapKitをインスタンス化 //すべての地図に関する命令は、このオブジェクトを使用する ofxiPhoneMapKit mapKit; //地図に関するイベント void regionWillChange(bool animated); void regionDidChange(bool animated); void willStartLoadingMap(); void didFinishLoadingMap(); void errorLoadingMap(string errorDescription); };
testApp.mm
#include "testApp.h" //表示する緯度と経度を定義(多摩美の場所) #define LATITUDE 35.61129013687765 #define LONGITUDE 139.34929847717285 //-------------------------------------------------------------- void testApp::setup(){ //iPhoneの基本設定 ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofSetLogLevel(OF_LOG_VERBOSE); ofEnableAlphaBlending(); //load font for displaying info //font.loadFont("verdana.ttf", 12); //MapViewを開く mapKit.open(); //最初に表示する位置と、拡大率(200m x 200m)を設定 mapKit.setRegionWithMeters(LATITUDE, LONGITUDE, 200, 200); //マップに関するイベントのリスナーを追加する mapKit.addListener(this); //ユーザの現在位置を表示(青い点で表示される) mapKit.setShowUserLocation(true); //マップの表示形式を設定 //通常の地図:OFXIPHONE_MAPKIT_MAP //衛星画像:OFXIPHONE_MAPKIT_SATELLITE //ハイブリット:OFXIPHONE_MAPKIT_HYRBID mapKit.setType(OFXIPHONE_MAPKIT_MAP); } //-------------------------------------------------------------- void testApp::update() { } //-------------------------------------------------------------- void testApp::draw() { } void testApp::regionWillChange(bool animated) { } void testApp::regionDidChange(bool animated) { } void testApp::willStartLoadingMap() { } void testApp::didFinishLoadingMap() { } void testApp::errorLoadingMap(string errorDescription) { } //-------------------------------------------------------------- void testApp::exit() { } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus() { } //-------------------------------------------------------------- void testApp::gotFocus() { } //-------------------------------------------------------------- void testApp::gotMemoryWarning() { } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
ステップ2:地図の中心の緯度経度を表示する
- 地図の中心位置の緯度と経度を取得し、地図に重ねて表示する
testApp.h
#pragma once #include "ofMain.h" #include "ofxiPhoneExtras.h" class testApp : public ofxiPhoneApp, ofxiPhoneMapKitListener { public: void setup(); void update(); void draw(); void exit(); void touchDown(ofTouchEventArgs &touch); void touchMoved(ofTouchEventArgs &touch); void touchUp(ofTouchEventArgs &touch); void touchDoubleTap(ofTouchEventArgs &touch); void lostFocus(); void gotFocus(); void gotMemoryWarning(); void deviceOrientationChanged(int newOrientation); //ofxiPhoneMapKitのインスタンス //すべての地図に関する命令は、このオブジェクトを使用する ofxiPhoneMapKit mapKit; //ログ出力用文字列 string log; //地図に関するイベント void regionWillChange(bool animated); void regionDidChange(bool animated); void willStartLoadingMap(); void didFinishLoadingMap(); void errorLoadingMap(string errorDescription); };
testApp.mm
#include "testApp.h" //表示する緯度と経度を定義(多摩美の場所) #define LATITUDE 35.61129013687765 #define LONGITUDE 139.34929847717285 //-------------------------------------------------------------- void testApp::setup(){ //iPhoneの基本設定 ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofSetLogLevel(OF_LOG_VERBOSE); ofEnableAlphaBlending(); //load font for displaying info //font.loadFont("verdana.ttf", 12); //MapViewを開く mapKit.open(); //最初に表示する位置と、拡大率(1000km x 1000km)を設定 mapKit.setRegionWithMeters(LATITUDE, LONGITUDE, 200, 200); //マップに関するイベントのリスナーを追加する mapKit.addListener(this); //ユーザの現在位置を表示(青い点で表示される) mapKit.setShowUserLocation(true); //マップの表示形式を設定 //通常の地図:OFXIPHONE_MAPKIT_MAP //衛星画像:OFXIPHONE_MAPKIT_SATELLITE //ハイブリット:OFXIPHONE_MAPKIT_HYRBID mapKit.setType(OFXIPHONE_MAPKIT_MAP); //OpenGLの表示を前面に ofxiPhoneSendGLViewToFront(); //OpenGLの透明度を有効に ofxiPhoneSetGLViewTransparent(true); //OpenGLの表示部分のインタラクションを無しに ofxiPhoneSetGLViewUserInteraction(false); } //-------------------------------------------------------------- void testApp::update() { if(mapKit.isOpen()) { //現在の中心の緯度と経度を表示 ofxMapKitLocation centerLocation = mapKit.getCenterLocation(); log = "latitude:"+ofToString(centerLocation.latitude,5)+", longitude:"+ofToString(centerLocation.longitude,5); } } //-------------------------------------------------------------- void testApp::draw() { if(mapKit.isOpen()) { ofFill(); ofSetColor(0, 0, 0, 200); ofRect(0, 0, ofGetWidth(), 20); ofSetColor(255, 255, 255); ofDrawBitmapString(log, 10, 10); //中心位置に円を表示 ofNoFill(); ofSetLineWidth(2); ofSetColor(255, 0, 0); ofCircle(ofGetWidth()/2, ofGetHeight()/2, 5); } } void testApp::regionWillChange(bool animated) { } void testApp::regionDidChange(bool animated) { } void testApp::willStartLoadingMap() { } void testApp::didFinishLoadingMap() { } void testApp::errorLoadingMap(string errorDescription) { } //-------------------------------------------------------------- void testApp::exit() { } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus() { } //-------------------------------------------------------------- void testApp::gotFocus() { } //-------------------------------------------------------------- void testApp::gotMemoryWarning() { } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
ステップ3:地図上に図形を配置する
- 緯度と経度を指定して、地図の上に図形を描いて配置していく
- 地図を拡大/縮小したり、位置を移動しても、地図上の点の位置がずれていないところに注目
testApp.h
#pragma once #include "ofMain.h" #include "ofxiPhoneExtras.h" class testApp : public ofxiPhoneApp, ofxiPhoneMapKitListener { public: void setup(); void update(); void draw(); void exit(); void touchDown(ofTouchEventArgs &touch); void touchMoved(ofTouchEventArgs &touch); void touchUp(ofTouchEventArgs &touch); void touchDoubleTap(ofTouchEventArgs &touch); void lostFocus(); void gotFocus(); void gotMemoryWarning(); void deviceOrientationChanged(int newOrientation); //ofxiPhoneMapKitのインスタンス //すべての地図に関する命令は、このオブジェクトを使用する ofxiPhoneMapKit mapKit; //ログ出力用文字列 string log; //緯度、経度で位置を指定するための配列 ofxMapKitLocation mapLoc[9]; //地図に関するイベント void regionWillChange(bool animated); void regionDidChange(bool animated); void willStartLoadingMap(); void didFinishLoadingMap(); void errorLoadingMap(string errorDescription); };
testApp.mm
#include "testApp.h" //表示する緯度と経度を定義(多摩美の場所) #define LATITUDE 35.61127 #define LONGITUDE 139.34983 //-------------------------------------------------------------- void testApp::setup(){ //iPhoneの基本設定 ofRegisterTouchEvents(this); ofxAccelerometer.setup(); ofxiPhoneAlerts.addListener(this); ofSetLogLevel(OF_LOG_VERBOSE); ofEnableAlphaBlending(); //緯度、経度で位置を指定 mapLoc[0].latitude = 35.61045; mapLoc[0].longitude = 139.35108; mapLoc[1].latitude = 35.61090; mapLoc[1].longitude = 139.35029; mapLoc[2].latitude = 35.61124; mapLoc[2].longitude = 139.34923; mapLoc[3].latitude = 35.61139; mapLoc[3].longitude = 139.35041; mapLoc[4].latitude = 35.61207; mapLoc[4].longitude = 139.35048; mapLoc[5].latitude = 35.61185; mapLoc[5].longitude = 139.34979; mapLoc[6].latitude = 35.61153; mapLoc[6].longitude = 139.35120; mapLoc[7].latitude = 35.61222; mapLoc[7].longitude = 139.34878; mapLoc[8].latitude = 35.61150; mapLoc[8].longitude = 139.34828; //MapViewを開く mapKit.open(); //最初に表示する位置と、拡大率(300m x 300m)を設定 mapKit.setRegionWithMeters(LATITUDE, LONGITUDE, 300, 300); //マップに関するイベントのリスナーを追加する mapKit.addListener(this); //ユーザの現在位置を表示(青い点で表示される) mapKit.setShowUserLocation(true); //マップの表示形式を設定 //通常の地図:OFXIPHONE_MAPKIT_MAP //衛星画像:OFXIPHONE_MAPKIT_SATELLITE //ハイブリット:OFXIPHONE_MAPKIT_HYRBID mapKit.setType(OFXIPHONE_MAPKIT_MAP); //OpenGLの表示を前面に ofxiPhoneSendGLViewToFront(); //OpenGLの透明度を有効に ofxiPhoneSetGLViewTransparent(true); //OpenGLの表示部分のインタラクションを無しに ofxiPhoneSetGLViewUserInteraction(false); } //-------------------------------------------------------------- void testApp::update() { if(mapKit.isOpen()) { //現在の中心の緯度と経度を表示 ofxMapKitLocation centerLocation = mapKit.getCenterLocation(); log = "latitude:"+ofToString(centerLocation.latitude,5)+", longitude:"+ofToString(centerLocation.longitude,5); } } //-------------------------------------------------------------- void testApp::draw() { if(mapKit.isOpen()) { ofFill(); ofSetColor(0, 0, 0, 200); ofRect(0, 0, ofGetWidth(), 20); ofSetColor(255, 255, 255); ofDrawBitmapString(log, 10, 10); //中心位置に赤い円を表示 ofNoFill(); ofSetLineWidth(2); ofSetColor(255, 0, 0); ofCircle(ofGetWidth()/2, ofGetHeight()/2, 5); //位置を指定した場所に青い円を表示 ofFill(); ofSetColor(0, 0, 255); for (int i=0; i<9; i++) { ofPoint loc = mapKit.getScreenCoordinatesForLocation(mapLoc[i].latitude, mapLoc[i].longitude); ofCircle(loc.x, loc.y, 5); } } } void testApp::regionWillChange(bool animated) { } void testApp::regionDidChange(bool animated) { } void testApp::willStartLoadingMap() { } void testApp::didFinishLoadingMap() { } void testApp::errorLoadingMap(string errorDescription) { } //-------------------------------------------------------------- void testApp::exit() { } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ } //-------------------------------------------------------------- void testApp::lostFocus() { } //-------------------------------------------------------------- void testApp::gotFocus() { } //-------------------------------------------------------------- void testApp::gotMemoryWarning() { } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ }
サンプルファイルのダウンロード
今日の授業の全てのサンプルファイルは、以下のリンクよりダウンロードしてください