File indexing completed on 2025-04-20 04:02:16
0001 /* 0002 * SPDX-FileCopyrightText: (C) 2015 Vishesh Handa <me@vhanda.in> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "reversegeocoder.h" 0008 0009 #include <QFile> 0010 #include <QStandardPaths> 0011 #include <QTextStream> 0012 0013 #include <QDebug> 0014 #include <QMutexLocker> 0015 0016 using namespace Koko; 0017 0018 ReverseGeoCoder::~ReverseGeoCoder() 0019 { 0020 deinit(); 0021 } 0022 0023 void ReverseGeoCoder::init() 0024 { 0025 QString citiesPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, "cities1000.txt"); 0026 Q_ASSERT(!citiesPath.isEmpty()); 0027 0028 QFile file(citiesPath); 0029 if (!file.open(QIODevice::ReadOnly)) { 0030 Q_ASSERT_X(0, "", "Failed to open cities1000.txt file"); 0031 } 0032 QTextStream fstream(&file); 0033 0034 while (!fstream.atEnd()) { 0035 QString str = fstream.readLine(); 0036 str.remove('\r'); 0037 0038 QStringList list = str.split('\t'); 0039 0040 // int geoId = list[0].toInt(); 0041 // QString name = list[1]; 0042 double lat = list[4].toDouble(); 0043 double lon = list[5].toDouble(); 0044 0045 QString countryCode = list[8]; 0046 QString admin1Code = list[10]; 0047 QString admin2Code = list[11]; 0048 0049 QVariantMap map = QVariantMap(); 0050 // map.insert("geoId", geoId); 0051 // map.insert("name", name); 0052 map.insert("countryCode", countryCode); 0053 map.insert("admin1Code", admin1Code); 0054 map.insert("admin2Code", admin2Code); 0055 0056 m_tree.insert(lat, lon, map); 0057 } 0058 0059 // Country 0060 QString countryPath = QStandardPaths::locate(QStandardPaths::AppDataLocation, "countries.csv"); 0061 Q_ASSERT(!countryPath.isEmpty()); 0062 0063 QFile cFile(countryPath); 0064 if (!cFile.open(QIODevice::ReadOnly)) { 0065 Q_ASSERT_X(0, "", "Failed to open countries.csv file"); 0066 } 0067 QTextStream cstream(&cFile); 0068 0069 while (!cstream.atEnd()) { 0070 QString str = cstream.readLine(); 0071 0072 QStringList list = str.split(','); 0073 0074 QString code = list[0]; 0075 QString name = list[1]; 0076 m_countryMap.insert(code, name); 0077 } 0078 Q_ASSERT_X(!m_countryMap.isEmpty(), "", "countries.csv file is empty. Packaging issue"); 0079 0080 // Admin1 0081 QString admin1Path = QStandardPaths::locate(QStandardPaths::AppDataLocation, "admin1Codes.txt"); 0082 Q_ASSERT(!admin1Path.isEmpty()); 0083 0084 QFile admin1File(admin1Path); 0085 if (!admin1File.open(QIODevice::ReadOnly)) { 0086 Q_ASSERT_X(0, "", "Failed to open admin1Codes.txt file"); 0087 } 0088 QTextStream a1fstream(&admin1File); 0089 0090 while (!a1fstream.atEnd()) { 0091 QString str = a1fstream.readLine(); 0092 str.remove('\r'); 0093 0094 QStringList list = str.split('\t'); 0095 0096 QString code = list[0]; 0097 QString name = list[1]; 0098 m_admin1Map.insert(code, name); 0099 } 0100 Q_ASSERT_X(!m_admin1Map.isEmpty(), "", "admin1Codes.txt file is empty. Packaging issue"); 0101 0102 // Admin2 0103 QString admin2Path = QStandardPaths::locate(QStandardPaths::AppDataLocation, "admin2Codes.txt"); 0104 Q_ASSERT(!admin2Path.isEmpty()); 0105 0106 QFile admin2File(admin2Path); 0107 if (!admin2File.open(QIODevice::ReadOnly)) { 0108 Q_ASSERT_X(0, "", "Failed to open admin2Codes.txt file"); 0109 } 0110 QTextStream a2fstream(&admin2File); 0111 0112 while (!a2fstream.atEnd()) { 0113 QString str = a2fstream.readLine(); 0114 str.remove('\r'); 0115 0116 QStringList list = str.split('\t'); 0117 0118 QString code = list[0]; 0119 QString name = list[1]; 0120 m_admin2Map.insert(code, name); 0121 } 0122 Q_ASSERT_X(!m_admin2Map.isEmpty(), "", "admin2Codes.txt file is empty. Packaging issue"); 0123 } 0124 0125 void ReverseGeoCoder::deinit() 0126 { 0127 QMutexLocker locker(&m_mutex); 0128 0129 m_tree.clear(); 0130 m_countryMap.clear(); 0131 m_admin1Map.clear(); 0132 m_admin2Map.clear(); 0133 } 0134 0135 bool ReverseGeoCoder::initialized() 0136 { 0137 return !m_tree.isEmpty(); 0138 } 0139 0140 QVariantMap ReverseGeoCoder::lookup(double lat, double lon) 0141 { 0142 QMutexLocker locker(&m_mutex); 0143 if (!initialized()) { 0144 init(); 0145 } 0146 Q_ASSERT(!m_tree.isEmpty()); 0147 0148 KdNode *res = m_tree.findNearest(lat, lon); 0149 if (res == nullptr) { 0150 return QVariantMap(); 0151 } 0152 0153 QVariantMap map = res->data; 0154 0155 QString country = map.value("countryCode").toString(); 0156 QString admin1 = country + '.' + map.value("admin1Code").toString(); 0157 QString admin2 = admin1 + '.' + map.value("admin2Code").toString(); 0158 0159 QVariantMap vMap; 0160 vMap.insert("country", m_countryMap.value(country)); 0161 vMap.insert("admin1", m_admin1Map.value(admin1)); 0162 vMap.insert("admin2", m_admin2Map.value(admin2)); 0163 0164 return vMap; 0165 }