简体   繁体   中英

Return Mapzen geocoding results to a C++ application (qt or wxwidgets)

I have an hybrid C++ / Javascript application that displays a Leaflet map inside a QtWebEngine view

http://leafletjs.com/

http://doc.qt.io/qt-5/qwebengineview.html

or inside an wxWebView

http://docs.wxwidgets.org/trunk/classwx_web_view.html

so far the communication has been 1 directional

in C++ I define Javascript as a C++ string and call the appropriate javascript running method (from Qt or WxWidgets), like this I can input , say latitude and longitude on the C++ side, and the javascrit side is just the end point.

for example, for Qt

void WebView::loadFinished(bool)
{
  std::string str_js = get_render_javascript_leaflet();
  page()->runJavaScript(QString::fromStdString(str_js));
}

std::string WebView::get_render_javascript_leaflet()
{
  std::string js;
  std::string str_lat;
  std::string str_lon;

  str_lat = std::to_string((long double)38.9250);
  str_lon = std::to_string((long double)-77.0387);

  js = "var map = L.map('map').setView([";
  js += str_lat;
  js += ",";
  js += str_lon;
  js += "], 14);";

  js += "map.options.scrollWheelZoom = false;";
  js += "map.options.minZoom = 2;";
  js += "map.options.maxZoom = 20;";

  js += "L.tileLayer('http://{s}.google.com/vt/lyrs=p&x={x}&y={y}&z={z}',{";
  js += "maxZoom: 20,";
  js += "subdomains:['mt0','mt1','mt2','mt3']";
  js += "}).addTo(map);";

  //mapzen geocoder
  js += "L.control.geocoder('mapzen-<YOUR MAPZEN KEY>').addTo(map);";

  return js;
}

but now , I want to add a geocoding input to the map, using Mapzeen,

https://github.com/mapzen/leaflet-geocoder

so i was wondering how the call

//mapzen geocoder
  js += "L.control.geocoder('mapzen-<YOUR MAPZEN KEY>').addTo(map);";

could return the geocoding results to the C++ side.

Qt has methods that allow peer-to-peer communication between a C++ application and a client (HTML/JavaScript) , but the question here is more what to retrieve from the Mapzen search

http://doc.qt.io/qt-5/qtwebchannel-index.html

There are 2 ways to solve this

1) First, read the Mazen documentation, always a good idea before asking.

2) The first way:

add an event listener for the "results" event on the geocoder

https://github.com/mapzen/leaflet-geocoder#on-results-or-error

then get the results data, and pass that as JSON through the qtwebchannel.

example of an mapzen event for a leaflet map (replace YOUR_API_KEY with a key obtained on the mapzen web site)

<script>
var map = L.map('map').setView([38.9250, -77.0387], 14);
map.options.scrollWheelZoom = false;
map.options.minZoom = 2;
map.options.maxZoom = 20;
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{
}).addTo(map);
var geocoder = L.control.geocoder('mapzen-YOUR_API_KEY');
geocoder.on('select', function (e) 
{
  alert(e.feature.properties.label);
});
geocoder.addTo(map);
</script>

3) A simpler way

Do a HTTP request using C sockets.

This way is pure C/C++ , so no need to use qtwebchannel to link to Javascript.

the result (latitude, longitude) can be sent directly to a leaflet map without the need to do the geocode query inside the javascript.

It's just a matter of constructing an HTTP header that has the query parameters we need.

an example in C++:

   http_t client(host_name, port); 
   //open connection
   if (client.open() < 0)
   {        
   }  
  std::string str_header;
  str_header += "GET /v1/search?api_key=mapzen-YOUR_API_KEY&text=YMCA&size=2 HTTP/1.1\r\n";
  str_header += "Host: ";
  str_header += "search.mapzen.com";
  str_header += "\r\n";
  str_header += "Accept: application/json\r\n";
  str_header += "Connection: close";
  str_header += "\r\n";
  str_header += "\r\n";
 //send request, using built in tcp_client_t socket
  if (client.write(str_header.c_str(), str_header.size()) < 0)
  {           
  } 
 //we sent a close() server request, so we can use the read_all function
 //that checks for recv() return value of zero (connection closed)
 if (client.read_all_get_close("mazen.response.txt", verbose)< 0)
 {        
 }
 client.close();

this uses lib_netsockets

https://github.com/pedro-vicente/lib_netsockets/blob/master/examples/http_client.cc

mapzen replied with this HTTP

    HTTP/1.1 200 OK
Age: 0
Via: 1.1 140.90.160.232 (McAfee Web Gateway 7.6.2.2.0.21927)
Date: Mon, 24 Apr 2017 19:13:45 GMT
etag: W/"734-KRn5K9yTLPWwZt8pN3/G4TSSTr0"
Vary: Accept-Encoding
charset: utf8
X-Cache: MISS, MISS from 140.90.160.232
X-Timer: S1493061226.560908,VS0,VE95
Connection: Close
X-Served-By: cache-iad2123-IAD
Content-Type: application/json; charset=utf-8
X-Cache-Hits: 0
x-powered-by: mapzen
Cache-Control: public, max-age=120
Content-Length: 1844
X-ApiaxleProxy-Qpd-Left: 29998
X-ApiaxleProxy-Qps-Left: 5
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Authorization, Content-Type, Accept, Origin, User-Agent, Cache-Control, Keep-Alive, If-Modified-Since, If-None-Match, X-Requested-With
Access-Control-Allow-Methods: GET, HEAD
Access-Control-Expose-Headers: Content-Type, Cache-Control, ETag, Expires, Last-Modified, Content-Length, X-ApiaxleProxy-Qpd-Left, X-ApiaxleProxy-Qpm-Left, X-ApiaxleProxy-Qps-Left, X-Cache
Access-Control-Allow-Credentials: true

{"geocoding":{"version":"0.2","attribution":"https://search.mapzen.com/v1/attribution","query":{"text":"YMCA","size":2,"private":false,"lang":{"name":"English","iso6391":"en","iso6393":"eng","defaulted":true},"querySize":4},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1493061225650},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-71.532305,43.020898]},"properties":{"id":"polyline:8893463","gid":"openstreetmap:street:polyline:8893463","layer":"street","source":"openstreetmap","source_id":"polyline:8893463","name":"YMCA","street":"YMCA","confidence":0.6,"accuracy":"centroid","country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"New Hampshire","region_gid":"whosonfirst:region:85688689","region_a":"NH","county":"Hillsborough County","county_gid":"whosonfirst:county:102085493","localadmin":"Goffstown","localadmin_gid":"whosonfirst:localadmin:404477175","neighbourhood":"Grasmere","neighbourhood_gid":"whosonfirst:neighbourhood:85822609","label":"YMCA, Goffstown, NH, USA"},"bbox":[-71.532563,43.020401,-71.532227,43.021076]},{"type":"Feature","geometry":{"type":"Point","coordinates":[19.143451,48.738157]},"properties":{"id":"node:388597045","gid":"openstreetmap:venue:node:388597045","layer":"venue","source":"openstreetmap","source_id":"node:388597045","name":"YMCA","confidence":0.6,"accuracy":"point","country":"Slovakia","country_gid":"whosonfirst:country:85633769","country_a":"SVK","region":"Banskobystrický kraj","region_gid":"whosonfirst:region:85688355","county":"Banská Bystrica","county_gid":"whosonfirst:county:102080531","locality":"Banská Bystrica","locality_gid":"whosonfirst:locality:101752053","label":"YMCA, Banská Bystrica, Slovakia"}}],"bbox":[-71.532563,43.020401,19.143451,48.738157]}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM