Skip to content

Commit

Permalink
Adding support for Bing Maps
Browse files Browse the repository at this point in the history
This makes a number of changes in the `tile_map` plugin in order to support
different types of tile servers, including Bing Maps.  Notable changes include:
- TileSource is now an abstract class
- WMTS server-specific behavior has been moved into a new WmtsSource class
- BingSource provides support for obtaining tiles from Bing Maps
- The UI for specifying server URLs has changed
  - Prefix and coordinate order are no longer separate fields
  - In URLs for WMTS sources, the variables {level}, {x}, and {y} will be substituted with appropriate values when tiles are requested
- Rather than generating hashes for image tiles based on their URLs, hashes are now generated by the TileSource implementations in order to support sources that can pull tiles from multiple servers
- Idle performance has been improved by removing redundant recalculations of the map view
- Added a dependency on libjsoncpp

Resolves #227

Conflicts:
	tile_map/CMakeLists.txt
	tile_map/package.xml
  • Loading branch information
pjreed committed Jul 22, 2016
1 parent 2010cf6 commit 103d8e2
Show file tree
Hide file tree
Showing 18 changed files with 817 additions and 417 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ Textured markers follow the same general approach as traditional markers, but ca
* Topic: The textured marker topic

### Tile Map
Projects a geo-referenced multi-resolution image tile map into the scene. Data is automatically streamed from [OpenMapQuest](http://open.mapquest.com/) (satellite and roads) or [Stamen Design] (http://maps.stamen.com/) (terrain, watercolor, and toner). Custom or local map servers can also be specified. Map data is cached to disk which enables some limited use completely offline.
Projects a geo-referenced multi-resolution image tile map into the scene. Map tiles can be obtained from [Bing Maps](https://www.bing.com/mapspreview) or any [WMTS Tile Service](http://www.opengeospatial.org/standards/wmts). Pre-defined services that access [Stamen Design](http://maps.stamen.com/) (terrain, watercolor, and toner) are provided. Custom or local WMTS map servers can also be specified. Map data is cached to disk which enables some limited use completely offline.

<img src="https://github.com/swri-robotics/mapviz/wiki/satellite.png" width="200" height="200" />
<img src="https://github.com/swri-robotics/mapviz/wiki/roads.png" width="200" height="200" />
Expand All @@ -255,7 +255,10 @@ Projects a geo-referenced multi-resolution image tile map into the scene. Data
<img src="https://github.com/swri-robotics/mapviz/wiki/toner.png" width="200" height="200" />

**Parameters**
* Source: The source of the tile data.
* Source: The name of source of the tile data.
* Base URL: A template URL used to obtain map tiles. When obtaining map tiles, parameters labeled `{level}`, `{x}`, and `{y}` in the URL will be replaced with appropriate values. For example, `http://tile.stamen.com/terrain/{level}/{x}/{y}.png` is appropriate for retrieving terrain tiles from Stamen Design.
* API Key: When the `Bing Maps (terrain)` source is selected, you must enter a Bing Maps access key here and click the `Save` button in order for tiles to be available. You can get a Bing Maps Key from the [Microsoft Developer Network](https://msdn.microsoft.com/en-us/library/ff428642.aspx).
* Max Zoom: The maximum zoom level that will be used when requesting tiles.

### TF Frame

Expand Down
20 changes: 15 additions & 5 deletions tile_map/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ add_definitions(
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")

find_package(PkgConfig REQUIRED)

find_package(GLU REQUIRED)

pkg_check_modules(JSONCPP REQUIRED jsoncpp)

catkin_package(
INCLUDE_DIRS include
DEPENDS Qt5Core Qt5Gui Qt5OpenGL Qt5Widgets
Expand All @@ -55,22 +59,28 @@ catkin_package(
# Fix conflict between Boost signals used by tf and QT signals used by mapviz
add_definitions(-DQT_NO_KEYWORDS)

include_directories(include ${catkin_INCLUDE_DIRS})
include_directories(include ${catkin_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIRS})

include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

file (GLOB TILE_SRC_FILES
src/image_cache.cpp
src/texture_cache.cpp
src/bing_source.cpp
src/tile_source.cpp
src/wmts_source.cpp
src/tile_map_view.cpp)
qt5_wrap_cpp(TILE_SRC_FILES include/tile_map/image_cache.h)
qt5_wrap_cpp(TILE_SRC_FILES
include/tile_map/image_cache.h
include/tile_map/tile_source.h
include/tile_map/wmts_source.h
include/tile_map/bing_source.h)
add_library(${PROJECT_NAME} ${TILE_SRC_FILES})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARIES} ${GLU_LIBRARY} ${catkin_LIBRARIES})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARIES} ${GLU_LIBRARY} ${JSONCPP_LIBRARIES} ${catkin_LIBRARIES})

file (GLOB PLUGIN_SRC_FILES
src/tile_map_plugin.cpp
src/tile_source.cpp)
src/tile_map_plugin.cpp)
file (GLOB PLUGIN_UI_FILES
src/tile_map_config.ui)
qt5_wrap_ui(PLUGIN_SRC_FILES ${PLUGIN_UI_FILES})
Expand Down
141 changes: 141 additions & 0 deletions tile_map/include/tile_map/bing_source.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// *****************************************************************************
//
// Copyright (c) 2015, Southwest Research Institute® (SwRI®)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Southwest Research Institute® (SwRI®) nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL Southwest Research Institute® BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// *****************************************************************************

#ifndef TILE_MAP_BING_SOURCE_H
#define TILE_MAP_BING_SOURCE_H

#include "tile_source.h"

#include <boost/functional/hash.hpp>
#include <boost/random.hpp>

#include <vector>

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QString>

namespace tile_map
{
class BingSource : public TileSource
{
Q_OBJECT
public:
/**
* Initializes a Bing map source with a given name.
*
* Note that currently, only a single, hard-coded Bing map source is supported.
* There's only one Bing Maps, after all.
* In the future, though, it would probably make sense to extend its
* functionality to allow pulling different tile sets from Bing.
* @param name The name the source will appear as in the combo box.
*/
explicit BingSource(const QString& name);

/**
* Generates a unique hash that identifies the tile as the given coordinates.
*
* Note that Bing Maps tiles could potentially be pulled from one of many
* different servers, depending on the subdomain list given to us after we
* authenticate with our API Key. That means the exact URL to any given tile
* should not be used as part of the hash, because there are many valid URLs
* for a tile.
* @param level The zoom level
* @param x The X coordinate
* @param y The Y coordinate
* @return A hash that uniquely identifies this tile
*/
virtual size_t GenerateTileHash(int32_t level, int64_t x, int64_t y);

/**
* Generates a URL that will retrieve a tile for the given coordinates.
*
* Since Bing can give us a list of subdomains to pull tiles from, the
* exact subdomain for a tile is chosen at random every time this function
* is called. That means you are not guaranteed to get the same URL for a
* tile every time you call this function.
* @param level The zoom level
* @param x The X coordinate
* @param y The Y coordinate
* @return A URL that points to this tile
*/
virtual QString GenerateTileUrl(int32_t level, int64_t x, int64_t y);

virtual QString GetType() const;

QString GetApiKey() const;

/**
* Bing requires an API key in order to access its tiles. The key provided
* will determine the URL we use to retrieve map tiles, so setting the API
* key will also cause this object to make a network request to the Bing Map
* server to get the appropriate URL.
*
* More information about getting an API key:
* https://msdn.microsoft.com/en-us/library/ff428642.aspx
* @param api_key A valid Bing Maps key
*/
void SetApiKey(const QString& api_key);

static const QString BING_TYPE;

protected Q_SLOTS:
void ReplyFinished(QNetworkReply* reply);

protected:
/**
* Bing Maps identifies tiles using a quadkey that is generated from the zoom
* level and x and y coordinates. Details on how the quadkey is generated can
* be found here:
* https://msdn.microsoft.com/en-us/library/bb259689.aspx
*
* @param level The zoom level
* @param x The X coordinate
* @param y The Y coordinate
* @return The quadkey that represents the tile at the requested location
*/
QString GenerateQuadKey(int32_t level, int64_t x, int64_t y) const;

QString api_key_;
boost::hash<std::string> hash_;
QNetworkAccessManager network_manager_;
boost::random::mt19937 rng_;
std::vector<QString> subdomains_;
QString tile_url_;

static const std::string BING_IMAGE_URL_KEY;
static const std::string BING_IMAGE_URL_SUBDOMAIN_KEY;
static const std::string BING_RESOURCE_SET_KEY;
static const std::string BING_RESOURCE_KEY;
static const std::string BING_STATUS_CODE_KEY;
};
}

#endif //TILE_MAP_BING_SOURCE_H
17 changes: 8 additions & 9 deletions tile_map/include/tile_map/image_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@

#include <string>

#include <boost/functional/hash.hpp>

#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>

#include <QCache>
Expand All @@ -51,10 +50,10 @@ namespace tile_map
class Image
{
public:
Image(const std::string& uri, size_t uri_hash, uint64_t priority = 0);
Image(const QString& uri, size_t uri_hash, uint64_t priority = 0);
~Image();
std::string Uri() const { return uri_; }

QString Uri() const { return uri_; }
size_t UriHash() const { return uri_hash_; }

boost::shared_ptr<QImage> GetImage() { return image_; }
Expand All @@ -72,7 +71,7 @@ namespace tile_map
void SetLoading(bool loading) { loading_ = loading; }

private:
std::string uri_;
QString uri_;

size_t uri_hash_;

Expand All @@ -93,7 +92,7 @@ namespace tile_map
explicit ImageCache(const QString& cache_dir, size_t size = 4096);
~ImageCache();

ImagePtr GetImage(size_t uri_hash, const std::string& uri, int32_t priority = 0);
ImagePtr GetImage(size_t uri_hash, const QString& uri, int32_t priority = 0);

public Q_SLOTS:
void ProcessRequest(QString uri);
Expand All @@ -105,10 +104,10 @@ namespace tile_map
QNetworkAccessManager network_manager_;

QString cache_dir_;

boost::hash<std::string> hash_function_;

QCache<size_t, ImagePtr> cache_;
QMap<size_t, ImagePtr> unprocessed_;
QMap<QString, size_t> uri_to_hash_map_;

QMutex cache_mutex_;
QMutex unprocessed_mutex_;
Expand Down
2 changes: 1 addition & 1 deletion tile_map/include/tile_map/texture_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace tile_map
public:
explicit TextureCache(ImageCachePtr image_cache, size_t size = 512);

TexturePtr GetTexture(size_t url_hash, const std::string& url, bool& failed);
TexturePtr GetTexture(size_t url_hash, const QString& url, bool& failed);
void AddTexture(const TexturePtr& texture);

void Clear();
Expand Down
21 changes: 14 additions & 7 deletions tile_map/include/tile_map/tile_map_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

// Boost libraries
#include <boost/filesystem.hpp>
#include <boost/shared_ptr.hpp>

#include <mapviz/mapviz_plugin.h>

Expand Down Expand Up @@ -74,19 +75,18 @@ namespace tile_map

QWidget* GetConfigWidget(QWidget* parent);

protected:
protected Q_SLOTS:
void PrintError(const std::string& message);
void PrintInfo(const std::string& message);
void PrintWarning(const std::string& message);

protected Q_SLOTS:
void DeleteTileSource();
void SelectSource(QString source_name);
void SelectSource(const QString& source_name);
void SaveCustomSource();
void ResetTileCache();

private:
void selectTileSource(const TileSource& tile_source);
void selectTileSource(const boost::shared_ptr<TileSource>& tile_source);
void startCustomEditing();
void stopCustomEditing();

Expand All @@ -99,15 +99,22 @@ namespace tile_map
bool transformed_;

TileMapView tile_map_;
std::map<QString, TileSource> tile_sources_;
std::map<QString, boost::shared_ptr<TileSource> > tile_sources_;

double last_center_x_;
double last_center_y_;
double last_scale_;
int32_t last_height_;
int32_t last_width_;

static std::string BASE_URL_KEY;
static std::string COORD_ORDER_KEY;
static std::string BING_API_KEY;
static std::string CUSTOM_SOURCES_KEY;
static std::string MAX_ZOOM_KEY;
static std::string NAME_KEY;
static std::string SOURCE_KEY;
static std::string SUFFIX_KEY;
static std::string TYPE_KEY;
static QString BING_NAME;
static QString STAMEN_TERRAIN_NAME;
static QString STAMEN_TONER_NAME;
static QString STAMEN_WATERCOLOR_NAME;
Expand Down
14 changes: 6 additions & 8 deletions tile_map/include/tile_map/tile_map_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@

#include <string>

#include <boost/functional/hash.hpp>

#include <tile_map/texture_cache.h>
#include <boost/shared_ptr.hpp>

#include <tile_map/tile_source.h>
#include <tile_map/texture_cache.h>

#include <swri_transform_util/transform.h>

Expand All @@ -47,7 +46,7 @@ namespace tile_map
struct Tile
{
public:
std::string url;
QString url;
size_t url_hash;
int32_t level;
int32_t subdiv_count;
Expand All @@ -66,7 +65,7 @@ namespace tile_map

void ResetCache();

void SetTileSource(const TileSource& tile_source);
void SetTileSource(const boost::shared_ptr<TileSource>& tile_source);

void SetTransform(const swri_transform_util::Transform& transform);

Expand All @@ -80,7 +79,7 @@ namespace tile_map
void Draw();

private:
TileSource tile_source_;
boost::shared_ptr<TileSource> tile_source_;

swri_transform_util::Transform transform_;

Expand All @@ -96,8 +95,7 @@ namespace tile_map

std::vector<Tile> tiles_;
std::vector<Tile> precache_;

boost::hash<std::string> hash_function_;

TextureCachePtr tile_cache_;

void ToLatLon(int32_t level, double x, double y, double& latitude, double& longitude);
Expand Down
Loading

0 comments on commit 103d8e2

Please sign in to comment.