├── .bumpversion.cfg ├── .dockerignore ├── .gitignore ├── CMakeLists.txt ├── Dockerfile-build ├── Dockerfile.focal ├── Dockerfile.jammy ├── MANIFEST.in ├── README.rst ├── VERSION ├── cmake ├── FindAnyProject.cmake ├── FindExtGDAL.cmake ├── FindExtProject.cmake ├── FindGDAL.cmake └── util.cmake ├── example └── demo.tiff ├── extension ├── TemporaryOutputStream.cpp ├── TemporaryOutputStream.hpp └── terratile.cpp ├── setup.py ├── terratile ├── __init__.py ├── preview.html └── server.py └── third-party ├── ctb ├── BoundingSphere.hpp ├── Bounds.hpp ├── CTBException.hpp ├── CTBFileOutputStream.cpp ├── CTBFileOutputStream.hpp ├── CTBOutputStream.hpp ├── CTBZOutputStream.cpp ├── CTBZOutputStream.hpp ├── Coordinate.hpp ├── Coordinate3D.hpp ├── GDAL2 │ └── gdaloverviewdataset.cpp ├── GDAL3 │ └── gdaloverviewdataset.cpp ├── GDALDatasetReader.cpp ├── GDALDatasetReader.hpp ├── GDALTile.cpp ├── GDALTile.hpp ├── GDALTiler.cpp ├── GDALTiler.hpp ├── GlobalGeodetic.cpp ├── GlobalGeodetic.hpp ├── GlobalMercator.cpp ├── GlobalMercator.hpp ├── Grid.hpp ├── HeightFieldChunker.hpp ├── Mesh.hpp ├── MeshTile.cpp ├── MeshTile.hpp ├── MeshTiler.cpp ├── MeshTiler.hpp ├── TerrainTile.cpp ├── TerrainTile.hpp ├── TerrainTiler.cpp ├── TerrainTiler.hpp ├── Tile.hpp ├── TileCoordinate.hpp ├── config.hpp.in ├── ctb.hpp └── types.hpp └── pybind11 ├── CMakeLists.txt ├── LICENSE ├── include └── pybind11 │ ├── attr.h │ ├── buffer_info.h │ ├── cast.h │ ├── chrono.h │ ├── common.h │ ├── complex.h │ ├── detail │ ├── class.h │ ├── common.h │ ├── descr.h │ ├── init.h │ ├── internals.h │ └── typeid.h │ ├── eigen.h │ ├── embed.h │ ├── eval.h │ ├── functional.h │ ├── iostream.h │ ├── numpy.h │ ├── operators.h │ ├── options.h │ ├── pybind11.h │ ├── pytypes.h │ ├── stl.h │ └── stl_bind.h └── tools ├── FindCatch.cmake ├── FindEigen3.cmake ├── FindPythonLibsNew.cmake ├── pybind11Config.cmake.in └── pybind11Tools.cmake /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.2.0.dev0 3 | parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\.(?P[a-z]+)(?P\d+))? 4 | serialize = 5 | {major}.{minor}.{patch}.{release}{dev} 6 | {major}.{minor}.{patch} 7 | commit = False 8 | tag = False 9 | tag_name = {new_version} 10 | message = Bump version to {new_version} 11 | 12 | [bumpversion:part:release] 13 | optional_value = release 14 | values = 15 | dev 16 | release 17 | 18 | [bumpversion:part:dev] 19 | 20 | [bumpversion:file:VERSION] 21 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | env* 2 | data/ 3 | Dockerfile* 4 | 5 | **/.git 6 | 7 | build/ 8 | *.egg-info 9 | **/*.so 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.so 3 | *.egg-info 4 | __pycache__ 5 | .vscode 6 | /env* 7 | /dist 8 | /build -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(terratile) 4 | 5 | # Some init settings 6 | set(CMAKE_COLOR_MAKEFILE ON) 7 | # Set path to additional CMake modules 8 | set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) 9 | include(FindAnyProject) 10 | 11 | include(util) 12 | check_version(CTB_VERSION_MAJOR CTB_VERSION_MINOR CTB_VERSION_PATCH) 13 | set(VERSION ${CTB_VERSION_MAJOR}.${CTB_VERSION_MINOR}.${CTB_VERSION_PATCH}) 14 | report_version("${PROJECT_NAME}" ${VERSION}) 15 | 16 | set(CMAKE_CXX_STANDARD 11) 17 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 18 | set(CMAKE_CXX_EXTENSIONS OFF) 19 | 20 | # Perform as many checks as possible on debug builds: 21 | # cmake -DCMAKE_BUILD_TYPE=Debug .. 22 | if(NOT MSVC) 23 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra --pedantic") 24 | endif() 25 | 26 | # CTB 27 | # The tile size (width and height). According to the spec this should always be 28 | # 65 29 | set(TERRAIN_TILE_SIZE 65) 30 | # The tile water mask size (width and height). According to the spec this 31 | # should always be 256 32 | set(TERRAIN_MASK_SIZE 256) 33 | 34 | set(CTB_SRC ${PROJECT_SOURCE_DIR}/third-party/ctb) 35 | 36 | configure_file( 37 | ${CTB_SRC}/config.hpp.in 38 | ${CMAKE_BINARY_DIR}/third-party/ctb/config.hpp 39 | ) 40 | 41 | include_directories( 42 | ${PROJECT_SOURCE_DIR}/third-party 43 | ${CMAKE_BINARY_DIR}/third-party/ctb 44 | ) 45 | 46 | # We need GDAL 47 | find_anyproject(GDAL REQUIRED VERSION 3.0) 48 | 49 | string(SUBSTRING ${GDAL_VERSION_STRING} 0 1 GDAL_VERSION_MAJOR) 50 | include_directories( 51 | ${PROJECT_SOURCE_DIR}/third-party/ctb/GDAL${GDAL_VERSION_MAJOR} 52 | ) 53 | 54 | # We need zlib 55 | find_anyproject(ZLIB REQUIRED) 56 | 57 | set(LIBS ${LIBS} ${ZLIB_LIBRARIES} ${GDAL_LIBRARIES}) 58 | 59 | # PYBIND11 60 | add_subdirectory(third-party/pybind11) 61 | 62 | pybind11_add_module(_terratile 63 | extension/terratile.cpp 64 | extension/TemporaryOutputStream.cpp 65 | ${CTB_SRC}/GDALTile.cpp 66 | ${CTB_SRC}/GDALTiler.cpp 67 | ${CTB_SRC}/GDALDatasetReader.cpp 68 | ${CTB_SRC}/TerrainTiler.cpp 69 | ${CTB_SRC}/TerrainTile.cpp 70 | ${CTB_SRC}/MeshTiler.cpp 71 | ${CTB_SRC}/MeshTile.cpp 72 | ${CTB_SRC}/GlobalMercator.cpp 73 | ${CTB_SRC}/GlobalGeodetic.cpp 74 | ${CTB_SRC}/CTBFileOutputStream.cpp 75 | ${CTB_SRC}/CTBZOutputStream.cpp 76 | ) 77 | 78 | target_link_libraries(_terratile PRIVATE ${LIBS}) 79 | -------------------------------------------------------------------------------- /Dockerfile-build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update -y && \ 6 | apt-get -y install --no-install-recommends --yes cmake build-essential \ 7 | libz-dev python3-distutils python3-dev python3-pip python3-setuptools libgdal-dev 8 | 9 | # Install the application. 10 | ADD . /usr/local/src/terratile/ 11 | 12 | # v1 via Cmake 13 | #RUN mkdir /usr/local/src/terratile/build 14 | #WORKDIR /usr/local/src/terratile/build 15 | #RUN cmake .. && cmake --build . --config release 16 | 17 | # v2 via pip 18 | RUN pip3 install -e /usr/local/src/terratile 19 | -------------------------------------------------------------------------------- /Dockerfile.focal: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 2 | ENV LC_ALL=C.UTF-8 3 | 4 | RUN set -ex; export DEBIAN_FRONTEND=noninteractive; \ 5 | apt-get update; apt-get --yes -qq install --no-install-recommends \ 6 | curl ca-certificates nano \ 7 | build-essential cmake \ 8 | python3-dev python3-pip python3-setuptools \ 9 | libgdal26 libgdal-dev \ 10 | zlib1g zlib1g-dev ; \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | COPY . /src 14 | WORKDIR /src 15 | 16 | RUN pip3 install ./[server] 17 | 18 | WORKDIR /src/example 19 | 20 | CMD uvicorn terratile.server:app --host 0.0.0.0 --port 8000 --workers 4 21 | EXPOSE 8000/tcp 22 | -------------------------------------------------------------------------------- /Dockerfile.jammy: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | ENV LC_ALL=C.UTF-8 3 | 4 | RUN set -ex; export DEBIAN_FRONTEND=noninteractive; \ 5 | apt-get update; apt-get --yes -qq install --no-install-recommends \ 6 | curl ca-certificates nano \ 7 | build-essential cmake \ 8 | python3-dev python3-pip python3-setuptools \ 9 | libgdal30 libgdal-dev \ 10 | zlib1g zlib1g-dev ; \ 11 | rm -rf /var/lib/apt/lists/* 12 | 13 | COPY . /src 14 | WORKDIR /src 15 | 16 | RUN pip3 install ./[server] 17 | 18 | WORKDIR /src/example 19 | 20 | CMD uvicorn terratile.server:app --host 0.0.0.0 --port 8000 --workers 4 21 | EXPOSE 8000/tcp 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include extension/*.?pp 2 | include CMakeLists.txt 3 | include terratile/preview.html 4 | 5 | include third-party/ctb/* 6 | 7 | include pybind11/CMakeLists.txt 8 | recursive-include pybind11/include * 9 | recursive-include pybind11/tools * 10 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Terratile 2 | ========= 3 | 4 | Installation 5 | ------------ 6 | 7 | Build requirements (package names in Ubuntu are shown in parentheses): 8 | 9 | * GDAL library (``libgdal20`` and ``libgdal-dev``) 10 | * ZLib library (``zlib1g``, ``zlib1g-dev``) 11 | * C++ compiler and CMake (``build-essential`` and ``cmake``) 12 | * Python 3.8+ with header files (``python-dev`` or ``python3-dev``) 13 | 14 | Install into virtualenv: 15 | 16 | .. code-block:: 17 | 18 | $ python3 -m venv env 19 | $ . env/bin/activate 20 | $ pip install git+https://github.com/nextgis/terratile.git 21 | 22 | Usage example 23 | ------------- 24 | 25 | .. code-block:: 26 | 27 | import terratile 28 | from osgeo import gdal 29 | 30 | ds = gdal.Open(path_to_dataset, gdal.GA_ReadOnly) 31 | data = terratile.mesh_tile(ds, (z, x, y)) 32 | 33 | Terrain tile server 34 | ------------------- 35 | 36 | Install terratile with ``[server]`` option: 37 | 38 | .. code-block:: 39 | 40 | $ pip install git+https://github.com/nextgis/terratile.git#egg=terratile[server] 41 | 42 | Put some geotiff to current directory (``demo.tiff`` in example) and start 43 | terrain tile server with ``uvicorn``: 44 | 45 | .. code-block:: 46 | 47 | $ uvicorn terratile.server:app --workers 4 48 | 49 | Go to http://localhost:8000/demo/preview to preview terrain tiles with simple 50 | Cesium frontend. Tiles for ``demo.tiff`` are located in 51 | ``http://localhost:8000/demo/{z}/{x}/{y}.terrain``. Metadata file ``layer.json`` 52 | is available at ``http://localhost:8000/demo/layer.json``. 53 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.0.dev0 -------------------------------------------------------------------------------- /cmake/FindExtGDAL.cmake: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Project: external projects 3 | # Purpose: CMake build scripts 4 | # Author: Dmitry Baryshnikov, polimax@mail.ru 5 | ################################################################################ 6 | # Copyright (C) 2015-2019, NextGIS 7 | # Copyright (C) 2015-2019 Dmitry Baryshnikov 8 | # 9 | # This script is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 2 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This script is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this script. If not, see . 21 | ################################################################################ 22 | 23 | set(repo nextgis-borsch/lib_gdal) 24 | set(repo_type github) 25 | # set(repo_branch master) # No need to set as master is default value 26 | 27 | # Set for binary artifacts 28 | set(repo_bin lib_gdal) 29 | set(repo_bin_type repka) 30 | set(repo_bin_url https://rm.nextgis.com) 31 | set(repo_bin_id 2) # additional parameter. Not needed for github -------------------------------------------------------------------------------- /cmake/FindGDAL.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # FindGDAL 3 | # -------- 4 | # 5 | # 6 | # 7 | # Locate gdal 8 | # 9 | # This module accepts the following environment variables: 10 | # 11 | # :: 12 | # 13 | # GDAL_DIR or GDAL_ROOT - Specify the location of GDAL 14 | # 15 | # 16 | # 17 | # This module defines the following CMake variables: 18 | # 19 | # :: 20 | # 21 | # GDAL_FOUND - True if libgdal is found 22 | # GDAL_LIBRARY - A variable pointing to the GDAL library 23 | # GDAL_INCLUDE_DIR - Where to find the headers 24 | 25 | #============================================================================= 26 | # Copyright 2007-2009 Kitware, Inc. 27 | # 28 | # Distributed under the OSI-approved BSD License (the "License"); 29 | # see accompanying file Copyright.txt for details. 30 | # 31 | # This software is distributed WITHOUT ANY WARRANTY; without even the 32 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 33 | # See the License for more information. 34 | #============================================================================= 35 | # (To distribute this file outside of CMake, substitute the full 36 | # License text for the above reference.) 37 | 38 | # 39 | # $GDALDIR is an environment variable that would 40 | # correspond to the ./configure --prefix=$GDAL_DIR 41 | # used in building gdal. 42 | # 43 | # Created by Eric Wing. I'm not a gdal user, but OpenSceneGraph uses it 44 | # for osgTerrain so I whipped this module together for completeness. 45 | # I actually don't know the conventions or where files are typically 46 | # placed in distros. 47 | # Any real gdal users are encouraged to correct this (but please don't 48 | # break the OS X framework stuff when doing so which is what usually seems 49 | # to happen). 50 | 51 | # This makes the presumption that you are include gdal.h like 52 | # 53 | #include "gdal.h" 54 | 55 | find_path(GDAL_INCLUDE_DIR gdal.h 56 | HINTS 57 | ENV GDAL_DIR 58 | ENV GDAL_ROOT 59 | PATH_SUFFIXES 60 | include/gdal 61 | include/gdal/1.10 62 | include/gdal/1.11 63 | include/gdal/2.0 64 | include/gdal/2.1 65 | include/GDAL 66 | include 67 | PATHS 68 | ~/Library/Frameworks/gdal.framework/Headers 69 | /Library/Frameworks/gdal.framework/Headers 70 | /sw # Fink 71 | /opt/local # DarwinPorts 72 | /opt/csw # Blastwave 73 | /opt 74 | ) 75 | 76 | if(UNIX) 77 | # Use gdal-config to obtain the library version (this should hopefully 78 | # allow us to -lgdal1.x.y where x.y are correct version) 79 | # For some reason, libgdal development packages do not contain 80 | # libgdal.so... 81 | find_program(GDAL_CONFIG gdal-config 82 | HINTS 83 | ENV GDAL_DIR 84 | ENV GDAL_ROOT 85 | PATH_SUFFIXES bin 86 | PATHS 87 | /sw # Fink 88 | /opt/local # DarwinPorts 89 | /opt/csw # Blastwave 90 | /opt 91 | ) 92 | 93 | if(GDAL_CONFIG) 94 | exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS) 95 | if(GDAL_CONFIG_LIBS) 96 | string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS}) 97 | string(REPLACE "-l" "" _gdal_lib "${_gdal_dashl}") 98 | string(REGEX MATCHALL "-L[^ ]+" _gdal_dashL ${GDAL_CONFIG_LIBS}) 99 | string(REPLACE "-L" "" _gdal_libpath "${_gdal_dashL}") 100 | endif() 101 | endif() 102 | endif() 103 | 104 | find_library(GDAL_LIBRARY 105 | NAMES ${_gdal_lib} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL 106 | HINTS 107 | ENV GDAL_DIR 108 | ENV GDAL_ROOT 109 | ${_gdal_libpath} 110 | PATH_SUFFIXES lib 111 | PATHS 112 | /sw 113 | /opt/local 114 | /opt/csw 115 | /opt 116 | /usr/freeware 117 | ) 118 | 119 | if(GDAL_INCLUDE_DIR) 120 | set(GDAL_VERSION_MAJOR 0) 121 | set(GDAL_VERSION_MINOR 0) 122 | set(GDAL_VERSION_PATCH 0) 123 | 124 | if(EXISTS "${GDAL_INCLUDE_DIR}/gdal_version.h") 125 | file(READ ${GDAL_INCLUDE_DIR}/gdal_version.h GDAL_VERSION_H_CONTENTS) 126 | string(REGEX MATCH "GDAL_VERSION_MAJOR[ \t]+([0-9]+)" 127 | GDAL_VERSION_MAJOR ${GDAL_VERSION_H_CONTENTS}) 128 | string (REGEX MATCH "([0-9]+)" 129 | GDAL_VERSION_MAJOR ${GDAL_VERSION_MAJOR}) 130 | string(REGEX MATCH "GDAL_VERSION_MINOR[ \t]+([0-9]+)" 131 | GDAL_VERSION_MINOR ${GDAL_VERSION_H_CONTENTS}) 132 | string (REGEX MATCH "([0-9]+)" 133 | GDAL_VERSION_MINOR ${GDAL_VERSION_MINOR}) 134 | string(REGEX MATCH "GDAL_VERSION_REV[ \t]+([0-9]+)" 135 | GDAL_VERSION_PATCH ${GDAL_VERSION_H_CONTENTS}) 136 | string (REGEX MATCH "([0-9]+)" 137 | GDAL_VERSION_PATCH ${GDAL_VERSION_PATCH}) 138 | 139 | unset(GDAL_VERSION_H_CONTENTS) 140 | endif() 141 | 142 | set(GDAL_VERSION_STRING "${GDAL_VERSION_MAJOR}.${GDAL_VERSION_MINOR}.${GDAL_VERSION_PATCH}") 143 | endif () 144 | 145 | 146 | # Handle the QUIETLY and REQUIRED arguments and set SPATIALINDEX_FOUND to TRUE 147 | # if all listed variables are TRUE 148 | include(FindPackageHandleStandardArgs) 149 | find_package_handle_standard_args(GDAL 150 | REQUIRED_VARS GDAL_LIBRARY GDAL_INCLUDE_DIR 151 | VERSION_VAR GDAL_VERSION_STRING) 152 | 153 | IF(GDAL_FOUND) 154 | set(GDAL_LIBRARIES ${GDAL_LIBRARY}) 155 | set(GDAL_INCLUDE_DIRS ${GDAL_INCLUDE_DIR}) 156 | ENDIF() 157 | 158 | # Hide internal variables 159 | mark_as_advanced( 160 | GDAL_INCLUDE_DIR 161 | GDAL_LIBRARY) 162 | 163 | #====================== 164 | -------------------------------------------------------------------------------- /cmake/util.cmake: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Project: external projects 3 | # Purpose: CMake build scripts 4 | # Author: Dmitry Baryshnikov, 5 | ################################################################################ 6 | # Copyright (C) 2017-2019, NextGIS 7 | # 8 | # This script is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This script is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this script. If not, see . 20 | ################################################################################ 21 | function(check_version major minor patch) 22 | 23 | string(TIMESTAMP CURRENT_YEAR "%y") 24 | string(TIMESTAMP CURRENT_MONTH "%m") 25 | math(EXPR CURRENT_MONTH "${CURRENT_MONTH}*1") 26 | 27 | # The version number 28 | set(CTB_VERSION_MAJOR 0) 29 | set(CTB_VERSION_MINOR 5) 30 | set(CTB_VERSION_PATCH 0) 31 | 32 | set(${major} ${CTB_VERSION_MAJOR} PARENT_SCOPE) 33 | set(${minor} ${CTB_VERSION_MINOR} PARENT_SCOPE) 34 | set(${patch} ${CTB_VERSION_PATCH} PARENT_SCOPE) 35 | 36 | # Store version string in file for installer needs 37 | file(TIMESTAMP ${CMAKE_CURRENT_SOURCE_DIR}/cmake/util.cmake VERSION_DATETIME "%Y-%m-%d %H:%M:%S" UTC) 38 | set(VERSION ${CTB_VERSION_MAJOR}.${CTB_VERSION_MINOR}.${CTB_VERSION_PATCH}) 39 | get_cpack_filename(${VERSION} PROJECT_CPACK_FILENAME) 40 | file(WRITE ${CMAKE_BINARY_DIR}/version.str "${VERSION}\n${VERSION_DATETIME}\n${PROJECT_CPACK_FILENAME}") 41 | 42 | endfunction(check_version) 43 | 44 | function(warning_msg text) 45 | if(NOT SUPPRESS_VERBOSE_OUTPUT) 46 | string(ASCII 27 Esc) 47 | set(Red "${Esc}[31m") 48 | set(ColourReset "${Esc}[m") 49 | 50 | message(STATUS "${Red}${text}${ColourReset}") 51 | endif() 52 | endfunction() 53 | 54 | function(info_msg text) 55 | if(NOT SUPPRESS_VERBOSE_OUTPUT) 56 | string(ASCII 27 Esc) 57 | set(Red "${Esc}[36m") 58 | set(ColourReset "${Esc}[m") 59 | 60 | message(STATUS "${Red}${text}${ColourReset}") 61 | endif() 62 | endfunction() 63 | 64 | function(report_version name ver) 65 | string(ASCII 27 Esc) 66 | set(BoldYellow "${Esc}[1;33m") 67 | set(ColourReset "${Esc}[m") 68 | 69 | message("${BoldYellow}${name} version ${ver}${ColourReset}") 70 | endfunction() 71 | 72 | # macro to find packages on the host OS 73 | macro( find_exthost_package ) 74 | if(CMAKE_CROSSCOMPILING) 75 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) 76 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) 77 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) 78 | 79 | find_package( ${ARGN} ) 80 | 81 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) 82 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) 83 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) 84 | else() 85 | find_package( ${ARGN} ) 86 | endif() 87 | endmacro() 88 | 89 | 90 | # macro to find programs on the host OS 91 | macro( find_exthost_program ) 92 | if(CMAKE_CROSSCOMPILING) 93 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) 94 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) 95 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) 96 | 97 | find_program( ${ARGN} ) 98 | 99 | set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) 100 | set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) 101 | set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) 102 | else() 103 | find_program( ${ARGN} ) 104 | endif() 105 | endmacro() 106 | 107 | 108 | function(get_prefix prefix IS_STATIC) 109 | if(IS_STATIC) 110 | set(STATIC_PREFIX "static-") 111 | if(ANDROID) 112 | set(STATIC_PREFIX "${STATIC_PREFIX}android-${ANDROID_ABI}-") 113 | elseif(IOS) 114 | set(STATIC_PREFIX "${STATIC_PREFIX}ios-${IOS_ARCH}-") 115 | endif() 116 | endif() 117 | set(${prefix} ${STATIC_PREFIX} PARENT_SCOPE) 118 | endfunction() 119 | 120 | 121 | function(get_cpack_filename ver name) 122 | get_compiler_version(COMPILER) 123 | 124 | if(NOT DEFINED BUILD_STATIC_LIBS) 125 | set(BUILD_STATIC_LIBS OFF) 126 | endif() 127 | 128 | get_prefix(STATIC_PREFIX ${BUILD_STATIC_LIBS}) 129 | 130 | set(${name} ${PROJECT_NAME}-${ver}-${STATIC_PREFIX}${COMPILER} PARENT_SCOPE) 131 | endfunction() 132 | 133 | function(get_compiler_version ver) 134 | ## Limit compiler version to 2 or 1 digits 135 | string(REPLACE "." ";" VERSION_LIST ${CMAKE_C_COMPILER_VERSION}) 136 | list(LENGTH VERSION_LIST VERSION_LIST_LEN) 137 | if(VERSION_LIST_LEN GREATER 2 OR VERSION_LIST_LEN EQUAL 2) 138 | list(GET VERSION_LIST 0 COMPILER_VERSION_MAJOR) 139 | list(GET VERSION_LIST 1 COMPILER_VERSION_MINOR) 140 | set(COMPILER ${CMAKE_C_COMPILER_ID}-${COMPILER_VERSION_MAJOR}.${COMPILER_VERSION_MINOR}) 141 | else() 142 | set(COMPILER ${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}) 143 | endif() 144 | 145 | if(WIN32) 146 | if(CMAKE_CL_64) 147 | set(COMPILER "${COMPILER}-64bit") 148 | endif() 149 | endif() 150 | 151 | set(${ver} ${COMPILER} PARENT_SCOPE) 152 | endfunction() 153 | -------------------------------------------------------------------------------- /example/demo.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextgis/terratile/4d1fc875059f2e0a2ce7b33b5d1cea7cd186a64b/example/demo.tiff -------------------------------------------------------------------------------- /extension/TemporaryOutputStream.cpp: -------------------------------------------------------------------------------- 1 | #include "zlib.h" 2 | 3 | #include "TemporaryOutputStream.hpp" 4 | 5 | constexpr int window_bits = 15 + 16; // gzip with windowbits of 15 6 | constexpr int mem_level = 8; 7 | 8 | uint32_t 9 | TemporaryOutputStream::write(const void *ptr, uint32_t size) 10 | { 11 | ss.write(static_cast(ptr), size); 12 | return size; 13 | } 14 | 15 | std::string TemporaryOutputStream::compress() 16 | { 17 | z_stream zs = {0}; 18 | if (deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, window_bits, mem_level, Z_DEFAULT_STRATEGY) != Z_OK) { 19 | throw(std::runtime_error("deflateInit failed while compressing!")); 20 | } 21 | 22 | std::string str = ss.str(); 23 | zs.next_in = (Bytef*)str.data(); 24 | zs.avail_in = str.size(); 25 | 26 | int ret; 27 | char outbuffer[32768]; 28 | std::string outstring; 29 | 30 | do { 31 | zs.next_out = reinterpret_cast(outbuffer); 32 | zs.avail_out = sizeof(outbuffer); 33 | 34 | ret = deflate(&zs, Z_FINISH); 35 | 36 | if (outstring.size() < zs.total_out) { 37 | outstring.append(outbuffer, zs.total_out - outstring.size()); 38 | } 39 | } while (ret == Z_OK); 40 | 41 | deflateEnd(&zs); 42 | 43 | if (ret != Z_STREAM_END) { 44 | throw(std::runtime_error("deflate failed while compressing!")); 45 | } 46 | 47 | return outstring; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /extension/TemporaryOutputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TEMPORARYOUTPUTSTREAM_HPP 2 | #define TEMPORARYOUTPUTSTREAM_HPP 3 | 4 | #include 5 | 6 | #include "ctb/CTBOutputStream.hpp" 7 | 8 | class TemporaryOutputStream: 9 | public ctb::CTBOutputStream 10 | { 11 | public: 12 | TemporaryOutputStream() {} 13 | virtual uint32_t write(const void *ptr, uint32_t size); 14 | std::string compress(); 15 | 16 | private: 17 | std::stringstream ss; 18 | }; 19 | 20 | #endif // TEMPORARYOUTPUTSTREAM_HPP 21 | -------------------------------------------------------------------------------- /extension/terratile.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | #include 3 | 4 | #include "gdal.h" 5 | #include "gdal_priv.h" 6 | 7 | #include "ctb/types.hpp" 8 | #include "ctb/GlobalGeodetic.hpp" 9 | #include "ctb/TileCoordinate.hpp" 10 | #include "ctb/MeshTiler.hpp" 11 | 12 | #include "TemporaryOutputStream.hpp" 13 | 14 | namespace py = pybind11; 15 | 16 | const ctb::Grid grid = ctb::GlobalGeodetic(); 17 | 18 | py::bytes meshTile( 19 | size_t dataset, 20 | ctb::i_zoom z, 21 | ctb::i_tile x, 22 | ctb::i_tile y, 23 | bool writeNormals=false, 24 | double meshQuality=1.0 25 | ) { 26 | GDALDataset *poDataset = (GDALDataset *) dataset; 27 | const ctb::TileCoordinate coord = ctb::TileCoordinate(z, x, y); 28 | const ctb::MeshTiler tiler = ctb::MeshTiler(poDataset, grid, meshQuality); 29 | const auto tile = tiler.createMesh(poDataset, coord); 30 | 31 | auto stream = TemporaryOutputStream(); 32 | tile->writeFile(stream, writeNormals); 33 | delete tile; 34 | 35 | return py::bytes(stream.compress()); 36 | } 37 | 38 | ctb::i_zoom maxZoom(size_t dataset) 39 | { 40 | const auto tiler = ctb::MeshTiler((GDALDataset *) dataset, grid); 41 | return tiler.maxZoomLevel(); 42 | } 43 | 44 | PYBIND11_MODULE(_terratile, m) { 45 | m.def("mesh_tile", &meshTile); 46 | m.def("max_zoom", &maxZoom); 47 | 48 | #ifdef VERSION_INFO 49 | m.attr("__version__") = VERSION_INFO; 50 | #else 51 | m.attr("__version__") = "dev"; 52 | #endif 53 | } 54 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import subprocess 4 | from os import path, makedirs 5 | 6 | from setuptools import setup, find_packages, Extension 7 | from setuptools.command.build_ext import build_ext 8 | 9 | 10 | with open('VERSION', 'r') as fd: 11 | VERSION = fd.read().rstrip() 12 | 13 | 14 | here = path.abspath(path.dirname(__file__)) 15 | 16 | 17 | class CMakeExtension(Extension): 18 | def __init__(self, name): 19 | Extension.__init__(self, name, sources=[]) 20 | 21 | 22 | class CMakeBuild(build_ext): 23 | 24 | def run(self): 25 | for ext in self.extensions: 26 | self.build_cmake(ext) 27 | 28 | def build_cmake(self, ext): 29 | if not os.path.isdir(self.build_temp): 30 | makedirs(self.build_temp) 31 | 32 | extdir = self.get_ext_fullpath(ext.name) 33 | 34 | config = 'Debug' if self.debug else 'Release' 35 | cmake_args = [ 36 | '-DPYTHON_EXECUTABLE=' + sys.executable, 37 | '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + os.path.abspath(os.path.split(extdir)[0]), 38 | '-DCMAKE_BUILD_TYPE=' + config, 39 | ] 40 | 41 | build_args = ['--config', config, '--', '-j2'] 42 | 43 | env = os.environ.copy() 44 | subprocess.check_call( 45 | ['cmake', os.path.abspath(os.path.dirname(__file__))] + cmake_args, 46 | cwd=self.build_temp, env=env) 47 | 48 | if not self.dry_run: 49 | subprocess.check_call( 50 | ['cmake', '--build', '.'] + build_args, 51 | cwd=self.build_temp, env=env) 52 | 53 | 54 | try: 55 | gv = subprocess.check_output(['gdal-config', '--version'], universal_newlines=True).strip() 56 | except subprocess.CalledProcessError: 57 | gv = None 58 | 59 | 60 | setup( 61 | name='terratile', 62 | description='Simple wrapper of cesium terrain builder (libctb) for terrain tiles generation.', 63 | version=VERSION, 64 | python_requires='>=3.8, <4', 65 | url='https://github.com/nextgis/terratile', 66 | author='NextGIS', 67 | author_email='info@nextgis.com', 68 | license='MIT', 69 | packages=['terratile', ], 70 | ext_modules=[CMakeExtension('_terratile')], 71 | cmdclass=dict(build_ext=CMakeBuild), 72 | zip_safe=False, 73 | extras_require={'server': [ 74 | 'fastapi', 75 | 'uvicorn', 76 | 'jinja2', 77 | 'pygdal' + (('==%s.*' % gv) if gv else ''), 78 | ]}, 79 | package_data={ 80 | '': ['*.html', 'example/*'] 81 | }, 82 | ) 83 | -------------------------------------------------------------------------------- /terratile/__init__.py: -------------------------------------------------------------------------------- 1 | import _terratile 2 | 3 | 4 | def mesh_tile(dataset, tile, write_normals=False, quality=1.0): 5 | z, x, y = tile 6 | return _terratile.mesh_tile( 7 | int(dataset.this), 8 | int(z), int(x), int(y), 9 | bool(write_normals), float(quality)) 10 | 11 | 12 | def max_zoom(dataset): 13 | return _terratile.max_zoom(int(dataset.this)) 14 | -------------------------------------------------------------------------------- /terratile/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Terratile preview 7 | 8 | 9 | 19 | 20 | 21 |
22 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /terratile/server.py: -------------------------------------------------------------------------------- 1 | import os 2 | import math 3 | from pathlib import Path 4 | from collections import OrderedDict 5 | 6 | from fastapi import FastAPI, HTTPException 7 | from starlette.requests import Request 8 | from starlette.responses import Response, JSONResponse 9 | from starlette.templating import Jinja2Templates 10 | 11 | from osgeo import gdal, osr 12 | 13 | from terratile import mesh_tile, max_zoom 14 | 15 | CFG_DATA_PATH = Path(os.environ.get('TERRATILE_DATA_PATH', './')) 16 | CFG_EXTENSIONS = ('.tif', '.tiff', '.vrt') 17 | 18 | EPSG_4326 = osr.SpatialReference() 19 | EPSG_4326.ImportFromEPSG(4326) 20 | 21 | 22 | class Dataset: 23 | datasets = dict() 24 | 25 | @classmethod 26 | def from_name(cls, name): 27 | result = cls.datasets.get(name) 28 | if result is not None: 29 | return result 30 | 31 | for s in ('', ) + CFG_EXTENSIONS: 32 | fn = CFG_DATA_PATH / (name + s) 33 | if fn.is_file(): 34 | obj = Dataset(str(fn)) 35 | cls.datasets[name] = obj 36 | return obj 37 | 38 | raise HTTPException(status_code=404, detail=f"Dataset '{name}' not found.") 39 | 40 | def __init__(self, filename): 41 | self.gdal_ds = gdal.Open(filename, gdal.GA_ReadOnly) 42 | self.sr = osr.SpatialReference(wkt=self.gdal_ds.GetProjection()) 43 | 44 | self.tile_res = 180 45 | self.tile_origin = (-180, -90) 46 | 47 | ulx, xres, xskew, uly, yskew, yres = self.gdal_ds.GetGeoTransform() 48 | lrx = ulx + (self.gdal_ds.RasterXSize * xres) 49 | lry = uly + (self.gdal_ds.RasterYSize * yres) 50 | 51 | transform = osr.CoordinateTransformation(self.sr, EPSG_4326) 52 | ul = transform.TransformPoint(ulx, uly) 53 | lr = transform.TransformPoint(lrx, lry) 54 | 55 | self.min_x, self.min_y = min(ul[0], lr[0]), min(ul[1], lr[1]) 56 | self.max_x, self.max_y = max(ul[0], lr[0]), max(ul[1], lr[1]) 57 | 58 | self.bounds = (self.min_x, self.min_y, self.max_x, self.max_y) 59 | 60 | tres = self.tile_res 61 | self.avtile = [] 62 | for z in range(0, max_zoom(self.gdal_ds)): 63 | self.avtile.append(( 64 | math.floor((self.min_x - self.tile_origin[0]) / tres), 65 | math.floor((self.min_y - self.tile_origin[1]) / tres), 66 | math.ceil((self.max_x - self.tile_origin[0]) / tres) - 1, 67 | math.ceil((self.max_y - self.tile_origin[1]) / tres) - 1, 68 | ) if z > 0 else (0, 0, 1, 0)) 69 | 70 | tres /= 2 71 | 72 | 73 | app = FastAPI() 74 | templates = Jinja2Templates(directory=str(Path(__file__).parent.resolve())) 75 | 76 | 77 | @app.get('/{dataset}/layer.json') 78 | def layer_json(dataset: str, normals:bool=False): 79 | ds = Dataset.from_name(dataset) 80 | tiles_url='{z}/{x}/{y}.terrain' 81 | if normals: 82 | tiles_url+='?normals=True' 83 | data = OrderedDict( 84 | tilejson='2.1.0', 85 | name=dataset, 86 | description='', 87 | version='1.1.0', 88 | format='quantized-mesh-1.0', 89 | attribution='', 90 | schema='tms', 91 | extensions=['octvertexnormals'] if normals else [], 92 | tiles=(tiles_url, ), 93 | projection='EPSG:4326', 94 | bounds=ds.bounds, 95 | available=[ 96 | (OrderedDict(zip(('startX', 'startY', 'endX', 'endY'), a)), ) 97 | for a in ds.avtile 98 | ] 99 | ) 100 | 101 | return JSONResponse(data) 102 | 103 | 104 | @app.get('/{dataset}/{z}/{x}/{y}.terrain') 105 | def tile(dataset: str, z: int, x: int, y: int, normals: bool=False, quality: float=1.0): 106 | ds = Dataset.from_name(dataset) 107 | data = mesh_tile(ds.gdal_ds, (z, x, y), write_normals=normals, quality=quality) 108 | return Response(data, media_type="application/octet-stream", headers={ 109 | 'Access-Control-Allow-Origin': '*', 110 | 'Content-Encoding': 'gzip', 111 | 'Cache-Control': 'max-age=600' 112 | }) 113 | 114 | 115 | @app.get('/{dataset}/preview') 116 | def preview(request: Request, dataset: str, normals:bool=None, quality:float=None): 117 | ds = Dataset.from_name(dataset) 118 | return templates.TemplateResponse('preview.html', { 119 | 'request': request, 120 | 'dataset': dataset, 121 | 'bounds': ds.bounds, 122 | 'quality': quality, 123 | 'normals':normals 124 | }) 125 | -------------------------------------------------------------------------------- /third-party/ctb/BoundingSphere.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BBSPHERE_HPP 2 | #define BBSPHERE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file BoundingSphere.hpp 22 | * @brief This declares and defines the `BoundingSphere` class 23 | * @author Alvaro Huarte 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "Coordinate3D.hpp" 30 | #include "types.hpp" 31 | 32 | namespace ctb { 33 | template class BoundingSphere; 34 | template class BoundingBox; 35 | } 36 | 37 | /// A spherical bounding region which is defined by a center point and a radius 38 | template 39 | class ctb::BoundingSphere { 40 | public: 41 | Coordinate3D center; ///< The center of the BoundingSphere 42 | double radius; ///< The radius of the BoundingSphere 43 | 44 | /// Create an empty BoundingSphere 45 | BoundingSphere() { 46 | } 47 | /// Create a BoundingSphere from the specified point stream 48 | BoundingSphere(const std::vector> &points) { 49 | fromPoints(points); 50 | } 51 | 52 | /// Calculate the center and radius from the specified point stream 53 | /// Based on Ritter's algorithm 54 | void fromPoints(const std::vector> &points) { 55 | const T MAX = std::numeric_limits::infinity(); 56 | const T MIN = -std::numeric_limits::infinity(); 57 | 58 | Coordinate3D minPointX(MAX, MAX, MAX); 59 | Coordinate3D minPointY(MAX, MAX, MAX); 60 | Coordinate3D minPointZ(MAX, MAX, MAX); 61 | Coordinate3D maxPointX(MIN, MIN, MIN); 62 | Coordinate3D maxPointY(MIN, MIN, MIN); 63 | Coordinate3D maxPointZ(MIN, MIN, MIN); 64 | 65 | // Store the points containing the smallest and largest component 66 | // Used for the naive approach 67 | for (int i = 0, icount = points.size(); i < icount; i++) { 68 | const Coordinate3D &point = points[i]; 69 | 70 | if (point.x < minPointX.x) minPointX = point; 71 | if (point.y < minPointY.y) minPointY = point; 72 | if (point.z < minPointZ.z) minPointZ = point; 73 | if (point.x > maxPointX.x) maxPointX = point; 74 | if (point.y > maxPointY.y) maxPointY = point; 75 | if (point.z > maxPointZ.z) maxPointZ = point; 76 | } 77 | 78 | // Squared distance between each component min and max 79 | T xSpan = (maxPointX - minPointX).magnitudeSquared(); 80 | T ySpan = (maxPointY - minPointY).magnitudeSquared(); 81 | T zSpan = (maxPointZ - minPointZ).magnitudeSquared(); 82 | 83 | Coordinate3D diameter1 = minPointX; 84 | Coordinate3D diameter2 = maxPointX; 85 | T maxSpan = xSpan; 86 | if (ySpan > maxSpan) { 87 | diameter1 = minPointY; 88 | diameter2 = maxPointY; 89 | maxSpan = ySpan; 90 | } 91 | if (zSpan > maxSpan) { 92 | diameter1 = minPointZ; 93 | diameter2 = maxPointZ; 94 | maxSpan = zSpan; 95 | } 96 | 97 | Coordinate3D ritterCenter = Coordinate3D( 98 | (diameter1.x + diameter2.x) * 0.5, 99 | (diameter1.y + diameter2.y) * 0.5, 100 | (diameter1.z + diameter2.z) * 0.5 101 | ); 102 | T radiusSquared = (diameter2 - ritterCenter).magnitudeSquared(); 103 | T ritterRadius = std::sqrt(radiusSquared); 104 | 105 | // Initial center and radius (naive) get min and max box 106 | Coordinate3D minBoxPt(minPointX.x, minPointY.y, minPointZ.z); 107 | Coordinate3D maxBoxPt(maxPointX.x, maxPointY.y, maxPointZ.z); 108 | Coordinate3D naiveCenter = (minBoxPt + maxBoxPt) * 0.5; 109 | T naiveRadius = 0; 110 | 111 | for (int i = 0, icount = points.size(); i < icount; i++) { 112 | const Coordinate3D &point = points[i]; 113 | 114 | // Find the furthest point from the naive center to calculate the naive radius. 115 | T r = (point - naiveCenter).magnitude(); 116 | if (r > naiveRadius) naiveRadius = r; 117 | 118 | // Make adjustments to the Ritter Sphere to include all points. 119 | T oldCenterToPointSquared = (point - ritterCenter).magnitudeSquared(); 120 | 121 | if (oldCenterToPointSquared > radiusSquared) { 122 | T oldCenterToPoint = std::sqrt(oldCenterToPointSquared); 123 | ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5; 124 | 125 | // Calculate center of new Ritter sphere 126 | T oldToNew = oldCenterToPoint - ritterRadius; 127 | ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * point.x) / oldCenterToPoint; 128 | ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * point.y) / oldCenterToPoint; 129 | ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * point.z) / oldCenterToPoint; 130 | } 131 | } 132 | 133 | // Keep the naive sphere if smaller 134 | if (naiveRadius < ritterRadius) { 135 | center = ritterCenter; 136 | radius = ritterRadius; 137 | } 138 | else { 139 | center = naiveCenter; 140 | radius = naiveRadius; 141 | } 142 | } 143 | }; 144 | 145 | /// A bounding box which is defined by a pair of minimum and maximum coordinates 146 | template 147 | class ctb::BoundingBox { 148 | public: 149 | Coordinate3D min; ///< The min coordinate of the BoundingBox 150 | Coordinate3D max; ///< The max coordinate of the BoundingBox 151 | 152 | /// Create an empty BoundingBox 153 | BoundingBox() { 154 | } 155 | /// Create a BoundingBox from the specified point stream 156 | BoundingBox(const std::vector> &points) { 157 | fromPoints(points); 158 | } 159 | 160 | /// Calculate the BBOX from the specified point stream 161 | void fromPoints(const std::vector> &points) { 162 | const T MAX = std::numeric_limits::infinity(); 163 | const T MIN = -std::numeric_limits::infinity(); 164 | min.x = MAX; 165 | min.y = MAX; 166 | min.z = MAX; 167 | max.x = MIN; 168 | max.y = MIN; 169 | max.z = MIN; 170 | 171 | for (int i = 0, icount = points.size(); i < icount; i++) { 172 | const Coordinate3D &point = points[i]; 173 | 174 | if (point.x < min.x) min.x = point.x; 175 | if (point.y < min.y) min.y = point.y; 176 | if (point.z < min.z) min.z = point.z; 177 | if (point.x > max.x) max.x = point.x; 178 | if (point.y > max.y) max.y = point.y; 179 | if (point.z > max.z) max.z = point.z; 180 | } 181 | } 182 | }; 183 | 184 | #endif /* BBSPHERE_HPP */ 185 | -------------------------------------------------------------------------------- /third-party/ctb/Bounds.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOUNDS_HPP 2 | #define BOUNDS_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file Bounds.hpp 22 | * @brief This declares and defines the `Bounds` class 23 | */ 24 | 25 | #include "Coordinate.hpp" 26 | #include "CTBException.hpp" 27 | 28 | namespace ctb { 29 | template class Bounds; 30 | } 31 | 32 | /// A representation of an extent 33 | template 34 | class ctb::Bounds { 35 | public: 36 | 37 | /// Create an empty bounds 38 | Bounds() { 39 | bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0; 40 | } 41 | 42 | /// Create bounds from individual extents 43 | Bounds(T minx, T miny, T maxx, T maxy) { 44 | setBounds(minx, miny, maxx, maxy); 45 | } 46 | 47 | /// Create bounds represented by lower left and upper right coordinates 48 | Bounds(const Coordinate &lowerLeft, const Coordinate &upperRight) { 49 | setBounds(lowerLeft, upperRight); 50 | } 51 | 52 | /// Overload the equality operator 53 | virtual bool 54 | operator==(const Bounds &other) const { 55 | return bounds[0] == other.bounds[0] 56 | && bounds[1] == other.bounds[1] 57 | && bounds[2] == other.bounds[2] 58 | && bounds[3] == other.bounds[3]; 59 | } 60 | 61 | /// Set the bounds from extents 62 | inline void 63 | setBounds(T minx, T miny, T maxx, T maxy) { 64 | if (minx > maxx) { 65 | throw CTBException("The minimum X value is greater than the maximum X value"); 66 | } else if (miny > maxy) { 67 | throw CTBException("The minimum Y value is greater than the maximum Y value"); 68 | } 69 | 70 | bounds[0] = minx; 71 | bounds[1] = miny; 72 | bounds[2] = maxx; 73 | bounds[3] = maxy; 74 | } 75 | 76 | /// Set the bounds from lower left and upper right coordinates 77 | inline void 78 | setBounds(const Coordinate &lowerLeft, const Coordinate &upperRight) { 79 | setBounds(lowerLeft.x, lowerLeft.y, upperRight.x, upperRight.y); 80 | } 81 | 82 | /// Get the minimum X value 83 | inline T 84 | getMinX() const { 85 | return bounds[0]; 86 | } 87 | 88 | /// Get the minimum Y value 89 | inline T 90 | getMinY() const { 91 | return bounds[1]; 92 | } 93 | 94 | /// Get the maximum X value 95 | inline T 96 | getMaxX() const { 97 | return bounds[2]; 98 | } 99 | 100 | /// Get the maximum Y value 101 | inline T 102 | getMaxY() const { 103 | return bounds[3]; 104 | } 105 | 106 | /// Set the minimum X value 107 | inline void 108 | setMinX(T newValue) { 109 | if (newValue > getMaxX()) 110 | throw CTBException("The value is greater than the maximum X value"); 111 | 112 | bounds[0] = newValue; 113 | } 114 | 115 | /// Set the minimum Y value 116 | inline void 117 | setMinY(T newValue) { 118 | if (newValue > getMaxY()) 119 | throw CTBException("The value is greater than the maximum Y value"); 120 | 121 | bounds[1] = newValue; 122 | } 123 | 124 | /// Set the maximum X value 125 | inline void 126 | setMaxX(T newValue) { 127 | if (newValue < getMinX()) 128 | throw CTBException("The value is less than the minimum X value"); 129 | 130 | bounds[2] = newValue; 131 | } 132 | 133 | /// Set the maximum Y value 134 | inline void 135 | setMaxY(T newValue) { 136 | if (newValue < getMinY()) 137 | throw CTBException("The value is less than the minimum Y value"); 138 | 139 | bounds[3] = newValue; 140 | } 141 | 142 | /// Get the lower left corner 143 | inline Coordinate 144 | getLowerLeft() const { 145 | return Coordinate(getMinX(), getMinY()); 146 | } 147 | 148 | /// Get the lower right corner 149 | inline Coordinate 150 | getLowerRight() const { 151 | return Coordinate(getMaxX(), getMinY()); 152 | } 153 | 154 | /// Get the upper right corner 155 | inline Coordinate 156 | getUpperRight() const { 157 | return Coordinate(getMaxX(), getMaxY()); 158 | } 159 | 160 | /// Get the upper left corner 161 | inline Coordinate 162 | getUpperLeft() const { 163 | return Coordinate(getMinX(), getMaxY()); 164 | } 165 | 166 | /// Get the width 167 | inline T 168 | getWidth() const { 169 | return getMaxX() - getMinX(); 170 | } 171 | 172 | /// Get the height 173 | inline T 174 | getHeight() const { 175 | return getMaxY() - getMinY(); 176 | } 177 | 178 | /// Get the lower left quarter of the extents 179 | inline Bounds 180 | getSW() const { 181 | return Bounds(getMinX(), 182 | getMinY(), 183 | getMinX() + (getWidth() / 2), 184 | getMinY() + (getHeight() / 2)); 185 | } 186 | 187 | /// Get the upper left quarter of the extents 188 | inline Bounds 189 | getNW() const { 190 | return Bounds(getMinX(), 191 | getMaxY() - (getHeight() / 2), 192 | getMinX() + (getWidth() / 2), 193 | getMaxY()); 194 | } 195 | 196 | /// Get the upper right quarter of the extents 197 | inline Bounds 198 | getNE() const { 199 | return Bounds(getMaxX() - (getWidth() / 2), 200 | getMaxY() - (getHeight() / 2), 201 | getMaxX(), 202 | getMaxY()); 203 | } 204 | 205 | /// Get the lower right quarter of the extents 206 | inline Bounds 207 | getSE() const { 208 | return Bounds(getMaxX() - (getWidth() / 2), 209 | getMinY(), 210 | getMaxX(), 211 | getMinY() + (getHeight() / 2)); 212 | } 213 | 214 | /// Do these bounds overlap with another? 215 | inline bool 216 | overlaps(const Bounds *other) const { 217 | return overlaps(*other); 218 | } 219 | 220 | /// Do these bounds overlap with another? 221 | inline bool 222 | overlaps(const Bounds &other) const { 223 | // see 224 | // 225 | return getMinX() < other.getMaxX() && other.getMinX() < getMaxX() && 226 | getMinY() < other.getMaxY() && other.getMinY() < getMaxY(); 227 | } 228 | 229 | private: 230 | /// The extents themselves as { minx, miny, maxx, maxy } 231 | T bounds[4]; 232 | }; 233 | 234 | #endif /* BOUNDS_HPP */ 235 | -------------------------------------------------------------------------------- /third-party/ctb/CTBException.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBEXCEPTION_HPP 2 | #define CTBEXCEPTION_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file CTBException.hpp 22 | * @brief This declares and defines the `CTBException` class 23 | */ 24 | 25 | #include 26 | 27 | namespace ctb { 28 | class CTBException; 29 | } 30 | 31 | /// This represents a CTB runtime error 32 | class ctb::CTBException: 33 | public std::runtime_error 34 | { 35 | public: 36 | CTBException(const char *message): 37 | std::runtime_error(message) 38 | {} 39 | }; 40 | 41 | #endif /* CTBEXCEPTION_HPP */ 42 | -------------------------------------------------------------------------------- /third-party/ctb/CTBFileOutputStream.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2018 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file CTBFileOutputStream.cpp 19 | * @brief This defines the `CTBFileOutputStream` class 20 | */ 21 | 22 | #include "CTBFileOutputStream.hpp" 23 | 24 | using namespace ctb; 25 | 26 | /** 27 | * @details 28 | * Writes a sequence of memory pointed by ptr into the FILE*. 29 | */ 30 | uint32_t 31 | ctb::CTBFileOutputStream::write(const void *ptr, uint32_t size) { 32 | return (uint32_t)fwrite(ptr, size, 1, fp); 33 | } 34 | 35 | /** 36 | * @details 37 | * Writes a sequence of memory pointed by ptr into the ostream. 38 | */ 39 | uint32_t 40 | ctb::CTBStdOutputStream::write(const void *ptr, uint32_t size) { 41 | mstream.write((const char *)ptr, size); 42 | return size; 43 | } 44 | -------------------------------------------------------------------------------- /third-party/ctb/CTBFileOutputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBFILEOUTPUTSTREAM_HPP 2 | #define CTBFILEOUTPUTSTREAM_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file CTBFileOutputStream.hpp 22 | * @brief This declares and defines the `CTBFileOutputStream` and `CTBStdOutputStream` classes 23 | */ 24 | 25 | #include 26 | #include 27 | #include "CTBOutputStream.hpp" 28 | 29 | namespace ctb { 30 | class CTBFileOutputStream; 31 | class CTBStdOutputStream; 32 | } 33 | 34 | /// Implements CTBOutputStream for `FILE*` objects 35 | class CTB_DLL ctb::CTBFileOutputStream : public ctb::CTBOutputStream { 36 | public: 37 | CTBFileOutputStream(FILE *fptr): fp(fptr) {} 38 | 39 | /// Writes a sequence of memory pointed by ptr into the stream 40 | virtual uint32_t write(const void *ptr, uint32_t size); 41 | 42 | protected: 43 | /// The underlying FILE* 44 | FILE *fp; 45 | }; 46 | 47 | /// Implements CTBOutputStream for `std::ostream` objects 48 | class CTB_DLL ctb::CTBStdOutputStream : public ctb::CTBOutputStream { 49 | public: 50 | CTBStdOutputStream(std::ostream &stream): mstream(stream) {} 51 | 52 | /// Writes a sequence of memory pointed by ptr into the stream 53 | virtual uint32_t write(const void *ptr, uint32_t size); 54 | 55 | protected: 56 | /// The underlying std::ostream 57 | std::ostream &mstream; 58 | }; 59 | 60 | #endif /* CTBFILEOUTPUTSTREAM_HPP */ 61 | -------------------------------------------------------------------------------- /third-party/ctb/CTBOutputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBOUTPUTSTREAM_HPP 2 | #define CTBOUTPUTSTREAM_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file CTBOutputStream.hpp 22 | * @brief This declares and defines the `CTBOutputStream` class 23 | */ 24 | 25 | #include "config.hpp" 26 | #include "types.hpp" 27 | 28 | namespace ctb { 29 | class CTBOutputStream; 30 | } 31 | 32 | /// This represents a generic CTB output stream to write raw data 33 | class CTB_DLL ctb::CTBOutputStream { 34 | public: 35 | 36 | /// Writes a sequence of memory pointed by ptr into the stream 37 | virtual uint32_t write(const void *ptr, uint32_t size) = 0; 38 | }; 39 | 40 | #endif /* CTBOUTPUTSTREAM_HPP */ 41 | -------------------------------------------------------------------------------- /third-party/ctb/CTBZOutputStream.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2018 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file CTBZOutputStream.cpp 19 | * @brief This defines the `CTBZOutputStream` and `CTBZFileOutputStream` classes 20 | */ 21 | 22 | #include "CTBException.hpp" 23 | #include "CTBZOutputStream.hpp" 24 | 25 | using namespace ctb; 26 | 27 | /** 28 | * @details 29 | * Writes a sequence of memory pointed by ptr into the GZFILE*. 30 | */ 31 | uint32_t 32 | ctb::CTBZOutputStream::write(const void *ptr, uint32_t size) { 33 | if (size == 1) { 34 | int c = *((const char *)ptr); 35 | return gzputc(fp, c) == -1 ? 0 : 1; 36 | } 37 | else { 38 | return gzwrite(fp, ptr, size) == 0 ? 0 : size; 39 | } 40 | } 41 | 42 | ctb::CTBZFileOutputStream::CTBZFileOutputStream(const char *fileName) : CTBZOutputStream(NULL) { 43 | gzFile file = gzopen(fileName, "wb"); 44 | 45 | if (file == NULL) { 46 | throw CTBException("Failed to open file"); 47 | } 48 | fp = file; 49 | } 50 | 51 | ctb::CTBZFileOutputStream::~CTBZFileOutputStream() { 52 | close(); 53 | } 54 | 55 | void 56 | ctb::CTBZFileOutputStream::close() { 57 | 58 | // Try and close the file 59 | if (fp) { 60 | switch (gzclose(fp)) { 61 | case Z_OK: 62 | break; 63 | case Z_STREAM_ERROR: 64 | case Z_ERRNO: 65 | case Z_MEM_ERROR: 66 | case Z_BUF_ERROR: 67 | default: 68 | throw CTBException("Failed to close file"); 69 | } 70 | fp = NULL; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /third-party/ctb/CTBZOutputStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBZOUTPUTSTREAM_HPP 2 | #define CTBZOUTPUTSTREAM_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file CTBZOutputStream.hpp 22 | * @brief This declares and defines the `CTBZOutputStream` class 23 | */ 24 | 25 | #include "zlib.h" 26 | #include "CTBOutputStream.hpp" 27 | 28 | namespace ctb { 29 | class CTBZFileOutputStream; 30 | class CTBZOutputStream; 31 | } 32 | 33 | /// Implements CTBOutputStream for `GZFILE` object 34 | class CTB_DLL ctb::CTBZOutputStream : public ctb::CTBOutputStream { 35 | public: 36 | CTBZOutputStream(gzFile gzptr): fp(gzptr) {} 37 | 38 | /// Writes a sequence of memory pointed by ptr into the stream 39 | virtual uint32_t write(const void *ptr, uint32_t size); 40 | 41 | protected: 42 | /// The underlying GZFILE* 43 | gzFile fp; 44 | }; 45 | 46 | /// Implements CTBOutputStream for gzipped files 47 | class CTB_DLL ctb::CTBZFileOutputStream : public ctb::CTBZOutputStream { 48 | public: 49 | CTBZFileOutputStream(const char *fileName); 50 | ~CTBZFileOutputStream(); 51 | 52 | void close(); 53 | }; 54 | 55 | #endif /* CTBZOUTPUTSTREAM_HPP */ 56 | -------------------------------------------------------------------------------- /third-party/ctb/Coordinate.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COORDINATE_HPP 2 | #define COORDINATE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file Coordinate.hpp 22 | * @brief This declares and defines the `Coordinate` class 23 | */ 24 | 25 | namespace ctb { 26 | template class Coordinate; 27 | } 28 | 29 | /// A representation of a point coordinate 30 | template 31 | class ctb::Coordinate { 32 | public: 33 | 34 | /// Create an empty coordinate 35 | Coordinate(): 36 | x(0), 37 | y(0) 38 | {} 39 | 40 | /// The const copy constructor 41 | Coordinate(const Coordinate &other): 42 | x(other.x), 43 | y(other.y) 44 | {} 45 | 46 | /// Instantiate a coordinate from an x and y value 47 | Coordinate(T x, T y): 48 | x(x), 49 | y(y) 50 | {} 51 | 52 | /// Overload the equality operator 53 | virtual bool 54 | operator==(const Coordinate &other) const { 55 | return x == other.x 56 | && y == other.y; 57 | } 58 | 59 | /// Overload the assignment operator 60 | virtual void 61 | operator=(const Coordinate &other) { 62 | x = other.x; 63 | y = other.y; 64 | } 65 | 66 | T x, y; ///< The x and y coordinate members 67 | }; 68 | 69 | #endif /* COORDINATE_HPP */ 70 | -------------------------------------------------------------------------------- /third-party/ctb/Coordinate3D.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COORDINATE3D_HPP 2 | #define COORDINATE3D_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | #include 21 | #include 22 | 23 | /** 24 | * @file Coordinate3D.hpp 25 | * @brief This declares and defines the `Coordinate3D` class 26 | * @author Alvaro Huarte 27 | */ 28 | 29 | namespace ctb { 30 | template class Coordinate3D; 31 | } 32 | 33 | /// A representation of a 3-dimensional point coordinate 34 | template 35 | class ctb::Coordinate3D { 36 | public: 37 | T x, y, z; ///< The x, y and z coordinate members 38 | 39 | /// Create an empty coordinate 40 | Coordinate3D(): 41 | x(0), 42 | y(0), 43 | z(0) 44 | {} 45 | 46 | /// The const copy constructor 47 | Coordinate3D(const Coordinate3D &other): 48 | x(other.x), 49 | y(other.y), 50 | z(other.z) 51 | {} 52 | 53 | /// Instantiate a coordinate from an x, y and z value 54 | Coordinate3D(T x, T y, T z): 55 | x(x), 56 | y(y), 57 | z(z) 58 | {} 59 | 60 | /// Overload the equality operator 61 | virtual bool 62 | operator==(const Coordinate3D &other) const { 63 | return x == other.x 64 | && y == other.y 65 | && z == other.z; 66 | } 67 | 68 | /// Overload the assignment operator 69 | virtual void 70 | operator=(const Coordinate3D &other) { 71 | x = other.x; 72 | y = other.y; 73 | z = other.z; 74 | } 75 | 76 | /// Gets a read-only index-ordinate of the coordinate 77 | inline virtual T operator[](const int index) const { 78 | return (index == 0) ? x : (index == 1 ? y : z); 79 | } 80 | 81 | /// Add operator 82 | inline virtual Coordinate3D operator+(const Coordinate3D& other) const { 83 | return Coordinate3D(x + other.x, y + other.y, z + other.z); 84 | } 85 | /// Subtract operator 86 | inline virtual Coordinate3D operator-(const Coordinate3D& other) const { 87 | return Coordinate3D(x - other.x, y - other.y, z - other.z); 88 | } 89 | /// Multiply operator 90 | inline virtual Coordinate3D operator*(const Coordinate3D& other) const { 91 | return Coordinate3D(x * other.x, y * other.y, z * other.z); 92 | } 93 | /// Divide operator 94 | inline virtual Coordinate3D operator/(const Coordinate3D& other) const { 95 | return Coordinate3D(x / other.x, y / other.y, z / other.z); 96 | } 97 | 98 | /// AddByScalar operator 99 | inline virtual Coordinate3D operator+(const T scalar) const { 100 | return Coordinate3D(x + scalar, y + scalar, z + scalar); 101 | } 102 | /// SubtractByScalar operator 103 | inline virtual Coordinate3D operator-(const T scalar) const { 104 | return Coordinate3D(x - scalar, y - scalar, z - scalar); 105 | } 106 | /// MultiplyByScalar operator 107 | inline virtual Coordinate3D operator*(const T scalar) const { 108 | return Coordinate3D(x * scalar, y * scalar, z * scalar); 109 | } 110 | /// DivideByScalar operator 111 | inline virtual Coordinate3D operator/(const T scalar) const { 112 | return Coordinate3D(x / scalar, y / scalar, z / scalar); 113 | } 114 | 115 | /// Cross product 116 | inline Coordinate3D cross(const Coordinate3D &other) const { 117 | return Coordinate3D((y * other.z) - (other.y * z), 118 | (z * other.x) - (other.z * x), 119 | (x * other.y) - (other.x * y)); 120 | } 121 | /// Dot product 122 | inline double dot(const Coordinate3D &other) const { 123 | return (x * other.x) + (y * other.y) + (z * other.z); 124 | } 125 | 126 | // Cartesian3d methods 127 | inline T magnitudeSquared(void) const { 128 | return (x * x) + (y * y) + (z * z); 129 | } 130 | inline T magnitude(void) const { 131 | return std::sqrt(magnitudeSquared()); 132 | } 133 | inline static Coordinate3D add(const Coordinate3D &p1, const Coordinate3D &p2) { 134 | return p1 + p2; 135 | } 136 | inline static Coordinate3D subtract(const Coordinate3D &p1, const Coordinate3D &p2) { 137 | return p1 - p2; 138 | } 139 | inline static T distanceSquared(const Coordinate3D &p1, const Coordinate3D &p2) { 140 | T xdiff = p1.x - p2.x; 141 | T ydiff = p1.y - p2.y; 142 | T zdiff = p1.z - p2.z; 143 | return (xdiff * xdiff) + (ydiff * ydiff) + (zdiff * zdiff); 144 | } 145 | inline static T distance(const Coordinate3D &p1, const Coordinate3D &p2) { 146 | return std::sqrt(distanceSquared(p1, p2)); 147 | } 148 | inline Coordinate3D normalize(void) const { 149 | T mgn = magnitude(); 150 | return Coordinate3D(x / mgn, y / mgn, z / mgn); 151 | } 152 | }; 153 | 154 | #endif /* COORDINATE3D_HPP */ 155 | -------------------------------------------------------------------------------- /third-party/ctb/GDALDatasetReader.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2018 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file GDALDatasetReader.cpp 19 | * @brief This defines the `GDALDatasetReader` class 20 | */ 21 | 22 | #include "gdal_priv.h" 23 | #include "gdalwarper.h" 24 | 25 | #include "CTBException.hpp" 26 | #include "GDALDatasetReader.hpp" 27 | #include "TerrainTiler.hpp" 28 | 29 | using namespace ctb; 30 | 31 | /** 32 | * @details 33 | * Read a region of raster heights for the specified Dataset and Coordinate. 34 | * This method uses `GDALRasterBand::RasterIO` function. 35 | */ 36 | float * 37 | ctb::GDALDatasetReader::readRasterHeights(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) { 38 | GDALTile *rasterTile = createRasterTile(tiler, dataset, coord); // the raster associated with this tile coordinate 39 | 40 | const ctb::i_tile TILE_CELL_SIZE = tileSizeX * tileSizeY; 41 | float *rasterHeights = (float *)CPLCalloc(TILE_CELL_SIZE, sizeof(float)); 42 | 43 | GDALRasterBand *heightsBand = rasterTile->dataset->GetRasterBand(1); 44 | 45 | if (heightsBand->RasterIO(GF_Read, 0, 0, tileSizeX, tileSizeY, 46 | (void *) rasterHeights, tileSizeX, tileSizeY, GDT_Float32, 47 | 0, 0) != CE_None) { 48 | delete rasterTile; 49 | CPLFree(rasterHeights); 50 | 51 | throw CTBException("Could not read heights from raster"); 52 | } 53 | delete rasterTile; 54 | return rasterHeights; 55 | } 56 | 57 | /// Create a raster tile from a tile coordinate 58 | GDALTile * 59 | ctb::GDALDatasetReader::createRasterTile(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord) { 60 | return tiler.createRasterTile(dataset, coord); 61 | } 62 | 63 | /// Create a VTR raster overview from a GDALDataset 64 | GDALDataset * 65 | ctb::GDALDatasetReader::createOverview(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord, int overviewIndex) { 66 | int nFactorScale = 2 << overviewIndex; 67 | int nRasterXSize = dataset->GetRasterXSize() / nFactorScale; 68 | int nRasterYSize = dataset->GetRasterYSize() / nFactorScale; 69 | 70 | GDALDataset *poOverview = NULL; 71 | double adfGeoTransform[6]; 72 | 73 | // Should We create an overview of the Dataset? 74 | if (nRasterXSize > 4 && nRasterYSize > 4 && dataset->GetGeoTransform(adfGeoTransform) == CE_None) { 75 | adfGeoTransform[1] *= nFactorScale; 76 | adfGeoTransform[5] *= nFactorScale; 77 | 78 | TerrainTiler tempTiler(tiler.dataset(), tiler.grid(), tiler.options); 79 | tempTiler.crsWKT = ""; 80 | GDALTile *rasterTile = createRasterTile(tempTiler, dataset, coord); 81 | if (rasterTile) { 82 | poOverview = rasterTile->detach(); 83 | delete rasterTile; 84 | } 85 | } 86 | return poOverview; 87 | } 88 | 89 | /// The destructor 90 | ctb::GDALDatasetReaderWithOverviews::~GDALDatasetReaderWithOverviews() { 91 | reset(); 92 | } 93 | 94 | /// Read a region of raster heights into an array for the specified Dataset and Coordinate 95 | float * 96 | ctb::GDALDatasetReaderWithOverviews::readRasterHeights(GDALDataset *dataset, const TileCoordinate &coord, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) { 97 | GDALDataset *mainDataset = dataset; 98 | 99 | const ctb::i_tile TILE_CELL_SIZE = tileSizeX * tileSizeY; 100 | float *rasterHeights = (float *)CPLCalloc(TILE_CELL_SIZE, sizeof(float)); 101 | 102 | // Replace GDAL Dataset by last valid Overview. 103 | for (int i = mOverviews.size() - 1; i >= 0; --i) { 104 | if (mOverviews[i]) { 105 | dataset = mOverviews[i]; 106 | break; 107 | } 108 | } 109 | 110 | // Extract the raster data, using overviews when necessary 111 | bool rasterOk = false; 112 | while (!rasterOk) { 113 | GDALTile *rasterTile = createRasterTile(poTiler, dataset, coord); // the raster associated with this tile coordinate 114 | 115 | GDALRasterBand *heightsBand = rasterTile->dataset->GetRasterBand(1); 116 | 117 | if (heightsBand->RasterIO(GF_Read, 0, 0, tileSizeX, tileSizeY, 118 | (void *) rasterHeights, tileSizeX, tileSizeY, GDT_Float32, 119 | 0, 0) != CE_None) { 120 | 121 | GDALDataset *psOverview = createOverview(poTiler, mainDataset, coord, mOverviewIndex++); 122 | if (psOverview) { 123 | mOverviews.push_back(psOverview); 124 | dataset = psOverview; 125 | } 126 | else { 127 | delete rasterTile; 128 | CPLFree(rasterHeights); 129 | throw CTBException("Could not create an overview of current GDAL dataset"); 130 | } 131 | } 132 | else { 133 | rasterOk = true; 134 | } 135 | delete rasterTile; 136 | } 137 | 138 | // Everything ok? 139 | if (!rasterOk) { 140 | CPLFree(rasterHeights); 141 | throw CTBException("Could not read heights from raster"); 142 | } 143 | return rasterHeights; 144 | } 145 | 146 | /// Releases all overviews 147 | void 148 | ctb::GDALDatasetReaderWithOverviews::reset() { 149 | mOverviewIndex = 0; 150 | 151 | for (int i = mOverviews.size() - 1; i >= 0; --i) { 152 | GDALDataset *poOverview = mOverviews[i]; 153 | GDALClose(poOverview); 154 | } 155 | mOverviews.clear(); 156 | } 157 | -------------------------------------------------------------------------------- /third-party/ctb/GDALDatasetReader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GDALDATASETREADER_HPP 2 | #define GDALDATASETREADER_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file GDALDatasetReader.hpp 22 | * @brief This declares the `GDALDatasetReader` class 23 | */ 24 | 25 | #include 26 | #include 27 | #include "gdalwarper.h" 28 | 29 | #include "TileCoordinate.hpp" 30 | #include "GDALTiler.hpp" 31 | 32 | namespace ctb { 33 | class GDALDatasetReader; 34 | class GDALDatasetReaderWithOverviews; 35 | } 36 | 37 | /** 38 | * @brief Read raster tiles from a GDAL Dataset 39 | * 40 | * This abstract base class is associated with a GDAL dataset. 41 | * It allows to read a region of the raster according to 42 | * a region defined by a Tile Coordinate. 43 | * 44 | * We can define our own 45 | */ 46 | class CTB_DLL ctb::GDALDatasetReader { 47 | public: 48 | /// Read a region of raster heights into an array for the specified Dataset and Coordinate 49 | static float * 50 | readRasterHeights(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY); 51 | 52 | /// Read a region of raster heights into an array for the specified Dataset and Coordinate 53 | virtual float * 54 | readRasterHeights(GDALDataset *dataset, const TileCoordinate &coord, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) = 0; 55 | 56 | protected: 57 | /// Create a raster tile from a tile coordinate 58 | static GDALTile * 59 | createRasterTile(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord); 60 | 61 | /// Create a VTR raster overview from a GDALDataset 62 | static GDALDataset * 63 | createOverview(const GDALTiler &tiler, GDALDataset *dataset, const TileCoordinate &coord, int overviewIndex); 64 | }; 65 | 66 | /** 67 | * @brief Implements a GDALDatasetReader that takes care of 'Integer overflow' errors. 68 | * 69 | * This class creates Overviews to avoid 'Integer overflow' errors when extracting 70 | * raster data. 71 | */ 72 | class CTB_DLL ctb::GDALDatasetReaderWithOverviews : public ctb::GDALDatasetReader { 73 | public: 74 | 75 | /// Instantiate a GDALDatasetReaderWithOverviews 76 | GDALDatasetReaderWithOverviews(const GDALTiler &tiler): 77 | poTiler(tiler), 78 | mOverviewIndex(0) {} 79 | 80 | /// The destructor 81 | ~GDALDatasetReaderWithOverviews(); 82 | 83 | /// Read a region of raster heights into an array for the specified Dataset and Coordinate 84 | virtual float * 85 | readRasterHeights(GDALDataset *dataset, const TileCoordinate &coord, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) override; 86 | 87 | /// Releases all overviews 88 | void reset(); 89 | 90 | protected: 91 | /// The tiler to use 92 | const GDALTiler &poTiler; 93 | 94 | /// List of VRT Overviews of the underlying GDAL dataset 95 | std::vector mOverviews; 96 | /// Current VRT Overview 97 | int mOverviewIndex; 98 | }; 99 | 100 | #endif /* GDALDATASETREADER_HPP */ 101 | -------------------------------------------------------------------------------- /third-party/ctb/GDALTile.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file GDALTile.cpp 19 | * @brief This defines the `GDALTile` class 20 | */ 21 | 22 | #include "gdalwarper.h" 23 | 24 | #include "GDALTile.hpp" 25 | 26 | using namespace ctb; 27 | 28 | GDALTile::~GDALTile() { 29 | if (dataset != NULL) { 30 | GDALClose(dataset); 31 | 32 | if (transformer != NULL) { 33 | GDALDestroyGenImgProjTransformer(transformer); 34 | } 35 | } 36 | } 37 | 38 | /// Detach the underlying GDAL dataset 39 | GDALDataset *GDALTile::detach() { 40 | if (dataset != NULL) { 41 | GDALDataset *poDataset = dataset; 42 | dataset = NULL; 43 | 44 | if (transformer != NULL) { 45 | GDALDestroyGenImgProjTransformer(transformer); 46 | transformer = NULL; 47 | } 48 | return poDataset; 49 | } 50 | return NULL; 51 | } 52 | -------------------------------------------------------------------------------- /third-party/ctb/GDALTile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GDALTILE_HPP 2 | #define GDALTILE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file GDALTile.hpp 22 | * @brief This declares the `GDALTile` class 23 | */ 24 | 25 | #include "gdal_priv.h" 26 | 27 | #include "config.hpp" // for CTB_DLL 28 | #include "Tile.hpp" 29 | 30 | namespace ctb { 31 | class GDALTile; 32 | class GDALTiler; // forward declaration 33 | } 34 | 35 | /** 36 | * A representation of a `Tile` with a GDAL datasource 37 | * 38 | * This is composed of a GDAL VRT datasource and optionally a GDAL image 39 | * transformer, along with a `TileCoordinate`. The transformer handle is 40 | * necessary in cases where the VRT is warped using a linear approximation 41 | * (`GDALApproxTransform`). In this case there is the top level transformer (the 42 | * linear approximation) which wraps an image transformer. The VRT owns any top 43 | * level transformer, but we are responsible for the wrapped image transformer. 44 | */ 45 | class CTB_DLL ctb::GDALTile : 46 | public Tile 47 | { 48 | public: 49 | /// Take ownership of a dataset and optional transformer 50 | GDALTile(GDALDataset *dataset, void *transformer): 51 | Tile(), 52 | dataset(dataset), 53 | transformer(transformer) 54 | {} 55 | 56 | ~GDALTile(); 57 | 58 | GDALDataset *dataset; 59 | 60 | /// Detach the underlying GDAL dataset 61 | GDALDataset *detach(); 62 | 63 | protected: 64 | friend class GDALTiler; 65 | 66 | /// The image to image transformer 67 | void *transformer; 68 | }; 69 | 70 | #endif /* GDALTILE_HPP */ 71 | -------------------------------------------------------------------------------- /third-party/ctb/GDALTiler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GDALTILER_HPP 2 | #define GDALTILER_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file GDALTiler.hpp 22 | * @brief This declares the `GDALTiler` class 23 | */ 24 | 25 | #include 26 | #include "gdalwarper.h" 27 | 28 | #include "TileCoordinate.hpp" 29 | #include "GlobalGeodetic.hpp" 30 | #include "GDALTile.hpp" 31 | #include "Bounds.hpp" 32 | 33 | namespace ctb { 34 | struct TilerOptions; 35 | class GDALTiler; 36 | class GDALDatasetReader; // forward declaration 37 | } 38 | 39 | /// Options passed to a `GDALTiler` 40 | struct ctb::TilerOptions { 41 | /// The error threshold in pixels passed to the approximation transformer 42 | float errorThreshold = 0.125; // the `gdalwarp` default 43 | /// The memory limit of the warper in bytes 44 | double warpMemoryLimit = 0.0; // default to GDAL internal setting 45 | /// The warp resampling algorithm 46 | GDALResampleAlg resampleAlg = GRA_Average; // recommended by GDAL maintainer 47 | }; 48 | 49 | /** 50 | * @brief Create raster tiles from a GDAL Dataset 51 | * 52 | * This abstract base class is associated with a GDAL dataset from which it 53 | * determines the maximum zoom level (see `GDALTiler::maxZoomLevel`) and tile 54 | * extents for a particular zoom level (see `GDALTiler::tileBoundsForZoom`). 55 | * This information can be used to create `TileCoordinate` instances which in 56 | * turn can be used to create raster representations of a tile coverage (see 57 | * `GDALTiler::createRasterTile`). This mechanism is intended to be leveraged 58 | * by derived classes to override the `GDALTiler::createTile` method. 59 | * 60 | * The GDAL dataset assigned to the tiler has its reference count incremented 61 | * when a tiler is instantiated or copied, meaning that the dataset is shared 62 | * with any other handles that may also be in use. When the tiler is destroyed 63 | * the reference count is decremented and, if it reaches `0`, the dataset is 64 | * closed. 65 | */ 66 | class CTB_DLL ctb::GDALTiler { 67 | public: 68 | 69 | /// Instantiate a tiler with all required arguments 70 | GDALTiler(GDALDataset *poDataset, const Grid &grid, const TilerOptions &options); 71 | 72 | /// Instantiate a tiler with an empty GDAL dataset 73 | GDALTiler(): 74 | GDALTiler(NULL, GlobalGeodetic()) {} 75 | 76 | /// Instantiate a tiler with a dataset and grid but no options 77 | GDALTiler(GDALDataset *poDataset, const Grid &grid): 78 | GDALTiler(poDataset, grid, TilerOptions()) {} 79 | 80 | /// The const copy constructor 81 | GDALTiler(const GDALTiler &other); 82 | 83 | /// The non const copy constructor 84 | GDALTiler(GDALTiler &other); 85 | 86 | /// Overload the assignment operator 87 | GDALTiler & 88 | operator=(const GDALTiler &other); 89 | 90 | /// The destructor 91 | ~GDALTiler(); 92 | 93 | /// Create a tile from a tile coordinate 94 | virtual Tile * 95 | createTile(GDALDataset *dataset, const TileCoordinate &coord) const = 0; 96 | 97 | /// Get the maximum zoom level for the dataset 98 | inline i_zoom 99 | maxZoomLevel() const { 100 | return mGrid.zoomForResolution(resolution()); 101 | } 102 | 103 | /// Get the lower left tile for a particular zoom level 104 | inline TileCoordinate 105 | lowerLeftTile(i_zoom zoom) const { 106 | return mGrid.crsToTile(mBounds.getLowerLeft(), zoom); 107 | } 108 | 109 | /// Get the upper right tile for a particular zoom level 110 | inline TileCoordinate 111 | upperRightTile(i_zoom zoom) const { 112 | return mGrid.crsToTile(mBounds.getUpperRight(), zoom); 113 | } 114 | 115 | /// Get the tile bounds for a particular zoom level 116 | inline TileBounds 117 | tileBoundsForZoom(i_zoom zoom) const { 118 | TileCoordinate ll = mGrid.crsToTile(mBounds.getLowerLeft(), zoom), 119 | ur = mGrid.crsToTile(mBounds.getUpperRight(), zoom); 120 | 121 | return TileBounds(ll, ur); 122 | } 123 | 124 | /// Get the resolution of the underlying GDAL dataset 125 | inline double 126 | resolution() const { 127 | return mResolution; 128 | } 129 | 130 | /// Get the associated GDAL dataset 131 | inline GDALDataset * 132 | dataset() const { 133 | return poDataset; 134 | } 135 | 136 | /// Get the associated grid 137 | inline const Grid & 138 | grid() const { 139 | return mGrid; 140 | } 141 | 142 | /// Get the dataset bounds in EPSG:4326 coordinates 143 | inline const CRSBounds & 144 | bounds() const { 145 | return const_cast(mBounds); 146 | } 147 | 148 | /// Does the dataset require reprojecting to EPSG:4326? 149 | inline bool 150 | requiresReprojection() const { 151 | return crsWKT.size() > 0; 152 | } 153 | 154 | protected: 155 | friend class GDALDatasetReader; 156 | 157 | /// Close the underlying dataset 158 | void closeDataset(); 159 | 160 | /// Create a raster tile from a tile coordinate 161 | virtual GDALTile * 162 | createRasterTile(GDALDataset *dataset, const TileCoordinate &coord) const; 163 | 164 | /// Create a raster tile from a geo transform 165 | virtual GDALTile * 166 | createRasterTile(GDALDataset *dataset, double (&adfGeoTransform)[6]) const; 167 | 168 | /// The grid used for generating tiles 169 | Grid mGrid; 170 | 171 | /// The dataset from which to generate tiles 172 | GDALDataset *poDataset; 173 | 174 | TilerOptions options; 175 | 176 | /// The extent of the underlying dataset in latitude and longitude 177 | CRSBounds mBounds; 178 | 179 | /// The cell resolution of the underlying dataset 180 | double mResolution; 181 | 182 | /** 183 | * @brief The dataset projection in Well Known Text format 184 | * 185 | * This is only set if the underlying dataset does not match the coordinate 186 | * reference system of the grid being used. 187 | */ 188 | std::string crsWKT; 189 | }; 190 | 191 | #endif /* GDALTILER_HPP */ 192 | -------------------------------------------------------------------------------- /third-party/ctb/GlobalGeodetic.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file GlobalGeodetic.cpp 19 | * @brief This defines the `GlobalGeodetic` class 20 | */ 21 | 22 | #include "GlobalGeodetic.hpp" 23 | 24 | using namespace ctb; 25 | 26 | // Set the spatial reference 27 | static OGRSpatialReference 28 | setSRS(void) { 29 | OGRSpatialReference srs; 30 | 31 | #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) 32 | srs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 33 | #endif // GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) 34 | 35 | srs.importFromEPSG(4326); 36 | return srs; 37 | } 38 | 39 | const OGRSpatialReference GlobalGeodetic::cSRS = setSRS(); 40 | -------------------------------------------------------------------------------- /third-party/ctb/GlobalGeodetic.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALGEODETIC_HPP 2 | #define GLOBALGEODETIC_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file GlobalGeodetic.hpp 22 | * @brief This defines and declares the `GlobalGeodetic` class 23 | */ 24 | 25 | #include "config.hpp" 26 | #include "Grid.hpp" 27 | 28 | namespace ctb { 29 | class GlobalGeodetic; 30 | } 31 | 32 | /** 33 | * @brief An implementation of the TMS Global Geodetic Profile 34 | * 35 | * This class models the [Tile Mapping Service Global Geodetic 36 | * Profile](http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic). 37 | */ 38 | class CTB_DLL ctb::GlobalGeodetic : 39 | public Grid { 40 | public: 41 | 42 | /// Initialise the profile with a specific tile size 43 | GlobalGeodetic(i_tile tileSize = TILE_SIZE, bool tmsCompatible = true): 44 | Grid(tileSize, 45 | CRSBounds(-180, -90, 180, 90), 46 | cSRS, 47 | (tmsCompatible) ? 2 : 1) 48 | {} 49 | 50 | protected: 51 | 52 | /// The EPSG:4326 spatial reference system 53 | static const OGRSpatialReference cSRS; 54 | }; 55 | 56 | #endif /* GLOBALGEODETIC_HPP */ 57 | -------------------------------------------------------------------------------- /third-party/ctb/GlobalMercator.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file GlobalMercator.cpp 19 | * @brief This defines the `GlobalMercator` class 20 | */ 21 | 22 | #define _USE_MATH_DEFINES // for M_PI 23 | 24 | #include "GlobalMercator.hpp" 25 | 26 | using namespace ctb; 27 | 28 | // Set the class level properties 29 | const unsigned int GlobalMercator::cSemiMajorAxis = 6378137; 30 | const double GlobalMercator::cEarthCircumference = 2 * M_PI * GlobalMercator::cSemiMajorAxis; 31 | const double GlobalMercator::cOriginShift = GlobalMercator::cEarthCircumference / 2.0; 32 | 33 | // Set the spatial reference 34 | static OGRSpatialReference 35 | setSRS(void) { 36 | OGRSpatialReference srs; 37 | 38 | #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) 39 | srs.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); 40 | #endif // GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,0,0) 41 | 42 | srs.importFromEPSG(3857); 43 | return srs; 44 | } 45 | 46 | const OGRSpatialReference GlobalMercator::cSRS = setSRS(); 47 | -------------------------------------------------------------------------------- /third-party/ctb/GlobalMercator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALMERCATOR_HPP 2 | #define GLOBALMERCATOR_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file GlobalMercator.hpp 22 | * @brief This defines the `GlobalMercator` class 23 | */ 24 | 25 | #include "config.hpp" // for CTB_DLL 26 | #include "Grid.hpp" 27 | 28 | namespace ctb { 29 | class GlobalMercator; 30 | } 31 | 32 | /** 33 | * @brief An implementation of the TMS Global Mercator Profile 34 | * 35 | * This class models the [Tile Mapping Service Global Mercator 36 | * Profile](http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-mercator). 37 | */ 38 | class CTB_DLL ctb::GlobalMercator : 39 | public Grid { 40 | public: 41 | 42 | GlobalMercator(i_tile tileSize = 256): 43 | Grid(tileSize, 44 | CRSBounds(-cOriginShift, -cOriginShift, cOriginShift, cOriginShift), 45 | cSRS) 46 | {} 47 | 48 | protected: 49 | 50 | /// The semi major axis of the WGS84 ellipsoid (the radius of the earth in 51 | /// meters) 52 | static const unsigned int cSemiMajorAxis; 53 | 54 | /// The circumference of the earth in meters 55 | static const double cEarthCircumference; 56 | 57 | /// The coordinate origin (the middle of the grid extent) 58 | static const double cOriginShift; 59 | 60 | /// The EPSG:3785 spatial reference system 61 | static const OGRSpatialReference cSRS; 62 | }; 63 | 64 | #endif /* GLOBALMERCATOR_HPP */ 65 | -------------------------------------------------------------------------------- /third-party/ctb/Grid.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBGRID_HPP 2 | #define CTBGRID_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file Grid.hpp 22 | * @brief This defines and declares the `Grid` class 23 | */ 24 | 25 | #include 26 | 27 | #include "ogr_spatialref.h" 28 | 29 | #include "types.hpp" 30 | #include "TileCoordinate.hpp" 31 | 32 | namespace ctb { 33 | class Grid; 34 | } 35 | 36 | /** 37 | * @brief A generic grid for cutting tile sets 38 | * 39 | * This class models a grid for use in cutting up an area into zoom levels and 40 | * tiles. It provides functionality such as relating a coordinate in a native 41 | * coordinate reference system (CRS) to a tile (see `Grid::crsToTile`) and 42 | * getting the CRS bounds of a tile (see `Grid::tileBounds`). 43 | * 44 | * The `Grid` class should be able to model most grid systems. The 45 | * `GlobalMercator` and `GlobalGeodetic` subclasses implement the specific Tile 46 | * Mapping Service grid profiles. 47 | * 48 | * The code here generalises the logic in the `gdal2tiles.py` script available 49 | * with the GDAL library. 50 | */ 51 | class ctb::Grid { 52 | public: 53 | 54 | /// An empty grid 55 | Grid() {} 56 | 57 | /// Initialise a grid tile 58 | Grid(i_tile tileSize, 59 | const CRSBounds extent, 60 | const OGRSpatialReference srs, 61 | unsigned short int rootTiles = 1, 62 | float zoomFactor = 2): 63 | mTileSize(tileSize), 64 | mExtent(extent), 65 | mSRS(srs), 66 | mInitialResolution((extent.getWidth() / rootTiles) / tileSize ), 67 | mXOriginShift(extent.getWidth() / 2), 68 | mYOriginShift(extent.getHeight() / 2), 69 | mZoomFactor(zoomFactor) 70 | {} 71 | 72 | /// Overload the assignment operator 73 | Grid & 74 | operator=(const Grid &other) { 75 | mTileSize = other.mTileSize; 76 | mExtent = other.mExtent; 77 | mSRS = other.mSRS; 78 | mInitialResolution = other.mInitialResolution; 79 | mXOriginShift = other.mXOriginShift; 80 | mYOriginShift = other.mYOriginShift; 81 | mZoomFactor = other.mZoomFactor; 82 | 83 | return *this; 84 | } 85 | 86 | /// Override the equality operator 87 | bool 88 | operator==(const Grid &other) const { 89 | return mTileSize == other.mTileSize 90 | && mExtent == other.mExtent 91 | && mSRS.IsSame(&(other.mSRS)) 92 | && mInitialResolution == other.mInitialResolution 93 | && mXOriginShift == other.mXOriginShift 94 | && mYOriginShift == other.mYOriginShift 95 | && mZoomFactor == other.mZoomFactor; 96 | } 97 | 98 | /// Get the resolution for a particular zoom level 99 | inline double 100 | resolution(i_zoom zoom) const { 101 | return mInitialResolution / pow(mZoomFactor, zoom); 102 | } 103 | 104 | /** 105 | * @brief Get the zoom level for a particular resolution 106 | * 107 | * If the resolution does not exactly match a zoom level then the zoom level 108 | * is 'rounded up' to the next level. 109 | */ 110 | inline i_zoom 111 | zoomForResolution(double resolution) const { 112 | // if mZoomFactor == 2 the following is the same as using: 113 | // log2(mInitialResolution) - log2(resolution) 114 | return (i_zoom) ceil((log(mInitialResolution)/log(mZoomFactor)) - (log(resolution)/log(mZoomFactor))); 115 | } 116 | 117 | /// Get the tile covering a pixel location 118 | inline TilePoint 119 | pixelsToTile(const PixelPoint &pixel) const { 120 | i_tile tx = (i_tile) (pixel.x / mTileSize), 121 | ty = (i_tile) (pixel.y / mTileSize); 122 | 123 | return TilePoint(tx, ty); 124 | } 125 | 126 | /// Convert pixel coordinates at a given zoom level to CRS coordinates 127 | inline CRSPoint 128 | pixelsToCrs(const PixelPoint &pixel, i_zoom zoom) const { 129 | double res = resolution(zoom); 130 | 131 | return CRSPoint((pixel.x * res) - mXOriginShift, 132 | (pixel.y * res) - mYOriginShift); 133 | } 134 | 135 | /// Get the pixel location represented by a CRS point and zoom level 136 | inline PixelPoint 137 | crsToPixels(const CRSPoint &coord, i_zoom zoom) const { 138 | double res = resolution(zoom); 139 | i_pixel px = (mXOriginShift + coord.x) / res, 140 | py = (mYOriginShift + coord.y) / res; 141 | 142 | return PixelPoint(px, py); 143 | } 144 | 145 | /// Get the tile coordinate in which a location falls at a specific zoom level 146 | inline TileCoordinate 147 | crsToTile(const CRSPoint &coord, i_zoom zoom) const { 148 | const PixelPoint pixel = crsToPixels(coord, zoom); 149 | TilePoint tile = pixelsToTile(pixel); 150 | 151 | return TileCoordinate(zoom, tile); 152 | } 153 | 154 | /// Get the CRS bounds of a particular tile 155 | inline CRSBounds 156 | tileBounds(const TileCoordinate &coord) const { 157 | // get the pixels coordinates representing the tile bounds 158 | const PixelPoint pxLowerLeft(coord.x * mTileSize, coord.y * mTileSize), 159 | pxUpperRight((coord.x + 1) * mTileSize, (coord.y + 1) * mTileSize); 160 | 161 | // convert pixels to native coordinates 162 | const CRSPoint lowerLeft = pixelsToCrs(pxLowerLeft, coord.zoom), 163 | upperRight = pixelsToCrs(pxUpperRight, coord.zoom); 164 | 165 | return CRSBounds(lowerLeft, upperRight); 166 | } 167 | 168 | /// Get the tile size associated with this grid 169 | inline i_tile 170 | tileSize() const { 171 | return mTileSize; 172 | } 173 | 174 | /// Get the tile size associated with this grid 175 | inline const OGRSpatialReference & 176 | getSRS() const { 177 | return mSRS; 178 | } 179 | 180 | /// Get the extent covered by the grid in CRS coordinates 181 | inline const CRSBounds & 182 | getExtent() const { 183 | return mExtent; 184 | } 185 | 186 | /// Get the extent covered by the grid in tile coordinates for a zoom level 187 | inline TileBounds 188 | getTileExtent(i_zoom zoom) const { 189 | TileCoordinate ll = crsToTile(mExtent.getLowerLeft(), zoom), 190 | ur = crsToTile(mExtent.getUpperRight(), zoom); 191 | 192 | return TileBounds(ll, ur); 193 | } 194 | 195 | protected: 196 | 197 | /// The tile size associated with this grid 198 | i_tile mTileSize; 199 | 200 | /// The area covered by the grid 201 | CRSBounds mExtent; 202 | 203 | /// The spatial reference system covered by the grid 204 | OGRSpatialReference mSRS; 205 | 206 | double mInitialResolution, ///< The initial resolution of this particular profile 207 | mXOriginShift, ///< The shift in CRS coordinates to get to the origin from minx 208 | mYOriginShift; ///< The shift in CRS coordinates to get to the origin from miny 209 | 210 | /// By what factor will the scale increase at each zoom level? 211 | float mZoomFactor; 212 | }; 213 | 214 | #endif /* CTBGRID_HPP */ 215 | -------------------------------------------------------------------------------- /third-party/ctb/Mesh.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBMESH_HPP 2 | #define CTBMESH_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file Mesh.hpp 22 | * @brief This declares the `Mesh` class 23 | * @author Alvaro Huarte 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include "types.hpp" 30 | #include "CTBException.hpp" 31 | 32 | namespace ctb { 33 | class Mesh; 34 | } 35 | 36 | /** 37 | * @brief An abstract base class for a mesh of triangles 38 | */ 39 | class ctb::Mesh 40 | { 41 | public: 42 | 43 | /// Create an empty mesh 44 | Mesh() 45 | {} 46 | 47 | public: 48 | 49 | /// The array of shared vertices of a mesh 50 | std::vector vertices; 51 | 52 | /// The index collection for each triangle in the mesh (3 for each triangle) 53 | std::vector indices; 54 | 55 | /// Write mesh data to a WKT file 56 | void writeWktFile(const char *fileName) const { 57 | FILE *fp = fopen(fileName, "w"); 58 | 59 | if (fp == NULL) { 60 | throw CTBException("Failed to open file"); 61 | } 62 | 63 | char wktText[512]; 64 | memset(wktText, 0, sizeof(wktText)); 65 | 66 | for (int i = 0, icount = indices.size(); i < icount; i += 3) { 67 | CRSVertex v0 = vertices[indices[i]]; 68 | CRSVertex v1 = vertices[indices[i+1]]; 69 | CRSVertex v2 = vertices[indices[i+2]]; 70 | 71 | sprintf(wktText, "(%.8f %.8f %f, %.8f %.8f %f, %.8f %.8f %f, %.8f %.8f %f)", 72 | v0.x, v0.y, v0.z, 73 | v1.x, v1.y, v1.z, 74 | v2.x, v2.y, v2.z, 75 | v0.x, v0.y, v0.z); 76 | fprintf(fp, "POLYGON Z(%s)\n", wktText); 77 | } 78 | fclose(fp); 79 | }; 80 | }; 81 | 82 | #endif /* CTBMESH_HPP */ 83 | -------------------------------------------------------------------------------- /third-party/ctb/MeshTile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MESHTILE_HPP 2 | #define MESHTILE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file MeshTile.hpp 22 | * @brief This declares the `MeshTile` class 23 | * @author Alvaro Huarte 24 | */ 25 | 26 | #include "config.hpp" 27 | #include "Mesh.hpp" 28 | #include "TileCoordinate.hpp" 29 | #include "Tile.hpp" 30 | #include "CTBOutputStream.hpp" 31 | 32 | namespace ctb { 33 | class MeshTile; 34 | } 35 | 36 | /** 37 | * @brief `Terrain` data associated with a `Mesh` 38 | * 39 | * This aims to implement the Cesium [quantized-mesh-1.0 terrain 40 | * format](https://github.com/AnalyticalGraphicsInc/quantized-mesh). 41 | */ 42 | class CTB_DLL ctb::MeshTile : 43 | public Tile 44 | { 45 | friend class MeshTiler; 46 | 47 | public: 48 | 49 | /// Create an empty mesh tile object 50 | MeshTile(); 51 | 52 | /// Create a mesh tile from a tile coordinate 53 | MeshTile(const TileCoordinate &coord); 54 | 55 | /// Write terrain data to the filesystem 56 | void 57 | writeFile(const char *fileName, bool writeVertexNormals = false) const; 58 | 59 | /// Write terrain data to an output stream 60 | void 61 | writeFile(CTBOutputStream &ostream, bool writeVertexNormals = false) const; 62 | 63 | /// Does the terrain tile have child tiles? 64 | bool 65 | hasChildren() const; 66 | 67 | /// Does the terrain tile have a south west child tile? 68 | bool 69 | hasChildSW() const; 70 | 71 | /// Does the terrain tile have a south east child tile? 72 | bool 73 | hasChildSE() const; 74 | 75 | /// Does the terrain tile have a north west child tile? 76 | bool 77 | hasChildNW() const; 78 | 79 | /// Does the terrain tile have a north east child tile? 80 | bool 81 | hasChildNE() const; 82 | 83 | /// Specify that there is a south west child tile 84 | void 85 | setChildSW(bool on = true); 86 | 87 | /// Specify that there is a south east child tile 88 | void 89 | setChildSE(bool on = true); 90 | 91 | /// Specify that there is a north west child tile 92 | void 93 | setChildNW(bool on = true); 94 | 95 | /// Specify that there is a north east child tile 96 | void 97 | setChildNE(bool on = true); 98 | 99 | /// Specify that all child tiles are present 100 | void 101 | setAllChildren(bool on = true); 102 | 103 | /// Get the mesh data as a const object 104 | const ctb::Mesh & getMesh() const; 105 | 106 | /// Get the mesh data 107 | ctb::Mesh & getMesh(); 108 | 109 | protected: 110 | 111 | /// The terrain mesh data 112 | ctb::Mesh mMesh; 113 | 114 | private: 115 | 116 | char mChildren; ///< The child flags 117 | 118 | /** 119 | * @brief Bit flags defining child tile existence 120 | * 121 | * There is a good discussion on bitflags 122 | * [here](http://www.dylanleigh.net/notes/c-cpp-tricks.html#Using_"Bitflags"). 123 | */ 124 | enum Children { 125 | TERRAIN_CHILD_SW = 1, // 2^0, bit 0 126 | TERRAIN_CHILD_SE = 2, // 2^1, bit 1 127 | TERRAIN_CHILD_NW = 4, // 2^2, bit 2 128 | TERRAIN_CHILD_NE = 8 // 2^3, bit 3 129 | }; 130 | }; 131 | 132 | #endif /* MESHTILE_HPP */ 133 | -------------------------------------------------------------------------------- /third-party/ctb/MeshTiler.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2018 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file MeshTiler.cpp 19 | * @brief This defines the `MeshTiler` class 20 | * @author Alvaro Huarte 21 | */ 22 | 23 | #include "CTBException.hpp" 24 | #include "MeshTiler.hpp" 25 | #include "HeightFieldChunker.hpp" 26 | #include "GDALDatasetReader.hpp" 27 | 28 | using namespace ctb; 29 | 30 | //////////////////////////////////////////////////////////////////////////////// 31 | 32 | /** 33 | * Implementation of ctb::chunk::mesh for ctb::Mesh class. 34 | */ 35 | class WrapperMesh : public ctb::chunk::mesh { 36 | private: 37 | CRSBounds &mBounds; 38 | Mesh &mMesh; 39 | double mCellSizeX; 40 | double mCellSizeY; 41 | 42 | std::map mIndicesMap; 43 | Coordinate mTriangles[3]; 44 | bool mTriOddOrder; 45 | int mTriIndex; 46 | 47 | public: 48 | WrapperMesh(CRSBounds &bounds, Mesh &mesh, i_tile tileSizeX, i_tile tileSizeY): 49 | mMesh(mesh), 50 | mBounds(bounds), 51 | mTriOddOrder(false), 52 | mTriIndex(0) { 53 | mCellSizeX = (bounds.getMaxX() - bounds.getMinX()) / (double)(tileSizeX - 1); 54 | mCellSizeY = (bounds.getMaxY() - bounds.getMinY()) / (double)(tileSizeY - 1); 55 | } 56 | 57 | virtual void clear() { 58 | mMesh.vertices.clear(); 59 | mMesh.indices.clear(); 60 | mIndicesMap.clear(); 61 | mTriOddOrder = false; 62 | mTriIndex = 0; 63 | } 64 | virtual void emit_vertex(const ctb::chunk::heightfield &heightfield, int x, int y) { 65 | mTriangles[mTriIndex].x = x; 66 | mTriangles[mTriIndex].y = y; 67 | mTriIndex++; 68 | 69 | if (mTriIndex == 3) { 70 | mTriOddOrder = !mTriOddOrder; 71 | 72 | if (mTriOddOrder) { 73 | appendVertex(heightfield, mTriangles[0].x, mTriangles[0].y); 74 | appendVertex(heightfield, mTriangles[1].x, mTriangles[1].y); 75 | appendVertex(heightfield, mTriangles[2].x, mTriangles[2].y); 76 | } 77 | else { 78 | appendVertex(heightfield, mTriangles[1].x, mTriangles[1].y); 79 | appendVertex(heightfield, mTriangles[0].x, mTriangles[0].y); 80 | appendVertex(heightfield, mTriangles[2].x, mTriangles[2].y); 81 | } 82 | mTriangles[0].x = mTriangles[1].x; 83 | mTriangles[0].y = mTriangles[1].y; 84 | mTriangles[1].x = mTriangles[2].x; 85 | mTriangles[1].y = mTriangles[2].y; 86 | mTriIndex--; 87 | } 88 | } 89 | void appendVertex(const ctb::chunk::heightfield &heightfield, int x, int y) { 90 | int iv; 91 | int index = heightfield.indexOfGridCoordinate(x, y); 92 | 93 | std::map::iterator it = mIndicesMap.find(index); 94 | 95 | if (it == mIndicesMap.end()) { 96 | iv = mMesh.vertices.size(); 97 | 98 | double xmin = mBounds.getMinX(); 99 | double ymax = mBounds.getMaxY(); 100 | double height = heightfield.height(x, y); 101 | 102 | mMesh.vertices.push_back(CRSVertex(xmin + (x * mCellSizeX), ymax - (y * mCellSizeY), height)); 103 | mIndicesMap.insert(std::make_pair(index, iv)); 104 | } 105 | else { 106 | iv = it->second; 107 | } 108 | mMesh.indices.push_back(iv); 109 | } 110 | }; 111 | 112 | //////////////////////////////////////////////////////////////////////////////// 113 | 114 | void 115 | ctb::MeshTiler::prepareSettingsOfTile(MeshTile *terrainTile, GDALDataset *dataset, const TileCoordinate &coord, float *rasterHeights, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) const { 116 | const ctb::i_tile TILE_SIZE = tileSizeX; 117 | 118 | // Number of tiles in the horizontal direction at tile level zero. 119 | double resolutionAtLevelZero = mGrid.resolution(0); 120 | int numberOfTilesAtLevelZero = (int)(mGrid.getExtent().getWidth() / (tileSizeX * resolutionAtLevelZero)); 121 | // Default quality of terrain created from heightmaps (TerrainProvider.js). 122 | double heightmapTerrainQuality = 0.25; 123 | // Earth semi-major-axis in meters. 124 | const double semiMajorAxis = 6378137.0; 125 | // Appropriate geometric error estimate when the geometry comes from a heightmap (TerrainProvider.js). 126 | double maximumGeometricError = MeshTiler::getEstimatedLevelZeroGeometricErrorForAHeightmap( 127 | semiMajorAxis, 128 | heightmapTerrainQuality * mMeshQualityFactor, 129 | TILE_SIZE, 130 | numberOfTilesAtLevelZero 131 | ); 132 | // Geometric error for current Level. 133 | maximumGeometricError /= (double)(1 << coord.zoom); 134 | 135 | // Convert the raster grid into an irregular mesh applying the Chunked LOD strategy by 'Thatcher Ulrich'. 136 | // http://tulrich.com/geekstuff/chunklod.html 137 | // 138 | ctb::chunk::heightfield heightfield(rasterHeights, TILE_SIZE); 139 | heightfield.applyGeometricError(maximumGeometricError, coord.zoom <= 6); 140 | // 141 | // Propagate the geometric error of neighbours to avoid gaps in borders. 142 | if (coord.zoom > 6) { 143 | ctb::CRSBounds datasetBounds = bounds(); 144 | 145 | for (int borderIndex = 0; borderIndex < 4; borderIndex++) { 146 | bool okNeighborCoord = true; 147 | ctb::TileCoordinate neighborCoord = ctb::chunk::heightfield::neighborCoord(mGrid, coord, borderIndex, okNeighborCoord); 148 | if (!okNeighborCoord) 149 | continue; 150 | 151 | ctb::CRSBounds neighborBounds = mGrid.tileBounds(neighborCoord); 152 | 153 | if (datasetBounds.overlaps(neighborBounds)) { 154 | float *neighborHeights = ctb::GDALDatasetReader::readRasterHeights(*this, dataset, neighborCoord, mGrid.tileSize(), mGrid.tileSize()); 155 | 156 | ctb::chunk::heightfield neighborHeightfield(neighborHeights, TILE_SIZE); 157 | neighborHeightfield.applyGeometricError(maximumGeometricError); 158 | heightfield.applyBorderActivationState(neighborHeightfield, borderIndex); 159 | 160 | CPLFree(neighborHeights); 161 | } 162 | } 163 | } 164 | ctb::CRSBounds mGridBounds = mGrid.tileBounds(coord); 165 | Mesh &tileMesh = terrainTile->getMesh(); 166 | WrapperMesh mesh(mGridBounds, tileMesh, tileSizeX, tileSizeY); 167 | heightfield.generateMesh(mesh, 0); 168 | heightfield.clear(); 169 | 170 | // If we are not at the maximum zoom level we need to set child flags on the 171 | // tile where child tiles overlap the dataset bounds. 172 | if (coord.zoom != maxZoomLevel()) { 173 | CRSBounds tileBounds = mGrid.tileBounds(coord); 174 | 175 | if (! (bounds().overlaps(tileBounds))) { 176 | terrainTile->setAllChildren(false); 177 | } else { 178 | if (bounds().overlaps(tileBounds.getSW())) { 179 | terrainTile->setChildSW(); 180 | } 181 | if (bounds().overlaps(tileBounds.getNW())) { 182 | terrainTile->setChildNW(); 183 | } 184 | if (bounds().overlaps(tileBounds.getNE())) { 185 | terrainTile->setChildNE(); 186 | } 187 | if (bounds().overlaps(tileBounds.getSE())) { 188 | terrainTile->setChildSE(); 189 | } 190 | } 191 | } 192 | } 193 | 194 | MeshTile * 195 | ctb::MeshTiler::createMesh(GDALDataset *dataset, const TileCoordinate &coord) const { 196 | // Copy the raster data into an array 197 | float *rasterHeights = ctb::GDALDatasetReader::readRasterHeights(*this, dataset, coord, mGrid.tileSize(), mGrid.tileSize()); 198 | 199 | // Get a mesh tile represented by the tile coordinate 200 | MeshTile *terrainTile = new MeshTile(coord); 201 | prepareSettingsOfTile(terrainTile, dataset, coord, rasterHeights, mGrid.tileSize(), mGrid.tileSize()); 202 | CPLFree(rasterHeights); 203 | 204 | return terrainTile; 205 | } 206 | 207 | MeshTile * 208 | ctb::MeshTiler::createMesh(GDALDataset *dataset, const TileCoordinate &coord, ctb::GDALDatasetReader *reader) const { 209 | // Copy the raster data into an array 210 | float *rasterHeights = reader->readRasterHeights(dataset, coord, mGrid.tileSize(), mGrid.tileSize()); 211 | 212 | // Get a mesh tile represented by the tile coordinate 213 | MeshTile *terrainTile = new MeshTile(coord); 214 | prepareSettingsOfTile(terrainTile, dataset, coord, rasterHeights, mGrid.tileSize(), mGrid.tileSize()); 215 | CPLFree(rasterHeights); 216 | 217 | return terrainTile; 218 | } 219 | 220 | MeshTiler & 221 | ctb::MeshTiler::operator=(const MeshTiler &other) { 222 | TerrainTiler::operator=(other); 223 | 224 | return *this; 225 | } 226 | 227 | double ctb::MeshTiler::getEstimatedLevelZeroGeometricErrorForAHeightmap( 228 | double maximumRadius, 229 | double heightmapTerrainQuality, 230 | int tileWidth, 231 | int numberOfTilesAtLevelZero) 232 | { 233 | double error = maximumRadius * 2 * M_PI * heightmapTerrainQuality; 234 | error /= (double)(tileWidth * numberOfTilesAtLevelZero); 235 | return error; 236 | } 237 | -------------------------------------------------------------------------------- /third-party/ctb/MeshTiler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MESHTILER_HPP 2 | #define MESHTILER_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2018 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file MeshTiler.hpp 22 | * @brief This declares the `MeshTiler` class 23 | * @author Alvaro Huarte 24 | */ 25 | 26 | #include "MeshTile.hpp" 27 | #include "TerrainTiler.hpp" 28 | 29 | namespace ctb { 30 | class MeshTiler; 31 | } 32 | 33 | /** 34 | * @brief Create `MeshTile`s from a GDAL Dataset 35 | * 36 | * This class derives from `GDALTiler` and `TerrainTiler` enabling `MeshTile`s 37 | * to be created for a specific `TileCoordinate`. 38 | */ 39 | class CTB_DLL ctb::MeshTiler : 40 | public TerrainTiler 41 | { 42 | public: 43 | 44 | /// Instantiate a tiler with all required arguments 45 | MeshTiler(GDALDataset *poDataset, const Grid &grid, const TilerOptions &options, double meshQualityFactor = 1.0): 46 | TerrainTiler(poDataset, grid, options), 47 | mMeshQualityFactor(meshQualityFactor) {} 48 | 49 | /// Instantiate a tiler with an empty GDAL dataset 50 | MeshTiler(double meshQualityFactor = 1.0): 51 | TerrainTiler(), 52 | mMeshQualityFactor(meshQualityFactor) {} 53 | 54 | /// Instantiate a tiler with a dataset and grid but no options 55 | MeshTiler(GDALDataset *poDataset, const Grid &grid, double meshQualityFactor = 1.0): 56 | TerrainTiler(poDataset, grid, TilerOptions()), 57 | mMeshQualityFactor(meshQualityFactor) {} 58 | 59 | /// Overload the assignment operator 60 | MeshTiler & 61 | operator=(const MeshTiler &other); 62 | 63 | /// Create a mesh from a tile coordinate 64 | MeshTile * 65 | createMesh(GDALDataset *dataset, const TileCoordinate &coord) const; 66 | 67 | /// Create a mesh from a tile coordinate 68 | MeshTile * 69 | createMesh(GDALDataset *dataset, const TileCoordinate &coord, GDALDatasetReader *reader) const; 70 | 71 | protected: 72 | 73 | // Specifies the factor of the quality to convert terrain heightmaps to meshes. 74 | double mMeshQualityFactor; 75 | 76 | // Determines an appropriate geometric error estimate when the geometry comes from a heightmap. 77 | static double getEstimatedLevelZeroGeometricErrorForAHeightmap( 78 | double maximumRadius, 79 | double heightmapTerrainQuality, 80 | int tileWidth, 81 | int numberOfTilesAtLevelZero); 82 | 83 | /// Assigns settings of Tile just to use. 84 | void prepareSettingsOfTile(MeshTile *tile, GDALDataset *dataset, const TileCoordinate &coord, float *rasterHeights, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) const; 85 | }; 86 | 87 | #endif /* MESHTILER_HPP */ 88 | -------------------------------------------------------------------------------- /third-party/ctb/TerrainTile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TERRAINTILE_HPP 2 | #define TERRAINTILE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file TerrainTile.hpp 22 | * @brief This declares the `Terrain` and `TerrainTile` classes 23 | */ 24 | 25 | #include 26 | 27 | #include "gdal_priv.h" 28 | 29 | #include "config.hpp" 30 | #include "Tile.hpp" 31 | #include "TileCoordinate.hpp" 32 | #include "CTBOutputStream.hpp" 33 | 34 | namespace ctb { 35 | class Terrain; 36 | class TerrainTile; 37 | } 38 | 39 | /** 40 | * @brief Model the terrain heightmap specification 41 | * 42 | * This aims to implement the Cesium [heightmap-1.0 terrain 43 | * format](http://cesiumjs.org/data-and-assets/terrain/formats/heightmap-1.0.html). 44 | */ 45 | class CTB_DLL ctb::Terrain { 46 | public: 47 | 48 | /// Create an empty terrain object 49 | Terrain(); 50 | 51 | /// Instantiate using terrain data on the file system 52 | Terrain(const char *fileName); 53 | 54 | /// Read terrain data from a file handle 55 | Terrain(FILE *fp); 56 | 57 | /// Read terrain data from the filesystem 58 | void 59 | readFile(const char *fileName); 60 | 61 | /// Write terrain data to a file handle 62 | void 63 | writeFile(FILE *fp) const; 64 | 65 | /// Write terrain data to the filesystem 66 | void 67 | writeFile(const char *fileName) const; 68 | 69 | /// Write terrain data to an output stream 70 | void 71 | writeFile(CTBOutputStream &ostream) const; 72 | 73 | /// Get the water mask as a boolean mask 74 | std::vector 75 | mask(); 76 | 77 | /// Does the terrain tile have child tiles? 78 | bool 79 | hasChildren() const; 80 | 81 | /// Does the terrain tile have a south west child tile? 82 | bool 83 | hasChildSW() const; 84 | 85 | /// Does the terrain tile have a south east child tile? 86 | bool 87 | hasChildSE() const; 88 | 89 | /// Does the terrain tile have a north west child tile? 90 | bool 91 | hasChildNW() const; 92 | 93 | /// Does the terrain tile have a north east child tile? 94 | bool 95 | hasChildNE() const; 96 | 97 | /// Specify that there is a south west child tile 98 | void 99 | setChildSW(bool on = true); 100 | 101 | /// Specify that there is a south east child tile 102 | void 103 | setChildSE(bool on = true); 104 | 105 | /// Specify that there is a north west child tile 106 | void 107 | setChildNW(bool on = true); 108 | 109 | /// Specify that there is a north east child tile 110 | void 111 | setChildNE(bool on = true); 112 | 113 | /// Specify that all child tiles are present 114 | void 115 | setAllChildren(bool on = true); 116 | 117 | /// Specify that this tile is all water 118 | void 119 | setIsWater(); 120 | 121 | /// Is this tile all water? 122 | bool 123 | isWater() const; 124 | 125 | /// Specify that this tile is all land 126 | void 127 | setIsLand(); 128 | 129 | /// Is this tile all land? 130 | bool 131 | isLand() const; 132 | 133 | /// Does this tile have a water mask? 134 | bool 135 | hasWaterMask() const; 136 | 137 | /// Get the height data as a const vector 138 | const std::vector & 139 | getHeights() const; 140 | 141 | /// Get the height data as a vector 142 | std::vector & 143 | getHeights(); 144 | 145 | protected: 146 | /// The terrain height data 147 | std::vector mHeights; // replace with `std::array` in C++11 148 | 149 | /// The number of height cells within a terrain tile 150 | static const unsigned short int TILE_CELL_SIZE = TILE_SIZE * TILE_SIZE; 151 | 152 | /// The number of water mask cells within a terrain tile 153 | static const unsigned int MASK_CELL_SIZE = MASK_SIZE * MASK_SIZE; 154 | 155 | /** 156 | * @brief The maximum byte size of an uncompressed terrain tile 157 | * 158 | * This is calculated as (heights + child flags + water mask). 159 | */ 160 | static const unsigned int MAX_TERRAIN_SIZE = (TILE_CELL_SIZE * 2) + 1 + MASK_CELL_SIZE; 161 | 162 | private: 163 | 164 | char mChildren; ///< The child flags 165 | char mMask[MASK_CELL_SIZE]; ///< The water mask 166 | size_t mMaskLength; ///< What size is the water mask? 167 | 168 | /** 169 | * @brief Bit flags defining child tile existence 170 | * 171 | * There is a good discussion on bitflags 172 | * [here](http://www.dylanleigh.net/notes/c-cpp-tricks.html#Using_"Bitflags"). 173 | */ 174 | enum Children { 175 | TERRAIN_CHILD_SW = 1, // 2^0, bit 0 176 | TERRAIN_CHILD_SE = 2, // 2^1, bit 1 177 | TERRAIN_CHILD_NW = 4, // 2^2, bit 2 178 | TERRAIN_CHILD_NE = 8 // 2^3, bit 3 179 | }; 180 | }; 181 | 182 | /** 183 | * @brief `Terrain` data associated with a `Tile` 184 | * 185 | * Associating terrain data with a tile coordinate allows the tile to be 186 | * converted to a geo-referenced raster (see `TerrainTile::heightsToRaster`). 187 | */ 188 | class CTB_DLL ctb::TerrainTile : 189 | public Terrain, public Tile 190 | { 191 | friend class TerrainTiler; 192 | 193 | public: 194 | 195 | /// Create a terrain tile from a tile coordinate 196 | TerrainTile(const TileCoordinate &coord); 197 | 198 | /// Create a terrain tile from a file 199 | TerrainTile(const char *fileName, const TileCoordinate &coord); 200 | 201 | /// Create a terrain tile from terrain data 202 | TerrainTile(const Terrain &terrain, const TileCoordinate &coord); 203 | 204 | /// Get the height data as an in memory GDAL raster 205 | GDALDatasetH 206 | heightsToRaster() const; 207 | }; 208 | 209 | #endif /* TERRAINTILE_HPP */ 210 | -------------------------------------------------------------------------------- /third-party/ctb/TerrainTiler.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 GeoData 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy 6 | * of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations 14 | * under the License. 15 | *******************************************************************************/ 16 | 17 | /** 18 | * @file TerrainTiler.cpp 19 | * @brief This defines the `TerrainTiler` class 20 | */ 21 | 22 | #include "CTBException.hpp" 23 | #include "TerrainTiler.hpp" 24 | #include "GDALDatasetReader.hpp" 25 | 26 | using namespace ctb; 27 | 28 | void 29 | ctb::TerrainTiler::prepareSettingsOfTile(TerrainTile *terrainTile, const TileCoordinate &coord, float *rasterHeights, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) const { 30 | const ctb::i_tile TILE_CELL_SIZE = tileSizeX * tileSizeY; 31 | 32 | // Convert the raster data into the terrain tile heights. This assumes the 33 | // input raster data represents meters above sea level. Each terrain height 34 | // value is the number of 1/5 meter units above -1000 meters. 35 | // TODO: try doing this using a VRT derived band: 36 | // (http://www.gdal.org/gdal_vrttut.html) 37 | for (unsigned short int i = 0; i < TILE_CELL_SIZE; i++) { 38 | terrainTile->mHeights[i] = (i_terrain_height) ((rasterHeights[i] + 1000) * 5); 39 | } 40 | 41 | // If we are not at the maximum zoom level we need to set child flags on the 42 | // tile where child tiles overlap the dataset bounds. 43 | if (coord.zoom != maxZoomLevel()) { 44 | CRSBounds tileBounds = mGrid.tileBounds(coord); 45 | 46 | if (! (bounds().overlaps(tileBounds))) { 47 | terrainTile->setAllChildren(false); 48 | } else { 49 | if (bounds().overlaps(tileBounds.getSW())) { 50 | terrainTile->setChildSW(); 51 | } 52 | if (bounds().overlaps(tileBounds.getNW())) { 53 | terrainTile->setChildNW(); 54 | } 55 | if (bounds().overlaps(tileBounds.getNE())) { 56 | terrainTile->setChildNE(); 57 | } 58 | if (bounds().overlaps(tileBounds.getSE())) { 59 | terrainTile->setChildSE(); 60 | } 61 | } 62 | } 63 | } 64 | 65 | TerrainTile * 66 | ctb::TerrainTiler::createTile(GDALDataset *dataset, const TileCoordinate &coord) const { 67 | // Copy the raster data into an array 68 | float *rasterHeights = ctb::GDALDatasetReader::readRasterHeights(*this, dataset, coord, TILE_SIZE, TILE_SIZE); 69 | 70 | // Get a terrain tile represented by the tile coordinate 71 | TerrainTile *terrainTile = new TerrainTile(coord); 72 | prepareSettingsOfTile(terrainTile, coord, rasterHeights, TILE_SIZE, TILE_SIZE); 73 | CPLFree(rasterHeights); 74 | 75 | return terrainTile; 76 | } 77 | 78 | TerrainTile * 79 | ctb::TerrainTiler::createTile(GDALDataset *dataset, const TileCoordinate &coord, ctb::GDALDatasetReader *reader) const { 80 | // Copy the raster data into an array 81 | float *rasterHeights = reader->readRasterHeights(dataset, coord, TILE_SIZE, TILE_SIZE); 82 | 83 | // Get a mesh tile represented by the tile coordinate 84 | TerrainTile *terrainTile = new TerrainTile(coord); 85 | prepareSettingsOfTile(terrainTile, coord, rasterHeights, TILE_SIZE, TILE_SIZE); 86 | CPLFree(rasterHeights); 87 | 88 | return terrainTile; 89 | } 90 | 91 | GDALTile * 92 | ctb::TerrainTiler::createRasterTile(GDALDataset *dataset, const TileCoordinate &coord) const { 93 | // Ensure we have some data from which to create a tile 94 | if (dataset && dataset->GetRasterCount() < 1) { 95 | throw CTBException("At least one band must be present in the GDAL dataset"); 96 | } 97 | 98 | // Get the bounds and resolution for a tile coordinate which represents the 99 | // data overlap requested by the terrain specification. 100 | double resolution; 101 | CRSBounds tileBounds = terrainTileBounds(coord, resolution); 102 | 103 | // Convert the tile bounds into a geo transform 104 | double adfGeoTransform[6]; 105 | adfGeoTransform[0] = tileBounds.getMinX(); // min longitude 106 | adfGeoTransform[1] = resolution; 107 | adfGeoTransform[2] = 0; 108 | adfGeoTransform[3] = tileBounds.getMaxY(); // max latitude 109 | adfGeoTransform[4] = 0; 110 | adfGeoTransform[5] = -resolution; 111 | 112 | GDALTile *tile = GDALTiler::createRasterTile(dataset, adfGeoTransform); 113 | 114 | // The previous geotransform represented the data with an overlap as required 115 | // by the terrain specification. This now needs to be overwritten so that 116 | // the data is shifted to the bounds defined by tile itself. 117 | tileBounds = mGrid.tileBounds(coord); 118 | resolution = mGrid.resolution(coord.zoom); 119 | adfGeoTransform[0] = tileBounds.getMinX(); // min longitude 120 | adfGeoTransform[1] = resolution; 121 | adfGeoTransform[2] = 0; 122 | adfGeoTransform[3] = tileBounds.getMaxY(); // max latitude 123 | adfGeoTransform[4] = 0; 124 | adfGeoTransform[5] = -resolution; 125 | 126 | // Set the shifted geo transform to the VRT 127 | if (GDALSetGeoTransform(tile->dataset, adfGeoTransform) != CE_None) { 128 | throw CTBException("Could not set geo transform on VRT"); 129 | } 130 | 131 | return tile; 132 | } 133 | 134 | TerrainTiler & 135 | ctb::TerrainTiler::operator=(const TerrainTiler &other) { 136 | GDALTiler::operator=(other); 137 | 138 | return *this; 139 | } 140 | -------------------------------------------------------------------------------- /third-party/ctb/TerrainTiler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TERRAINTILER_HPP 2 | #define TERRAINTILER_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file TerrainTiler.hpp 22 | * @brief This declares the `TerrainTiler` class 23 | */ 24 | 25 | #include "TerrainTile.hpp" 26 | #include "GDALTiler.hpp" 27 | 28 | namespace ctb { 29 | class TerrainTiler; 30 | } 31 | 32 | /** 33 | * @brief Create `TerrainTile`s from a GDAL Dataset 34 | * 35 | * This class derives from `GDALTiler` and adds the 36 | * `GDALTiler::createTerrainTile` method enabling `TerrainTile`s to be created 37 | * for a specific `TileCoordinate`. 38 | */ 39 | class CTB_DLL ctb::TerrainTiler : 40 | public GDALTiler 41 | { 42 | public: 43 | 44 | /// Instantiate a tiler with all required arguments 45 | TerrainTiler(GDALDataset *poDataset, const Grid &grid, const TilerOptions &options): 46 | GDALTiler(poDataset, grid, options) {} 47 | 48 | /// Instantiate a tiler with an empty GDAL dataset 49 | TerrainTiler(): 50 | GDALTiler() {} 51 | 52 | /// Instantiate a tiler with a dataset and grid but no options 53 | TerrainTiler(GDALDataset *poDataset, const Grid &grid): 54 | TerrainTiler(poDataset, grid, TilerOptions()) {} 55 | 56 | /// Overload the assignment operator 57 | TerrainTiler & 58 | operator=(const TerrainTiler &other); 59 | 60 | /// Override to return a covariant data type 61 | TerrainTile * 62 | createTile(GDALDataset *dataset, const TileCoordinate &coord) const override; 63 | 64 | /// Create a tile from a tile coordinate 65 | TerrainTile * 66 | createTile(GDALDataset *dataset, const TileCoordinate &coord, GDALDatasetReader *reader) const; 67 | 68 | protected: 69 | 70 | /// Create a `GDALTile` representing the required terrain tile data 71 | virtual GDALTile * 72 | createRasterTile(GDALDataset *dataset, const TileCoordinate &coord) const override; 73 | 74 | /** 75 | * @brief Get terrain bounds shifted to introduce a pixel overlap 76 | * 77 | * Given a `TileCoordinate`, this sets the resolution and returns latitude 78 | * and longitude bounds for a tile which include a pixel's worth of data 79 | * outside the actual tile bounds to both the east and the north. This is 80 | * used to satisfy the terrain heightmap specification of terrain tiles 81 | * including a pixel's worth of data from surrounding tiles. 82 | * 83 | * @param coord The tile coordinate identifying the tile in question 84 | * @param resolution The resolution of the modified extent is set here 85 | */ 86 | inline CRSBounds 87 | terrainTileBounds(const TileCoordinate &coord, 88 | double &resolution) const { 89 | // The actual tile size accounting for a border 90 | i_tile lTileSize = mGrid.tileSize() - 1; 91 | CRSBounds tile = mGrid.tileBounds(coord); // the actual tile bounds 92 | 93 | // Get the resolution for the dataset without a border 94 | resolution = (tile.getMaxX() - tile.getMinX()) / lTileSize; 95 | 96 | // extend the easting by one pixel's worth 97 | tile.setMinX(tile.getMinX() - resolution); 98 | 99 | // extend the northing by one pixel's worth 100 | tile.setMaxY(tile.getMaxY() + resolution); 101 | 102 | return tile; 103 | } 104 | 105 | /// Assigns settings of Tile just to use. 106 | void prepareSettingsOfTile(TerrainTile *tile, const TileCoordinate &coord, float *rasterHeights, ctb::i_tile tileSizeX, ctb::i_tile tileSizeY) const; 107 | }; 108 | 109 | #endif /* TERRAINTILER_HPP */ 110 | -------------------------------------------------------------------------------- /third-party/ctb/Tile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBTILE_HPP 2 | #define CTBTILE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file Tile.hpp 22 | * @brief This declares the `Tile` class 23 | */ 24 | 25 | #include "Grid.hpp" 26 | 27 | namespace ctb { 28 | class Tile; 29 | } 30 | 31 | /** 32 | * @brief An abstract base class for a tile 33 | * 34 | * This provides a way of associating a `TileCoordinate` with tile data. 35 | */ 36 | class ctb::Tile : 37 | public TileCoordinate 38 | { 39 | public: 40 | virtual ~Tile () = 0; // this is an abstract base class 41 | 42 | /// Create an empty tile from a grid 43 | Tile(): 44 | TileCoordinate() 45 | {} 46 | 47 | /// Create a tile from a tile coordinate 48 | Tile(const TileCoordinate &coord): 49 | TileCoordinate(coord) 50 | {} 51 | }; 52 | 53 | inline ctb::Tile::~Tile() { } // prevents linker errors 54 | 55 | #endif /* CTBTILE_HPP */ 56 | -------------------------------------------------------------------------------- /third-party/ctb/TileCoordinate.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TILECOORDINATE_HPP 2 | #define TILECOORDINATE_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file TileCoordinate.hpp 22 | * @brief This declares and defines the `TileCoordinate` class 23 | */ 24 | 25 | #include "types.hpp" 26 | 27 | namespace ctb { 28 | class TileCoordinate; 29 | } 30 | 31 | /** 32 | * @brief A `TileCoordinate` identifies a particular tile 33 | * 34 | * An instance of this class is composed of a tile point and a zoom level: 35 | * together this identifies an individual tile. 36 | */ 37 | class ctb::TileCoordinate: 38 | public TilePoint { 39 | public: 40 | 41 | /// Create the 0-0-0 level tile coordinate 42 | TileCoordinate(): 43 | TilePoint(0, 0), 44 | zoom(0) 45 | {} 46 | 47 | /// The const copy constructor 48 | TileCoordinate(const TileCoordinate &other): 49 | TilePoint(other.x, other.y), 50 | zoom(other.zoom) 51 | {} 52 | 53 | /// Instantiate a tile coordinate from the zoom, x and y 54 | TileCoordinate(i_zoom zoom, i_tile x, i_tile y): 55 | TilePoint(x, y), 56 | zoom(zoom) 57 | {} 58 | 59 | /// Instantiate a tile coordinate using the zoom and a tile point 60 | TileCoordinate(i_zoom zoom, const TilePoint &coord): 61 | TilePoint(coord), 62 | zoom(zoom) 63 | {} 64 | 65 | /// Override the equality operator 66 | inline bool 67 | operator==(const TileCoordinate &other) const { 68 | return TilePoint::operator==(other) 69 | && zoom == other.zoom; 70 | } 71 | 72 | /// Override the assignment operator 73 | inline void 74 | operator=(const TileCoordinate &other) { 75 | TilePoint::operator=(other); 76 | zoom = other.zoom; 77 | } 78 | 79 | /// Set the point 80 | inline void 81 | setPoint(const TilePoint &point) { 82 | TilePoint::operator=(point); 83 | } 84 | 85 | i_zoom zoom; ///< The zoom level 86 | }; 87 | 88 | #endif /* TILECOORDINATE_HPP */ 89 | -------------------------------------------------------------------------------- /third-party/ctb/config.hpp.in: -------------------------------------------------------------------------------- 1 | #ifndef CTBCONFIG_HPP 2 | #define CTBCONFIG_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file config.hpp.in 22 | * @brief Build time configured options and settings 23 | * 24 | * This file is a template used by the CMake build system to create 25 | * `config.hpp`. 26 | */ 27 | 28 | /* Enable symbol export in Visual Studio 2013 as per issue #6. This is an 29 | adaptation of `CPL_DLL` in GDAL's `cpl_port.h`. */ 30 | #ifndef CTB_DLL 31 | #if defined(_MSC_VER) 32 | # if !defined(CPL_DISABLE_DLL) 33 | # define CTB_DLL __declspec(dllexport) 34 | # else 35 | # define CTB_DLL __declspec(dllimport) 36 | # endif 37 | #else 38 | # define CTB_DLL 39 | #endif 40 | #endif 41 | 42 | #include 43 | #include 44 | 45 | namespace ctb { 46 | 47 | /** 48 | * @brief Versioning object 49 | * 50 | * We use [semantic versioning](http://semver.org). 51 | */ 52 | const struct semver { 53 | /// The major version 54 | const unsigned short int major; 55 | /// The minor version 56 | const unsigned short int minor; 57 | /// The patch number 58 | const unsigned short int patch; 59 | 60 | /// The version string 61 | const char *cstr; 62 | 63 | } version = { 64 | @CTB_VERSION_MAJOR@, 65 | @CTB_VERSION_MINOR@, 66 | @CTB_VERSION_PATCH@, 67 | "@CTB_VERSION_MAJOR@.@CTB_VERSION_MINOR@.@CTB_VERSION_PATCH@" 68 | }; 69 | 70 | /// The width and height of height data in a tile 71 | const unsigned short int TILE_SIZE = @TERRAIN_TILE_SIZE@; 72 | 73 | /// The width and height of water mask data in a tile 74 | const unsigned short int MASK_SIZE = @TERRAIN_MASK_SIZE@; 75 | } 76 | 77 | #endif /* CTBCONFIG_HPP */ 78 | -------------------------------------------------------------------------------- /third-party/ctb/ctb.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTB_HPP 2 | #define CTB_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file ctb.hpp 22 | * @brief All required definitions for working with `libctb` 23 | * 24 | * @mainpage Cesium Terrain Builder Library (libctb) 25 | * 26 | * `libctb` is a C++ library used to create terrain tiles for use in the 27 | * [Cesium JavaScript library](http://cesiumjs.org). Terrain tiles are created 28 | * according to the [heightmap-1.0 terrain 29 | * format](http://cesiumjs.org/data-and-assets/terrain/formats/heightmap-1.0.html). 30 | * The library does not provide a way of serving up or storing the resulting 31 | * tiles: this is application specific. Its aim is simply to take a 32 | * [GDAL](http://www.gdal.org) compatible raster representing a Digital Terrain 33 | * Model (DTM) and convert this to terrain tiles. See the tools provided with 34 | * the library (e.g. `ctb-tile`) for an example on how the the library is used 35 | * to achieve this. 36 | * 37 | * To use the library include `ctb.hpp` e.g. 38 | * 39 | * \code 40 | * // test.cpp 41 | * #include 42 | * #include "ctb.hpp" 43 | * 44 | * using namespace std; 45 | * 46 | * int main() { 47 | * 48 | * cout << "Using libctb version " 49 | * << ctb::version.major << "." 50 | * << ctb::version.minor << "." 51 | * << ctb::version.patch << endl; 52 | * 53 | * return 0; 54 | * } 55 | * \endcode 56 | * 57 | * Assuming the library is installed on the system and you are using the `g++` 58 | * compiler, the above can be compiled using: 59 | * 60 | * \code{.sh} 61 | * g++ -lctb -o test test.cpp 62 | * \endcode 63 | * 64 | * ## Implementation overview 65 | * 66 | * The concept of a grid is implemented in the `ctb::Grid` class. The TMS 67 | * Global Geodetic and Global Merdcator profiles are specialisations of the grid 68 | * implemented in the `ctb::GlobalGeodetic` and `ctb::GlobalMercator` classes. 69 | * These classes define the tiling scheme which is then used to cut up GDAL 70 | * rasters into the output tiles. 71 | * 72 | * The `ctb::GDALTiler` and `ctb::TerrainTiler` classes composes an instance of 73 | * a grid with a GDAL raster dataset. They use the dataset to determine the 74 | * native raster resolution and extent. Once this is known the appropriate zoom 75 | * levels and tile coverage can be calculated from the grid. For each tile an 76 | * in memory GDAL [Virtual Raster](http://www.gdal.org/gdal_vrttut.html) (VRT) 77 | * can then be generated. This is a lightweight representation of the relevant 78 | * underlying data necessary to create populate the tile. The VRT can then be 79 | * used to generate an actual `ctb::TerrainTile` instance or raster dataset 80 | * which can then be stored as required by the application. 81 | * 82 | * There are various iterator classes providing convenient iteration over 83 | * tilesets created by grids and tilers. For instance, the 84 | * `ctb::TerrainIterator` class provides a simple interface for iterating over 85 | * all valid tiles represented by a `ctb::TerrainTiler`, and likewise the 86 | * `ctb::RasterIterator` over a `ctb::GDALTiler` instance. 87 | * 88 | * See the `README.md` file distributed with the source code for further 89 | * details. 90 | */ 91 | 92 | #include "ctb/Bounds.hpp" 93 | #include "ctb/Coordinate.hpp" 94 | #include "ctb/CTBException.hpp" 95 | #include "ctb/GDALTile.hpp" 96 | #include "ctb/GDALTiler.hpp" 97 | #include "ctb/GlobalGeodetic.hpp" 98 | #include "ctb/GlobalMercator.hpp" 99 | #include "ctb/Grid.hpp" 100 | #include "ctb/GridIterator.hpp" 101 | #include "ctb/RasterIterator.hpp" 102 | #include "ctb/RasterTiler.hpp" 103 | #include "ctb/TerrainIterator.hpp" 104 | #include "ctb/TerrainTile.hpp" 105 | #include "ctb/TerrainTiler.hpp" 106 | #include "ctb/TileCoordinate.hpp" 107 | #include "ctb/Tile.hpp" 108 | #include "ctb/TilerIterator.hpp" 109 | #include "ctb/types.hpp" 110 | 111 | #endif /* CTB_HPP */ 112 | -------------------------------------------------------------------------------- /third-party/ctb/types.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CTBTYPES_HPP 2 | #define CTBTYPES_HPP 3 | 4 | /******************************************************************************* 5 | * Copyright 2014 GeoData 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy 9 | * of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations 17 | * under the License. 18 | *******************************************************************************/ 19 | 20 | /** 21 | * @file types.hpp 22 | * @brief This declares basic types used by libctb 23 | */ 24 | 25 | #include // uint16_t 26 | 27 | #include "Bounds.hpp" 28 | #include "Coordinate3D.hpp" 29 | 30 | /// All terrain related data types reside in this namespace 31 | namespace ctb { 32 | 33 | // Simple types 34 | typedef unsigned int i_pixel; ///< A pixel value 35 | typedef unsigned int i_tile; ///< A tile coordinate 36 | typedef unsigned short int i_zoom; ///< A zoom level 37 | typedef uint16_t i_terrain_height; ///< A terrain tile height 38 | 39 | // Complex types 40 | typedef Bounds TileBounds; ///< Tile extents in tile coordinates 41 | typedef Coordinate PixelPoint; ///< The location of a pixel 42 | typedef Coordinate CRSPoint; ///< A Coordinate Reference System coordinate 43 | typedef Coordinate3D CRSVertex; ///< A 3D-Vertex of a mesh or tile in CRS coordinates 44 | typedef Bounds CRSBounds; ///< Extents in CRS coordinates 45 | typedef Coordinate TilePoint; ///< The location of a tile 46 | 47 | } 48 | 49 | #endif /* CTBTYPES_HPP */ 50 | -------------------------------------------------------------------------------- /third-party/pybind11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt -- Build system for the pybind11 modules 2 | # 3 | # Copyright (c) 2015 Wenzel Jakob 4 | # 5 | # All rights reserved. Use of this source code is governed by a 6 | # BSD-style license that can be found in the LICENSE file. 7 | 8 | cmake_minimum_required(VERSION 2.8.12) 9 | 10 | if (POLICY CMP0048) 11 | # cmake warns if loaded from a min-3.0-required parent dir, so silence the warning: 12 | cmake_policy(SET CMP0048 NEW) 13 | endif() 14 | 15 | # CMake versions < 3.4.0 do not support try_compile/pthread checks without C as active language. 16 | if(CMAKE_VERSION VERSION_LESS 3.4.0) 17 | project(pybind11) 18 | else() 19 | project(pybind11 CXX) 20 | endif() 21 | 22 | # Check if pybind11 is being used directly or via add_subdirectory 23 | set(PYBIND11_MASTER_PROJECT OFF) 24 | if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 25 | set(PYBIND11_MASTER_PROJECT ON) 26 | endif() 27 | 28 | option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT}) 29 | option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT}) 30 | 31 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/tools") 32 | 33 | include(pybind11Tools) 34 | 35 | # Cache variables so pybind11_add_module can be used in parent projects 36 | set(PYBIND11_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include" CACHE INTERNAL "") 37 | set(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} CACHE INTERNAL "") 38 | set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} CACHE INTERNAL "") 39 | set(PYTHON_MODULE_PREFIX ${PYTHON_MODULE_PREFIX} CACHE INTERNAL "") 40 | set(PYTHON_MODULE_EXTENSION ${PYTHON_MODULE_EXTENSION} CACHE INTERNAL "") 41 | set(PYTHON_VERSION_MAJOR ${PYTHON_VERSION_MAJOR} CACHE INTERNAL "") 42 | set(PYTHON_VERSION_MINOR ${PYTHON_VERSION_MINOR} CACHE INTERNAL "") 43 | 44 | # NB: when adding a header don't forget to also add it to setup.py 45 | set(PYBIND11_HEADERS 46 | include/pybind11/detail/class.h 47 | include/pybind11/detail/common.h 48 | include/pybind11/detail/descr.h 49 | include/pybind11/detail/init.h 50 | include/pybind11/detail/internals.h 51 | include/pybind11/detail/typeid.h 52 | include/pybind11/attr.h 53 | include/pybind11/buffer_info.h 54 | include/pybind11/cast.h 55 | include/pybind11/chrono.h 56 | include/pybind11/common.h 57 | include/pybind11/complex.h 58 | include/pybind11/options.h 59 | include/pybind11/eigen.h 60 | include/pybind11/embed.h 61 | include/pybind11/eval.h 62 | include/pybind11/functional.h 63 | include/pybind11/numpy.h 64 | include/pybind11/operators.h 65 | include/pybind11/pybind11.h 66 | include/pybind11/pytypes.h 67 | include/pybind11/stl.h 68 | include/pybind11/stl_bind.h 69 | ) 70 | string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" 71 | PYBIND11_HEADERS "${PYBIND11_HEADERS}") 72 | 73 | include(GNUInstallDirs) 74 | include(CMakePackageConfigHelpers) 75 | 76 | # extract project version from source 77 | file(STRINGS "${PYBIND11_INCLUDE_DIR}/pybind11/detail/common.h" pybind11_version_defines 78 | REGEX "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) ") 79 | foreach(ver ${pybind11_version_defines}) 80 | if (ver MATCHES "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") 81 | set(PYBIND11_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") 82 | endif() 83 | endforeach() 84 | set(${PROJECT_NAME}_VERSION ${PYBIND11_VERSION_MAJOR}.${PYBIND11_VERSION_MINOR}.${PYBIND11_VERSION_PATCH}) 85 | message(STATUS "pybind11 v${${PROJECT_NAME}_VERSION}") 86 | 87 | option (USE_PYTHON_INCLUDE_DIR "Install pybind11 headers in Python include directory instead of default installation prefix" OFF) 88 | if (USE_PYTHON_INCLUDE_DIR) 89 | file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS}) 90 | endif() 91 | 92 | if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) # CMake >= 3.0 93 | # Build an interface library target: 94 | add_library(pybind11 INTERFACE) 95 | add_library(pybind11::pybind11 ALIAS pybind11) # to match exported target 96 | target_include_directories(pybind11 INTERFACE $ 97 | $ 98 | $) 99 | target_compile_options(pybind11 INTERFACE $) 100 | 101 | add_library(module INTERFACE) 102 | add_library(pybind11::module ALIAS module) 103 | if(NOT MSVC) 104 | target_compile_options(module INTERFACE -fvisibility=hidden) 105 | endif() 106 | target_link_libraries(module INTERFACE pybind11::pybind11) 107 | if(WIN32 OR CYGWIN) 108 | target_link_libraries(module INTERFACE $) 109 | elseif(APPLE) 110 | target_link_libraries(module INTERFACE "-undefined dynamic_lookup") 111 | endif() 112 | 113 | add_library(embed INTERFACE) 114 | add_library(pybind11::embed ALIAS embed) 115 | target_link_libraries(embed INTERFACE pybind11::pybind11 $) 116 | endif() 117 | 118 | if (PYBIND11_INSTALL) 119 | install(DIRECTORY ${PYBIND11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 120 | # GNUInstallDirs "DATADIR" wrong here; CMake search path wants "share". 121 | set(PYBIND11_CMAKECONFIG_INSTALL_DIR "share/cmake/${PROJECT_NAME}" CACHE STRING "install path for pybind11Config.cmake") 122 | 123 | configure_package_config_file(tools/${PROJECT_NAME}Config.cmake.in 124 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 125 | INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR}) 126 | # Remove CMAKE_SIZEOF_VOID_P from ConfigVersion.cmake since the library does 127 | # not depend on architecture specific settings or libraries. 128 | set(_PYBIND11_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) 129 | unset(CMAKE_SIZEOF_VOID_P) 130 | write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 131 | VERSION ${${PROJECT_NAME}_VERSION} 132 | COMPATIBILITY AnyNewerVersion) 133 | set(CMAKE_SIZEOF_VOID_P ${_PYBIND11_CMAKE_SIZEOF_VOID_P}) 134 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake 135 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 136 | tools/FindPythonLibsNew.cmake 137 | tools/pybind11Tools.cmake 138 | DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR}) 139 | 140 | if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) 141 | if(NOT PYBIND11_EXPORT_NAME) 142 | set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets") 143 | endif() 144 | 145 | install(TARGETS pybind11 module embed 146 | EXPORT "${PYBIND11_EXPORT_NAME}") 147 | if(PYBIND11_MASTER_PROJECT) 148 | install(EXPORT "${PYBIND11_EXPORT_NAME}" 149 | NAMESPACE "${PROJECT_NAME}::" 150 | DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR}) 151 | endif() 152 | endif() 153 | endif() 154 | -------------------------------------------------------------------------------- /third-party/pybind11/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Wenzel Jakob , All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Please also refer to the file CONTRIBUTING.md, which clarifies licensing of 29 | external contributions to this project including patches, pull requests, etc. 30 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/buffer_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/buffer_info.h: Python buffer object interface 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "detail/common.h" 13 | 14 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 15 | 16 | /// Information record describing a Python buffer object 17 | struct buffer_info { 18 | void *ptr = nullptr; // Pointer to the underlying storage 19 | ssize_t itemsize = 0; // Size of individual items in bytes 20 | ssize_t size = 0; // Total number of entries 21 | std::string format; // For homogeneous buffers, this should be set to format_descriptor::format() 22 | ssize_t ndim = 0; // Number of dimensions 23 | std::vector shape; // Shape of the tensor (1 entry per dimension) 24 | std::vector strides; // Number of entries between adjacent entries (for each per dimension) 25 | 26 | buffer_info() { } 27 | 28 | buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, 29 | detail::any_container shape_in, detail::any_container strides_in) 30 | : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim), 31 | shape(std::move(shape_in)), strides(std::move(strides_in)) { 32 | if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) 33 | pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length"); 34 | for (size_t i = 0; i < (size_t) ndim; ++i) 35 | size *= shape[i]; 36 | } 37 | 38 | template 39 | buffer_info(T *ptr, detail::any_container shape_in, detail::any_container strides_in) 40 | : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor::format(), static_cast(shape_in->size()), std::move(shape_in), std::move(strides_in)) { } 41 | 42 | buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size) 43 | : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { } 44 | 45 | template 46 | buffer_info(T *ptr, ssize_t size) 47 | : buffer_info(ptr, sizeof(T), format_descriptor::format(), size) { } 48 | 49 | explicit buffer_info(Py_buffer *view, bool ownview = true) 50 | : buffer_info(view->buf, view->itemsize, view->format, view->ndim, 51 | {view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}) { 52 | this->view = view; 53 | this->ownview = ownview; 54 | } 55 | 56 | buffer_info(const buffer_info &) = delete; 57 | buffer_info& operator=(const buffer_info &) = delete; 58 | 59 | buffer_info(buffer_info &&other) { 60 | (*this) = std::move(other); 61 | } 62 | 63 | buffer_info& operator=(buffer_info &&rhs) { 64 | ptr = rhs.ptr; 65 | itemsize = rhs.itemsize; 66 | size = rhs.size; 67 | format = std::move(rhs.format); 68 | ndim = rhs.ndim; 69 | shape = std::move(rhs.shape); 70 | strides = std::move(rhs.strides); 71 | std::swap(view, rhs.view); 72 | std::swap(ownview, rhs.ownview); 73 | return *this; 74 | } 75 | 76 | ~buffer_info() { 77 | if (view && ownview) { PyBuffer_Release(view); delete view; } 78 | } 79 | 80 | private: 81 | struct private_ctr_tag { }; 82 | 83 | buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, 84 | detail::any_container &&shape_in, detail::any_container &&strides_in) 85 | : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in)) { } 86 | 87 | Py_buffer *view = nullptr; 88 | bool ownview = false; 89 | }; 90 | 91 | NAMESPACE_BEGIN(detail) 92 | 93 | template struct compare_buffer_info { 94 | static bool compare(const buffer_info& b) { 95 | return b.format == format_descriptor::format() && b.itemsize == (ssize_t) sizeof(T); 96 | } 97 | }; 98 | 99 | template struct compare_buffer_info::value>> { 100 | static bool compare(const buffer_info& b) { 101 | return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor::value || 102 | ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned::value ? "L" : "l")) || 103 | ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned::value ? "N" : "n"))); 104 | } 105 | }; 106 | 107 | NAMESPACE_END(detail) 108 | NAMESPACE_END(PYBIND11_NAMESPACE) 109 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/chrono.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/chrono.h: Transparent conversion between std::chrono and python's datetime 3 | 4 | Copyright (c) 2016 Trent Houliston and 5 | Wenzel Jakob 6 | 7 | All rights reserved. Use of this source code is governed by a 8 | BSD-style license that can be found in the LICENSE file. 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "pybind11.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // Backport the PyDateTime_DELTA functions from Python3.3 if required 20 | #ifndef PyDateTime_DELTA_GET_DAYS 21 | #define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) 22 | #endif 23 | #ifndef PyDateTime_DELTA_GET_SECONDS 24 | #define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) 25 | #endif 26 | #ifndef PyDateTime_DELTA_GET_MICROSECONDS 27 | #define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds) 28 | #endif 29 | 30 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 31 | NAMESPACE_BEGIN(detail) 32 | 33 | template class duration_caster { 34 | public: 35 | typedef typename type::rep rep; 36 | typedef typename type::period period; 37 | 38 | typedef std::chrono::duration> days; 39 | 40 | bool load(handle src, bool) { 41 | using namespace std::chrono; 42 | 43 | // Lazy initialise the PyDateTime import 44 | if (!PyDateTimeAPI) { PyDateTime_IMPORT; } 45 | 46 | if (!src) return false; 47 | // If invoked with datetime.delta object 48 | if (PyDelta_Check(src.ptr())) { 49 | value = type(duration_cast>( 50 | days(PyDateTime_DELTA_GET_DAYS(src.ptr())) 51 | + seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) 52 | + microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr())))); 53 | return true; 54 | } 55 | // If invoked with a float we assume it is seconds and convert 56 | else if (PyFloat_Check(src.ptr())) { 57 | value = type(duration_cast>(duration(PyFloat_AsDouble(src.ptr())))); 58 | return true; 59 | } 60 | else return false; 61 | } 62 | 63 | // If this is a duration just return it back 64 | static const std::chrono::duration& get_duration(const std::chrono::duration &src) { 65 | return src; 66 | } 67 | 68 | // If this is a time_point get the time_since_epoch 69 | template static std::chrono::duration get_duration(const std::chrono::time_point> &src) { 70 | return src.time_since_epoch(); 71 | } 72 | 73 | static handle cast(const type &src, return_value_policy /* policy */, handle /* parent */) { 74 | using namespace std::chrono; 75 | 76 | // Use overloaded function to get our duration from our source 77 | // Works out if it is a duration or time_point and get the duration 78 | auto d = get_duration(src); 79 | 80 | // Lazy initialise the PyDateTime import 81 | if (!PyDateTimeAPI) { PyDateTime_IMPORT; } 82 | 83 | // Declare these special duration types so the conversions happen with the correct primitive types (int) 84 | using dd_t = duration>; 85 | using ss_t = duration>; 86 | using us_t = duration; 87 | 88 | auto dd = duration_cast(d); 89 | auto subd = d - dd; 90 | auto ss = duration_cast(subd); 91 | auto us = duration_cast(subd - ss); 92 | return PyDelta_FromDSU(dd.count(), ss.count(), us.count()); 93 | } 94 | 95 | PYBIND11_TYPE_CASTER(type, _("datetime.timedelta")); 96 | }; 97 | 98 | // This is for casting times on the system clock into datetime.datetime instances 99 | template class type_caster> { 100 | public: 101 | typedef std::chrono::time_point type; 102 | bool load(handle src, bool) { 103 | using namespace std::chrono; 104 | 105 | // Lazy initialise the PyDateTime import 106 | if (!PyDateTimeAPI) { PyDateTime_IMPORT; } 107 | 108 | if (!src) return false; 109 | 110 | std::tm cal; 111 | microseconds msecs; 112 | 113 | if (PyDateTime_Check(src.ptr())) { 114 | cal.tm_sec = PyDateTime_DATE_GET_SECOND(src.ptr()); 115 | cal.tm_min = PyDateTime_DATE_GET_MINUTE(src.ptr()); 116 | cal.tm_hour = PyDateTime_DATE_GET_HOUR(src.ptr()); 117 | cal.tm_mday = PyDateTime_GET_DAY(src.ptr()); 118 | cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1; 119 | cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900; 120 | cal.tm_isdst = -1; 121 | msecs = microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr())); 122 | } else if (PyDate_Check(src.ptr())) { 123 | cal.tm_sec = 0; 124 | cal.tm_min = 0; 125 | cal.tm_hour = 0; 126 | cal.tm_mday = PyDateTime_GET_DAY(src.ptr()); 127 | cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1; 128 | cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900; 129 | cal.tm_isdst = -1; 130 | msecs = microseconds(0); 131 | } else if (PyTime_Check(src.ptr())) { 132 | cal.tm_sec = PyDateTime_TIME_GET_SECOND(src.ptr()); 133 | cal.tm_min = PyDateTime_TIME_GET_MINUTE(src.ptr()); 134 | cal.tm_hour = PyDateTime_TIME_GET_HOUR(src.ptr()); 135 | cal.tm_mday = 1; // This date (day, month, year) = (1, 0, 70) 136 | cal.tm_mon = 0; // represents 1-Jan-1970, which is the first 137 | cal.tm_year = 70; // earliest available date for Python's datetime 138 | cal.tm_isdst = -1; 139 | msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr())); 140 | } 141 | else return false; 142 | 143 | value = system_clock::from_time_t(std::mktime(&cal)) + msecs; 144 | return true; 145 | } 146 | 147 | static handle cast(const std::chrono::time_point &src, return_value_policy /* policy */, handle /* parent */) { 148 | using namespace std::chrono; 149 | 150 | // Lazy initialise the PyDateTime import 151 | if (!PyDateTimeAPI) { PyDateTime_IMPORT; } 152 | 153 | std::time_t tt = system_clock::to_time_t(time_point_cast(src)); 154 | // this function uses static memory so it's best to copy it out asap just in case 155 | // otherwise other code that is using localtime may break this (not just python code) 156 | std::tm localtime = *std::localtime(&tt); 157 | 158 | // Declare these special duration types so the conversions happen with the correct primitive types (int) 159 | using us_t = duration; 160 | 161 | return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, 162 | localtime.tm_mon + 1, 163 | localtime.tm_mday, 164 | localtime.tm_hour, 165 | localtime.tm_min, 166 | localtime.tm_sec, 167 | (duration_cast(src.time_since_epoch() % seconds(1))).count()); 168 | } 169 | PYBIND11_TYPE_CASTER(type, _("datetime.datetime")); 170 | }; 171 | 172 | // Other clocks that are not the system clock are not measured as datetime.datetime objects 173 | // since they are not measured on calendar time. So instead we just make them timedeltas 174 | // Or if they have passed us a time as a float we convert that 175 | template class type_caster> 176 | : public duration_caster> { 177 | }; 178 | 179 | template class type_caster> 180 | : public duration_caster> { 181 | }; 182 | 183 | NAMESPACE_END(detail) 184 | NAMESPACE_END(PYBIND11_NAMESPACE) 185 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/common.h: -------------------------------------------------------------------------------- 1 | #include "detail/common.h" 2 | #warning "Including 'common.h' is deprecated. It will be removed in v3.0. Use 'pybind11.h'." 3 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/complex.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/complex.h: Complex number support 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "pybind11.h" 13 | #include 14 | 15 | /// glibc defines I as a macro which breaks things, e.g., boost template names 16 | #ifdef I 17 | # undef I 18 | #endif 19 | 20 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 21 | 22 | template struct format_descriptor, detail::enable_if_t::value>> { 23 | static constexpr const char c = format_descriptor::c; 24 | static constexpr const char value[3] = { 'Z', c, '\0' }; 25 | static std::string format() { return std::string(value); } 26 | }; 27 | 28 | #ifndef PYBIND11_CPP17 29 | 30 | template constexpr const char format_descriptor< 31 | std::complex, detail::enable_if_t::value>>::value[3]; 32 | 33 | #endif 34 | 35 | NAMESPACE_BEGIN(detail) 36 | 37 | template struct is_fmt_numeric, detail::enable_if_t::value>> { 38 | static constexpr bool value = true; 39 | static constexpr int index = is_fmt_numeric::index + 3; 40 | }; 41 | 42 | template class type_caster> { 43 | public: 44 | bool load(handle src, bool convert) { 45 | if (!src) 46 | return false; 47 | if (!convert && !PyComplex_Check(src.ptr())) 48 | return false; 49 | Py_complex result = PyComplex_AsCComplex(src.ptr()); 50 | if (result.real == -1.0 && PyErr_Occurred()) { 51 | PyErr_Clear(); 52 | return false; 53 | } 54 | value = std::complex((T) result.real, (T) result.imag); 55 | return true; 56 | } 57 | 58 | static handle cast(const std::complex &src, return_value_policy /* policy */, handle /* parent */) { 59 | return PyComplex_FromDoubles((double) src.real(), (double) src.imag()); 60 | } 61 | 62 | PYBIND11_TYPE_CASTER(std::complex, _("complex")); 63 | }; 64 | NAMESPACE_END(detail) 65 | NAMESPACE_END(PYBIND11_NAMESPACE) 66 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/detail/descr.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "common.h" 13 | 14 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 15 | NAMESPACE_BEGIN(detail) 16 | 17 | #if !defined(_MSC_VER) 18 | # define PYBIND11_DESCR_CONSTEXPR static constexpr 19 | #else 20 | # define PYBIND11_DESCR_CONSTEXPR const 21 | #endif 22 | 23 | /* Concatenate type signatures at compile time */ 24 | template 25 | struct descr { 26 | char text[N + 1]; 27 | 28 | constexpr descr() : text{'\0'} { } 29 | constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence()) { } 30 | 31 | template 32 | constexpr descr(char const (&s)[N+1], index_sequence) : text{s[Is]..., '\0'} { } 33 | 34 | template 35 | constexpr descr(char c, Chars... cs) : text{c, static_cast(cs)..., '\0'} { } 36 | 37 | static constexpr std::array types() { 38 | return {{&typeid(Ts)..., nullptr}}; 39 | } 40 | }; 41 | 42 | template 43 | constexpr descr plus_impl(const descr &a, const descr &b, 44 | index_sequence, index_sequence) { 45 | return {a.text[Is1]..., b.text[Is2]...}; 46 | } 47 | 48 | template 49 | constexpr descr operator+(const descr &a, const descr &b) { 50 | return plus_impl(a, b, make_index_sequence(), make_index_sequence()); 51 | } 52 | 53 | template 54 | constexpr descr _(char const(&text)[N]) { return descr(text); } 55 | constexpr descr<0> _(char const(&)[1]) { return {}; } 56 | 57 | template struct int_to_str : int_to_str { }; 58 | template struct int_to_str<0, Digits...> { 59 | static constexpr auto digits = descr(('0' + Digits)...); 60 | }; 61 | 62 | // Ternary description (like std::conditional) 63 | template 64 | constexpr enable_if_t> _(char const(&text1)[N1], char const(&)[N2]) { 65 | return _(text1); 66 | } 67 | template 68 | constexpr enable_if_t> _(char const(&)[N1], char const(&text2)[N2]) { 69 | return _(text2); 70 | } 71 | 72 | template 73 | constexpr enable_if_t _(const T1 &d, const T2 &) { return d; } 74 | template 75 | constexpr enable_if_t _(const T1 &, const T2 &d) { return d; } 76 | 77 | template auto constexpr _() -> decltype(int_to_str::digits) { 78 | return int_to_str::digits; 79 | } 80 | 81 | template constexpr descr<1, Type> _() { return {'%'}; } 82 | 83 | constexpr descr<0> concat() { return {}; } 84 | 85 | template 86 | constexpr descr concat(const descr &descr) { return descr; } 87 | 88 | template 89 | constexpr auto concat(const descr &d, const Args &...args) 90 | -> decltype(std::declval>() + concat(args...)) { 91 | return d + _(", ") + concat(args...); 92 | } 93 | 94 | template 95 | constexpr descr type_descr(const descr &descr) { 96 | return _("{") + descr + _("}"); 97 | } 98 | 99 | NAMESPACE_END(detail) 100 | NAMESPACE_END(PYBIND11_NAMESPACE) 101 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/detail/typeid.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/detail/typeid.h: Compiler-independent access to type identifiers 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | 15 | #if defined(__GNUG__) 16 | #include 17 | #endif 18 | 19 | #include "common.h" 20 | 21 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 22 | NAMESPACE_BEGIN(detail) 23 | /// Erase all occurrences of a substring 24 | inline void erase_all(std::string &string, const std::string &search) { 25 | for (size_t pos = 0;;) { 26 | pos = string.find(search, pos); 27 | if (pos == std::string::npos) break; 28 | string.erase(pos, search.length()); 29 | } 30 | } 31 | 32 | PYBIND11_NOINLINE inline void clean_type_id(std::string &name) { 33 | #if defined(__GNUG__) 34 | int status = 0; 35 | std::unique_ptr res { 36 | abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free }; 37 | if (status == 0) 38 | name = res.get(); 39 | #else 40 | detail::erase_all(name, "class "); 41 | detail::erase_all(name, "struct "); 42 | detail::erase_all(name, "enum "); 43 | #endif 44 | detail::erase_all(name, "pybind11::"); 45 | } 46 | NAMESPACE_END(detail) 47 | 48 | /// Return a string representation of a C++ type 49 | template static std::string type_id() { 50 | std::string name(typeid(T).name()); 51 | detail::clean_type_id(name); 52 | return name; 53 | } 54 | 55 | NAMESPACE_END(PYBIND11_NAMESPACE) 56 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/embed.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/embed.h: Support for embedding the interpreter 3 | 4 | Copyright (c) 2017 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "pybind11.h" 13 | #include "eval.h" 14 | 15 | #if defined(PYPY_VERSION) 16 | # error Embedding the interpreter is not supported with PyPy 17 | #endif 18 | 19 | #if PY_MAJOR_VERSION >= 3 20 | # define PYBIND11_EMBEDDED_MODULE_IMPL(name) \ 21 | extern "C" PyObject *pybind11_init_impl_##name() { \ 22 | return pybind11_init_wrapper_##name(); \ 23 | } 24 | #else 25 | # define PYBIND11_EMBEDDED_MODULE_IMPL(name) \ 26 | extern "C" void pybind11_init_impl_##name() { \ 27 | pybind11_init_wrapper_##name(); \ 28 | } 29 | #endif 30 | 31 | /** \rst 32 | Add a new module to the table of builtins for the interpreter. Must be 33 | defined in global scope. The first macro parameter is the name of the 34 | module (without quotes). The second parameter is the variable which will 35 | be used as the interface to add functions and classes to the module. 36 | 37 | .. code-block:: cpp 38 | 39 | PYBIND11_EMBEDDED_MODULE(example, m) { 40 | // ... initialize functions and classes here 41 | m.def("foo", []() { 42 | return "Hello, World!"; 43 | }); 44 | } 45 | \endrst */ 46 | #define PYBIND11_EMBEDDED_MODULE(name, variable) \ 47 | static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \ 48 | static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \ 49 | auto m = pybind11::module(PYBIND11_TOSTRING(name)); \ 50 | try { \ 51 | PYBIND11_CONCAT(pybind11_init_, name)(m); \ 52 | return m.ptr(); \ 53 | } catch (pybind11::error_already_set &e) { \ 54 | PyErr_SetString(PyExc_ImportError, e.what()); \ 55 | return nullptr; \ 56 | } catch (const std::exception &e) { \ 57 | PyErr_SetString(PyExc_ImportError, e.what()); \ 58 | return nullptr; \ 59 | } \ 60 | } \ 61 | PYBIND11_EMBEDDED_MODULE_IMPL(name) \ 62 | pybind11::detail::embedded_module name(PYBIND11_TOSTRING(name), \ 63 | PYBIND11_CONCAT(pybind11_init_impl_, name)); \ 64 | void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable) 65 | 66 | 67 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 68 | NAMESPACE_BEGIN(detail) 69 | 70 | /// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks. 71 | struct embedded_module { 72 | #if PY_MAJOR_VERSION >= 3 73 | using init_t = PyObject *(*)(); 74 | #else 75 | using init_t = void (*)(); 76 | #endif 77 | embedded_module(const char *name, init_t init) { 78 | if (Py_IsInitialized()) 79 | pybind11_fail("Can't add new modules after the interpreter has been initialized"); 80 | 81 | auto result = PyImport_AppendInittab(name, init); 82 | if (result == -1) 83 | pybind11_fail("Insufficient memory to add a new module"); 84 | } 85 | }; 86 | 87 | NAMESPACE_END(detail) 88 | 89 | /** \rst 90 | Initialize the Python interpreter. No other pybind11 or CPython API functions can be 91 | called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The 92 | optional parameter can be used to skip the registration of signal handlers (see the 93 | `Python documentation`_ for details). Calling this function again after the interpreter 94 | has already been initialized is a fatal error. 95 | 96 | If initializing the Python interpreter fails, then the program is terminated. (This 97 | is controlled by the CPython runtime and is an exception to pybind11's normal behavior 98 | of throwing exceptions on errors.) 99 | 100 | .. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx 101 | \endrst */ 102 | inline void initialize_interpreter(bool init_signal_handlers = true) { 103 | if (Py_IsInitialized()) 104 | pybind11_fail("The interpreter is already running"); 105 | 106 | Py_InitializeEx(init_signal_handlers ? 1 : 0); 107 | 108 | // Make .py files in the working directory available by default 109 | module::import("sys").attr("path").cast().append("."); 110 | } 111 | 112 | /** \rst 113 | Shut down the Python interpreter. No pybind11 or CPython API functions can be called 114 | after this. In addition, pybind11 objects must not outlive the interpreter: 115 | 116 | .. code-block:: cpp 117 | 118 | { // BAD 119 | py::initialize_interpreter(); 120 | auto hello = py::str("Hello, World!"); 121 | py::finalize_interpreter(); 122 | } // <-- BOOM, hello's destructor is called after interpreter shutdown 123 | 124 | { // GOOD 125 | py::initialize_interpreter(); 126 | { // scoped 127 | auto hello = py::str("Hello, World!"); 128 | } // <-- OK, hello is cleaned up properly 129 | py::finalize_interpreter(); 130 | } 131 | 132 | { // BETTER 133 | py::scoped_interpreter guard{}; 134 | auto hello = py::str("Hello, World!"); 135 | } 136 | 137 | .. warning:: 138 | 139 | The interpreter can be restarted by calling `initialize_interpreter` again. 140 | Modules created using pybind11 can be safely re-initialized. However, Python 141 | itself cannot completely unload binary extension modules and there are several 142 | caveats with regard to interpreter restarting. All the details can be found 143 | in the CPython documentation. In short, not all interpreter memory may be 144 | freed, either due to reference cycles or user-created global data. 145 | 146 | \endrst */ 147 | inline void finalize_interpreter() { 148 | handle builtins(PyEval_GetBuiltins()); 149 | const char *id = PYBIND11_INTERNALS_ID; 150 | 151 | // Get the internals pointer (without creating it if it doesn't exist). It's possible for the 152 | // internals to be created during Py_Finalize() (e.g. if a py::capsule calls `get_internals()` 153 | // during destruction), so we get the pointer-pointer here and check it after Py_Finalize(). 154 | detail::internals **internals_ptr_ptr = detail::get_internals_pp(); 155 | // It could also be stashed in builtins, so look there too: 156 | if (builtins.contains(id) && isinstance(builtins[id])) 157 | internals_ptr_ptr = capsule(builtins[id]); 158 | 159 | Py_Finalize(); 160 | 161 | if (internals_ptr_ptr) { 162 | delete *internals_ptr_ptr; 163 | *internals_ptr_ptr = nullptr; 164 | } 165 | } 166 | 167 | /** \rst 168 | Scope guard version of `initialize_interpreter` and `finalize_interpreter`. 169 | This a move-only guard and only a single instance can exist. 170 | 171 | .. code-block:: cpp 172 | 173 | #include 174 | 175 | int main() { 176 | py::scoped_interpreter guard{}; 177 | py::print(Hello, World!); 178 | } // <-- interpreter shutdown 179 | \endrst */ 180 | class scoped_interpreter { 181 | public: 182 | scoped_interpreter(bool init_signal_handlers = true) { 183 | initialize_interpreter(init_signal_handlers); 184 | } 185 | 186 | scoped_interpreter(const scoped_interpreter &) = delete; 187 | scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; } 188 | scoped_interpreter &operator=(const scoped_interpreter &) = delete; 189 | scoped_interpreter &operator=(scoped_interpreter &&) = delete; 190 | 191 | ~scoped_interpreter() { 192 | if (is_valid) 193 | finalize_interpreter(); 194 | } 195 | 196 | private: 197 | bool is_valid = true; 198 | }; 199 | 200 | NAMESPACE_END(PYBIND11_NAMESPACE) 201 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/eval.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/exec.h: Support for evaluating Python expressions and statements 3 | from strings and files 4 | 5 | Copyright (c) 2016 Klemens Morgenstern and 6 | Wenzel Jakob 7 | 8 | All rights reserved. Use of this source code is governed by a 9 | BSD-style license that can be found in the LICENSE file. 10 | */ 11 | 12 | #pragma once 13 | 14 | #include "pybind11.h" 15 | 16 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 17 | 18 | enum eval_mode { 19 | /// Evaluate a string containing an isolated expression 20 | eval_expr, 21 | 22 | /// Evaluate a string containing a single statement. Returns \c none 23 | eval_single_statement, 24 | 25 | /// Evaluate a string containing a sequence of statement. Returns \c none 26 | eval_statements 27 | }; 28 | 29 | template 30 | object eval(str expr, object global = globals(), object local = object()) { 31 | if (!local) 32 | local = global; 33 | 34 | /* PyRun_String does not accept a PyObject / encoding specifier, 35 | this seems to be the only alternative */ 36 | std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr; 37 | 38 | int start; 39 | switch (mode) { 40 | case eval_expr: start = Py_eval_input; break; 41 | case eval_single_statement: start = Py_single_input; break; 42 | case eval_statements: start = Py_file_input; break; 43 | default: pybind11_fail("invalid evaluation mode"); 44 | } 45 | 46 | PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()); 47 | if (!result) 48 | throw error_already_set(); 49 | return reinterpret_steal(result); 50 | } 51 | 52 | template 53 | object eval(const char (&s)[N], object global = globals(), object local = object()) { 54 | /* Support raw string literals by removing common leading whitespace */ 55 | auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s)) 56 | : str(s); 57 | return eval(expr, global, local); 58 | } 59 | 60 | inline void exec(str expr, object global = globals(), object local = object()) { 61 | eval(expr, global, local); 62 | } 63 | 64 | template 65 | void exec(const char (&s)[N], object global = globals(), object local = object()) { 66 | eval(s, global, local); 67 | } 68 | 69 | template 70 | object eval_file(str fname, object global = globals(), object local = object()) { 71 | if (!local) 72 | local = global; 73 | 74 | int start; 75 | switch (mode) { 76 | case eval_expr: start = Py_eval_input; break; 77 | case eval_single_statement: start = Py_single_input; break; 78 | case eval_statements: start = Py_file_input; break; 79 | default: pybind11_fail("invalid evaluation mode"); 80 | } 81 | 82 | int closeFile = 1; 83 | std::string fname_str = (std::string) fname; 84 | #if PY_VERSION_HEX >= 0x03040000 85 | FILE *f = _Py_fopen_obj(fname.ptr(), "r"); 86 | #elif PY_VERSION_HEX >= 0x03000000 87 | FILE *f = _Py_fopen(fname.ptr(), "r"); 88 | #else 89 | /* No unicode support in open() :( */ 90 | auto fobj = reinterpret_steal(PyFile_FromString( 91 | const_cast(fname_str.c_str()), 92 | const_cast("r"))); 93 | FILE *f = nullptr; 94 | if (fobj) 95 | f = PyFile_AsFile(fobj.ptr()); 96 | closeFile = 0; 97 | #endif 98 | if (!f) { 99 | PyErr_Clear(); 100 | pybind11_fail("File \"" + fname_str + "\" could not be opened!"); 101 | } 102 | 103 | #if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION) 104 | PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(), 105 | local.ptr()); 106 | (void) closeFile; 107 | #else 108 | PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), 109 | local.ptr(), closeFile); 110 | #endif 111 | 112 | if (!result) 113 | throw error_already_set(); 114 | return reinterpret_steal(result); 115 | } 116 | 117 | NAMESPACE_END(PYBIND11_NAMESPACE) 118 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/functional.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/functional.h: std::function<> support 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "pybind11.h" 13 | #include 14 | 15 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 16 | NAMESPACE_BEGIN(detail) 17 | 18 | template 19 | struct type_caster> { 20 | using type = std::function; 21 | using retval_type = conditional_t::value, void_type, Return>; 22 | using function_type = Return (*) (Args...); 23 | 24 | public: 25 | bool load(handle src, bool convert) { 26 | if (src.is_none()) { 27 | // Defer accepting None to other overloads (if we aren't in convert mode): 28 | if (!convert) return false; 29 | return true; 30 | } 31 | 32 | if (!isinstance(src)) 33 | return false; 34 | 35 | auto func = reinterpret_borrow(src); 36 | 37 | /* 38 | When passing a C++ function as an argument to another C++ 39 | function via Python, every function call would normally involve 40 | a full C++ -> Python -> C++ roundtrip, which can be prohibitive. 41 | Here, we try to at least detect the case where the function is 42 | stateless (i.e. function pointer or lambda function without 43 | captured variables), in which case the roundtrip can be avoided. 44 | */ 45 | if (auto cfunc = func.cpp_function()) { 46 | auto c = reinterpret_borrow(PyCFunction_GET_SELF(cfunc.ptr())); 47 | auto rec = (function_record *) c; 48 | 49 | if (rec && rec->is_stateless && 50 | same_type(typeid(function_type), *reinterpret_cast(rec->data[1]))) { 51 | struct capture { function_type f; }; 52 | value = ((capture *) &rec->data)->f; 53 | return true; 54 | } 55 | } 56 | 57 | // ensure GIL is held during functor destruction 58 | struct func_handle { 59 | function f; 60 | func_handle(function&& f_) : f(std::move(f_)) {} 61 | func_handle(const func_handle&) = default; 62 | ~func_handle() { 63 | gil_scoped_acquire acq; 64 | function kill_f(std::move(f)); 65 | } 66 | }; 67 | 68 | // to emulate 'move initialization capture' in C++11 69 | struct func_wrapper { 70 | func_handle hfunc; 71 | func_wrapper(func_handle&& hf): hfunc(std::move(hf)) {} 72 | Return operator()(Args... args) const { 73 | gil_scoped_acquire acq; 74 | object retval(hfunc.f(std::forward(args)...)); 75 | /* Visual studio 2015 parser issue: need parentheses around this expression */ 76 | return (retval.template cast()); 77 | } 78 | }; 79 | 80 | value = func_wrapper(func_handle(std::move(func))); 81 | return true; 82 | } 83 | 84 | template 85 | static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { 86 | if (!f_) 87 | return none().inc_ref(); 88 | 89 | auto result = f_.template target(); 90 | if (result) 91 | return cpp_function(*result, policy).release(); 92 | else 93 | return cpp_function(std::forward(f_), policy).release(); 94 | } 95 | 96 | PYBIND11_TYPE_CASTER(type, _("Callable[[") + concat(make_caster::name...) + _("], ") 97 | + make_caster::name + _("]")); 98 | }; 99 | 100 | NAMESPACE_END(detail) 101 | NAMESPACE_END(PYBIND11_NAMESPACE) 102 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/iostream.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/iostream.h -- Tools to assist with redirecting cout and cerr to Python 3 | 4 | Copyright (c) 2017 Henry F. Schreiner 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "pybind11.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 21 | NAMESPACE_BEGIN(detail) 22 | 23 | // Buffer that writes to Python instead of C++ 24 | class pythonbuf : public std::streambuf { 25 | private: 26 | using traits_type = std::streambuf::traits_type; 27 | 28 | const size_t buf_size; 29 | std::unique_ptr d_buffer; 30 | object pywrite; 31 | object pyflush; 32 | 33 | int overflow(int c) { 34 | if (!traits_type::eq_int_type(c, traits_type::eof())) { 35 | *pptr() = traits_type::to_char_type(c); 36 | pbump(1); 37 | } 38 | return sync() == 0 ? traits_type::not_eof(c) : traits_type::eof(); 39 | } 40 | 41 | int sync() { 42 | if (pbase() != pptr()) { 43 | // This subtraction cannot be negative, so dropping the sign 44 | str line(pbase(), static_cast(pptr() - pbase())); 45 | 46 | { 47 | gil_scoped_acquire tmp; 48 | pywrite(line); 49 | pyflush(); 50 | } 51 | 52 | setp(pbase(), epptr()); 53 | } 54 | return 0; 55 | } 56 | 57 | public: 58 | 59 | pythonbuf(object pyostream, size_t buffer_size = 1024) 60 | : buf_size(buffer_size), 61 | d_buffer(new char[buf_size]), 62 | pywrite(pyostream.attr("write")), 63 | pyflush(pyostream.attr("flush")) { 64 | setp(d_buffer.get(), d_buffer.get() + buf_size - 1); 65 | } 66 | 67 | pythonbuf(pythonbuf&&) = default; 68 | 69 | /// Sync before destroy 70 | ~pythonbuf() { 71 | sync(); 72 | } 73 | }; 74 | 75 | NAMESPACE_END(detail) 76 | 77 | 78 | /** \rst 79 | This a move-only guard that redirects output. 80 | 81 | .. code-block:: cpp 82 | 83 | #include 84 | 85 | ... 86 | 87 | { 88 | py::scoped_ostream_redirect output; 89 | std::cout << "Hello, World!"; // Python stdout 90 | } // <-- return std::cout to normal 91 | 92 | You can explicitly pass the c++ stream and the python object, 93 | for example to guard stderr instead. 94 | 95 | .. code-block:: cpp 96 | 97 | { 98 | py::scoped_ostream_redirect output{std::cerr, py::module::import("sys").attr("stderr")}; 99 | std::cerr << "Hello, World!"; 100 | } 101 | \endrst */ 102 | class scoped_ostream_redirect { 103 | protected: 104 | std::streambuf *old; 105 | std::ostream &costream; 106 | detail::pythonbuf buffer; 107 | 108 | public: 109 | scoped_ostream_redirect( 110 | std::ostream &costream = std::cout, 111 | object pyostream = module::import("sys").attr("stdout")) 112 | : costream(costream), buffer(pyostream) { 113 | old = costream.rdbuf(&buffer); 114 | } 115 | 116 | ~scoped_ostream_redirect() { 117 | costream.rdbuf(old); 118 | } 119 | 120 | scoped_ostream_redirect(const scoped_ostream_redirect &) = delete; 121 | scoped_ostream_redirect(scoped_ostream_redirect &&other) = default; 122 | scoped_ostream_redirect &operator=(const scoped_ostream_redirect &) = delete; 123 | scoped_ostream_redirect &operator=(scoped_ostream_redirect &&) = delete; 124 | }; 125 | 126 | 127 | /** \rst 128 | Like `scoped_ostream_redirect`, but redirects cerr by default. This class 129 | is provided primary to make ``py::call_guard`` easier to make. 130 | 131 | .. code-block:: cpp 132 | 133 | m.def("noisy_func", &noisy_func, 134 | py::call_guard()); 136 | 137 | \endrst */ 138 | class scoped_estream_redirect : public scoped_ostream_redirect { 139 | public: 140 | scoped_estream_redirect( 141 | std::ostream &costream = std::cerr, 142 | object pyostream = module::import("sys").attr("stderr")) 143 | : scoped_ostream_redirect(costream,pyostream) {} 144 | }; 145 | 146 | 147 | NAMESPACE_BEGIN(detail) 148 | 149 | // Class to redirect output as a context manager. C++ backend. 150 | class OstreamRedirect { 151 | bool do_stdout_; 152 | bool do_stderr_; 153 | std::unique_ptr redirect_stdout; 154 | std::unique_ptr redirect_stderr; 155 | 156 | public: 157 | OstreamRedirect(bool do_stdout = true, bool do_stderr = true) 158 | : do_stdout_(do_stdout), do_stderr_(do_stderr) {} 159 | 160 | void enter() { 161 | if (do_stdout_) 162 | redirect_stdout.reset(new scoped_ostream_redirect()); 163 | if (do_stderr_) 164 | redirect_stderr.reset(new scoped_estream_redirect()); 165 | } 166 | 167 | void exit() { 168 | redirect_stdout.reset(); 169 | redirect_stderr.reset(); 170 | } 171 | }; 172 | 173 | NAMESPACE_END(detail) 174 | 175 | /** \rst 176 | This is a helper function to add a C++ redirect context manager to Python 177 | instead of using a C++ guard. To use it, add the following to your binding code: 178 | 179 | .. code-block:: cpp 180 | 181 | #include 182 | 183 | ... 184 | 185 | py::add_ostream_redirect(m, "ostream_redirect"); 186 | 187 | You now have a Python context manager that redirects your output: 188 | 189 | .. code-block:: python 190 | 191 | with m.ostream_redirect(): 192 | m.print_to_cout_function() 193 | 194 | This manager can optionally be told which streams to operate on: 195 | 196 | .. code-block:: python 197 | 198 | with m.ostream_redirect(stdout=true, stderr=true): 199 | m.noisy_function_with_error_printing() 200 | 201 | \endrst */ 202 | inline class_ add_ostream_redirect(module m, std::string name = "ostream_redirect") { 203 | return class_(m, name.c_str(), module_local()) 204 | .def(init(), arg("stdout")=true, arg("stderr")=true) 205 | .def("__enter__", &detail::OstreamRedirect::enter) 206 | .def("__exit__", [](detail::OstreamRedirect &self_, args) { self_.exit(); }); 207 | } 208 | 209 | NAMESPACE_END(PYBIND11_NAMESPACE) 210 | -------------------------------------------------------------------------------- /third-party/pybind11/include/pybind11/options.h: -------------------------------------------------------------------------------- 1 | /* 2 | pybind11/options.h: global settings that are configurable at runtime. 3 | 4 | Copyright (c) 2016 Wenzel Jakob 5 | 6 | All rights reserved. Use of this source code is governed by a 7 | BSD-style license that can be found in the LICENSE file. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "detail/common.h" 13 | 14 | NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 15 | 16 | class options { 17 | public: 18 | 19 | // Default RAII constructor, which leaves settings as they currently are. 20 | options() : previous_state(global_state()) {} 21 | 22 | // Class is non-copyable. 23 | options(const options&) = delete; 24 | options& operator=(const options&) = delete; 25 | 26 | // Destructor, which restores settings that were in effect before. 27 | ~options() { 28 | global_state() = previous_state; 29 | } 30 | 31 | // Setter methods (affect the global state): 32 | 33 | options& disable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = false; return *this; } 34 | 35 | options& enable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = true; return *this; } 36 | 37 | options& disable_function_signatures() & { global_state().show_function_signatures = false; return *this; } 38 | 39 | options& enable_function_signatures() & { global_state().show_function_signatures = true; return *this; } 40 | 41 | // Getter methods (return the global state): 42 | 43 | static bool show_user_defined_docstrings() { return global_state().show_user_defined_docstrings; } 44 | 45 | static bool show_function_signatures() { return global_state().show_function_signatures; } 46 | 47 | // This type is not meant to be allocated on the heap. 48 | void* operator new(size_t) = delete; 49 | 50 | private: 51 | 52 | struct state { 53 | bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings. 54 | bool show_function_signatures = true; //< Include auto-generated function signatures in docstrings. 55 | }; 56 | 57 | static state &global_state() { 58 | static state instance; 59 | return instance; 60 | } 61 | 62 | state previous_state; 63 | }; 64 | 65 | NAMESPACE_END(PYBIND11_NAMESPACE) 66 | -------------------------------------------------------------------------------- /third-party/pybind11/tools/FindCatch.cmake: -------------------------------------------------------------------------------- 1 | # - Find the Catch test framework or download it (single header) 2 | # 3 | # This is a quick module for internal use. It assumes that Catch is 4 | # REQUIRED and that a minimum version is provided (not EXACT). If 5 | # a suitable version isn't found locally, the single header file 6 | # will be downloaded and placed in the build dir: PROJECT_BINARY_DIR. 7 | # 8 | # This code sets the following variables: 9 | # CATCH_INCLUDE_DIR - path to catch.hpp 10 | # CATCH_VERSION - version number 11 | 12 | if(NOT Catch_FIND_VERSION) 13 | message(FATAL_ERROR "A version number must be specified.") 14 | elseif(Catch_FIND_REQUIRED) 15 | message(FATAL_ERROR "This module assumes Catch is not required.") 16 | elseif(Catch_FIND_VERSION_EXACT) 17 | message(FATAL_ERROR "Exact version numbers are not supported, only minimum.") 18 | endif() 19 | 20 | # Extract the version number from catch.hpp 21 | function(_get_catch_version) 22 | file(STRINGS "${CATCH_INCLUDE_DIR}/catch.hpp" version_line REGEX "Catch v.*" LIMIT_COUNT 1) 23 | if(version_line MATCHES "Catch v([0-9]+)\\.([0-9]+)\\.([0-9]+)") 24 | set(CATCH_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}" PARENT_SCOPE) 25 | endif() 26 | endfunction() 27 | 28 | # Download the single-header version of Catch 29 | function(_download_catch version destination_dir) 30 | message(STATUS "Downloading catch v${version}...") 31 | set(url https://github.com/philsquared/Catch/releases/download/v${version}/catch.hpp) 32 | file(DOWNLOAD ${url} "${destination_dir}/catch.hpp" STATUS status) 33 | list(GET status 0 error) 34 | if(error) 35 | message(FATAL_ERROR "Could not download ${url}") 36 | endif() 37 | set(CATCH_INCLUDE_DIR "${destination_dir}" CACHE INTERNAL "") 38 | endfunction() 39 | 40 | # Look for catch locally 41 | find_path(CATCH_INCLUDE_DIR NAMES catch.hpp PATH_SUFFIXES catch) 42 | if(CATCH_INCLUDE_DIR) 43 | _get_catch_version() 44 | endif() 45 | 46 | # Download the header if it wasn't found or if it's outdated 47 | if(NOT CATCH_VERSION OR CATCH_VERSION VERSION_LESS ${Catch_FIND_VERSION}) 48 | if(DOWNLOAD_CATCH) 49 | _download_catch(${Catch_FIND_VERSION} "${PROJECT_BINARY_DIR}/catch/") 50 | _get_catch_version() 51 | else() 52 | set(CATCH_FOUND FALSE) 53 | return() 54 | endif() 55 | endif() 56 | 57 | set(CATCH_FOUND TRUE) 58 | -------------------------------------------------------------------------------- /third-party/pybind11/tools/FindEigen3.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Eigen3 lib 2 | # 3 | # This module supports requiring a minimum version, e.g. you can do 4 | # find_package(Eigen3 3.1.2) 5 | # to require version 3.1.2 or newer of Eigen3. 6 | # 7 | # Once done this will define 8 | # 9 | # EIGEN3_FOUND - system has eigen lib with correct version 10 | # EIGEN3_INCLUDE_DIR - the eigen include directory 11 | # EIGEN3_VERSION - eigen version 12 | 13 | # Copyright (c) 2006, 2007 Montel Laurent, 14 | # Copyright (c) 2008, 2009 Gael Guennebaud, 15 | # Copyright (c) 2009 Benoit Jacob 16 | # Redistribution and use is allowed according to the terms of the 2-clause BSD license. 17 | 18 | if(NOT Eigen3_FIND_VERSION) 19 | if(NOT Eigen3_FIND_VERSION_MAJOR) 20 | set(Eigen3_FIND_VERSION_MAJOR 2) 21 | endif(NOT Eigen3_FIND_VERSION_MAJOR) 22 | if(NOT Eigen3_FIND_VERSION_MINOR) 23 | set(Eigen3_FIND_VERSION_MINOR 91) 24 | endif(NOT Eigen3_FIND_VERSION_MINOR) 25 | if(NOT Eigen3_FIND_VERSION_PATCH) 26 | set(Eigen3_FIND_VERSION_PATCH 0) 27 | endif(NOT Eigen3_FIND_VERSION_PATCH) 28 | 29 | set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") 30 | endif(NOT Eigen3_FIND_VERSION) 31 | 32 | macro(_eigen3_check_version) 33 | file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) 34 | 35 | string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") 36 | set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") 37 | string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") 38 | set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") 39 | string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") 40 | set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") 41 | 42 | set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) 43 | if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 44 | set(EIGEN3_VERSION_OK FALSE) 45 | else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 46 | set(EIGEN3_VERSION_OK TRUE) 47 | endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) 48 | 49 | if(NOT EIGEN3_VERSION_OK) 50 | 51 | message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " 52 | "but at least version ${Eigen3_FIND_VERSION} is required") 53 | endif(NOT EIGEN3_VERSION_OK) 54 | endmacro(_eigen3_check_version) 55 | 56 | if (EIGEN3_INCLUDE_DIR) 57 | 58 | # in cache already 59 | _eigen3_check_version() 60 | set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) 61 | 62 | else (EIGEN3_INCLUDE_DIR) 63 | 64 | find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library 65 | PATHS 66 | ${CMAKE_INSTALL_PREFIX}/include 67 | ${KDE4_INCLUDE_DIR} 68 | PATH_SUFFIXES eigen3 eigen 69 | ) 70 | 71 | if(EIGEN3_INCLUDE_DIR) 72 | _eigen3_check_version() 73 | endif(EIGEN3_INCLUDE_DIR) 74 | 75 | include(FindPackageHandleStandardArgs) 76 | find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) 77 | 78 | mark_as_advanced(EIGEN3_INCLUDE_DIR) 79 | 80 | endif(EIGEN3_INCLUDE_DIR) 81 | 82 | -------------------------------------------------------------------------------- /third-party/pybind11/tools/FindPythonLibsNew.cmake: -------------------------------------------------------------------------------- 1 | # - Find python libraries 2 | # This module finds the libraries corresponding to the Python interpreter 3 | # FindPythonInterp provides. 4 | # This code sets the following variables: 5 | # 6 | # PYTHONLIBS_FOUND - have the Python libs been found 7 | # PYTHON_PREFIX - path to the Python installation 8 | # PYTHON_LIBRARIES - path to the python library 9 | # PYTHON_INCLUDE_DIRS - path to where Python.h is found 10 | # PYTHON_MODULE_EXTENSION - lib extension, e.g. '.so' or '.pyd' 11 | # PYTHON_MODULE_PREFIX - lib name prefix: usually an empty string 12 | # PYTHON_SITE_PACKAGES - path to installation site-packages 13 | # PYTHON_IS_DEBUG - whether the Python interpreter is a debug build 14 | # 15 | # Thanks to talljimbo for the patch adding the 'LDVERSION' config 16 | # variable usage. 17 | 18 | #============================================================================= 19 | # Copyright 2001-2009 Kitware, Inc. 20 | # Copyright 2012 Continuum Analytics, Inc. 21 | # 22 | # All rights reserved. 23 | # 24 | # Redistribution and use in source and binary forms, with or without 25 | # modification, are permitted provided that the following conditions 26 | # are met: 27 | # 28 | # * Redistributions of source code must retain the above copyright 29 | # notice, this list of conditions and the following disclaimer. 30 | # 31 | # * Redistributions in binary form must reproduce the above copyright 32 | # notice, this list of conditions and the following disclaimer in the 33 | # documentation and/or other materials provided with the distribution. 34 | # 35 | # * Neither the names of Kitware, Inc., the Insight Software Consortium, 36 | # nor the names of their contributors may be used to endorse or promote 37 | # products derived from this software without specific prior written 38 | # permission. 39 | # 40 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 | # # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 | # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 | #============================================================================= 52 | 53 | # Checking for the extension makes sure that `LibsNew` was found and not just `Libs`. 54 | if(PYTHONLIBS_FOUND AND PYTHON_MODULE_EXTENSION) 55 | return() 56 | endif() 57 | 58 | # Use the Python interpreter to find the libs. 59 | if(PythonLibsNew_FIND_REQUIRED) 60 | find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} REQUIRED) 61 | else() 62 | find_package(PythonInterp ${PythonLibsNew_FIND_VERSION}) 63 | endif() 64 | 65 | if(NOT PYTHONINTERP_FOUND) 66 | set(PYTHONLIBS_FOUND FALSE) 67 | set(PythonLibsNew_FOUND FALSE) 68 | return() 69 | endif() 70 | 71 | # According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter 72 | # testing whether sys has the gettotalrefcount function is a reliable, cross-platform 73 | # way to detect a CPython debug interpreter. 74 | # 75 | # The library suffix is from the config var LDVERSION sometimes, otherwise 76 | # VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows. 77 | execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" 78 | "from distutils import sysconfig as s;import sys;import struct; 79 | print('.'.join(str(v) for v in sys.version_info)); 80 | print(sys.prefix); 81 | print(s.get_python_inc(plat_specific=True)); 82 | print(s.get_python_lib(plat_specific=True)); 83 | print(s.get_config_var('SO')); 84 | print(hasattr(sys, 'gettotalrefcount')+0); 85 | print(struct.calcsize('@P')); 86 | print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION')); 87 | print(s.get_config_var('LIBDIR') or ''); 88 | print(s.get_config_var('MULTIARCH') or ''); 89 | " 90 | RESULT_VARIABLE _PYTHON_SUCCESS 91 | OUTPUT_VARIABLE _PYTHON_VALUES 92 | ERROR_VARIABLE _PYTHON_ERROR_VALUE) 93 | 94 | if(NOT _PYTHON_SUCCESS MATCHES 0) 95 | if(PythonLibsNew_FIND_REQUIRED) 96 | message(FATAL_ERROR 97 | "Python config failure:\n${_PYTHON_ERROR_VALUE}") 98 | endif() 99 | set(PYTHONLIBS_FOUND FALSE) 100 | set(PythonLibsNew_FOUND FALSE) 101 | return() 102 | endif() 103 | 104 | # Convert the process output into a list 105 | if(WIN32) 106 | string(REGEX REPLACE "\\\\" "/" _PYTHON_VALUES ${_PYTHON_VALUES}) 107 | endif() 108 | string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES}) 109 | string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES}) 110 | list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST) 111 | list(GET _PYTHON_VALUES 1 PYTHON_PREFIX) 112 | list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR) 113 | list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES) 114 | list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION) 115 | list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG) 116 | list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P) 117 | list(GET _PYTHON_VALUES 7 PYTHON_LIBRARY_SUFFIX) 118 | list(GET _PYTHON_VALUES 8 PYTHON_LIBDIR) 119 | list(GET _PYTHON_VALUES 9 PYTHON_MULTIARCH) 120 | 121 | # Make sure the Python has the same pointer-size as the chosen compiler 122 | # Skip if CMAKE_SIZEOF_VOID_P is not defined 123 | if(CMAKE_SIZEOF_VOID_P AND (NOT "${PYTHON_SIZEOF_VOID_P}" STREQUAL "${CMAKE_SIZEOF_VOID_P}")) 124 | if(PythonLibsNew_FIND_REQUIRED) 125 | math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8") 126 | math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8") 127 | message(FATAL_ERROR 128 | "Python config failure: Python is ${_PYTHON_BITS}-bit, " 129 | "chosen compiler is ${_CMAKE_BITS}-bit") 130 | endif() 131 | set(PYTHONLIBS_FOUND FALSE) 132 | set(PythonLibsNew_FOUND FALSE) 133 | return() 134 | endif() 135 | 136 | # The built-in FindPython didn't always give the version numbers 137 | string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST}) 138 | list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR) 139 | list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR) 140 | list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH) 141 | 142 | # Make sure all directory separators are '/' 143 | string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX}) 144 | string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR}) 145 | string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES}) 146 | 147 | if(CMAKE_HOST_WIN32 AND NOT (MSYS OR MINGW)) 148 | set(PYTHON_LIBRARY 149 | "${PYTHON_PREFIX}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib") 150 | 151 | # when run in a venv, PYTHON_PREFIX points to it. But the libraries remain in the 152 | # original python installation. They may be found relative to PYTHON_INCLUDE_DIR. 153 | if(NOT EXISTS "${PYTHON_LIBRARY}") 154 | get_filename_component(_PYTHON_ROOT ${PYTHON_INCLUDE_DIR} DIRECTORY) 155 | set(PYTHON_LIBRARY 156 | "${_PYTHON_ROOT}/libs/Python${PYTHON_LIBRARY_SUFFIX}.lib") 157 | endif() 158 | 159 | # raise an error if the python libs are still not found. 160 | if(NOT EXISTS "${PYTHON_LIBRARY}") 161 | message(FATAL_ERROR "Python libraries not found") 162 | endif() 163 | 164 | else() 165 | if(PYTHON_MULTIARCH) 166 | set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}/${PYTHON_MULTIARCH}" "${PYTHON_LIBDIR}") 167 | else() 168 | set(_PYTHON_LIBS_SEARCH "${PYTHON_LIBDIR}") 169 | endif() 170 | #message(STATUS "Searching for Python libs in ${_PYTHON_LIBS_SEARCH}") 171 | # Probably this needs to be more involved. It would be nice if the config 172 | # information the python interpreter itself gave us were more complete. 173 | find_library(PYTHON_LIBRARY 174 | NAMES "python${PYTHON_LIBRARY_SUFFIX}" 175 | PATHS ${_PYTHON_LIBS_SEARCH} 176 | NO_DEFAULT_PATH) 177 | 178 | # If all else fails, just set the name/version and let the linker figure out the path. 179 | if(NOT PYTHON_LIBRARY) 180 | set(PYTHON_LIBRARY python${PYTHON_LIBRARY_SUFFIX}) 181 | endif() 182 | endif() 183 | 184 | MARK_AS_ADVANCED( 185 | PYTHON_LIBRARY 186 | PYTHON_INCLUDE_DIR 187 | ) 188 | 189 | # We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the 190 | # cache entries because they are meant to specify the location of a single 191 | # library. We now set the variables listed by the documentation for this 192 | # module. 193 | SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") 194 | SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") 195 | SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}") 196 | 197 | find_package_message(PYTHON 198 | "Found PythonLibs: ${PYTHON_LIBRARY}" 199 | "${PYTHON_EXECUTABLE}${PYTHON_VERSION}") 200 | 201 | set(PYTHONLIBS_FOUND TRUE) 202 | set(PythonLibsNew_FOUND TRUE) 203 | -------------------------------------------------------------------------------- /third-party/pybind11/tools/pybind11Config.cmake.in: -------------------------------------------------------------------------------- 1 | # pybind11Config.cmake 2 | # -------------------- 3 | # 4 | # PYBIND11 cmake module. 5 | # This module sets the following variables in your project:: 6 | # 7 | # pybind11_FOUND - true if pybind11 and all required components found on the system 8 | # pybind11_VERSION - pybind11 version in format Major.Minor.Release 9 | # pybind11_INCLUDE_DIRS - Directories where pybind11 and python headers are located. 10 | # pybind11_INCLUDE_DIR - Directory where pybind11 headers are located. 11 | # pybind11_DEFINITIONS - Definitions necessary to use pybind11, namely USING_pybind11. 12 | # pybind11_LIBRARIES - compile flags and python libraries (as needed) to link against. 13 | # pybind11_LIBRARY - empty. 14 | # CMAKE_MODULE_PATH - appends location of accompanying FindPythonLibsNew.cmake and 15 | # pybind11Tools.cmake modules. 16 | # 17 | # 18 | # Available components: None 19 | # 20 | # 21 | # Exported targets:: 22 | # 23 | # If pybind11 is found, this module defines the following :prop_tgt:`IMPORTED` 24 | # interface library targets:: 25 | # 26 | # pybind11::module - for extension modules 27 | # pybind11::embed - for embedding the Python interpreter 28 | # 29 | # Python headers, libraries (as needed by platform), and the C++ standard 30 | # are attached to the target. Set PythonLibsNew variables to influence 31 | # python detection and PYBIND11_CPP_STANDARD (-std=c++11 or -std=c++14) to 32 | # influence standard setting. :: 33 | # 34 | # find_package(pybind11 CONFIG REQUIRED) 35 | # message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}") 36 | # 37 | # # Create an extension module 38 | # add_library(mylib MODULE main.cpp) 39 | # target_link_libraries(mylib pybind11::module) 40 | # 41 | # # Or embed the Python interpreter into an executable 42 | # add_executable(myexe main.cpp) 43 | # target_link_libraries(myexe pybind11::embed) 44 | # 45 | # Suggested usage:: 46 | # 47 | # find_package with version info is not recommended except for release versions. :: 48 | # 49 | # find_package(pybind11 CONFIG) 50 | # find_package(pybind11 2.0 EXACT CONFIG REQUIRED) 51 | # 52 | # 53 | # The following variables can be set to guide the search for this package:: 54 | # 55 | # pybind11_DIR - CMake variable, set to directory containing this Config file 56 | # CMAKE_PREFIX_PATH - CMake variable, set to root directory of this package 57 | # PATH - environment variable, set to bin directory of this package 58 | # CMAKE_DISABLE_FIND_PACKAGE_pybind11 - CMake variable, disables 59 | # find_package(pybind11) when not REQUIRED, perhaps to force internal build 60 | 61 | @PACKAGE_INIT@ 62 | 63 | set(PN pybind11) 64 | 65 | # location of pybind11/pybind11.h 66 | set(${PN}_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@") 67 | 68 | set(${PN}_LIBRARY "") 69 | set(${PN}_DEFINITIONS USING_${PN}) 70 | 71 | check_required_components(${PN}) 72 | 73 | # make detectable the FindPythonLibsNew.cmake module 74 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) 75 | 76 | include(pybind11Tools) 77 | 78 | if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) 79 | #----------------------------------------------------------------------------- 80 | # Don't include targets if this file is being picked up by another 81 | # project which has already built this as a subproject 82 | #----------------------------------------------------------------------------- 83 | if(NOT TARGET ${PN}::pybind11) 84 | include("${CMAKE_CURRENT_LIST_DIR}/${PN}Targets.cmake") 85 | 86 | find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} MODULE REQUIRED) 87 | set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_DIRS}) 88 | set_property(TARGET ${PN}::embed APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIBRARIES}) 89 | if(WIN32 OR CYGWIN) 90 | set_property(TARGET ${PN}::module APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${PYTHON_LIBRARIES}) 91 | endif() 92 | 93 | if(CMAKE_VERSION VERSION_LESS 3.3) 94 | set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "${PYBIND11_CPP_STANDARD}") 95 | else() 96 | set_property(TARGET ${PN}::pybind11 APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $<$:${PYBIND11_CPP_STANDARD}>) 97 | endif() 98 | 99 | get_property(_iid TARGET ${PN}::pybind11 PROPERTY INTERFACE_INCLUDE_DIRECTORIES) 100 | get_property(_ill TARGET ${PN}::module PROPERTY INTERFACE_LINK_LIBRARIES) 101 | set(${PN}_INCLUDE_DIRS ${_iid}) 102 | set(${PN}_LIBRARIES ${_ico} ${_ill}) 103 | endif() 104 | endif() 105 | --------------------------------------------------------------------------------