01 First project

Overview

This tutorial will teach the basics to create a project with the native NavigationSDK.
You will learn how to add the NavigationSDK as a project dependency, how to initialize it correctly and which additional data you need. The SDK runs on all major platforms like Windows, Linux and MacOS. To be able to quickly adapt the tutorials to these different platforms and to avoid using platform specific APIs, we used the Qt Framework (min. Version 5.8) and CMake for our tutorials.
CMake can generate project files for Visual Studio, XCode, QtCreator and many more environments, so you are free to use any of these systems to build the tutorials. For example, QtCreator can directly open CMake project files. XCode project files can be generated by CMake using the "-G Xcode" command line parameter.

Note

We will use Visual Studio 2015, Qt 5.8 and CMake 3.5 for these tutorials.

The native SDK package contains the following directories:

  • docs (SDK documentation files)
  • res (necessary data to run the tutorials)

  • maps (prepackaged map data)

  • sdk (NavigationSDK libraries and headers)
  • tutorial (tutorial sources)
  • license.key (license key for the SDK)

Attention

With your copy of the SDK you get a test license.key file. With this license.key you are able to test the SDK until a specified date. Please contact PTV if your test license.key has expired.

Create your first NavigationSDK project

Please install Visual Studio 2015, Qt 5.8 and CMake 3.5 or higher and add the Qt main directory to the system variable "CMAKE_PREFIX_PATH".
The delivered source code of our tutorials is devided into chapters like this documentation. Each chapter has it's own tutorial source code, but all tutorials are built on each other. In this step by step tutorial, we will alter the sources in one directory, so you don't have to create a separate directory for every chapter.

Create an application directory
Create a directory with a name of your choice and create a file called CMakeLists.txt in this directory with the following text:

cmake_minimum_required(VERSION 3.5)
project(Tutorials)

set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{CMAKE_PREFIX_PATH})

LINK_DIRECTORIES(${CMAKE_SOURCE_DIR}/navigationSDK)

if(WIN32)
    message(STATUS "System: Windows")
else()
    message(STATUS "System: Most likely Posix")
    add_definitions(-DPOSIX)
endif(WIN32)

add_subdirectory(Tutorial)

As you can see, this is a little stripped down version of the original CMakeLists.txt file in the top level directory of our tutorials.

Create a subdirectory and name it "Tutorial".
Create a CMakeLists.txt file in the "Tutorial" directory with the following text:

cmake_minimum_required(VERSION 3.5)

set(Tutorial_RES

)

set(Tutorial_SRCS

)

set(Tutorial_HEADER    

    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKInterface.h
    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKError.h
    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKDef.h
)

set(Tutorial_ALL_SRCS
    ${Tutorial_RES}
    ${Tutorial_SRCS}
    ${Tutorial_HEADER}
)



set(Tutorial_LIBS
    Qt5::Widgets
    navigationSDK
)

# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

# Find the QtWidgets library
find_package(Qt5Widgets)

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

add_executable(Tutorial ${Tutorial_ALL_SRCS})

target_link_libraries(Tutorial ${Tutorial_LIBS})

add_custom_command(TARGET Tutorial POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        "${PROJECT_SOURCE_DIR}/navigationsdk/navigationSDK.dll"
        $<TARGET_FILE_DIR:Tutorial>) 

# generate proper GUI program on specified platform
if(WIN32) # Check if we are on Windows
    if(MSVC) # Check if we are using the Visual Studio compiler
        set_target_properties(Tutorial PROPERTIES
            WIN32_EXECUTABLE YES
            LINK_FLAGS "/ENTRY:mainCRTStartup"
        )
    elseif(CMAKE_COMPILER_IS_GNUCXX)
            # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested
    else()
        message(SEND_ERROR "You are using an unsupported Windows compiler! (Not MSVC or GCC)")
    endif(MSVC)
elseif(APPLE)
    set_target_properties(Tutorial PROPERTIES
            MACOSX_BUNDLE YES
    )
elseif(UNIX)
    # Nothing special required
else()
    message(SEND_ERROR "You are on an unsupported platform! (Not Win32, Mac OS X or Unix)")
endif(WIN32)

This Cmake file has four main sections:

  • Tutorial_RES In this section we will add the resource files
  • Tutorial_SRCS In this section we will add the source files
  • Tutorial_HEADER In this section we will add the header files
  • Tutorial_LIBS In this section we will add the libraries

NavigationSDK library directory
Create a directory named "navigationSDK" in your previous created top level directory and copy the include files

  • SDKDef.h
  • SDKError.h
  • SDKInterface.h

from the sdk/include directory of the SDK package to it. Also copy the relevant libraries to this directory. In our tutorials, we will build under Windows, so copy the .dll and the .lib file from the sdk/lib/Win32/X86Rel/ directory of the SDK package to the "navigationSDK" directory. For building on other platforms like linux or MacOS, use the appropriate lib files).

Our navigationSDK directory should now contain the files:

  • SDKDef.h
  • SDKError.h
  • SDKInterface.h
  • navigationSDK.lib
  • navigationSDK.dll

Build directory
Create a directory named "build" in the top level directory. We later build the project files with the command "cmake ../" in this build directory. This has the advantage that all compiled files will be built under this directory and not in the directory where the sources are. The solution files are also generated in this directory.

After these steps, the top level directory should look like this:

Prepare the app data
Before we can use the SDK, your app needs some app data. Copy the directories addr, data, and maps from the res directory of the SDK package to a place of your choice.

  • maps (copy your map data to here)
    The maps directory is mandatory. All used maps must be copied to this folder. Deleting a map file will cause the SDK to not initialize.
  • addr (copy your POI data to here)
    The addr directory contains the POI data and can be left empty if POIs are not used.
  • data (copy the rendering data and your license.key to here)
    This directory contains the subfolders "bmp", "renderer" and "profiles" in the tutorials.
    Generally, all files besides the license.key in the data directory are optional. The SDK will still work without the rendering data, but the map will look incomplete.
    In the top level, the *.cmp files are used for all text renderings on the map. If you delete them, no street or town names will be rendered anymore. All other files in the top level directory of data can be removed, they are only used for the tutorials.
    In the bmp directory you can find all icons that are directly rendered onto the map like POI or restriction icons. If you don't need any of these icons, you can delete them. Have in mind that a blue dot will be rendered at the POI position as a fallback if POI data is present in the addr directory but icons are missing.
    In the renderer directory the map design files reside. You can remove this directory if you don't want to change the map design.
    The profiles directory contains files with predefined route options for various vehicles (see Tutorial 5 for loading such a file).

Attention

With your copy of the SDK you get a test license.key file. With this license.key you are able to test the SDK until a specified date. Please contact PTV if your test license.key has expired.

Implementation

Create the following empty files:

main.cpp
Constants.cpp
Constants.h
MainWindow.cpp
MainWindow.h

in the "Tutorial" directory. Edit the CMakeLists.txt file in the "Tutorial" directory and add the file names of the newly created files to the appropriate sections (add also a file called mainwindow.ui to the Tutorial_RES section, we will later create it with the Qt designer tool):

...
set(Tutorial_RES
    mainwindow.ui
)

set(Tutorial_SRCS
    main.cpp
    MainWindow.cpp
    Constants.cpp
)

set(Tutorial_HEADER    
    MainWindow.h
    Constants.h
    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKInterface.h
    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKError.h
    ${PROJECT_SOURCE_DIR}/navigationsdk/SDKDef.h
)

...

Add the following to the main.cpp:

main.cpp:

#include "MainWindow.h"
#include <QApplication>

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    MainWindow window;
    window.show();
    return app.exec();
}

In the main function, we create a QApplication object and a MainWindow object, which we later will add to our project.

The Constants class

Add the following to the Constants class:

Constants.h:

#pragma once

#include "../navigationSDK/SDKDef.h"
#include <QString>

class Constants
{

public:
    Constants();
    ~Constants();

    static QString getAddrPath();
    static QString getDataPath();
    static QString getMapPath();
};

Constants.cpp:

#include "Constants.h"

Constants::Constants()
{

}

Constants::~Constants()
{
}

QString Constants::getAddrPath()
{
    return "C:/ptvgroup/addr/";
}

QString Constants::getDataPath()
{
    return "C:/ptvgroup/data/";
}

QString Constants::getMapPath()
{
    return "C:/ptvgroup/maps/";
}

This class provides the paths to the data, addr and maps directories, so we later can easily access them in other classes. Edit the paths so that they point to the correct directories that you created/copied in section Prepare the app data.

Create the Qt Main Window with the Designer tool
Next, we open the Qt Designer and create a new Main Window. Save the newly created window in the "Tutorial" directory and name it mainwindow.ui.

The MainWindow class

Add the following to the MainWindow class:

MainWindow.h:

#pragma once

#include "ui_mainwindow.h"
#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QMainWindow * parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow ui;

};

MainWindow.cpp:

#include "../navigationsdk/SDKInterface.h"
#include "MainWindow.h"
#include "Constants.h"


MainWindow::MainWindow(QMainWindow * parent) : QMainWindow(parent)
{
    ui.setupUi(this);

    SDK_ERROR rc = SDK_Initialize(Constants::getMapPath().toStdWString().c_str(), L"deu",
        Constants::getAddrPath().toStdWString().c_str(),
        Constants::getDataPath().toStdWString().c_str(), SDK_FALSE);

    if (rc == SDK_ERROR_Ok)
        setWindowTitle("SDK initialization successful");
    else
        setWindowTitle("SDK initialization failed");

}

MainWindow::~MainWindow()
{
}

As you can see, we implemented the first call to the NavigationSDK in our MainWindow.cpp to initialize the SDK:

SDK_ERROR rc = SDK_Initialize(Constants::getMapPath().toStdWString().c_str(), L"deu",
        Constants::getAddrPath().toStdWString().c_str(),
        Constants::getDataPath().toStdWString().c_str(), SDK_FALSE);

SDK_Initialize() needs three paths, a map name and a boolean.
The three paths are the maps, addr and data directories you just created. The map name is the file name without the file extension (e.g. deu). The boolean is sued to tell the SDK if files should be opened with memory mapping (for the beginning, set this to SDK_FALSE).

Note

Every SDK function returns an error code to check if the call has succeeded or not. A list of all error codes can be found in the SDKError.h header. In our tutorials, we mostly don't check the returned error codes for better readability. A productive app should always check the return values.

Now, we have all code together, so we can open a command prompt in the build directory and run the command "cmake ../". If everything worked, the project solution file will be created in the same directory. Open the solution in Visual Studio and build the tutorial. After starting the program, in the window title you can see if the SDK could have been initialized successfully or not.

That's it. You can now use the NavigationSDK.

Attention

If initialization returns SDK_ERROR_NoLicense (code: -53) you either forgot to copy the license.key file to your data directory or your test license.key has expired.