サンプル・プログラム
address2geowin.msi | インストーラ |
bin/address2geowin.exe | 実行プログラム本体 |
bin/libcurl-x64.dll | 実行時に必要になるDLL |
bin/etc/help.chm | ヘルプ・ファイル |
sour/address2geowin.cpp | ソース・プログラム |
sour/resource.h | リソース・ヘッダ |
sour/resource.rc | リソース・ファイル |
sour/application.ico | アプリケーション・アイコン |
sour/mystrings.cpp | 汎用文字列処理関数など(ソース) |
sour/mystrings.h | 汎用文字列処理関数など(ヘッダ) |
sour/pahooGeocode.cpp | 住所・緯度・経度に関わるクラス(ソース) |
sour/pahooGeocode.cpp | 住所・緯度・経度に関わるクラス(ヘッダ) |
sour/apikey.cpp | APIキーの管理(ソース) |
sour/apikey.hpp | APIキーの管理(ヘッダ) |
sour/makefile | ビルド |
バージョン | 更新日 | 内容 |
---|---|---|
1.2.3 | 2024/08/17 | 使用ライブラリ更新 |
1.2.2 | 2024/03/23 | 使用ライブラリ更新 |
1.2.1 | 2023/11/11 | 使用ライブラリ更新 |
1.2.0 | 2023/07/02 | 国土地理院ジオコーディングAPIを使用出来るように |
1.1.2 | 2023/04/01 | 使用ライブラリ更新 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/05/03 | getMyPath()をapikey.appのgetMyPath()関数に変更 |
1.7.0 | 2024/04/27 | Edge対応に伴いデバッグ用コードを廃棄 |
1.6.0 | 2023/07/02 | getPointsGSI()メソッド追加 |
1.5 | 2022/09/03 | デバッグコード埋め込み |
1.4 | 2021/05/01 | makeMapLeaflet() 引数追加 |
バージョン | 更新日 | 内容 |
---|---|---|
1.2.0 | 2024/05/06 | getModulePath() 追加 |
1.12 | 2021/01/31 | readWebContents() 引数post追加 |
1.11 | 2020/10/17 | htmlspecialchars() 追加 |
1.1 | 2020/10/17 | GetVersion2()追加,readWebContents() 引数ua追加 |
1.01 | 2020/10/03 | setClipboardData() bug-fix |
使用ライブラリ
リソースの準備
Eclipse を起動し、新規プロジェクト address2geowin を用意する。
ResEdit を起動し、resource.rc を用意する。
Eclipse に戻り、ソース・プログラム "address2geowin.cpp" を追加する。
リンカー・フラグを -mwindows -static -lstdc++ -lgcc -lwinpthread -lcurl -lssl -lole32 "C:\pleiades\eclipse\mingw\mysys2\mingw32\bin\libcurl.dll" に設定する。
MSYS2 コマンドラインからビルドするのであれば、"makefile" を利用してほしい。
解説:定数など
36: // 定数など ==================================================================
37: #define MAKER "pahoo.org" //作成者
38: #define APPNAME "address2geowin" //アプリケーション名
39: #define APPNAMEJP "住所などから緯度・経度を求める"
40: //アプリケーション名(日本語)
41: #define APPVERSION "1.2.3" //バージョン
42: #define APPYEAR "2020-24" //作成年
43: #define REFERENCE "https://www.pahoo.org/e-soul/webtech/cpp01/cpp01-14-01.shtm" // 参考サイト
44:
45: //ヘルプ・ファイル
46: #define HELPFILE ".\\etc\\help.chm"
47:
48: //デフォルト保存ファイル名
49: #define SAVEFILE "address2geowin.txt"
50:
51: //現在のインターフェイス
52: HINSTANCE hInst;
53:
54: //アプリケーション・ウィンドウ
55: HWND hParent;
56:
57: //アプリケーション・ウィンドウ位置
58: unsigned hParent_X, hParent_Y;
59:
60: //検索キー格納用
61: string Query;
62:
63: //エラー・メッセージ格納用【変更不可】
64: string ErrorMessage;
65:
66: //UserAgent
67: string UserAgent;
68:
69: //pahooGeocodeオブジェクト
70: pahooGeocode *pGC;
解説:クラス
今回は、クラウドサービスにアクセする処理を pahooGeocode クラス としてコーディングした。ソースは "pahooGeocode.cpp" ヘッダは "pahooGeocode.hpp" である。
31: using namespace std;
32: using namespace boost;
33: using namespace boost::property_tree;
34:
35: /**
36: * コンストラクタ
37: * @param string appname アプリケーション名
38: */
39: pahooGeocode::pahooGeocode(std::string appname) {
40: this->appname = appname;
41: this->readGoogleApiKey();
42: //ホットペッパーグルメWebサービス APIキー読み込み
43: readApiKey(FNAME_YAHOO_API, &this->YahooAPIkey);
44: }
45:
46: //デストラクタ
47: pahooGeocode::~pahooGeocode() {
48: }
49:
50: // 各種処理 ==================================================================
ここでは、GoogleAPIキーやYahoo!アプリケーションIDの読み込みを行う。
このデストラクタは何もしない。
解説:住所検索サービスAPI
値 | サービス名 | メソッド | 制 約 |
---|---|---|---|
1 | getPointsGoogle | 有料(決められた無料枠あり)。全世界の住所、ランドマークの検索可能。 | |
2 | Yahoo!JAPAN | getPointsYOLP | 無料(?)。住所、ランドマーク、海外のどれを検索するか指定。ランドマークや海外地名検索はGoogleに劣る。 |
11 | HeartRails Geo API | getPointsHRG | 無料。住所、または住所の一部のみ検索可能。 |
12 | OSM Nominatim Search API | getPointsNominatim | 無料。全世界の住所、ランドマークの検索可能。精度はGoogleに劣る。 |
13 | 国土地理院ジオコーディングAPI | getPointsGSI | 無料。日本国内の住所、ランドマークの検索可能。精度はGoogleに劣る。 |
652: /**
653: * ジオコーダAPI を用いて検索キーワードから緯度・経度を求める
654: *
655: * @param wstring query 検索キーワード
656: * 郵便番号表記 ###-####または#######(半角数字)
657: * 緯度・経度表記 E##.##.##.#N###.##.##.#(半角数字)
658: * 緯度・経度表記 ##.##,###.##(緯度,経度;半角数字)
659: * @param string ua UserAgent
660: * @param int api 0:APIを自動選定(省略時)
661: * 1:Google Geocoding API
662: * 2:Yahoo!ジオコーダAPI
663: * 11:HeartRails Geo API
664: * 12:OSM Nominatim Search API
665: * 13:国土地理院ジオコーディングAPI
666: * @return int ヒットした地点数
667: */
668: int pahooGeocode::searchPoints(wstring query, string ua, int api=0) {
669: static int apilist[] = { 1, 2, 11, 12, 13 };
670: int cnt;
671: wsmatch mt1;
672: //郵便番号パターン
673: wregex re01(_SW("([0-9]{3})\\-?([0-9]{4})"));
674: //緯度・経度パターン
675: wregex re11(_SW("(E|e|W|w|N|n|S|s)([0-9]+)\\.([0-9]+)\\.([0-9]+\\.?[0-9]*)(E|e|W|w|N|n|S|s)([0-9]+)\\.([0-9]+)\\.([0-9]+\\.?[0-9]*)"));
676: wregex re12(_SW("(E|e|W|w|N|n|S|s)([0-9]+\\.?[0-9]*)(E|e|W|w|N|n|S|s)([0-9]+\\.?[0-9]*)"));
677: wregex re13(_SW("(\\+|\\-)*([0-9]+\\.?[0-9]*)\\s*,\\s*(\\+|\\-)*([0-9]+\\.?[0-9]*)"));
678:
679: //配列の初期化
680: for (int i = 0; i < __SIZE_PPOINTS; i++) {
681: this->Ppoints[i].longitude = 0;
682: this->Ppoints[i].latitude = 0;
683: this->Ppoints[i].address = L"";
684: }
685:
686: //郵便番号かどうか
687: if (regex_search(query, mt1, re01)) {
688: cnt = this->getPointsHRG_postal(_WS(mt1[1].str() + mt1[2].str()), ua);
689:
690: //緯度・経度表記かどうか
691: } else if (regex_search(query, mt1, re11)) {
692: cnt = 0;
693: string s1 = _WS(mt1[1].str());
694: string s2 = _WS(mt1[5].str());
695: double d1 = stod(mt1[2].str()) + stod(mt1[3].str()) / 60 + stod(mt1[4].str()) / (60 * 60);
696: double d2 = stod(mt1[6].str()) + stod(mt1[7].str()) / 60 + stod(mt1[8].str()) / (60 * 60);
697: if ((s1 == "E") || (s1 == "e")) {
698: this->Ppoints[cnt].longitude = d1;
699: } else if ((s1 == "S") || (s1 == "s")) {
700: this->Ppoints[cnt].longitude = -d1;
701: } else if ((s1 == "N") || (s1 == "n")) {
702: this->Ppoints[cnt].latitude = d1;
703: } else if ((s1 == "S") || (s1 == "s")) {
704: this->Ppoints[cnt].latitude = -d1;
705: }
706: if ((s2 == "E") || (s2 == "e")) {
707: this->Ppoints[cnt].longitude = d2;
708: } else if ((s2 == "S") || (s2 == "s")) {
709: this->Ppoints[cnt].longitude = -d2;
710: } else if ((s2 == "N") || (s2 == "n")) {
711: this->Ppoints[cnt].latitude = d2;
712: } else if ((s2 == "S") || (s2 == "s")) {
713: this->Ppoints[cnt].latitude = -d2;
714: }
715: cnt++;
716: } else if (regex_search(query, mt1, re12)) {
717: cnt = 0;
718: string s1 = _WS(mt1[1].str());
719: string s2 = _WS(mt1[3].str());
720: double d1 = stod(mt1[2].str());
721: double d2 = stod(mt1[4].str());
722: if ((s1 == "E") || (s1 == "e")) {
723: this->Ppoints[cnt].longitude = d1;
724: } else if ((s1 == "S") || (s1 == "s")) {
725: this->Ppoints[cnt].longitude = -d1;
726: } else if ((s1 == "N") || (s1 == "n")) {
727: this->Ppoints[cnt].latitude = d1;
728: } else if ((s1 == "S") || (s1 == "s")) {
729: this->Ppoints[cnt].latitude = -d1;
730: }
731: if ((s2 == "E") || (s2 == "e")) {
732: this->Ppoints[cnt].longitude = d2;
733: } else if ((s2 == "S") || (s2 == "s")) {
734: this->Ppoints[cnt].longitude = -d2;
735: } else if ((s2 == "N") || (s2 == "n")) {
736: this->Ppoints[cnt].latitude = d2;
737: } else if ((s2 == "S") || (s2 == "s")) {
738: this->Ppoints[cnt].latitude = -d2;
739: }
740: cnt++;
741: } else if (regex_search(query, mt1, re13)) {
742: cnt = 0;
743: string s1 = _WS(mt1[1].str());
744: string s2 = _WS(mt1[3].str());
745: double d1 = stod(mt1[2].str());
746: double d2 = stod(mt1[4].str());
747: if ((s1 == "") || (s1 == "+")) {
748: this->Ppoints[cnt].latitude = d1;
749: } else if (s1 == "-") {
750: this->Ppoints[cnt].latitude = -d1;
751: }
752: if ((s2 == "") || (s2 == "+")) {
753: this->Ppoints[cnt].longitude = d2;
754: } else if (s2 == "-") {
755: this->Ppoints[cnt].longitude = -d2;
756: }
757: cnt++;
758:
759: //APIを自動選定
760: } else if (api == 0) {
761: for (int api : apilist) {
762: this->resetError();
763: cnt = this->__searchPoints(query, ua, api);
764: if (cnt > 0) break;
765: }
766: //API指定
767: } else {
768: cnt = this->__searchPoints(query, ua, api);
769: }
770:
771: return cnt;
772: }
自動選定の順序は、上表にしたがう。GoogleAPIキーやYahoo!アプリケーションIDが未登録の場合は、これらの呼び出しをスキップする。また、そのクラウドサービスを利用することができなかったり、検索結果がゼロだった場合は、次点のサービスを自動的に呼び出す。
参考サイト
- PHPで住所・ランドマークから緯度・経度を求める:ぱふぅ家のホームページ
- PHPでクラスを使ってテキストの読みやすさを調べる:ぱふぅ家のホームページ
- WiX によるWindowsインストーラー作成:ぱふぅ家のホームページ
- C++ 開発環境の準備:ぱふぅ家のホームページ
- デジタルスチルカメラ用画像ファイルフォーマット規格 Exif 2.3:カメラ映像機器工業会規格
「PHPで住所・ランドマークから緯度・経度を求める」で作ったPHPプログラムをC++に移植したものである。
(2024年8月17日)使用ライブラリ更新
(2024年3月23日)使用ライブラリ更新
(2023年11月11日)使用ライブラリ更新