bing_source.cpp
Go to the documentation of this file.
00001 // *****************************************************************************
00002 //
00003 // Copyright (c) 2015, Southwest Research Institute® (SwRI®)
00004 // All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that the following conditions are met:
00008 //     * Redistributions of source code must retain the above copyright
00009 //       notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above copyright
00011 //       notice, this list of conditions and the following disclaimer in the
00012 //       documentation and/or other materials provided with the distribution.
00013 //     * Neither the name of Southwest Research Institute® (SwRI®) nor the
00014 //       names of its contributors may be used to endorse or promote products
00015 //       derived from this software without specific prior written permission.
00016 //
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020 // ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE 
00021 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00022 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00023 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00024 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00025 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00027 // DAMAGE.
00028 //
00029 // *****************************************************************************
00030 
00031 #include <tile_map/bing_source.h>
00032 #include <boost/lexical_cast.hpp>
00033 #include <boost/random.hpp>
00034 
00035 #include <QRegExp>
00036 #include <QString>
00037 
00038 #include <json/json.h>
00039 
00040 namespace tile_map
00041 {
00042   const QString BingSource::BING_TYPE = "bing";
00043   const std::string BingSource::BING_IMAGE_URL_KEY = "imageUrl";
00044   const std::string BingSource::BING_IMAGE_URL_SUBDOMAIN_KEY = "imageUrlSubdomains";
00045   const std::string BingSource::BING_RESOURCE_SET_KEY = "resourceSets";
00046   const std::string BingSource::BING_RESOURCE_KEY = "resources";
00047   const std::string BingSource::BING_STATUS_CODE_KEY = "statusCode";
00048 
00049   BingSource::BingSource(const QString& name) :
00050     network_manager_(this)
00051   {
00052     name_ = name;
00053     is_custom_ = false;
00054     max_zoom_ = 19;
00055     base_url_ = "https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?uriScheme=https&include=ImageryProviders&key={api_key}";
00056     tile_url_ = "";
00057     min_zoom_ = 2;
00058 
00059     QObject::connect(&network_manager_, SIGNAL(finished(QNetworkReply*)),
00060                      this, SLOT(ReplyFinished(QNetworkReply*)));
00061   }
00062 
00063   size_t BingSource::GenerateTileHash(int32_t level, int64_t x, int64_t y)
00064   {
00065     size_t hash = hash_((base_url_ + api_key_ + GenerateQuadKey(level, x, y)).toStdString());
00066     return hash;
00067   }
00068 
00069   QString BingSource::GenerateTileUrl(int32_t level, int64_t x, int64_t y)
00070   {
00071     QString url = tile_url_;
00072     if (!subdomains_.empty())
00073     {
00074       boost::random::uniform_int_distribution<> random(0, (int) subdomains_.size() - 1);
00075       url.replace(QString::fromStdString("{subdomain}"), subdomains_[random(rng_)]);
00076     }
00077     url.replace(QString::fromStdString("{quadkey}"), GenerateQuadKey(level, x, y));
00078     return url;
00079   }
00080 
00081   QString BingSource::GetType() const
00082   {
00083     return BING_TYPE;
00084   }
00085 
00086   QString BingSource::GetApiKey() const
00087   {
00088     return api_key_;
00089   }
00090 
00091   void BingSource::SetApiKey(const QString& api_key)
00092   {
00093     api_key_ = api_key.trimmed();
00094     if (!api_key_.isEmpty())
00095     {
00096       QString url(base_url_);
00097       url.replace(QString::fromStdString("{api_key}"), api_key_);
00098       // Changing the API key will result in the tile URL changing; go ahead
00099       // and blank it out so we don't make requests using the old one.
00100       tile_url_= "";
00101       subdomains_.clear();
00102       network_manager_.get(QNetworkRequest(QUrl(url)));
00103     }
00104   }
00105 
00106   QString BingSource::GenerateQuadKey(int32_t level, int64_t x, int64_t y) const
00107   {
00108     QString quadkey;
00109     for (int32_t i = level; i > 0; i--)
00110     {
00111       int32_t bitmask = 1 << (i-1);
00112       int32_t digit = 0;
00113       if ((x & bitmask) != 0)
00114       {
00115         digit |= 1;
00116       }
00117       if ((y & bitmask) != 0)
00118       {
00119         digit |= 2;
00120       }
00121       quadkey.append(QString::number(digit));
00122     }
00123 
00124     return quadkey;
00125   }
00126 
00127   void BingSource::ReplyFinished(QNetworkReply* reply)
00128   {
00129     QString reply_string(reply->readAll());
00130     Json::Reader reader;
00131     Json::Value root;
00132     reader.parse(reply_string.toStdString(), root);
00133 
00134     int status = root[BING_STATUS_CODE_KEY].asInt();
00135     if (status != 200)
00136     {
00137       Q_EMIT ErrorMessage("Bing authorization error: " + boost::lexical_cast<std::string>(status));
00138     }
00139     else
00140     {
00141       if (!root[BING_RESOURCE_SET_KEY].isArray() ||
00142           root[BING_RESOURCE_SET_KEY].size() == 0)
00143       {
00144         Q_EMIT ErrorMessage("No Bing resource sets found.");
00145         return;
00146       }
00147       Json::Value firstResourceSet = root[BING_RESOURCE_SET_KEY][0];
00148 
00149       if (!firstResourceSet[BING_RESOURCE_KEY].isArray() ||
00150           firstResourceSet[BING_RESOURCE_KEY].size() == 0)
00151       {
00152         Q_EMIT ErrorMessage("No Bing resources found.");
00153         return;
00154       }
00155 
00156       Json::Value first_resource = firstResourceSet[BING_RESOURCE_KEY][0];
00157 
00158       std::string image_url = first_resource[BING_IMAGE_URL_KEY].asString();
00159 
00160       if (image_url.empty())
00161       {
00162         Q_EMIT ErrorMessage("No Bing image URL found.");
00163         return;
00164       }
00165 
00166       tile_url_ = QString::fromStdString(image_url);
00167       SetMaxZoom(19);
00168 
00169 
00170       if (!first_resource[BING_IMAGE_URL_SUBDOMAIN_KEY].isArray() ||
00171           first_resource[BING_IMAGE_URL_SUBDOMAIN_KEY].size() == 0)
00172       {
00173         Q_EMIT ErrorMessage("No image URL subdomains; maybe that's ok sometimes?");
00174       }
00175 
00176       for (int i = 0; i < first_resource[BING_IMAGE_URL_SUBDOMAIN_KEY].size(); i++)
00177       {
00178         Json::Value subdomain = first_resource[BING_IMAGE_URL_SUBDOMAIN_KEY][i];
00179         subdomains_.push_back(QString::fromStdString(subdomain.asString()));
00180       }
00181 
00182       Q_EMIT InfoMessage("API Key Set.");
00183     }
00184   }
00185 }


tile_map
Author(s): Marc Alban
autogenerated on Thu Aug 24 2017 02:46:24