├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── extern ├── gflags │ ├── .travis.yml │ ├── AUTHORS.txt │ ├── BUILD │ ├── CMakeLists.txt │ ├── COPYING.txt │ ├── ChangeLog.txt │ ├── INSTALL.md │ ├── README.md │ ├── WORKSPACE │ ├── appveyor.yml │ ├── bazel │ │ └── gflags.bzl │ ├── cmake │ │ ├── README_runtime.txt │ │ ├── cmake_uninstall.cmake.in │ │ ├── config.cmake.in │ │ ├── execute_test.cmake │ │ ├── package.cmake.in │ │ ├── package.pc.in │ │ ├── utils.cmake │ │ └── version.cmake.in │ ├── src │ │ ├── config.h.in │ │ ├── gflags.cc │ │ ├── gflags.h.in │ │ ├── gflags_completions.cc │ │ ├── gflags_completions.h.in │ │ ├── gflags_completions.sh │ │ ├── gflags_declare.h.in │ │ ├── gflags_ns.h.in │ │ ├── gflags_reporting.cc │ │ ├── mutex.h │ │ ├── util.h │ │ ├── windows_port.cc │ │ └── windows_port.h │ └── test │ │ ├── CMakeLists.txt │ │ ├── config │ │ ├── CMakeLists.txt │ │ └── main.cc │ │ ├── flagfile.1 │ │ ├── flagfile.2 │ │ ├── flagfile.3 │ │ ├── gflags_build.py.in │ │ ├── gflags_declare_flags.cc │ │ ├── gflags_declare_test.cc │ │ ├── gflags_strip_flags_test.cc │ │ ├── gflags_strip_flags_test.cmake │ │ ├── gflags_unittest.cc │ │ ├── gflags_unittest_flagfile │ │ └── nc │ │ ├── CMakeLists.txt │ │ └── gflags_nc.cc ├── hsvrgb.cpp └── tinyply.cpp ├── img └── PointCloudRegistrationTool_demo.gif ├── include ├── Registrator.hpp ├── Visualizer.hpp ├── hsvrgb.hpp ├── tiny_obj_loader.h ├── tinyply.h ├── types.hpp └── util.hpp └── src ├── Registrator.cpp ├── Visualizer.cpp ├── main.cpp └── util.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Cmake build files 35 | build/ 36 | bin/ 37 | 38 | # Mac System Files 39 | .DS_Store 40 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6 FATAL_ERROR) 2 | set(CMAKE_CXX_STANDARD 11) 3 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -O1") 4 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w -Ofast") 5 | 6 | project(Point_Cloud_Registration_Tool) 7 | 8 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 9 | set(HEADER_DIR ${PROJECT_SOURCE_DIR}/include) 10 | set(SOURCE_DIR ${PROJECT_SOURCE_DIR}/src) 11 | set(EXTERN_DIR ${PROJECT_SOURCE_DIR}/extern) 12 | set(SOURCE_FILES ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/util.cpp ${SOURCE_DIR}/Visualizer.cpp ${SOURCE_DIR}/Registrator.cpp ${EXTERN_DIR}/tinyply.cpp ${EXTERN_DIR}/hsvrgb.cpp) 13 | set(HEADER_FILES ${HEADER_DIR}/types.hpp ${HEADER_DIR}/util.hpp ${HEADER_DIR}/Visualizer.hpp ${HEADER_DIR}/Registrator.hpp ${HEADER_DIR}/tinyply.h ${HEADER_DIR}/tiny_obj_loader.h ${HEADER_DIR}/hsvrgb.hpp) 14 | option(WITH_OPENMP "WITH_OPENMP" ON) 15 | 16 | add_subdirectory(${EXTERN_DIR}/gflags) 17 | find_package(PCL 1.7 REQUIRED COMPONENTS common io kdtree features visualization recognition) 18 | 19 | if(WITH_OPENMP) 20 | find_package(OpenMP) 21 | 22 | if(OPENMP_FOUND) 23 | message("OpenMP found") 24 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 26 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") 27 | endif() 28 | 29 | endif() 30 | 31 | if(PCL_FOUND) 32 | message("PCL found") 33 | 34 | include_directories(${PCL_INCLUDE_DIRS}) 35 | include_directories(${HEADER_DIR}) 36 | 37 | add_definitions(${PCL_DEFINITIONS}) 38 | 39 | add_executable(point_cloud_registration_tool ${SOURCE_FILES} ${HEADER_FILES}) 40 | 41 | target_link_libraries(point_cloud_registration_tool gflags) 42 | target_link_libraries(point_cloud_registration_tool ${PCL_COMMON_LIBRARIES} 43 | ${PCL_IO_LIBRARIES} ${PCL_KDTREE_LIBRARIES} ${PCL_FEATURES_LIBRARIES} ${PCL_VISUALIZATION_LIBRARIES} ${PCL_RECOGNITION_LIBRARIES}) 44 | endif() 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2017, Dario Rethage 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Point Cloud Registration Tool 2 | ==== 3 | Automatically registers (aligns) and visualizes point clouds, or processes a whole bunch at once 4 | 5 | ### Main Features: 6 | * Coarse-to-fine registration (correspondence-based followed by ICP refinement) 7 | * PLY/OBJ input support 8 | * GUI 9 | * Batch processing 10 | * Parallelized 11 | * Outputs to disk: 12 | * Registered cloud with residual colormap 13 | * Transformation matrix 14 | * [F-score](https://en.wikipedia.org/wiki/F1_score) 15 | * Histogram of residuals (in GUI mode) 16 | 17 | ### Demo: 18 | ![Example Screenshot](img/PointCloudRegistrationTool_demo.gif) 19 | 20 | Each point is colored proportional to its distance to the closest point on the target cloud. 21 | 22 | Color range of the residual colormap: RED = 0cm, BLUE = maximum residual threshold (default: 10cm) 23 | 24 | Up/down arrow keys adjust the: maximum residual threshold. 25 | 26 | ### Install: 27 | 28 | #### Ubuntu 14.04: 29 | 30 | If you already have ROS installed: 31 | ``` 32 | sudo apt-get install libpcl-1.7-all-dev 33 | ``` 34 | 35 | Else: 36 | ``` 37 | sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl 38 | sudo apt-get update 39 | sudo apt-get install libpcl-all 40 | ``` 41 | 42 | #### Ubuntu 16.04: 43 | 44 | ``` 45 | sudo apt-get update 46 | sudo apt-get install libpcl-dev 47 | ``` 48 | 49 | #### MacOS: 50 | 51 | ``` 52 | brew install pcl 53 | ``` 54 | 55 | ###### More info at: [Install PCL on MacOS via Homebrew](http://www.pointclouds.org/documentation/tutorials/installing_homebrew.php) 56 | 57 | ### Build: 58 | 59 | ``` 60 | mkdir build && cd build 61 | cmake -DCMAKE_BUILD_TYPE=Release .. 62 | make 63 | ``` 64 | 65 | In MacOS, you may need to use a different compiler than the one shipped with Xcode to build with openMP, 66 | 67 | to compile without openMP parallelization add: `-DWITH_OPENMP=OFF` 68 | 69 | ### Example Usage: 70 | 71 | The **source** cloud is the one we want to register to the **target** cloud 72 | 73 | `./point_cloud_registration_tool --verbose --gui source_cloud.ply target_cloud.ply` 74 | 75 | ##### Some Flags: 76 | * --verbose, print information along the way 77 | * --gui, show the GUI 78 | * --batch_file, path to a text file containing paths to point cloud pairs 79 | 80 | ##### Batch File Format: 81 | ``` 82 | source_cloud_1.ply,target_cloud_1.ply 83 | source_cloud_2.obj,target_cloud_2.obj 84 | source_cloud_3.ply,target_cloud_3.obj 85 | ``` 86 | 87 | you can adjust many parameters of the registration routine, just ask `--help` 88 | 89 | ### Tested on: 90 | * Ubuntu (PCL 1.7) 91 | * MacOS (PCL 1.8) 92 | 93 | ###### Minimum PCL 1.7 required 94 | 95 | ### License 96 | 97 | [BSD 2-Clause License](LICENSE) -------------------------------------------------------------------------------- /extern/gflags/.travis.yml: -------------------------------------------------------------------------------- 1 | # Ubuntu 14.04 Trusty support, to get newer cmake and compilers. 2 | sudo: required 3 | dist: trusty 4 | 5 | language: cpp 6 | 7 | os: 8 | - linux 9 | - osx 10 | 11 | compiler: 12 | - clang 13 | - gcc 14 | 15 | env: 16 | - CONFIG=Release 17 | - CONFIG=Debug 18 | 19 | script: 20 | - mkdir out && cd out && cmake -D CMAKE_BUILD_TYPE=$CONFIG -D GFLAGS_BUILD_SHARED_LIBS=ON -D GFLAGS_BUILD_STATIC_LIBS=ON -D GFLAGS_BUILD_TESTING=ON .. && cmake --build . --config $CONFIG && ctest 21 | -------------------------------------------------------------------------------- /extern/gflags/AUTHORS.txt: -------------------------------------------------------------------------------- 1 | google-gflags@googlegroups.com 2 | 3 | -------------------------------------------------------------------------------- /extern/gflags/BUILD: -------------------------------------------------------------------------------- 1 | # Bazel (http://bazel.io/) BUILD file for gflags. 2 | # 3 | # See INSTALL.md for instructions for adding gflags to a Bazel workspace. 4 | 5 | licenses(["notice"]) 6 | 7 | exports_files(["src/gflags_complections.sh", "COPYING.txt"]) 8 | 9 | load(":bazel/gflags.bzl", "gflags_sources", "gflags_library") 10 | (hdrs, srcs) = gflags_sources(namespace=["gflags", "google"]) 11 | gflags_library(hdrs=hdrs, srcs=srcs, threads=0) 12 | gflags_library(hdrs=hdrs, srcs=srcs, threads=1) 13 | -------------------------------------------------------------------------------- /extern/gflags/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /extern/gflags/ChangeLog.txt: -------------------------------------------------------------------------------- 1 | * Tue Jul 11 2017 - Andreas Schuh 2 | 3 | - gflags: version 2.2.1 4 | - Link to online documentation in README 5 | - Merged 194: Include utils by file instead of CMAKE_MODULE_PATH search 6 | - Merged 195: Remove unused program_name variable 7 | - Merged 196: Enable language C for older CMake versions when needed 8 | - Merged 202: Changed include directory in bazel build 9 | - Merged 207: Mark single argument constructors in mutex.h as explicit 10 | - Merged 209: Use inttypes.h on VC++ 2013 and later 11 | - Merged 212: Fix statically linked gflags library with MSVC 12 | - Meregd 213: Modify installation paths on Windows for vcpkg 13 | - Merged 215: Fix static initialization order fiasco caused by global registry lock 14 | - Merged 216: Fix use of ARGC in CMake macros 15 | - Merged 222: Static code analyzer error regarding strncmp with empty kRootDir 16 | - Merged 224: Check HAVE_STDINT_H or HAVE_INTTYPES_H for older MSVC versions 17 | 18 | * Fri Nov 25 2016 - Andreas Schuh 19 | 20 | - gflags: version 2.2.0 21 | - Merged 178: Implicitly convert dashes in option names to underscores 22 | - Merged 159: CI builds and automatic tests with Travis CI and AppVeyor 23 | - Merged 158: Use enum for flag value types 24 | - Merged 126: File name postfix for static libraries on Windows 25 | - Closed issue 120: Configure and install gflags.pc file for pkg-config users 26 | - Fixed issue 127: snprintf already defined when building with MSVC 2015 27 | - Fixed issue 51/138: Memory leaks reported by valgrind 28 | - Fixed issue 173: Validate flags only once 29 | - Fixed issue 168: Unsigned and signed comparison in gflags_reporting.cc 30 | - Fixed issues 176/153: Add -lpthread link argument to Bazel build, refactor BUILD rules 31 | - Fixed issue 89: Add GFLAGS_IS_A_DLL to imported CMake target INTERFACE_COMPILE_DEFINITIONS 32 | - Fixed issue 104: Set INTERFACE_INCLUDE_DIRECTORIES of exported CMake targets 33 | - Fixed issue 174: Missing gflags-targets.cmake file after installation 34 | - Fixed issue 186: Error linking to gflags IMPLIB with MSVC using CMake 35 | - Closed issue 106: Add example project to test use of gflags library 36 | 37 | * Tue Mar 24 2014 - Andreas Schuh 38 | 39 | - gflags: version 2.1.2 40 | - Moved project to GitHub 41 | - Added GFLAGS_NAMESPACE definition to gflags_declare.h 42 | - Fixed issue 94: Keep "google" as primary namespace and import symbols into "gflags" namespace 43 | - Fixed issue 96: Fix binary ABI compatibility with gflags 2.0 using "google" as primary namespace 44 | - Fixed issue 97/101: Removed (patched) CMake modules and enabled C language instead 45 | - Fixed issue 103: Set CMake policy CMP0042 to silence warning regarding MACOS_RPATH setting 46 | 47 | * Sun Mar 20 2014 - Andreas Schuh 48 | 49 | - gflags: version 2.1.1 50 | - Fixed issue 77: GFLAGS_IS_A_DLL expands to empty string in gflags_declare.h 51 | - Fixed issue 79: GFLAGS_NAMESPACE not expanded to actual namespace in gflags_declare.h 52 | - Fixed issue 80: Allow include path to differ from GFLAGS_NAMESPACE 53 | 54 | * Thu Mar 20 2014 - Andreas Schuh 55 | 56 | - gflags: version 2.1.0 57 | - Build system configuration using CMake instead of autotools 58 | - CPack packaging support for Debian/Ubuntu, Red Hat, and Mac OS X 59 | - Fixed issue 54: Fix "invalid suffix on literal" (C++11) 60 | - Fixed issue 57: Use _strdup instead of strdup on Windows 61 | - Fixed issue 62: Change all preprocessor include guards to start with GFLAGS_ 62 | - Fixed issue 64: Add DEFINE_validator macro 63 | - Fixed issue 73: Warnings in Visual Studio 2010 and unable to compile unit test 64 | 65 | * Wed Jan 25 2012 - Google Inc. 66 | 67 | - gflags: version 2.0 68 | - Changed the 'official' gflags email in setup.py/etc 69 | - Renamed google-gflags.sln to gflags.sln 70 | - Changed copyright text to reflect Google's relinquished ownership 71 | 72 | * Tue Dec 20 2011 - Google Inc. 73 | 74 | - google-gflags: version 1.7 75 | - Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji) 76 | - PORTING: flush after writing to stderr, needed on cygwin 77 | - PORTING: Clean up the GFLAGS_DLL_DECL stuff better 78 | - Fix a bug in StringPrintf() that affected large strings (csilvers) 79 | - Die at configure-time when g++ isn't installed 80 | 81 | * Fri Jul 29 2011 - Google Inc. 82 | 83 | - google-gflags: version 1.6 84 | - BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir) 85 | - Fix definition of clstring (jyrki) 86 | - Split up flag declares into its own file (jyrki) 87 | - Add --version support (csilvers) 88 | - Update the README for gflags with static libs 89 | - Update acx_pthread.m4 for nostdlib 90 | - Change ReparseCommandLineFlags to return void (csilvers) 91 | - Some doc typofixes and example augmentation (various) 92 | 93 | * Mon Jan 24 2011 - Google Inc. 94 | 95 | - google-gflags: version 1.5 96 | - Better reporting of current vs default value (handler) 97 | - Add API for cleaning up of memory at program-exit (jmarantz) 98 | - Fix macros to work inside namespaces (csilvers) 99 | - Use our own string typedef in case string is redefined (csilvers) 100 | - Updated to autoconf 2.65 101 | 102 | * Wed Oct 13 2010 - Google Inc. 103 | 104 | - google-gflags: version 1.4 105 | - Add a check to prevent passing 0 to DEFINE_string (jorg) 106 | - Reduce compile (.o) size (jyrki) 107 | - Some small changes to quiet debug compiles (alexk) 108 | - PORTING: better support static linking on windows (csilvers) 109 | - DOCUMENTATION: change default values, use validators, etc. 110 | - Update the NEWS file to be non-empty 111 | - Add pkg-config (.pc) files for libgflags and libgflags_nothreads 112 | 113 | * Mon Jan 4 2010 - Google Inc. 114 | 115 | - google-gflags: version 1.3 116 | - PORTABILITY: can now build and run tests under MSVC (csilvers) 117 | - Remove the python gflags code, which is now its own package (tansell) 118 | - Clarify that "last flag wins" in the docs (csilvers) 119 | - Comment danger of using GetAllFlags in validators (wojtekm) 120 | - PORTABILITY: Some fixes necessary for c++0x (mboerger) 121 | - Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres) 122 | - INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers) 123 | 124 | * Thu Sep 10 2009 - Google Inc. 125 | 126 | - google-gflags: version 1.2 127 | - PORTABILITY: can now build and run tests under mingw (csilvers) 128 | - Using a string arg for a bool flag is a compile-time error (rbayardo) 129 | - Add --helpxml to gflags.py (salcianu) 130 | - Protect against a hypothetical global d'tor mutex problem (csilvers) 131 | - BUGFIX: can now define a flag after 'using namespace google' (hamaji) 132 | 133 | * Tue Apr 14 2009 - Google Inc. 134 | 135 | - google-gflags: version 1.1 136 | - Add both foo and nofoo for boolean flags, with --undefok (andychu) 137 | - Better document how validators work (wojtekm) 138 | - Improve binary-detection for bash-completion (mtamsky) 139 | - Python: Add a concept of "key flags", used with --help (salcianu) 140 | - Python: Robustify flag_values (salcianu) 141 | - Python: Add a new DEFINE_bool alias (keir, andrewliu) 142 | - Python: Do module introspection based on module name (dsturtevant) 143 | - Fix autoconf a bit better, especially on windows and solaris (ajenjo) 144 | - BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo) 145 | - BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo) 146 | - PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers) 147 | - PORTABILITY: Update deb.sh for more recenty debuilds (csilvers) 148 | - PORTABILITY: #include more headers to satify new gcc's (csilvers) 149 | - INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers) 150 | 151 | * Fri Oct 3 2008 - Google Inc. 152 | 153 | - google-gflags: version 1.0 154 | - Add a missing newline to an error string (bcmills) 155 | - (otherwise exactly the same as gflags 1.0rc2) 156 | 157 | * Thu Sep 18 2008 - Google Inc. 158 | 159 | - google-gflags: version 1.0rc2 160 | - Report current flag values in --helpxml (hdn) 161 | - Fix compilation troubles with gcc 4.3.3 (simonb) 162 | - BUG FIX: I was missing a std:: in DECLARE_string (csilvers) 163 | - BUG FIX: Clarify in docs how to specify --bool flags (csilvers) 164 | - BUG FIX: Fix --helpshort for source files not in a subdir (csilvers) 165 | - BUG FIX: Fix python unittest for 64-bit builds (bcmills) 166 | 167 | * Tue Aug 19 2008 - Google Inc. 168 | 169 | - google-gflags: version 1.0rc1 170 | - Move #include files from google/ to gflags/ (csilvers) 171 | - Small optimizations to reduce binary (library) size (jyrki) 172 | - BUGFIX: forgot a std:: in one of the .h files (csilvers) 173 | - Speed up locking by making sure calls are inlined (ajenjo) 174 | - 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers) 175 | - PORTABILITY: fix Makefile to work with Cygwin (ajenjo) 176 | - PORTABILITY: fix code to compile under Visual Studio (ajenjo) 177 | - PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers) 178 | 179 | * Mon Jul 21 2008 - Google Inc. 180 | 181 | - google-gflags: version 0.9 182 | - Add the ability to validate a command-line flag (csilvers) 183 | - Add completion support for commandline flags in bash (daven) 184 | - Add -W compile flags to Makefile, when using gcc (csilvers) 185 | - Allow helpstring to be NULL (cristianoc) 186 | - Improved documentation of classes in the .cc file (csilvers) 187 | - Fix python bug with AppendFlagValues + shortnames (jjtswan) 188 | - Use bool instead of int for boolean flags in gflags.py (bcmills) 189 | - Simplify the way we declare flags, now more foolproof (csilvers) 190 | - Better error messages when bool flags collide (colohan) 191 | - Only evaluate DEFINE_foo macro args once (csilvers) 192 | 193 | * Wed Mar 26 2008 - Google Inc. 194 | 195 | - google-gflags: version 0.8 196 | - Export DescribeOneFlag() in the API 197 | - Add support for automatic line wrapping at 80 cols for gflags.py 198 | - Bugfix: do not treat an isolated "-" the same as an isolated "--" 199 | - Update rpm spec to point to Google Code rather than sourceforge (!) 200 | - Improve documentation (including documenting thread-safety) 201 | - Improve #include hygiene 202 | - Improve testing 203 | 204 | * Thu Oct 18 2007 - Google Inc. 205 | 206 | - google-gflags: version 0.7 207 | - Deal even more correctly with libpthread not linked in (csilvers) 208 | - Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe) 209 | - Be more accurate printing default flag values in --help (dsturtevant) 210 | - Reduce .o file size a bit by using shorter namespace names (jeff) 211 | - Use relative install path, so 'setup.py --home' works (csilvers) 212 | - Notice when a boolean flag has a non-boolean default (bnmouli) 213 | - Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie) 214 | - Fix "no modules match" message for --helpshort, etc (hendrie) 215 | 216 | * Wed Aug 15 2007 - Google Inc. 217 | 218 | - google-gflags: version 0.6 219 | - Deal correctly with case that libpthread is not linked in (csilvers) 220 | - Update Makefile/tests so we pass "make distcheck" (csilvers) 221 | - Document and test that last assignment to a flag wins (wan) 222 | 223 | * Tue Jun 12 2007 - Google Inc. 224 | 225 | - google-gflags: version 0.5 226 | - Include all m4 macros in the distribution (csilvers) 227 | - Python: Fix broken data_files field in setup.py (sidlon) 228 | - Python: better string serliaizing and unparsing (abo, csimmons) 229 | - Fix checks for NaN and inf to work with Mac OS X (csilvers) 230 | 231 | * Thu Apr 19 2007 - Google Inc. 232 | 233 | - google-gflags: version 0.4 234 | - Remove is_default from GetCommandLineFlagInfo (csilvers) 235 | - Portability fixes: includes, strtoll, gcc4.3 errors (csilvers) 236 | - A few doc typo cleanups (csilvers) 237 | 238 | * Wed Mar 28 2007 - Google Inc. 239 | 240 | - google-gflags: version 0.3 241 | - python portability fix: use popen instead of subprocess (csilvers) 242 | - Add is_default to CommandLineFlagInfo (pchien) 243 | - Make docs a bit prettier (csilvers) 244 | - Actually include the python files in the distribution! :-/ (csilvers) 245 | 246 | * Mon Jan 22 2007 - Google Inc. 247 | 248 | - google-gflags: version 0.2 249 | - added support for python commandlineflags, as well as c++ 250 | - gflags2man, a script to turn flags into a man page (dchristian) 251 | 252 | * Wed Dec 13 2006 - Google Inc. 253 | 254 | - google-gflags: version 0.1 255 | -------------------------------------------------------------------------------- /extern/gflags/INSTALL.md: -------------------------------------------------------------------------------- 1 | Installing a binary distribution package 2 | ======================================== 3 | 4 | No official binary distribution packages are provided by the gflags developers. 5 | There may, however, be binary packages available for your OS. Please consult 6 | also the package repositories of your Linux distribution. 7 | 8 | For example on Debian/Ubuntu Linux, gflags can be installed using the 9 | following command: 10 | 11 | sudo apt-get install libgflags-dev 12 | 13 | 14 | Compiling the source code with CMake 15 | ========================= 16 | 17 | The build system of gflags is since version 2.1 based on [CMake](http://cmake.org). 18 | The common steps to build, test, and install software are therefore: 19 | 20 | 1. Extract source files. 21 | 2. Create build directory and change to it. 22 | 3. Run CMake to configure the build tree. 23 | 4. Build the software using selected build tool. 24 | 5. Test the built software. 25 | 6. Install the built files. 26 | 27 | On Unix-like systems with GNU Make as build tool, these build steps can be 28 | summarized by the following sequence of commands executed in a shell, 29 | where ```$package``` and ```$version``` are shell variables which represent 30 | the name of this package and the obtained version of the software. 31 | 32 | $ tar xzf gflags-$version-source.tar.gz 33 | $ cd gflags-$version 34 | $ mkdir build && cd build 35 | $ ccmake .. 36 | 37 | - Press 'c' to configure the build system and 'e' to ignore warnings. 38 | - Set CMAKE_INSTALL_PREFIX and other CMake variables and options. 39 | - Continue pressing 'c' until the option 'g' is available. 40 | - Then press 'g' to generate the configuration files for GNU Make. 41 | 42 | $ make 43 | $ make test (optional) 44 | $ make install (optional) 45 | 46 | In the following, only gflags-specific CMake settings available to 47 | configure the build and installation are documented. Note that most of these 48 | variables are for advanced users and binary package maintainers only. 49 | They usually do not have to be modified. 50 | 51 | 52 | CMake Option | Description 53 | --------------------------- | ------------------------------------------------------- 54 | CMAKE_INSTALL_PREFIX | Installation directory, e.g., "/usr/local" on Unix and "C:\Program Files\gflags" on Windows. 55 | BUILD_SHARED_LIBS | Request build of dynamic link libraries. 56 | BUILD_STATIC_LIBS | Request build of static link libraries. Implied if BUILD_SHARED_LIBS is OFF. 57 | BUILD_PACKAGING | Enable binary package generation using CPack. 58 | BUILD_TESTING | Build tests for execution by CTest. 59 | BUILD_NC_TESTS | Request inclusion of negative compilation tests (requires Python). 60 | BUILD_CONFIG_TESTS | Request inclusion of package configuration tests (requires Python). 61 | BUILD_gflags_LIBS | Request build of multi-threaded gflags libraries (if threading library found). 62 | BUILD_gflags_nothreads_LIBS | Request build of single-threaded gflags libraries. 63 | GFLAGS_NAMESPACE | Name of the C++ namespace to be used by the gflags library. Note that the public source header files are installed in a subdirectory named after this namespace. To maintain backwards compatibility with the Google Commandline Flags, set this variable to "google". The default is "gflags". 64 | GFLAGS_INTTYPES_FORMAT | String identifying format of built-in integer types. 65 | GFLAGS_INCLUDE_DIR | Name of headers installation directory relative to CMAKE_INSTALL_PREFIX. 66 | LIBRARY_INSTALL_DIR | Name of library installation directory relative to CMAKE_INSTALL_PREFIX. 67 | INSTALL_HEADERS | Request installation of public header files. 68 | 69 | Using gflags with [Bazel](http://bazel.io) 70 | ========================= 71 | 72 | To use gflags in a Bazel project, map it in as an external dependency by editing 73 | your WORKSPACE file: 74 | 75 | git_repository( 76 | name = "com_github_gflags_gflags", 77 | commit = "", 78 | remote = "https://github.com/gflags/gflags.git", 79 | ) 80 | 81 | bind( 82 | name = "gflags", 83 | actual = "@com_github_gflags_gflags//:gflags", 84 | ) 85 | 86 | You can then add `//external:gflags` to the `deps` section of a `cc_binary` or 87 | `cc_library` rule, and `#include ` to include it in your source 88 | code. 89 | -------------------------------------------------------------------------------- /extern/gflags/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/gflags/gflags.svg?branch=master)](https://travis-ci.org/gflags/gflags) 2 | [![Build status](https://ci.appveyor.com/api/projects/status/4ctod566ysraus74/branch/master?svg=true)](https://ci.appveyor.com/project/schuhschuh/gflags/branch/master) 3 | 4 | The documentation of the gflags library is available online at https://gflags.github.io/gflags/. 5 | 6 | 11 July 2017 7 | ------------ 8 | 9 | I've just released gflags 2.2.1. 10 | 11 | This maintenance release primarily fixes build issues on Windows and 12 | false alarms reported by static code analyzers. 13 | 14 | Please report any further issues with this release using the GitHub issue tracker. 15 | 16 | 17 | 25 November 2016 18 | ---------------- 19 | 20 | I've finally released gflags 2.2.0. 21 | 22 | This release adds support for use of the gflags library as external dependency 23 | not only in projects using CMake, but also [Bazel](https://bazel.build/), 24 | or [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/). 25 | One new minor feature is added in this release: when a command flag argument 26 | contains dashes, these are implicitly converted to underscores. 27 | This is to allow those used to separate words of the flag name by dashes 28 | to do so, while the flag variable names are required to use underscores. 29 | 30 | Memory leaks reported by valgrind should be resolved by this release. 31 | This release fixes build errors with MS Visual Studio 2015. 32 | 33 | Please report any further issues with this release using the GitHub issue tracker. 34 | 35 | 36 | 24 March 2015 37 | ------------- 38 | 39 | I've just released gflags 2.1.2. 40 | 41 | This release completes the namespace change fixes. In particular, 42 | it restores binary ABI compatibility with release version 2.0. 43 | The deprecated "google" namespace is by default still kept as 44 | primary namespace while symbols are imported into the new "gflags" namespace. 45 | This can be overridden using the CMake variable GFLAGS_NAMESPACE. 46 | 47 | Other fixes of the build configuration are related to the (patched) 48 | CMake modules FindThreads.cmake and CheckTypeSize.cmake. These have 49 | been removed and instead the C language is enabled again even though 50 | gflags is written in C++ only. 51 | 52 | This release also marks the complete move of the gflags project 53 | from Google Code to GitHub. Email addresses of original issue 54 | reporters got lost in the process. Given the age of most issue reports, 55 | this should be negligable. 56 | 57 | Please report any further issues using the GitHub issue tracker. 58 | 59 | 60 | 30 March 2014 61 | ------------- 62 | 63 | I've just released gflags 2.1.1. 64 | 65 | This release fixes a few bugs in the configuration of gflags\_declare.h 66 | and adds a separate GFLAGS\_INCLUDE\_DIR CMake variable to the build configuration. 67 | Setting GFLAGS\_NAMESPACE to "google" no longer changes also the include 68 | path of the public header files. This allows the use of the library with 69 | other Google projects such as glog which still use the deprecated "google" 70 | namespace for the gflags library, but include it as "gflags/gflags.h". 71 | 72 | 20 March 2014 73 | ------------- 74 | 75 | I've just released gflags 2.1. 76 | 77 | The major changes are the use of CMake for the build configuration instead 78 | of the autotools and packaging support through CPack. The default namespace 79 | of all C++ symbols is now "gflags" instead of "google". This can be 80 | configured via the GFLAGS\_NAMESPACE variable. 81 | 82 | This release compiles with all major compilers without warnings and passed 83 | the unit tests on Ubuntu 12.04, Windows 7 (Visual Studio 2008 and 2010, 84 | Cygwin, MinGW), and Mac OS X (Xcode 5.1). 85 | 86 | The SVN repository on Google Code is now frozen and replaced by a Git 87 | repository such that it can be used as Git submodule by projects. The main 88 | hosting of this project remains at Google Code. Thanks to the distributed 89 | character of Git, I can push (and pull) changes from both GitHub and Google Code 90 | in order to keep the two public repositories in sync. 91 | When fixing an issue for a pull request through either of these hosting 92 | platforms, please reference the issue number as 93 | [described here](https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control). 94 | For the further development, I am following the 95 | [Git branching model](http://nvie.com/posts/a-successful-git-branching-model/) 96 | with feature branch names prefixed by "feature/" and bugfix branch names 97 | prefixed by "bugfix/", respectively. 98 | 99 | Binary and source [packages](https://github.com/schuhschuh/gflags/releases) are available on GitHub. 100 | 101 | 102 | 14 January 2014 103 | --------------- 104 | 105 | The migration of the build system to CMake is almost complete. 106 | What remains to be done is rewriting the tests in Python such they can be 107 | executed on non-Unix platforms and splitting them up into separate CTest tests. 108 | Though merging these changes into the master branch yet remains to be done, 109 | it is recommended to already start using the 110 | [cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) branch. 111 | 112 | 113 | 20 April 2013 114 | ------------- 115 | 116 | More than a year has past since I (Andreas) took over the maintenance for 117 | `gflags`. Only few minor changes have been made since then, much to my regret. 118 | To get more involved and stimulate participation in the further 119 | development of the library, I moved the project source code today to 120 | [GitHub](https://github.com/schuhschuh/gflags). 121 | I believe that the strengths of [Git](http://git-scm.com/) will allow for better community collaboration 122 | as well as ease the integration of changes made by others. I encourage everyone 123 | who would like to contribute to send me pull requests. 124 | Git's lightweight feature branches will also provide the right tool for more 125 | radical changes which should only be merged back into the master branch 126 | after these are complete and implement the desired behavior. 127 | 128 | The SVN repository remains accessible at Google Code and I will keep the 129 | master branch of the Git repository hosted at GitHub and the trunk of the 130 | Subversion repository synchronized. Initially, I was going to simply switch the 131 | Google Code project to Git, but in this case the SVN repository would be 132 | frozen and force everyone who would like the latest development changes to 133 | use Git as well. Therefore I decided to host the public Git repository at GitHub 134 | instead. 135 | 136 | Please continue to report any issues with gflags on Google Code. The GitHub project will 137 | only be used to host the Git repository. 138 | 139 | One major change of the project structure I have in mind for the next weeks 140 | is the migration from autotools to [CMake](http://www.cmake.org/). 141 | Check out the (unstable!) 142 | [cmake-migration](https://github.com/schuhschuh/gflags/tree/cmake-migration) 143 | branch on GitHub for details. 144 | 145 | 146 | 25 January 2012 147 | --------------- 148 | 149 | I've just released gflags 2.0. 150 | 151 | The `google-gflags` project has been renamed to `gflags`. I 152 | (csilvers) am stepping down as maintainer, to be replaced by Andreas 153 | Schuh. Welcome to the team, Andreas! I've seen the energy you have 154 | around gflags and the ideas you have for the project going forward, 155 | and look forward to having you on the team. 156 | 157 | I bumped the major version number up to 2 to reflect the new community 158 | ownership of the project. All the [changes](ChangeLog.txt) 159 | are related to the renaming. There are no functional changes from 160 | gflags 1.7. In particular, I've kept the code in the namespace 161 | `google`, though in a future version it should be renamed to `gflags`. 162 | I've also kept the `/usr/local/include/google/` subdirectory as 163 | synonym of `/usr/local/include/gflags/`, though the former name has 164 | been obsolete for some time now. 165 | 166 | 167 | 18 January 2011 168 | --------------- 169 | 170 | The `google-gflags` Google Code page has been renamed to 171 | `gflags`, in preparation for the project being renamed to 172 | `gflags`. In the coming weeks, I'll be stepping down as 173 | maintainer for the gflags project, and as part of that Google is 174 | relinquishing ownership of the project; it will now be entirely 175 | community run. The name change reflects that shift. 176 | 177 | 178 | 20 December 2011 179 | ---------------- 180 | 181 | I've just released gflags 1.7. This is a minor release; the major 182 | change is that `CommandLineFlagInfo` now exports the address in memory 183 | where the flag is located. There has also been a bugfix involving 184 | very long --help strings, and some other minor [changes](ChangeLog.txt). 185 | 186 | 29 July 2011 187 | ------------ 188 | 189 | I've just released gflags 1.6. The major new feature in this release 190 | is support for setting version info, so that --version does something 191 | useful. 192 | 193 | One minor change has required bumping the library number: 194 | `ReparseCommandlineFlags` now returns `void` instead of `int` (the int 195 | return value was always meaningless). Though I doubt anyone ever used 196 | this (meaningless) return value, technically it's a change to the ABI 197 | that requires a version bump. A bit sad. 198 | 199 | There's also a procedural change with this release: I've changed the 200 | internal tools used to integrate Google-supplied patches for gflags 201 | into the opensource release. These new tools should result in more 202 | frequent updates with better change descriptions. They will also 203 | result in future `ChangeLog` entries being much more verbose (for better 204 | or for worse). 205 | 206 | See the [ChangeLog](ChangeLog.txt) for a full list of changes for this release. 207 | 208 | 24 January 2011 209 | --------------- 210 | 211 | I've just released gflags 1.5. This release has only minor changes 212 | from 1.4, including some slightly better reporting in --help, and 213 | an new memory-cleanup function that can help when running gflags-using 214 | libraries under valgrind. The major change is to fix up the macros 215 | (`DEFINE_bool` and the like) to work more reliably inside namespaces. 216 | 217 | If you have not had a problem with these macros, and don't need any of 218 | the other changes described, there is no need to upgrade. See the 219 | [ChangeLog](ChangeLog.txt) for a full list of changes for this release. 220 | 221 | 11 October 2010 222 | --------------- 223 | 224 | I've just released gflags 1.4. This release has only minor changes 225 | from 1.3, including some documentation tweaks and some work to make 226 | the library smaller. If 1.3 is working well for you, there's no 227 | particular reason to upgrade. 228 | 229 | 4 January 2010 230 | -------------- 231 | 232 | I've just released gflags 1.3. gflags now compiles under MSVC, and 233 | all tests pass. I **really** never thought non-unix-y Windows folks 234 | would want gflags, but at least some of them do. 235 | 236 | The major news, though, is that I've separated out the python package 237 | into its own library, [python-gflags](http://code.google.com/p/python-gflags). 238 | If you're interested in the Python version of gflags, that's the place to 239 | get it now. 240 | 241 | 10 September 2009 242 | ----------------- 243 | 244 | I've just released gflags 1.2. The major change from gflags 1.1 is it 245 | now compiles under MinGW (as well as cygwin), and all tests pass. I 246 | never thought Windows folks would want unix-style command-line flags, 247 | since they're so different from the Windows style, but I guess I was 248 | wrong! 249 | 250 | The other changes are minor, such as support for --htmlxml in the 251 | python version of gflags. 252 | 253 | 15 April 2009 254 | ------------- 255 | 256 | I've just released gflags 1.1. It has only minor changes fdrom gflags 257 | 1.0 (see the [ChangeLog](ChangeLog.txt) for details). 258 | The major change is that I moved to a new system for creating .deb and .rpm files. 259 | This allows me to create x86\_64 deb and rpm files. 260 | 261 | In the process of moving to this new system, I noticed an 262 | inconsistency: the tar.gz and .rpm files created libraries named 263 | libgflags.so, but the deb file created libgoogle-gflags.so. I have 264 | fixed the deb file to create libraries like the others. I'm no expert 265 | in debian packaging, but I believe this has caused the package name to 266 | change as well. Please let me know (at 267 | [[mailto:google-gflags@googlegroups.com](mailto:google-gflags@googlegroups.com) 268 | google-gflags@googlegroups.com]) if this causes problems for you -- 269 | especially if you know of a fix! I would be happy to change the deb 270 | packages to add symlinks from the old library name to the new 271 | (libgoogle-gflags.so -> libgflags.so), but that is beyond my knowledge 272 | of how to make .debs. 273 | 274 | If you've tried to install a .rpm or .deb and it doesn't work for you, 275 | let me know. I'm excited to finally have 64-bit package files, but 276 | there may still be some wrinkles in the new system to iron out. 277 | 278 | 1 October 2008 279 | -------------- 280 | 281 | gflags 1.0rc2 was out for a few weeks without any issues, so gflags 282 | 1.0 is now released. This is much like gflags 0.9. The major change 283 | is that the .h files have been moved from `/usr/include/google` to 284 | `/usr/include/gflags`. While I have backwards-compatibility 285 | forwarding headeds in place, please rewrite existing code to say 286 | ``` 287 | #include 288 | ``` 289 | instead of 290 | ``` 291 | #include 292 | ``` 293 | 294 | I've kept the default namespace to google. You can still change with 295 | with the appropriate flag to the configure script (`./configure 296 | --help` to see the flags). If you have feedback as to whether the 297 | default namespace should change to gflags, which would be a 298 | non-backwards-compatible change, send mail to 299 | `google-gflags@googlegroups.com`! 300 | 301 | Version 1.0 also has some neat new features, like support for bash 302 | commandline-completion of help flags. See the [ChangeLog](ChangeLog.txt) 303 | for more details. 304 | 305 | If I don't hear any bad news for a few weeks, I'll release 1.0-final. 306 | -------------------------------------------------------------------------------- /extern/gflags/WORKSPACE: -------------------------------------------------------------------------------- 1 | # Copyright 2006 Google Inc. All Rights Reserved. 2 | # Use of this source code is governed by a BSD-style 3 | # license that can be found in the COPYING.txt file. 4 | 5 | # Bazel (http://bazel.io/) WORKSPACE file for gflags. 6 | workspace(name="com_github_gflags_gflags") 7 | -------------------------------------------------------------------------------- /extern/gflags/appveyor.yml: -------------------------------------------------------------------------------- 1 | # Configuration for continuous integration service at appveyor.com 2 | 3 | version: '{build}' 4 | 5 | os: Visual Studio 2015 6 | 7 | environment: 8 | matrix: 9 | - Toolset: v140 10 | - Toolset: v120 11 | - Toolset: v110 12 | - Toolset: v100 13 | - Toolset: v90 14 | 15 | platform: 16 | - Win32 17 | - x64 18 | 19 | configuration: 20 | - Release 21 | 22 | matrix: 23 | exclude: 24 | - Toolset: v90 25 | platform: x64 26 | - Toolset: v100 27 | platform: x64 28 | 29 | build: 30 | verbosity: minimal 31 | 32 | before_build: 33 | - ps: | 34 | Write-Output "Configuration: $env:CONFIGURATION" 35 | Write-Output "Platform: $env:PLATFORM" 36 | $generator = switch ($env:TOOLSET) 37 | { 38 | "v140" {"Visual Studio 14 2015"} 39 | "v120" {"Visual Studio 12 2013"} 40 | "v110" {"Visual Studio 11 2012"} 41 | "v100" {"Visual Studio 10 2010"} 42 | "v90" {"Visual Studio 9 2008"} 43 | } 44 | if ($env:PLATFORM -eq "x64") 45 | { 46 | $generator = "$generator Win64" 47 | } 48 | 49 | build_script: 50 | - ps: | 51 | md _build -Force | Out-Null 52 | cd _build 53 | 54 | & cmake -G "$generator" -D CMAKE_CONFIGURATION_TYPES="Debug;Release" -D GFLAGS_BUILD_TESTING=ON -D GFLAGS_BUILD_SHARED_LIBS=ON -D GFLAGS_BUILD_STATIC_LIBS=ON .. 55 | if ($LastExitCode -ne 0) { 56 | throw "Exec: $ErrorMessage" 57 | } 58 | & cmake --build . --config $env:CONFIGURATION 59 | if ($LastExitCode -ne 0) { 60 | throw "Exec: $ErrorMessage" 61 | } 62 | 63 | test_script: 64 | - ps: | 65 | & ctest -C $env:CONFIGURATION --output-on-failure 66 | if ($LastExitCode -ne 0) { 67 | throw "Exec: $ErrorMessage" 68 | } 69 | -------------------------------------------------------------------------------- /extern/gflags/bazel/gflags.bzl: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------ 2 | # Add native rules to configure source files 3 | def gflags_sources(namespace=["google", "gflags"]): 4 | native.genrule( 5 | name = "config_h", 6 | srcs = ["src/config.h.in"], 7 | outs = ["config.h"], 8 | cmd = "awk '{ gsub(/^#cmakedefine/, \"//cmakedefine\"); print; }' $(<) > $(@)" 9 | ) 10 | native.genrule( 11 | name = "gflags_declare_h", 12 | srcs = ["src/gflags_declare.h.in"], 13 | outs = ["include/gflags/gflags_declare.h"], 14 | cmd = ("awk '{ " + 15 | "gsub(/@GFLAGS_NAMESPACE@/, \"" + namespace[0] + "\"); " + 16 | "gsub(/@(HAVE_STDINT_H|HAVE_SYS_TYPES_H|HAVE_INTTYPES_H|GFLAGS_INTTYPES_FORMAT_C99)@/, \"1\"); " + 17 | "gsub(/@([A-Z0-9_]+)@/, \"0\"); " + 18 | "print; }' $(<) > $(@)") 19 | ) 20 | gflags_ns_h_files = [] 21 | for ns in namespace[1:]: 22 | gflags_ns_h_file = "gflags_{}.h".format(ns) 23 | native.genrule( 24 | name = gflags_ns_h_file.replace('.', '_'), 25 | srcs = ["src/gflags_ns.h.in"], 26 | outs = ["include/gflags/" + gflags_ns_h_file], 27 | cmd = ("awk '{ " + 28 | "gsub(/@ns@/, \"" + ns + "\"); " + 29 | "gsub(/@NS@/, \"" + ns.upper() + "\"); " + 30 | "print; }' $(<) > $(@)") 31 | ) 32 | gflags_ns_h_files.append(gflags_ns_h_file) 33 | native.genrule( 34 | name = "gflags_h", 35 | srcs = ["src/gflags.h.in"], 36 | outs = ["include/gflags/gflags.h"], 37 | cmd = ("awk '{ " + 38 | "gsub(/@GFLAGS_ATTRIBUTE_UNUSED@/, \"\"); " + 39 | "gsub(/@INCLUDE_GFLAGS_NS_H@/, \"" + '\n'.join(["#include \\\"gflags/{}\\\"".format(hdr) for hdr in gflags_ns_h_files]) + "\"); " + 40 | "print; }' $(<) > $(@)") 41 | ) 42 | native.genrule( 43 | name = "gflags_completions_h", 44 | srcs = ["src/gflags_completions.h.in"], 45 | outs = ["include/gflags/gflags_completions.h"], 46 | cmd = "awk '{ gsub(/@GFLAGS_NAMESPACE@/, \"" + namespace[0] + "\"); print; }' $(<) > $(@)" 47 | ) 48 | hdrs = [":gflags_h", ":gflags_declare_h", ":gflags_completions_h"] 49 | hdrs.extend([':' + hdr.replace('.', '_') for hdr in gflags_ns_h_files]) 50 | srcs = [ 51 | ":config_h", 52 | "src/gflags.cc", 53 | "src/gflags_completions.cc", 54 | "src/gflags_reporting.cc", 55 | "src/mutex.h", 56 | "src/util.h" 57 | ] 58 | return [hdrs, srcs] 59 | 60 | # ------------------------------------------------------------------------------ 61 | # Add native rule to build gflags library 62 | def gflags_library(hdrs=[], srcs=[], threads=1): 63 | name = "gflags" 64 | copts = [ 65 | "-DHAVE_STDINT_H", 66 | "-DHAVE_SYS_TYPES_H", 67 | "-DHAVE_INTTYPES_H", 68 | "-DHAVE_SYS_STAT_H", 69 | "-DHAVE_UNISTD_H", 70 | "-DHAVE_FNMATCH_H", 71 | "-DHAVE_STRTOLL", 72 | "-DHAVE_STRTOQ", 73 | "-DHAVE_PTHREAD", 74 | "-DHAVE_RWLOCK", 75 | "-DGFLAGS_INTTYPES_FORMAT_C99", 76 | "-DGFLAGS_IS_A_DLL=0", 77 | ] 78 | linkopts = [] 79 | if threads: 80 | linkopts.append("-lpthread") 81 | else: 82 | name += "_nothreads" 83 | copts.append("-DNO_THREADS") 84 | native.cc_library( 85 | name = name, 86 | hdrs = hdrs, 87 | srcs = srcs, 88 | includes = ["include/"], 89 | copts = copts, 90 | linkopts = linkopts, 91 | visibility = ["//visibility:public"] 92 | ) 93 | -------------------------------------------------------------------------------- /extern/gflags/cmake/README_runtime.txt: -------------------------------------------------------------------------------- 1 | This package contains runtime libraries only which are required 2 | by applications that use these libraries for the commandline flags 3 | processing. If you want to develop such application, download 4 | and install the development package instead. 5 | -------------------------------------------------------------------------------- /extern/gflags/cmake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | 5 | if (NOT DEFINED CMAKE_INSTALL_PREFIX) 6 | set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@") 7 | endif () 8 | message(${CMAKE_INSTALL_PREFIX}) 9 | 10 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 11 | string(REGEX REPLACE "\n" ";" files "${files}") 12 | foreach(file ${files}) 13 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 14 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 15 | exec_program( 16 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 17 | OUTPUT_VARIABLE rm_out 18 | RETURN_VALUE rm_retval 19 | ) 20 | if(NOT "${rm_retval}" STREQUAL 0) 21 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 22 | endif(NOT "${rm_retval}" STREQUAL 0) 23 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 24 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 25 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 26 | endforeach(file) 27 | -------------------------------------------------------------------------------- /extern/gflags/cmake/config.cmake.in: -------------------------------------------------------------------------------- 1 | ## gflags CMake configuration file 2 | 3 | # library version information 4 | set (@PACKAGE_PREFIX@_VERSION_STRING "@PACKAGE_VERSION@") 5 | set (@PACKAGE_PREFIX@_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@) 6 | set (@PACKAGE_PREFIX@_VERSION_MINOR @PACKAGE_VERSION_MINOR@) 7 | set (@PACKAGE_PREFIX@_VERSION_PATCH @PACKAGE_VERSION_PATCH@) 8 | 9 | # import targets 10 | include ("${CMAKE_CURRENT_LIST_DIR}/@EXPORT_NAME@.cmake") 11 | 12 | # installation prefix 13 | get_filename_component (CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 14 | get_filename_component (_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_PREFIX_REL2CONFIG_DIR@" ABSOLUTE) 15 | 16 | # include directory 17 | # 18 | # Newer versions of CMake set the INTERFACE_INCLUDE_DIRECTORIES property 19 | # of the imported targets. It is hence not necessary to add this path 20 | # manually to the include search path for targets which link to gflags. 21 | set (@PACKAGE_PREFIX@_INCLUDE_DIR "${_INSTALL_PREFIX}/@INCLUDE_INSTALL_DIR@") 22 | 23 | if (@PACKAGE_NAME@_FIND_COMPONENTS) 24 | foreach (@PACKAGE_NAME@_FIND_COMPONENT IN LISTS @PACKAGE_NAME@_FIND_COMPONENTS) 25 | if (@PACKAGE_NAME@_FIND_REQUIRED_${@PACKAGE_NAME@_FIND_COMPONENT} AND NOT TARGET @PACKAGE_NAME@_${@PACKAGE_NAME@_FIND_COMPONENT}) 26 | message (FATAL_ERROR "Package @PACKAGE_NAME@ was installed without required component ${@PACKAGE_NAME@_FIND_COMPONENT}!") 27 | endif () 28 | endforeach () 29 | list (GET @PACKAGE_NAME@_FIND_COMPONENTS 0 @PACKAGE_NAME@_FIND_COMPONENT) 30 | else () 31 | set (@PACKAGE_NAME@_FIND_COMPONENT) 32 | endif () 33 | 34 | # default settings of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS 35 | # 36 | # It is recommended to use either one of the following find_package commands 37 | # instead of setting the @PACKAGE_PREFIX@_(SHARED|NOTHREADS) variables: 38 | # - find_package(@PACKAGE_NAME@ REQUIRED) 39 | # - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_static) 40 | # - find_package(@PACKAGE_NAME@ COMPONENTS nothreads_shared) 41 | # - find_package(@PACKAGE_NAME@ COMPONENTS static) 42 | # - find_package(@PACKAGE_NAME@ COMPONENTS shared) 43 | if (NOT DEFINED @PACKAGE_PREFIX@_SHARED) 44 | if (DEFINED @PACKAGE_NAME@_SHARED) 45 | set (@PACKAGE_PREFIX@_SHARED ${@PACKAGE_NAME@_SHARED}) 46 | elseif (@PACKAGE_NAME@_FIND_COMPONENT) 47 | if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "shared") 48 | set (@PACKAGE_PREFIX@_SHARED TRUE) 49 | else () 50 | set (@PACKAGE_PREFIX@_SHARED FALSE) 51 | endif () 52 | elseif (TARGET @PACKAGE_NAME@_shared OR TARGET @PACKAGE_NAME@_nothreads_shared) 53 | set (@PACKAGE_PREFIX@_SHARED TRUE) 54 | else () 55 | set (@PACKAGE_PREFIX@_SHARED FALSE) 56 | endif () 57 | endif () 58 | if (NOT DEFINED @PACKAGE_PREFIX@_NOTHREADS) 59 | if (DEFINED @PACKAGE_NAME@_NOTHREADS) 60 | set (@PACKAGE_PREFIX@_NOTHREADS ${@PACKAGE_NAME@_NOTHREADS}) 61 | elseif (@PACKAGE_NAME@_FIND_COMPONENT) 62 | if (@PACKAGE_NAME@_FIND_COMPONENT MATCHES "nothreads") 63 | set (@PACKAGE_PREFIX@_NOTHREADS TRUE) 64 | else () 65 | set (@PACKAGE_PREFIX@_NOTHREADS FALSE) 66 | endif () 67 | elseif (TARGET @PACKAGE_NAME@_static OR TARGET @PACKAGE_NAME@_shared) 68 | set (@PACKAGE_PREFIX@_NOTHREADS FALSE) 69 | else () 70 | set (@PACKAGE_PREFIX@_NOTHREADS TRUE) 71 | endif () 72 | endif () 73 | 74 | # choose imported library target 75 | if (NOT @PACKAGE_PREFIX@_TARGET) 76 | if (@PACKAGE_NAME@_TARGET) 77 | set (@PACKAGE_PREFIX@_TARGET ${@PACKAGE_NAME@_TARGET}) 78 | elseif (@PACKAGE_PREFIX@_SHARED) 79 | if (@PACKAGE_PREFIX@_NOTHREADS) 80 | set (@PACKAGE_PREFIX@_TARGET @PACKAGE_NAME@_nothreads_shared) 81 | else () 82 | set (@PACKAGE_PREFIX@_TARGET @PACKAGE_NAME@_shared) 83 | endif () 84 | else () 85 | if (@PACKAGE_PREFIX@_NOTHREADS) 86 | set (@PACKAGE_PREFIX@_TARGET @PACKAGE_NAME@_nothreads_static) 87 | else () 88 | set (@PACKAGE_PREFIX@_TARGET @PACKAGE_NAME@_static) 89 | endif () 90 | endif () 91 | endif () 92 | if (NOT TARGET ${@PACKAGE_PREFIX@_TARGET}) 93 | message (FATAL_ERROR "Your @PACKAGE_NAME@ installation does not contain a ${@PACKAGE_PREFIX@_TARGET} library target!" 94 | " Try a different combination of @PACKAGE_PREFIX@_SHARED and @PACKAGE_PREFIX@_NOTHREADS.") 95 | endif () 96 | 97 | # add more convenient "@PACKAGE_NAME@" import target 98 | if (NOT TARGET @PACKAGE_NAME@) 99 | if (@PACKAGE_PREFIX@_SHARED) 100 | add_library (@PACKAGE_NAME@ SHARED IMPORTED) 101 | else () 102 | add_library (@PACKAGE_NAME@ STATIC IMPORTED) 103 | endif () 104 | # copy INTERFACE_* properties 105 | foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS 106 | COMPILE_DEFINITIONS 107 | COMPILE_FEATURES 108 | COMPILE_OPTIONS 109 | INCLUDE_DIRECTORIES 110 | LINK_LIBRARIES 111 | POSITION_INDEPENDENT_CODE 112 | ) 113 | get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME}) 114 | if (_@PACKAGE_PREFIX@_PROPERTY_VALUE) 115 | set_target_properties(@PACKAGE_NAME@ PROPERTIES 116 | INTERFACE_${_@PACKAGE_PREFIX@_PROPERTY_NAME} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}" 117 | ) 118 | endif () 119 | endforeach () 120 | # copy IMPORTED_*_ properties 121 | get_target_property (_@PACKAGE_PREFIX@_CONFIGURATIONS ${@PACKAGE_PREFIX@_TARGET} IMPORTED_CONFIGURATIONS) 122 | set_target_properties (@PACKAGE_NAME@ PROPERTIES IMPORTED_CONFIGURATIONS "${_@PACKAGE_PREFIX@_CONFIGURATIONS}") 123 | foreach (_@PACKAGE_PREFIX@_PROPERTY_NAME IN ITEMS 124 | IMPLIB 125 | LOCATION 126 | LINK_DEPENDENT_LIBRARIES 127 | LINK_INTERFACE_LIBRARIES 128 | LINK_INTERFACE_LANGUAGES 129 | LINK_INTERFACE_MULTIPLICITY 130 | NO_SONAME 131 | SONAME 132 | ) 133 | foreach (_@PACKAGE_PREFIX@_CONFIG IN LISTS _@PACKAGE_PREFIX@_CONFIGURATIONS) 134 | get_target_property (_@PACKAGE_PREFIX@_PROPERTY_VALUE ${@PACKAGE_PREFIX@_TARGET} IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG}) 135 | if (_@PACKAGE_PREFIX@_PROPERTY_VALUE) 136 | set_target_properties(@PACKAGE_NAME@ PROPERTIES 137 | IMPORTED_${_@PACKAGE_PREFIX@_PROPERTY_NAME}_${_@PACKAGE_PREFIX@_CONFIG} "${_@PACKAGE_PREFIX@_PROPERTY_VALUE}" 138 | ) 139 | endif () 140 | endforeach () 141 | endforeach () 142 | unset (_@PACKAGE_PREFIX@_CONFIGURATIONS) 143 | unset (_@PACKAGE_PREFIX@_CONFIG) 144 | unset (_@PACKAGE_PREFIX@_PROPERTY_NAME) 145 | unset (_@PACKAGE_PREFIX@_PROPERTY_VALUE) 146 | endif () 147 | 148 | # alias for default import target to be compatible with older CMake package configurations 149 | set (@PACKAGE_PREFIX@_LIBRARIES "${@PACKAGE_PREFIX@_TARGET}") 150 | 151 | # set @PACKAGE_NAME@_* variables for backwards compatibility 152 | if (NOT "^@PACKAGE_NAME@$" STREQUAL "^@PACKAGE_PREFIX@$") 153 | foreach (_@PACKAGE_PREFIX@_VARIABLE IN ITEMS 154 | VERSION_STRING 155 | VERSION_MAJOR 156 | VERSION_MINOR 157 | VERSION_PATCH 158 | INCLUDE_DIR 159 | LIBRARIES 160 | TARGET 161 | ) 162 | set (@PACKAGE_NAME@_${_@PACKAGE_PREFIX@_VARIABLE} "${@PACKAGE_PREFIX@_${_@PACKAGE_PREFIX@_VARIABLE}}") 163 | endforeach () 164 | unset (_@PACKAGE_PREFIX@_VARIABLE) 165 | endif () 166 | 167 | # unset private variables 168 | unset (@PACKAGE_NAME@_FIND_COMPONENT) 169 | unset (_INSTALL_PREFIX) 170 | -------------------------------------------------------------------------------- /extern/gflags/cmake/execute_test.cmake: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # sanitize string stored in variable for use in regular expression. 3 | macro (sanitize_for_regex STRVAR) 4 | string (REGEX REPLACE "([.+*?^$()])" "\\\\\\1" ${STRVAR} "${${STRVAR}}") 5 | endmacro () 6 | 7 | # ---------------------------------------------------------------------------- 8 | # script arguments 9 | if (NOT COMMAND) 10 | message (FATAL_ERROR "Test command not specified!") 11 | endif () 12 | if (NOT DEFINED EXPECTED_RC) 13 | set (EXPECTED_RC 0) 14 | endif () 15 | if (EXPECTED_OUTPUT) 16 | sanitize_for_regex(EXPECTED_OUTPUT) 17 | endif () 18 | if (UNEXPECTED_OUTPUT) 19 | sanitize_for_regex(UNEXPECTED_OUTPUT) 20 | endif () 21 | 22 | # ---------------------------------------------------------------------------- 23 | # set a few environment variables (useful for --tryfromenv) 24 | set (ENV{FLAGS_undefok} "foo,bar") 25 | set (ENV{FLAGS_weirdo} "") 26 | set (ENV{FLAGS_version} "true") 27 | set (ENV{FLAGS_help} "false") 28 | 29 | # ---------------------------------------------------------------------------- 30 | # execute test command 31 | execute_process( 32 | COMMAND ${COMMAND} 33 | RESULT_VARIABLE RC 34 | OUTPUT_VARIABLE OUTPUT 35 | ERROR_VARIABLE OUTPUT 36 | ) 37 | 38 | if (OUTPUT) 39 | message ("${OUTPUT}") 40 | endif () 41 | 42 | # ---------------------------------------------------------------------------- 43 | # check test result 44 | if (NOT RC EQUAL EXPECTED_RC) 45 | string (REPLACE ";" " " COMMAND "${COMMAND}") 46 | message (FATAL_ERROR "Command:\n\t${COMMAND}\nExit status is ${RC}, expected ${EXPECTED_RC}") 47 | endif () 48 | if (EXPECTED_OUTPUT AND NOT OUTPUT MATCHES "${EXPECTED_OUTPUT}") 49 | message (FATAL_ERROR "Test output does not match expected output: ${EXPECTED_OUTPUT}") 50 | endif () 51 | if (UNEXPECTED_OUTPUT AND OUTPUT MATCHES "${UNEXPECTED_OUTPUT}") 52 | message (FATAL_ERROR "Test output matches unexpected output: ${UNEXPECTED_OUTPUT}") 53 | endif () -------------------------------------------------------------------------------- /extern/gflags/cmake/package.cmake.in: -------------------------------------------------------------------------------- 1 | # Per-generator CPack configuration file. See CPACK_PROJECT_CONFIG_FILE documented at 2 | # http://www.cmake.org/cmake/help/v2.8.12/cpack.html#variable:CPACK_PROJECT_CONFIG_FILE 3 | # 4 | # All common CPACK_* variables are set in CMakeLists.txt already. This file only 5 | # overrides some of these to provide package generator specific settings. 6 | 7 | # whether package contains all development files or only runtime files 8 | set (DEVEL @INSTALL_HEADERS@) 9 | 10 | # ------------------------------------------------------------------------------ 11 | # Mac OS X package 12 | if (CPACK_GENERATOR MATCHES "PackageMaker|DragNDrop") 13 | 14 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") 15 | if (DEVEL) 16 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel") 17 | endif () 18 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}") 19 | 20 | # ------------------------------------------------------------------------------ 21 | # Debian package 22 | elseif (CPACK_GENERATOR MATCHES "DEB") 23 | 24 | set (CPACK_PACKAGE_FILE_NAME "lib${CPACK_PACKAGE_NAME}") 25 | if (DEVEL) 26 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-dev") 27 | else () 28 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}0") 29 | endif () 30 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}_${CPACK_PACKAGE_VERSION}-1_${CPACK_PACKAGE_ARCHITECTURE}") 31 | 32 | set (CPACK_DEBIAN_PACKAGE_DEPENDS) 33 | set (CPACK_DEBIAN_PACKAGE_SECTION "devel") 34 | set (CPACK_DEBIAN_PACKAGE_PRIORITY "optional") 35 | set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CPACK_RPM_PACKAGE_URL}") 36 | set (CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_VENDOR}") 37 | set (CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_PACKAGE_ARCHITECTURE}") 38 | 39 | # ------------------------------------------------------------------------------ 40 | # RPM package 41 | elseif (CPACK_GENERATOR MATCHES "RPM") 42 | 43 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}") 44 | if (DEVEL) 45 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-devel") 46 | endif () 47 | set (CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_PACKAGE_VERSION}-1.${CPACK_PACKAGE_ARCHITECTURE}") 48 | 49 | endif () 50 | -------------------------------------------------------------------------------- /extern/gflags/cmake/package.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | bindir=${prefix}/@RUNTIME_INSTALL_DIR@ 4 | libdir=${prefix}/@LIBRARY_INSTALL_DIR@ 5 | includedir=${prefix}/@INCLUDE_INSTALL_DIR@ 6 | 7 | Name: @PACKAGE_NAME@ 8 | Version: @PACKAGE_VERSION@ 9 | Description: @PACKAGE_DESCRIPTION@ 10 | URL: @PACKAGE_URL@ 11 | Requires: 12 | Libs: -L${libdir} -lgflags 13 | Libs.private: -lpthread 14 | Cflags: -I${includedir} 15 | -------------------------------------------------------------------------------- /extern/gflags/cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | ## Utility CMake functions. 2 | 3 | # ---------------------------------------------------------------------------- 4 | ## Convert boolean value to 0 or 1 5 | macro (bool_to_int VAR) 6 | if (${VAR}) 7 | set (${VAR} 1) 8 | else () 9 | set (${VAR} 0) 10 | endif () 11 | endmacro () 12 | 13 | # ---------------------------------------------------------------------------- 14 | ## Extract version numbers from version string 15 | function (version_numbers version major minor patch) 16 | if (version MATCHES "([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(rc[1-9][0-9]*|[a-z]+)?") 17 | if (CMAKE_MATCH_1) 18 | set (_major ${CMAKE_MATCH_1}) 19 | else () 20 | set (_major 0) 21 | endif () 22 | if (CMAKE_MATCH_2) 23 | set (_minor ${CMAKE_MATCH_2}) 24 | string (REGEX REPLACE "^\\." "" _minor "${_minor}") 25 | else () 26 | set (_minor 0) 27 | endif () 28 | if (CMAKE_MATCH_3) 29 | set (_patch ${CMAKE_MATCH_3}) 30 | string (REGEX REPLACE "^\\." "" _patch "${_patch}") 31 | else () 32 | set (_patch 0) 33 | endif () 34 | else () 35 | set (_major 0) 36 | set (_minor 0) 37 | set (_patch 0) 38 | endif () 39 | set ("${major}" "${_major}" PARENT_SCOPE) 40 | set ("${minor}" "${_minor}" PARENT_SCOPE) 41 | set ("${patch}" "${_patch}" PARENT_SCOPE) 42 | endfunction () 43 | 44 | # ---------------------------------------------------------------------------- 45 | ## Determine if cache entry exists 46 | macro (gflags_is_cached retvar varname) 47 | if (DEFINED ${varname}) 48 | get_property (${retvar} CACHE ${varname} PROPERTY TYPE SET) 49 | else () 50 | set (${retvar} FALSE) 51 | endif () 52 | endmacro () 53 | 54 | # ---------------------------------------------------------------------------- 55 | ## Add gflags configuration variable 56 | # 57 | # The default value of the (cached) configuration value can be overridden either 58 | # on the CMake command-line or the super-project by setting the GFLAGS_ 59 | # variable. When gflags is a subproject of another project (GFLAGS_IS_SUBPROJECT), 60 | # the variable is not added to the CMake cache. Otherwise it is cached. 61 | macro (gflags_define type varname docstring default) 62 | # note that ARGC must be expanded here, as it is not a "real" variable 63 | # (see the CMake documentation for the macro command) 64 | if ("${ARGC}" GREATER 5) 65 | message (FATAL_ERROR "gflags_variable: Too many macro arguments") 66 | endif () 67 | if (NOT DEFINED GFLAGS_${varname}) 68 | if (GFLAGS_IS_SUBPROJECT AND "${ARGC}" EQUAL 5) 69 | set (GFLAGS_${varname} "${ARGV4}") 70 | else () 71 | set (GFLAGS_${varname} "${default}") 72 | endif () 73 | endif () 74 | if (GFLAGS_IS_SUBPROJECT) 75 | if (NOT DEFINED ${varname}) 76 | set (${varname} "${GFLAGS_${varname}}") 77 | endif () 78 | else () 79 | set (${varname} "${GFLAGS_${varname}}" CACHE ${type} "${docstring}") 80 | endif () 81 | endmacro () 82 | 83 | # ---------------------------------------------------------------------------- 84 | ## Set property of cached gflags configuration variable 85 | macro (gflags_property varname property value) 86 | gflags_is_cached (_cached ${varname}) 87 | if (_cached) 88 | # note that property must be expanded here, as it is not a "real" variable 89 | # (see the CMake documentation for the macro command) 90 | if ("${property}" STREQUAL "ADVANCED") 91 | if (${value}) 92 | mark_as_advanced (FORCE ${varname}) 93 | else () 94 | mark_as_advanced (CLEAR ${varname}) 95 | endif () 96 | else () 97 | set_property (CACHE ${varname} PROPERTY "${property}" "${value}") 98 | endif () 99 | endif () 100 | unset (_cached) 101 | endmacro () 102 | 103 | # ---------------------------------------------------------------------------- 104 | ## Modify value of gflags configuration variable 105 | macro (gflags_set varname value) 106 | gflags_is_cached (_cached ${varname}) 107 | if (_cached) 108 | set_property (CACHE ${varname} PROPERTY VALUE "${value}") 109 | else () 110 | set (${varname} "${value}") 111 | endif () 112 | unset (_cached) 113 | endmacro () 114 | 115 | # ---------------------------------------------------------------------------- 116 | ## Configure public header files 117 | function (configure_headers out) 118 | set (tmp) 119 | foreach (src IN LISTS ARGN) 120 | if (IS_ABSOLUTE "${src}") 121 | list (APPEND tmp "${src}") 122 | elseif (EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in") 123 | configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY) 124 | list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") 125 | else () 126 | configure_file ("${PROJECT_SOURCE_DIR}/src/${src}" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" COPYONLY) 127 | list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") 128 | endif () 129 | endforeach () 130 | set (${out} "${tmp}" PARENT_SCOPE) 131 | endfunction () 132 | 133 | # ---------------------------------------------------------------------------- 134 | ## Configure source files with .in suffix 135 | function (configure_sources out) 136 | set (tmp) 137 | foreach (src IN LISTS ARGN) 138 | if (src MATCHES ".h$" AND EXISTS "${PROJECT_SOURCE_DIR}/src/${src}.in") 139 | configure_file ("${PROJECT_SOURCE_DIR}/src/${src}.in" "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}" @ONLY) 140 | list (APPEND tmp "${PROJECT_BINARY_DIR}/include/${GFLAGS_INCLUDE_DIR}/${src}") 141 | else () 142 | list (APPEND tmp "${PROJECT_SOURCE_DIR}/src/${src}") 143 | endif () 144 | endforeach () 145 | set (${out} "${tmp}" PARENT_SCOPE) 146 | endfunction () 147 | 148 | # ---------------------------------------------------------------------------- 149 | ## Add usage test 150 | # 151 | # Using PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION would 152 | # do as well, but CMake/CTest does not allow us to specify an 153 | # expected exit status. Moreover, the execute_test.cmake script 154 | # sets environment variables needed by the --fromenv/--tryfromenv tests. 155 | macro (add_gflags_test name expected_rc expected_output unexpected_output cmd) 156 | set (args "--test_tmpdir=${PROJECT_BINARY_DIR}/Testing/Temporary" 157 | "--srcdir=${PROJECT_SOURCE_DIR}/test") 158 | add_test ( 159 | NAME ${name} 160 | COMMAND "${CMAKE_COMMAND}" "-DCOMMAND:STRING=$;${args};${ARGN}" 161 | "-DEXPECTED_RC:STRING=${expected_rc}" 162 | "-DEXPECTED_OUTPUT:STRING=${expected_output}" 163 | "-DUNEXPECTED_OUTPUT:STRING=${unexpected_output}" 164 | -P "${PROJECT_SOURCE_DIR}/cmake/execute_test.cmake" 165 | WORKING_DIRECTORY "${GFLAGS_FLAGFILES_DIR}" 166 | ) 167 | endmacro () 168 | 169 | # ------------------------------------------------------------------------------ 170 | ## Register installed package with CMake 171 | # 172 | # This function adds an entry to the CMake registry for packages with the 173 | # path of the directory where the package configuration file of the installed 174 | # package is located in order to help CMake find the package in a custom 175 | # installation prefix. This differs from CMake's export(PACKAGE) command 176 | # which registers the build directory instead. 177 | function (register_gflags_package CONFIG_DIR) 178 | if (NOT IS_ABSOLUTE "${CONFIG_DIR}") 179 | set (CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CONFIG_DIR}") 180 | endif () 181 | string (MD5 REGISTRY_ENTRY "${CONFIG_DIR}") 182 | if (WIN32) 183 | install (CODE 184 | "execute_process ( 185 | COMMAND reg add \"HKCU\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\" /v \"${REGISTRY_ENTRY}\" /d \"${CONFIG_DIR}\" /t REG_SZ /f 186 | RESULT_VARIABLE RT 187 | ERROR_VARIABLE ERR 188 | OUTPUT_QUIET 189 | ) 190 | if (RT EQUAL 0) 191 | message (STATUS \"Register: Added HKEY_CURRENT_USER\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PACKAGE_NAME}\\\\${REGISTRY_ENTRY}\") 192 | else () 193 | string (STRIP \"\${ERR}\" ERR) 194 | message (STATUS \"Register: Failed to add registry entry: \${ERR}\") 195 | endif ()" 196 | ) 197 | elseif (IS_DIRECTORY "$ENV{HOME}") 198 | file (WRITE "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry" "${CONFIG_DIR}") 199 | install ( 200 | FILES "${PROJECT_BINARY_DIR}/${PACKAGE_NAME}-registry-entry" 201 | DESTINATION "$ENV{HOME}/.cmake/packages/${PACKAGE_NAME}" 202 | RENAME "${REGISTRY_ENTRY}" 203 | ) 204 | endif () 205 | endfunction () 206 | -------------------------------------------------------------------------------- /extern/gflags/cmake/version.cmake.in: -------------------------------------------------------------------------------- 1 | ## gflags CMake configuration version file 2 | 3 | # ----------------------------------------------------------------------------- 4 | # library version 5 | set (PACKAGE_VERSION "@PACKAGE_VERSION@") 6 | 7 | # ----------------------------------------------------------------------------- 8 | # check compatibility 9 | 10 | # Perform compatibility check here using the input CMake variables. 11 | # See example in http://www.cmake.org/Wiki/CMake_2.6_Notes. 12 | 13 | set (PACKAGE_VERSION_COMPATIBLE TRUE) 14 | set (PACKAGE_VERSION_UNSUITABLE FALSE) 15 | 16 | if ("${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@PACKAGE_VERSION_MAJOR@" AND 17 | "${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@PACKAGE_VERSION_MINOR@") 18 | set (PACKAGE_VERSION_EXACT TRUE) 19 | else () 20 | set (PACKAGE_VERSION_EXACT FALSE) 21 | endif () 22 | -------------------------------------------------------------------------------- /extern/gflags/src/config.h.in: -------------------------------------------------------------------------------- 1 | /* Generated from config.h.in during build configuration using CMake. */ 2 | 3 | // Note: This header file is only used internally. It is not part of public interface! 4 | 5 | #ifndef GFLAGS_CONFIG_H_ 6 | #define GFLAGS_CONFIG_H_ 7 | 8 | 9 | // --------------------------------------------------------------------------- 10 | // System checks 11 | 12 | // Define if you build this library for a MS Windows OS. 13 | #cmakedefine OS_WINDOWS 14 | 15 | // Define if you have the header file. 16 | #cmakedefine HAVE_STDINT_H 17 | 18 | // Define if you have the header file. 19 | #cmakedefine HAVE_SYS_TYPES_H 20 | 21 | // Define if you have the header file. 22 | #cmakedefine HAVE_INTTYPES_H 23 | 24 | // Define if you have the header file. 25 | #cmakedefine HAVE_SYS_STAT_H 26 | 27 | // Define if you have the header file. 28 | #cmakedefine HAVE_UNISTD_H 29 | 30 | // Define if you have the header file. 31 | #cmakedefine HAVE_FNMATCH_H 32 | 33 | // Define if you have the header file (Windows 2000/XP). 34 | #cmakedefine HAVE_SHLWAPI_H 35 | 36 | // Define if you have the strtoll function. 37 | #cmakedefine HAVE_STRTOLL 38 | 39 | // Define if you have the strtoq function. 40 | #cmakedefine HAVE_STRTOQ 41 | 42 | // Define if you have the header file. 43 | #cmakedefine HAVE_PTHREAD 44 | 45 | // Define if your pthread library defines the type pthread_rwlock_t 46 | #cmakedefine HAVE_RWLOCK 47 | 48 | // gcc requires this to get PRId64, etc. 49 | #if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS) 50 | # define __STDC_FORMAT_MACROS 1 51 | #endif 52 | 53 | // --------------------------------------------------------------------------- 54 | // Package information 55 | 56 | // Name of package. 57 | #define PACKAGE @PROJECT_NAME@ 58 | 59 | // Define to the full name of this package. 60 | #define PACKAGE_NAME @PACKAGE_NAME@ 61 | 62 | // Define to the full name and version of this package. 63 | #define PACKAGE_STRING @PACKAGE_STRING@ 64 | 65 | // Define to the one symbol short name of this package. 66 | #define PACKAGE_TARNAME @PACKAGE_TARNAME@ 67 | 68 | // Define to the version of this package. 69 | #define PACKAGE_VERSION @PACKAGE_VERSION@ 70 | 71 | // Version number of package. 72 | #define VERSION PACKAGE_VERSION 73 | 74 | // Define to the address where bug reports for this package should be sent. 75 | #define PACKAGE_BUGREPORT @PACKAGE_BUGREPORT@ 76 | 77 | // --------------------------------------------------------------------------- 78 | // Path separator 79 | #ifndef PATH_SEPARATOR 80 | # ifdef OS_WINDOWS 81 | # define PATH_SEPARATOR '\\' 82 | # else 83 | # define PATH_SEPARATOR '/' 84 | # endif 85 | #endif 86 | 87 | // --------------------------------------------------------------------------- 88 | // Windows 89 | 90 | // Always export symbols when compiling a shared library as this file is only 91 | // included by internal modules when building the gflags library itself. 92 | // The gflags_declare.h header file will set it to import these symbols otherwise. 93 | #ifndef GFLAGS_DLL_DECL 94 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 95 | # define GFLAGS_DLL_DECL __declspec(dllexport) 96 | # else 97 | # define GFLAGS_DLL_DECL 98 | # endif 99 | #endif 100 | // Flags defined by the gflags library itself must be exported 101 | #ifndef GFLAGS_DLL_DEFINE_FLAG 102 | # define GFLAGS_DLL_DEFINE_FLAG GFLAGS_DLL_DECL 103 | #endif 104 | 105 | #ifdef OS_WINDOWS 106 | // The unittests import the symbols of the shared gflags library 107 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 108 | # define GFLAGS_DLL_DECL_FOR_UNITTESTS __declspec(dllimport) 109 | # endif 110 | # include "windows_port.h" 111 | #endif 112 | 113 | 114 | #endif // GFLAGS_CONFIG_H_ 115 | -------------------------------------------------------------------------------- /extern/gflags/src/gflags_completions.h.in: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | 32 | // 33 | // Implement helpful bash-style command line flag completions 34 | // 35 | // ** Functional API: 36 | // HandleCommandLineCompletions() should be called early during 37 | // program startup, but after command line flag code has been 38 | // initialized, such as the beginning of HandleCommandLineHelpFlags(). 39 | // It checks the value of the flag --tab_completion_word. If this 40 | // flag is empty, nothing happens here. If it contains a string, 41 | // however, then HandleCommandLineCompletions() will hijack the 42 | // process, attempting to identify the intention behind this 43 | // completion. Regardless of the outcome of this deduction, the 44 | // process will be terminated, similar to --helpshort flag 45 | // handling. 46 | // 47 | // ** Overview of Bash completions: 48 | // Bash can be told to programatically determine completions for the 49 | // current 'cursor word'. It does this by (in this case) invoking a 50 | // command with some additional arguments identifying the command 51 | // being executed, the word being completed, and the previous word 52 | // (if any). Bash then expects a sequence of output lines to be 53 | // printed to stdout. If these lines all contain a common prefix 54 | // longer than the cursor word, bash will replace the cursor word 55 | // with that common prefix, and display nothing. If there isn't such 56 | // a common prefix, bash will display the lines in pages using 'more'. 57 | // 58 | // ** Strategy taken for command line completions: 59 | // If we can deduce either the exact flag intended, or a common flag 60 | // prefix, we'll output exactly that. Otherwise, if information 61 | // must be displayed to the user, we'll take the opportunity to add 62 | // some helpful information beyond just the flag name (specifically, 63 | // we'll include the default flag value and as much of the flag's 64 | // description as can fit on a single terminal line width, as specified 65 | // by the flag --tab_completion_columns). Furthermore, we'll try to 66 | // make bash order the output such that the most useful or relevent 67 | // flags are the most likely to be shown at the top. 68 | // 69 | // ** Additional features: 70 | // To assist in finding that one really useful flag, substring matching 71 | // was implemented. Before pressing a to get completion for the 72 | // current word, you can append one or more '?' to the flag to do 73 | // substring matching. Here's the semantics: 74 | // --foo Show me all flags with names prefixed by 'foo' 75 | // --foo? Show me all flags with 'foo' somewhere in the name 76 | // --foo?? Same as prior case, but also search in module 77 | // definition path for 'foo' 78 | // --foo??? Same as prior case, but also search in flag 79 | // descriptions for 'foo' 80 | // Finally, we'll trim the output to a relatively small number of 81 | // flags to keep bash quiet about the verbosity of output. If one 82 | // really wanted to see all possible matches, appending a '+' to the 83 | // search word will force the exhaustive list of matches to be printed. 84 | // 85 | // ** How to have bash accept completions from a binary: 86 | // Bash requires that it be informed about each command that programmatic 87 | // completion should be enabled for. Example addition to a .bashrc 88 | // file would be (your path to gflags_completions.sh file may differ): 89 | 90 | /* 91 | $ complete -o bashdefault -o default -o nospace -C \ 92 | '/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \ 93 | time env binary_name another_binary [...] 94 | */ 95 | 96 | // This would allow the following to work: 97 | // $ /path/to/binary_name --vmodule 98 | // Or: 99 | // $ ./bin/path/another_binary --gfs_u 100 | // (etc) 101 | // 102 | // Sadly, it appears that bash gives no easy way to force this behavior for 103 | // all commands. That's where the "time" in the above example comes in. 104 | // If you haven't specifically added a command to the list of completion 105 | // supported commands, you can still get completions by prefixing the 106 | // entire command with "env". 107 | // $ env /some/brand/new/binary --vmod 108 | // Assuming that "binary" is a newly compiled binary, this should still 109 | // produce the expected completion output. 110 | 111 | 112 | #ifndef GFLAGS_COMPLETIONS_H_ 113 | #define GFLAGS_COMPLETIONS_H_ 114 | 115 | namespace @GFLAGS_NAMESPACE@ { 116 | 117 | extern void HandleCommandLineCompletions(void); 118 | 119 | } 120 | 121 | #endif // GFLAGS_COMPLETIONS_H_ 122 | -------------------------------------------------------------------------------- /extern/gflags/src/gflags_completions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2008, Google Inc. 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above 13 | # copyright notice, this list of conditions and the following disclaimer 14 | # in the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of Google Inc. nor the names of its 17 | # contributors may be used to endorse or promote products derived from 18 | # this software without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | # 32 | # --- 33 | # Author: Dave Nicponski 34 | # 35 | # This script is invoked by bash in response to a matching compspec. When 36 | # this happens, bash calls this script using the command shown in the -C 37 | # block of the complete entry, but also appends 3 arguments. They are: 38 | # - The command being used for completion 39 | # - The word being completed 40 | # - The word preceding the completion word. 41 | # 42 | # Here's an example of how you might use this script: 43 | # $ complete -o bashdefault -o default -o nospace -C \ 44 | # '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \ 45 | # time env binary_name another_binary [...] 46 | 47 | # completion_word_index gets the index of the (N-1)th argument for 48 | # this command line. completion_word gets the actual argument from 49 | # this command line at the (N-1)th position 50 | completion_word_index="$(($# - 1))" 51 | completion_word="${!completion_word_index}" 52 | 53 | # TODO(user): Replace this once gflags_completions.cc has 54 | # a bool parameter indicating unambiguously to hijack the process for 55 | # completion purposes. 56 | if [ -z "$completion_word" ]; then 57 | # Until an empty value for the completion word stops being misunderstood 58 | # by binaries, don't actually execute the binary or the process 59 | # won't be hijacked! 60 | exit 0 61 | fi 62 | 63 | # binary_index gets the index of the command being completed (which bash 64 | # places in the (N-2)nd position. binary gets the actual command from 65 | # this command line at that (N-2)nd position 66 | binary_index="$(($# - 2))" 67 | binary="${!binary_index}" 68 | 69 | # For completions to be universal, we may have setup the compspec to 70 | # trigger on 'harmless pass-through' commands, like 'time' or 'env'. 71 | # If the command being completed is one of those two, we'll need to 72 | # identify the actual command being executed. To do this, we need 73 | # the actual command line that the was pressed on. Bash helpfully 74 | # places this in the $COMP_LINE variable. 75 | if [ "$binary" == "time" ] || [ "$binary" == "env" ]; then 76 | # we'll assume that the first 'argument' is actually the 77 | # binary 78 | 79 | 80 | # TODO(user): This is not perfect - the 'env' command, for instance, 81 | # is allowed to have options between the 'env' and 'the command to 82 | # be executed'. For example, consider: 83 | # $ env FOO="bar" bin/do_something --help 84 | # In this case, we'll mistake the FOO="bar" portion as the binary. 85 | # Perhaps we should continuing consuming leading words until we 86 | # either run out of words, or find a word that is a valid file 87 | # marked as executable. I can't think of any reason this wouldn't 88 | # work. 89 | 90 | # Break up the 'original command line' (not this script's command line, 91 | # rather the one the was pressed on) and find the second word. 92 | parts=( ${COMP_LINE} ) 93 | binary=${parts[1]} 94 | fi 95 | 96 | # Build the command line to use for completion. Basically it involves 97 | # passing through all the arguments given to this script (except the 3 98 | # that bash added), and appending a '--tab_completion_word "WORD"' to 99 | # the arguments. 100 | params="" 101 | for ((i=1; i<=$(($# - 3)); ++i)); do 102 | params="$params \"${!i}\""; 103 | done 104 | params="$params --tab_completion_word \"$completion_word\"" 105 | 106 | # TODO(user): Perhaps stash the output in a temporary file somewhere 107 | # in /tmp, and only cat it to stdout if the command returned a success 108 | # code, to prevent false positives 109 | 110 | # If we think we have a reasonable command to execute, then execute it 111 | # and hope for the best. 112 | candidate=$(type -p "$binary") 113 | if [ ! -z "$candidate" ]; then 114 | eval "$candidate 2>/dev/null $params" 115 | elif [ -f "$binary" ] && [ -x "$binary" ]; then 116 | eval "$binary 2>/dev/null $params" 117 | fi 118 | -------------------------------------------------------------------------------- /extern/gflags/src/gflags_declare.h.in: -------------------------------------------------------------------------------- 1 | // Copyright (c) 1999, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // 32 | // Revamped and reorganized by Craig Silverstein 33 | // 34 | // This is the file that should be included by any file which declares 35 | // command line flag. 36 | 37 | #ifndef GFLAGS_DECLARE_H_ 38 | #define GFLAGS_DECLARE_H_ 39 | 40 | 41 | // --------------------------------------------------------------------------- 42 | // Namespace of gflags library symbols. 43 | #define GFLAGS_NAMESPACE @GFLAGS_NAMESPACE@ 44 | 45 | // --------------------------------------------------------------------------- 46 | // Windows DLL import/export. 47 | 48 | // Whether gflags library is a DLL. 49 | // 50 | // Set to 1 by default when the shared gflags library was built on Windows. 51 | // Must be overwritten when this header file is used with the optionally also 52 | // built static library instead; set by CMake's INTERFACE_COMPILE_DEFINITIONS. 53 | #ifndef GFLAGS_IS_A_DLL 54 | # define GFLAGS_IS_A_DLL @GFLAGS_IS_A_DLL@ 55 | #endif 56 | 57 | // We always want to import the symbols of the gflags library. 58 | #ifndef GFLAGS_DLL_DECL 59 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 60 | # define GFLAGS_DLL_DECL __declspec(dllimport) 61 | # else 62 | # define GFLAGS_DLL_DECL 63 | # endif 64 | #endif 65 | 66 | // We always want to import variables declared in user code. 67 | #ifndef GFLAGS_DLL_DECLARE_FLAG 68 | # if GFLAGS_IS_A_DLL && defined(_MSC_VER) 69 | # define GFLAGS_DLL_DECLARE_FLAG __declspec(dllimport) 70 | # else 71 | # define GFLAGS_DLL_DECLARE_FLAG 72 | # endif 73 | #endif 74 | 75 | // --------------------------------------------------------------------------- 76 | // Flag types 77 | #include 78 | #if @HAVE_STDINT_H@ 79 | # include // the normal place uint32_t is defined 80 | #elif @HAVE_SYS_TYPES_H@ 81 | # include // the normal place u_int32_t is defined 82 | #elif @HAVE_INTTYPES_H@ 83 | # include // a third place for uint32_t or u_int32_t 84 | #endif 85 | 86 | namespace GFLAGS_NAMESPACE { 87 | 88 | #if @GFLAGS_INTTYPES_FORMAT_C99@ // C99 89 | typedef int32_t int32; 90 | typedef uint32_t uint32; 91 | typedef int64_t int64; 92 | typedef uint64_t uint64; 93 | #elif @GFLAGS_INTTYPES_FORMAT_BSD@ // BSD 94 | typedef int32_t int32; 95 | typedef u_int32_t uint32; 96 | typedef int64_t int64; 97 | typedef u_int64_t uint64; 98 | #elif @GFLAGS_INTTYPES_FORMAT_VC7@ // Windows 99 | typedef __int32 int32; 100 | typedef unsigned __int32 uint32; 101 | typedef __int64 int64; 102 | typedef unsigned __int64 uint64; 103 | #else 104 | # error Do not know how to define a 32-bit integer quantity on your system 105 | #endif 106 | 107 | } // namespace GFLAGS_NAMESPACE 108 | 109 | 110 | namespace fLS { 111 | 112 | // The meaning of "string" might be different between now and when the 113 | // macros below get invoked (e.g., if someone is experimenting with 114 | // other string implementations that get defined after this file is 115 | // included). Save the current meaning now and use it in the macros. 116 | typedef std::string clstring; 117 | 118 | } // namespace fLS 119 | 120 | 121 | #define DECLARE_VARIABLE(type, shorttype, name) \ 122 | /* We always want to import declared variables, dll or no */ \ 123 | namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \ 124 | using fL##shorttype::FLAGS_##name 125 | 126 | #define DECLARE_bool(name) \ 127 | DECLARE_VARIABLE(bool, B, name) 128 | 129 | #define DECLARE_int32(name) \ 130 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int32, I, name) 131 | 132 | #define DECLARE_uint32(name) \ 133 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint32, U, name) 134 | 135 | #define DECLARE_int64(name) \ 136 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::int64, I64, name) 137 | 138 | #define DECLARE_uint64(name) \ 139 | DECLARE_VARIABLE(::GFLAGS_NAMESPACE::uint64, U64, name) 140 | 141 | #define DECLARE_double(name) \ 142 | DECLARE_VARIABLE(double, D, name) 143 | 144 | #define DECLARE_string(name) \ 145 | /* We always want to import declared variables, dll or no */ \ 146 | namespace fLS { \ 147 | using ::fLS::clstring; \ 148 | extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \ 149 | } \ 150 | using fLS::FLAGS_##name 151 | 152 | 153 | #endif // GFLAGS_DECLARE_H_ 154 | -------------------------------------------------------------------------------- /extern/gflags/src/gflags_ns.h.in: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Andreas Schuh 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Imports the gflags library symbols into an alternative/deprecated namespace. 32 | 33 | #ifndef GFLAGS_GFLAGS_H_ 34 | # error The internal header gflags_@ns@.h may only be included by gflags.h 35 | #endif 36 | 37 | #ifndef GFLAGS_NS_@NS@_H_ 38 | #define GFLAGS_NS_@NS@_H_ 39 | 40 | 41 | namespace @ns@ { 42 | 43 | 44 | using GFLAGS_NAMESPACE::int32; 45 | using GFLAGS_NAMESPACE::uint32; 46 | using GFLAGS_NAMESPACE::int64; 47 | using GFLAGS_NAMESPACE::uint64; 48 | 49 | using GFLAGS_NAMESPACE::RegisterFlagValidator; 50 | using GFLAGS_NAMESPACE::CommandLineFlagInfo; 51 | using GFLAGS_NAMESPACE::GetAllFlags; 52 | using GFLAGS_NAMESPACE::ShowUsageWithFlags; 53 | using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict; 54 | using GFLAGS_NAMESPACE::DescribeOneFlag; 55 | using GFLAGS_NAMESPACE::SetArgv; 56 | using GFLAGS_NAMESPACE::GetArgvs; 57 | using GFLAGS_NAMESPACE::GetArgv; 58 | using GFLAGS_NAMESPACE::GetArgv0; 59 | using GFLAGS_NAMESPACE::GetArgvSum; 60 | using GFLAGS_NAMESPACE::ProgramInvocationName; 61 | using GFLAGS_NAMESPACE::ProgramInvocationShortName; 62 | using GFLAGS_NAMESPACE::ProgramUsage; 63 | using GFLAGS_NAMESPACE::VersionString; 64 | using GFLAGS_NAMESPACE::GetCommandLineOption; 65 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfo; 66 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie; 67 | using GFLAGS_NAMESPACE::FlagSettingMode; 68 | using GFLAGS_NAMESPACE::SET_FLAGS_VALUE; 69 | using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT; 70 | using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT; 71 | using GFLAGS_NAMESPACE::SetCommandLineOption; 72 | using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode; 73 | using GFLAGS_NAMESPACE::FlagSaver; 74 | using GFLAGS_NAMESPACE::CommandlineFlagsIntoString; 75 | using GFLAGS_NAMESPACE::ReadFlagsFromString; 76 | using GFLAGS_NAMESPACE::AppendFlagsIntoFile; 77 | using GFLAGS_NAMESPACE::ReadFromFlagsFile; 78 | using GFLAGS_NAMESPACE::BoolFromEnv; 79 | using GFLAGS_NAMESPACE::Int32FromEnv; 80 | using GFLAGS_NAMESPACE::Uint32FromEnv; 81 | using GFLAGS_NAMESPACE::Int64FromEnv; 82 | using GFLAGS_NAMESPACE::Uint64FromEnv; 83 | using GFLAGS_NAMESPACE::DoubleFromEnv; 84 | using GFLAGS_NAMESPACE::StringFromEnv; 85 | using GFLAGS_NAMESPACE::SetUsageMessage; 86 | using GFLAGS_NAMESPACE::SetVersionString; 87 | using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags; 88 | using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags; 89 | using GFLAGS_NAMESPACE::AllowCommandLineReparsing; 90 | using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags; 91 | using GFLAGS_NAMESPACE::ShutDownCommandLineFlags; 92 | using GFLAGS_NAMESPACE::FlagRegisterer; 93 | 94 | #ifndef SWIG 95 | using GFLAGS_NAMESPACE::ParseCommandLineFlags; 96 | #endif 97 | 98 | 99 | } // namespace @ns@ 100 | 101 | 102 | #endif // GFLAGS_NS_@NS@_H_ 103 | -------------------------------------------------------------------------------- /extern/gflags/src/util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // --- 30 | // 31 | // Some generically useful utility routines that in google-land would 32 | // be their own projects. We make a shortened version here. 33 | 34 | #ifndef GFLAGS_UTIL_H_ 35 | #define GFLAGS_UTIL_H_ 36 | 37 | #include "config.h" 38 | 39 | #include 40 | #ifdef HAVE_INTTYPES_H 41 | # include 42 | #endif 43 | #include // for va_* 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #ifdef HAVE_SYS_STAT_H 50 | # include // for mkdir 51 | #endif 52 | 53 | 54 | namespace GFLAGS_NAMESPACE { 55 | 56 | 57 | // This is used for unittests for death-testing. It is defined in gflags.cc. 58 | extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int); 59 | 60 | // Work properly if either strtoll or strtoq is on this system. 61 | #if defined(strtoll) || defined(HAVE_STRTOLL) 62 | # define strto64 strtoll 63 | # define strtou64 strtoull 64 | #elif defined(HAVE_STRTOQ) 65 | # define strto64 strtoq 66 | # define strtou64 strtouq 67 | // Neither strtoll nor strtoq are defined. I hope strtol works! 68 | #else 69 | # define strto64 strtol 70 | # define strtou64 strtoul 71 | #endif 72 | 73 | // If we have inttypes.h, it will have defined PRId32/etc for us. 74 | // If not, take our best guess. 75 | #ifndef PRId32 76 | # define PRId32 "d" 77 | #endif 78 | #ifndef PRId64 79 | # define PRId64 "lld" 80 | #endif 81 | #ifndef PRIu64 82 | # define PRIu64 "llu" 83 | #endif 84 | 85 | typedef signed char int8; 86 | typedef unsigned char uint8; 87 | 88 | // -- utility macros --------------------------------------------------------- 89 | 90 | template struct CompileAssert; 91 | template <> struct CompileAssert {}; 92 | #define COMPILE_ASSERT(expr, msg) \ 93 | enum { assert_##msg = sizeof(CompileAssert) } 94 | 95 | // Returns the number of elements in an array. 96 | #define arraysize(arr) (sizeof(arr)/sizeof(*(arr))) 97 | 98 | 99 | // -- logging and testing --------------------------------------------------- 100 | 101 | // For now, we ignore the level for logging, and don't show *VLOG's at 102 | // all, except by hand-editing the lines below 103 | #define LOG(level) std::cerr 104 | #define VLOG(level) if (true) {} else std::cerr 105 | #define DVLOG(level) if (true) {} else std::cerr 106 | 107 | // CHECK dies with a fatal error if condition is not true. It is *not* 108 | // controlled by NDEBUG, so the check will be executed regardless of 109 | // compilation mode. Therefore, it is safe to do things like: 110 | // CHECK(fp->Write(x) == 4) 111 | // We allow stream-like objects after this for debugging, but they're ignored. 112 | #define EXPECT_TRUE(condition) \ 113 | if (true) { \ 114 | if (!(condition)) { \ 115 | fprintf(stderr, "Check failed: %s\n", #condition); \ 116 | exit(1); \ 117 | } \ 118 | } else std::cerr << "" 119 | 120 | #define EXPECT_OP(op, val1, val2) \ 121 | if (true) { \ 122 | if (!((val1) op (val2))) { \ 123 | fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \ 124 | exit(1); \ 125 | } \ 126 | } else std::cerr << "" 127 | 128 | #define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2) 129 | #define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2) 130 | #define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2) 131 | #define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2) 132 | #define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2) 133 | #define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2) 134 | #define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond)) 135 | 136 | // C99 declares isnan and isinf should be macros, so the #ifdef test 137 | // should be reliable everywhere. Of course, it's not, but these 138 | // are testing pertty marginal functionality anyway, so it's ok to 139 | // not-run them even in situations they might, with effort, be made to work. 140 | #ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this 141 | #define EXPECT_NAN(arg) \ 142 | do { \ 143 | if (!isnan(arg)) { \ 144 | fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \ 145 | exit(1); \ 146 | } \ 147 | } while (0) 148 | #else 149 | #define EXPECT_NAN(arg) 150 | #endif 151 | 152 | #ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this 153 | #define EXPECT_INF(arg) \ 154 | do { \ 155 | if (!isinf(arg)) { \ 156 | fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \ 157 | exit(1); \ 158 | } \ 159 | } while (0) 160 | #else 161 | #define EXPECT_INF(arg) 162 | #endif 163 | 164 | #define EXPECT_DOUBLE_EQ(val1, val2) \ 165 | do { \ 166 | if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \ 167 | fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \ 168 | exit(1); \ 169 | } \ 170 | } while (0) 171 | 172 | #define EXPECT_STREQ(val1, val2) \ 173 | do { \ 174 | if (strcmp((val1), (val2)) != 0) { \ 175 | fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \ 176 | exit(1); \ 177 | } \ 178 | } while (0) 179 | 180 | // Call this in a .cc file where you will later call RUN_ALL_TESTS in main(). 181 | #define TEST_INIT \ 182 | static std::vector g_testlist; /* the tests to run */ \ 183 | static int RUN_ALL_TESTS() { \ 184 | std::vector::const_iterator it; \ 185 | for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \ 186 | (*it)(); /* The test will error-exit if there's a problem. */ \ 187 | } \ 188 | fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \ 189 | static_cast(g_testlist.size())); \ 190 | return 0; \ 191 | } 192 | 193 | // Note that this macro uses a FlagSaver to keep tests isolated. 194 | #define TEST(a, b) \ 195 | struct Test_##a##_##b { \ 196 | Test_##a##_##b() { g_testlist.push_back(&Run); } \ 197 | static void Run() { \ 198 | FlagSaver fs; \ 199 | fprintf(stderr, "Running test %s/%s\n", #a, #b); \ 200 | RunTest(); \ 201 | } \ 202 | static void RunTest(); \ 203 | }; \ 204 | static Test_##a##_##b g_test_##a##_##b; \ 205 | void Test_##a##_##b::RunTest() 206 | 207 | // This is a dummy class that eases the google->opensource transition. 208 | namespace testing { 209 | class Test {}; 210 | } 211 | 212 | // Call this in a .cc file where you will later call EXPECT_DEATH 213 | #define EXPECT_DEATH_INIT \ 214 | static bool g_called_exit; \ 215 | static void CalledExit(int) { g_called_exit = true; } 216 | 217 | #define EXPECT_DEATH(fn, msg) \ 218 | do { \ 219 | g_called_exit = false; \ 220 | gflags_exitfunc = &CalledExit; \ 221 | fn; \ 222 | gflags_exitfunc = &exit; /* set back to its default */ \ 223 | if (!g_called_exit) { \ 224 | fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \ 225 | exit(1); \ 226 | } \ 227 | } while (0) 228 | 229 | #define GTEST_HAS_DEATH_TEST 1 230 | 231 | // -- path routines ---------------------------------------------------------- 232 | 233 | // Tries to create the directory path as a temp-dir. If it fails, 234 | // changes path to some directory it *can* create. 235 | #if defined(__MINGW32__) 236 | #include 237 | inline void MakeTmpdir(std::string* path) { 238 | if (!path->empty()) { 239 | path->append("/gflags_unittest_testdir"); 240 | int err = mkdir(path->c_str()); 241 | if (err == 0 || errno == EEXIST) return; 242 | } 243 | // I had trouble creating a directory in /tmp from mingw 244 | *path = "./gflags_unittest"; 245 | mkdir(path->c_str()); 246 | } 247 | #elif defined(_MSC_VER) 248 | #include 249 | inline void MakeTmpdir(std::string* path) { 250 | if (!path->empty()) { 251 | int err = _mkdir(path->c_str()); 252 | if (err == 0 || errno == EEXIST) return; 253 | } 254 | char tmppath_buffer[1024]; 255 | int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer); 256 | assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer)); 257 | assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it 258 | *path = std::string(tmppath_buffer) + "gflags_unittest"; 259 | _mkdir(path->c_str()); 260 | } 261 | #else 262 | inline void MakeTmpdir(std::string* path) { 263 | if (!path->empty()) { 264 | int err = mkdir(path->c_str(), 0755); 265 | if (err == 0 || errno == EEXIST) return; 266 | } 267 | mkdir("/tmp/gflags_unittest", 0755); 268 | } 269 | #endif 270 | 271 | // -- string routines -------------------------------------------------------- 272 | 273 | inline void InternalStringPrintf(std::string* output, const char* format, 274 | va_list ap) { 275 | char space[128]; // try a small buffer and hope it fits 276 | 277 | // It's possible for methods that use a va_list to invalidate 278 | // the data in it upon use. The fix is to make a copy 279 | // of the structure before using it and use that copy instead. 280 | va_list backup_ap; 281 | va_copy(backup_ap, ap); 282 | int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap); 283 | va_end(backup_ap); 284 | 285 | if ((bytes_written >= 0) && (static_cast(bytes_written) < sizeof(space))) { 286 | output->append(space, bytes_written); 287 | return; 288 | } 289 | 290 | // Repeatedly increase buffer size until it fits. 291 | int length = sizeof(space); 292 | while (true) { 293 | if (bytes_written < 0) { 294 | // Older snprintf() behavior. :-( Just try doubling the buffer size 295 | length *= 2; 296 | } else { 297 | // We need exactly "bytes_written+1" characters 298 | length = bytes_written+1; 299 | } 300 | char* buf = new char[length]; 301 | 302 | // Restore the va_list before we use it again 303 | va_copy(backup_ap, ap); 304 | bytes_written = vsnprintf(buf, length, format, backup_ap); 305 | va_end(backup_ap); 306 | 307 | if ((bytes_written >= 0) && (bytes_written < length)) { 308 | output->append(buf, bytes_written); 309 | delete[] buf; 310 | return; 311 | } 312 | delete[] buf; 313 | } 314 | } 315 | 316 | // Clears output before writing to it. 317 | inline void SStringPrintf(std::string* output, const char* format, ...) { 318 | va_list ap; 319 | va_start(ap, format); 320 | output->clear(); 321 | InternalStringPrintf(output, format, ap); 322 | va_end(ap); 323 | } 324 | 325 | inline void StringAppendF(std::string* output, const char* format, ...) { 326 | va_list ap; 327 | va_start(ap, format); 328 | InternalStringPrintf(output, format, ap); 329 | va_end(ap); 330 | } 331 | 332 | inline std::string StringPrintf(const char* format, ...) { 333 | va_list ap; 334 | va_start(ap, format); 335 | std::string output; 336 | InternalStringPrintf(&output, format, ap); 337 | va_end(ap); 338 | return output; 339 | } 340 | 341 | inline bool SafeGetEnv(const char *varname, std::string &valstr) 342 | { 343 | #if defined(_MSC_VER) && _MSC_VER >= 1400 344 | char *val; 345 | size_t sz; 346 | if (_dupenv_s(&val, &sz, varname) != 0 || !val) return false; 347 | valstr = val; 348 | free(val); 349 | #else 350 | const char * const val = getenv(varname); 351 | if (!val) return false; 352 | valstr = val; 353 | #endif 354 | return true; 355 | } 356 | 357 | inline int SafeFOpen(FILE **fp, const char* fname, const char *mode) 358 | { 359 | #if defined(_MSC_VER) && _MSC_VER >= 1400 360 | return fopen_s(fp, fname, mode); 361 | #else 362 | assert(fp != NULL); 363 | *fp = fopen(fname, mode); 364 | // errno only guaranteed to be set on failure 365 | return ((*fp == NULL) ? errno : 0); 366 | #endif 367 | } 368 | 369 | 370 | } // namespace GFLAGS_NAMESPACE 371 | 372 | 373 | #endif // GFLAGS_UTIL_H_ 374 | -------------------------------------------------------------------------------- /extern/gflags/src/windows_port.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | */ 33 | 34 | #ifndef _WIN32 35 | # error You should only be including windows/port.cc in a windows environment! 36 | #endif 37 | 38 | #include // for strlen(), memset(), memcmp() 39 | #include 40 | #include // for va_list, va_start, va_end 41 | #include 42 | 43 | #include "windows_port.h" 44 | 45 | // These call the windows _vsnprintf, but always NUL-terminate. 46 | #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ 47 | #if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */ 48 | 49 | #ifdef _MSC_VER 50 | # pragma warning(push) 51 | # pragma warning(disable: 4996) // ignore _vsnprintf security warning 52 | #endif 53 | int safe_vsnprintf(char *str, size_t size, const char *format, va_list ap) { 54 | if (size == 0) // not even room for a \0? 55 | return -1; // not what C99 says to do, but what windows does 56 | str[size-1] = '\0'; 57 | return _vsnprintf(str, size-1, format, ap); 58 | } 59 | #ifdef _MSC_VER 60 | # pragma warning(pop) 61 | #endif 62 | 63 | int snprintf(char *str, size_t size, const char *format, ...) { 64 | int r; 65 | va_list ap; 66 | va_start(ap, format); 67 | r = vsnprintf(str, size, format, ap); 68 | va_end(ap); 69 | return r; 70 | } 71 | 72 | #endif /* if !(defined(_MSC_VER) && _MSC_VER >= 1900) */ 73 | #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ 74 | -------------------------------------------------------------------------------- /extern/gflags/src/windows_port.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | * 33 | * These are some portability typedefs and defines to make it a bit 34 | * easier to compile this code under VC++. 35 | * 36 | * Several of these are taken from glib: 37 | * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html 38 | */ 39 | 40 | #ifndef GFLAGS_WINDOWS_PORT_H_ 41 | #define GFLAGS_WINDOWS_PORT_H_ 42 | 43 | #include "config.h" 44 | 45 | // This must be defined before the windows.h is included. 46 | // It's needed for mutex.h, to give access to the TryLock method. 47 | # if !defined(_WIN32_WINNT) && !(defined( __MINGW32__) || defined(__MINGW64__)) 48 | # define _WIN32_WINNT 0x0400 49 | # endif 50 | // We always want minimal includes 51 | #ifndef WIN32_LEAN_AND_MEAN 52 | # define WIN32_LEAN_AND_MEAN 53 | #endif 54 | #include 55 | #include /* for mkdir */ 56 | #include /* for _putenv, getenv */ 57 | #include /* need this to override stdio's snprintf, also defines _unlink used by unit tests */ 58 | #include /* util.h uses va_copy */ 59 | #include /* for _stricmp and _strdup */ 60 | 61 | /* We can't just use _vsnprintf and _snprintf as drop-in-replacements, 62 | * because they don't always NUL-terminate. :-( We also can't use the 63 | * name vsnprintf, since windows defines that (but not snprintf (!)). 64 | */ 65 | #if !defined(__MINGW32__) && !defined(__MINGW64__) /* mingw already defines */ 66 | #if !(defined(_MSC_VER) && _MSC_VER >= 1900) /* msvc 2015 already defines */ 67 | extern GFLAGS_DLL_DECL int snprintf(char *str, size_t size, 68 | const char *format, ...); 69 | extern int GFLAGS_DLL_DECL safe_vsnprintf(char *str, size_t size, 70 | const char *format, va_list ap); 71 | #define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap) 72 | #define va_copy(dst, src) (dst) = (src) 73 | #endif 74 | #endif /* #if !defined(__MINGW32__) && !defined(__MINGW64__) */ 75 | 76 | #ifdef _MSC_VER 77 | # pragma warning(push) 78 | # pragma warning(disable: 4996) // ignore getenv security warning 79 | #endif 80 | inline void setenv(const char* name, const char* value, int) { 81 | // In windows, it's impossible to set a variable to the empty string. 82 | // We handle this by setting it to "0" and the NUL-ing out the \0. 83 | // That is, we putenv("FOO=0") and then find out where in memory the 84 | // putenv wrote "FOO=0", and change it in-place to "FOO=\0". 85 | // c.f. http://svn.apache.org/viewvc/stdcxx/trunk/tests/src/environ.cpp?r1=611451&r2=637508&pathrev=637508 86 | static const char* const kFakeZero = "0"; 87 | if (*value == '\0') 88 | value = kFakeZero; 89 | // Apparently the semantics of putenv() is that the input 90 | // must live forever, so we leak memory here. :-( 91 | const size_t nameval_len = strlen(name) + 1 + strlen(value) + 1; 92 | char* nameval = reinterpret_cast(malloc(nameval_len)); 93 | snprintf(nameval, nameval_len, "%s=%s", name, value); 94 | _putenv(nameval); 95 | if (value == kFakeZero) { 96 | nameval[nameval_len - 2] = '\0'; // works when putenv() makes no copy 97 | if (*getenv(name) != '\0') 98 | *getenv(name) = '\0'; // works when putenv() copies nameval 99 | } 100 | } 101 | #ifdef _MSC_VER 102 | # pragma warning(pop) 103 | #endif 104 | 105 | #define strcasecmp _stricmp 106 | 107 | #if defined(_MSC_VER) && _MSC_VER >= 1400 108 | #define strdup _strdup 109 | #define unlink _unlink 110 | #endif 111 | 112 | #if defined(_MSC_VER) && _MSC_VER >= 1800 113 | #include 114 | #else 115 | #define PRId32 "d" 116 | #define PRIu32 "u" 117 | #define PRId64 "I64d" 118 | #define PRIu64 "I64u" 119 | #endif 120 | 121 | #if !defined(__MINGW32__) && !defined(__MINGW64__) 122 | #define strtoq _strtoi64 123 | #define strtouq _strtoui64 124 | #define strtoll _strtoi64 125 | #define strtoull _strtoui64 126 | #define atoll _atoi64 127 | #endif 128 | 129 | #ifndef PATH_MAX 130 | #define PATH_MAX 1024 131 | #endif 132 | 133 | #endif /* GFLAGS_WINDOWS_PORT_H_ */ 134 | -------------------------------------------------------------------------------- /extern/gflags/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## gflags tests 2 | 3 | # ---------------------------------------------------------------------------- 4 | # output directories 5 | set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") 6 | set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") 7 | set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") 8 | 9 | # set working directory of test commands 10 | set (GFLAGS_FLAGFILES_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 11 | 12 | # ---------------------------------------------------------------------------- 13 | # common include directories and link libraries 14 | include_directories ("${CMAKE_CURRENT_SOURCE_DIR}") 15 | include_directories ("${gflags_SOURCE_DIR}/src") 16 | include_directories ("${gflags_BINARY_DIR}/include") 17 | include_directories ("${gflags_BINARY_DIR}/include/gflags") 18 | 19 | if (BUILD_SHARED_LIBS) 20 | set (type shared) 21 | if (GFLAGS_IS_A_DLL) 22 | add_definitions(-DGFLAGS_IS_A_DLL) 23 | endif () 24 | else () 25 | set (type static) 26 | endif () 27 | if (BUILD_gflags_LIB) 28 | link_libraries (gflags_${type}) 29 | else () 30 | link_libraries (gflags_nothreads_${type}) 31 | endif () 32 | 33 | # ---------------------------------------------------------------------------- 34 | # STRIP_FLAG_HELP 35 | add_executable (gflags_strip_flags_test gflags_strip_flags_test.cc) 36 | # Make sure the --help output doesn't print the stripped text. 37 | add_gflags_test (strip_flags_help 1 "" "This text should be stripped out" gflags_strip_flags_test --help) 38 | # Make sure the stripped text isn't in the binary at all. 39 | add_test ( 40 | NAME strip_flags_binary 41 | COMMAND "${CMAKE_COMMAND}" "-DBINARY=$" 42 | -P "${CMAKE_CURRENT_SOURCE_DIR}/gflags_strip_flags_test.cmake" 43 | CONFIGURATIONS Release MinSizeRel 44 | ) 45 | 46 | # ---------------------------------------------------------------------------- 47 | # unit tests 48 | configure_file (gflags_unittest.cc gflags_unittest-main.cc COPYONLY) 49 | configure_file (gflags_unittest.cc gflags_unittest_main.cc COPYONLY) 50 | 51 | add_executable (gflags_unittest gflags_unittest.cc) 52 | add_executable (gflags_unittest-main gflags_unittest-main.cc) 53 | add_executable (gflags_unittest_main gflags_unittest_main.cc) 54 | 55 | if (OS_WINDOWS) 56 | set (SLASH "\\\\") 57 | else () 58 | set (SLASH "/") 59 | endif () 60 | 61 | # First, just make sure the gflags_unittest works as-is 62 | add_gflags_test(unittest 0 "" "" gflags_unittest) 63 | 64 | # --help should show all flags, including flags from gflags_reporting 65 | add_gflags_test(help-reporting 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --help) 66 | 67 | # Make sure that --help prints even very long helpstrings. 68 | add_gflags_test(long-helpstring 1 "end of a long helpstring" "" gflags_unittest --help) 69 | 70 | # Make sure --help reflects flag changes made before flag-parsing 71 | add_gflags_test(changed_bool1 1 "-changed_bool1 (changed) type: bool default: true" "" gflags_unittest --help) 72 | add_gflags_test(changed_bool2 1 "-changed_bool2 (changed) type: bool default: false currently: true" "" gflags_unittest --help) 73 | # And on the command-line, too 74 | add_gflags_test(changeable_string_var 1 "-changeable_string_var () type: string default: \"1\" currently: \"2\"" "" gflags_unittest --changeable_string_var 2 --help) 75 | 76 | # --nohelp and --help=false should be as if we didn't say anything 77 | add_gflags_test(nohelp 0 "PASS" "" gflags_unittest --nohelp) 78 | add_gflags_test(help=false 0 "PASS" "" gflags_unittest --help=false) 79 | 80 | # --helpfull is the same as help 81 | add_gflags_test(helpfull 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helpfull) 82 | 83 | # --helpshort should show only flags from the gflags_unittest itself 84 | add_gflags_test(helpshort 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest --helpshort) 85 | 86 | # --helpshort should show the tldflag we created in the gflags_unittest dir 87 | add_gflags_test(helpshort-tldflag1 1 "tldflag1" "${SLASH}google.cc:" gflags_unittest --helpshort) 88 | add_gflags_test(helpshort-tldflag2 1 "tldflag2" "${SLASH}google.cc:" gflags_unittest --helpshort) 89 | 90 | # --helpshort should work if the main source file is suffixed with [_-]main 91 | add_gflags_test(helpshort-main 1 "${SLASH}gflags_unittest-main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest-main --helpshort) 92 | add_gflags_test(helpshort_main 1 "${SLASH}gflags_unittest_main.cc:" "${SLASH}gflags_reporting.cc:" gflags_unittest_main --helpshort) 93 | 94 | # --helpon needs an argument 95 | add_gflags_test(helpon 1 "'--helpon' is missing its argument; flag description: show help on" "" gflags_unittest --helpon) 96 | # --helpon argument indicates what file we'll show args from 97 | add_gflags_test(helpon=gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon=gflags) 98 | # another way of specifying the argument 99 | add_gflags_test(helpon_gflags 1 "${SLASH}gflags.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpon gflags) 100 | # test another argument 101 | add_gflags_test(helpon=gflags_unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest --helpon=gflags_unittest) 102 | 103 | # helpmatch is like helpon but takes substrings 104 | add_gflags_test(helpmatch_reporting 1 "${SLASH}gflags_reporting.cc:" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch reporting) 105 | add_gflags_test(helpmatch=unittest 1 "${SLASH}gflags_unittest.cc:" "${SLASH}gflags.cc:" gflags_unittest -helpmatch=unittest) 106 | 107 | # if no flags are found with helpmatch or helpon, suggest --help 108 | add_gflags_test(helpmatch=nosuchsubstring 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpmatch=nosuchsubstring) 109 | add_gflags_test(helpon=nosuchmodule 1 "No modules matched" "${SLASH}gflags_unittest.cc:" gflags_unittest -helpon=nosuchmodule) 110 | 111 | # helppackage shows all the flags in the same dir as this unittest 112 | # --help should show all flags, including flags from google.cc 113 | add_gflags_test(helppackage 1 "${SLASH}gflags_reporting.cc:" "" gflags_unittest --helppackage) 114 | 115 | # xml! 116 | add_gflags_test(helpxml 1 "${SLASH}gflags_unittest.cc" "${SLASH}gflags_unittest.cc:" gflags_unittest --helpxml) 117 | 118 | # just print the version info and exit 119 | add_gflags_test(version-1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --version) 120 | add_gflags_test(version-2 0 "version test_version" "${SLASH}gflags_unittest.cc:" gflags_unittest --version) 121 | 122 | # --undefok is a fun flag... 123 | add_gflags_test(undefok-1 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok= --foo --unused_bool) 124 | add_gflags_test(undefok-2 0 "PASS" "" gflags_unittest --undefok=foo --foo --unused_bool) 125 | # If you say foo is ok to be undefined, we'll accept --nofoo as well 126 | add_gflags_test(undefok-3 0 "PASS" "" gflags_unittest --undefok=foo --nofoo --unused_bool) 127 | # It's ok if the foo is in the middle 128 | add_gflags_test(undefok-4 0 "PASS" "" gflags_unittest --undefok=fee,fi,foo,fum --foo --unused_bool) 129 | # But the spelling has to be just right... 130 | add_gflags_test(undefok-5 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=fo --foo --unused_bool) 131 | add_gflags_test(undefok-6 1 "unknown command line flag 'foo'" "" gflags_unittest --undefok=foot --foo --unused_bool) 132 | 133 | # See if we can successfully load our flags from the flagfile 134 | add_gflags_test(flagfile.1 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest "--flagfile=flagfile.1") 135 | add_gflags_test(flagfile.2 0 "PASS" "" gflags_unittest "--flagfile=flagfile.2") 136 | add_gflags_test(flagfile.3 0 "PASS" "" gflags_unittest "--flagfile=flagfile.3") 137 | 138 | # Also try to load flags from the environment 139 | add_gflags_test(fromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=version) 140 | add_gflags_test(tryfromenv=version 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=version) 141 | add_gflags_test(fromenv=help 0 "PASS" "" gflags_unittest --fromenv=help) 142 | add_gflags_test(tryfromenv=help 0 "PASS" "" gflags_unittest --tryfromenv=help) 143 | add_gflags_test(fromenv=helpfull 1 "helpfull not found in environment" "" gflags_unittest --fromenv=helpfull) 144 | add_gflags_test(tryfromenv=helpfull 0 "PASS" "" gflags_unittest --tryfromenv=helpfull) 145 | add_gflags_test(tryfromenv=undefok 0 "PASS" "" gflags_unittest --tryfromenv=undefok --foo) 146 | add_gflags_test(tryfromenv=weirdo 1 "unknown command line flag" "" gflags_unittest --tryfromenv=weirdo) 147 | add_gflags_test(tryfromenv-multiple 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --tryfromenv=test_bool,version,unused_bool) 148 | add_gflags_test(fromenv=test_bool 1 "not found in environment" "" gflags_unittest --fromenv=test_bool) 149 | add_gflags_test(fromenv=test_bool-ok 1 "unknown command line flag" "" gflags_unittest --fromenv=test_bool,ok) 150 | # Here, the --version overrides the fromenv 151 | add_gflags_test(version-overrides-fromenv 0 "gflags_unittest" "${SLASH}gflags_unittest.cc:" gflags_unittest --fromenv=test_bool,version,ok) 152 | 153 | # Make sure -- by itself stops argv processing 154 | add_gflags_test(dashdash 0 "PASS" "" gflags_unittest -- --help) 155 | 156 | # And we should die if the flag value doesn't pass the validator 157 | add_gflags_test(always_fail 1 "ERROR: failed validation of new value 'true' for flag 'always_fail'" "" gflags_unittest --always_fail) 158 | 159 | # And if locking in validators fails 160 | # TODO(andreas): Worked on Windows 7 Release configuration, but causes 161 | # debugger abort() intervention in case of Debug configuration. 162 | #add_gflags_test(deadlock_if_cant_lock 0 "PASS" "" gflags_unittest --deadlock_if_cant_lock) 163 | 164 | # ---------------------------------------------------------------------------- 165 | # use gflags_declare.h 166 | add_executable (gflags_declare_test gflags_declare_test.cc gflags_declare_flags.cc) 167 | 168 | add_test(NAME gflags_declare COMMAND gflags_declare_test --message "Hello gflags!") 169 | set_tests_properties(gflags_declare PROPERTIES PASS_REGULAR_EXPRESSION "Hello gflags!") 170 | 171 | # ---------------------------------------------------------------------------- 172 | # configure Python script which configures and builds a test project 173 | if (BUILD_NC_TESTS OR BUILD_CONFIG_TESTS) 174 | find_package (PythonInterp) 175 | if (NOT PYTHON_EXECUTABLE) 176 | message (FATAL_ERROR "No Python installation found! It is required by the (negative) compilation tests." 177 | " Either install Python or set BUILD_NC_TESTS and BUILD_CONFIG_TESTS to FALSE.") 178 | endif () 179 | set (TMPDIR "${PROJECT_BINARY_DIR}/Testing/Temporary") 180 | configure_file (gflags_build.py.in "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" @ONLY) 181 | function (add_gflags_build_test name srcdir expect_fail) 182 | set (srcdir "${CMAKE_CURRENT_SOURCE_DIR}/${srcdir}") 183 | add_test ( 184 | NAME "${name}" 185 | COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/build.py" 186 | ${name} ${srcdir} ${expect_fail} 187 | ) 188 | endfunction () 189 | endif () 190 | 191 | # ---------------------------------------------------------------------------- 192 | # negative compilation tests 193 | option (BUILD_NC_TESTS "Request addition of negative compilation tests." OFF) 194 | mark_as_advanced (BUILD_NC_TESTS) 195 | if (BUILD_NC_TESTS) 196 | add_gflags_build_test (nc_sanity nc 0) 197 | add_gflags_build_test (nc_swapped_args nc 1) 198 | add_gflags_build_test (nc_int_instead_of_bool nc 1) 199 | add_gflags_build_test (nc_bool_in_quotes nc 1) 200 | add_gflags_build_test (nc_define_string_with_0 nc 1) 201 | endif () 202 | 203 | # ---------------------------------------------------------------------------- 204 | # build configuration test 205 | option (BUILD_CONFIG_TESTS "Request addition of package configuration tests." OFF) 206 | mark_as_advanced (BUILD_CONFIG_TESTS) 207 | if (BUILD_CONFIG_TESTS) 208 | add_gflags_build_test (cmake_config config 0) 209 | endif () 210 | -------------------------------------------------------------------------------- /extern/gflags/test/config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## gflags package configuration tests 2 | 3 | cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) 4 | 5 | project (gflags_${TEST_NAME}) 6 | 7 | find_package (gflags REQUIRED) 8 | 9 | add_executable (foo main.cc) 10 | target_link_libraries (foo gflags) 11 | -------------------------------------------------------------------------------- /extern/gflags/test/config/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DEFINE_string(message, "Hello World!", "The message to print"); 5 | 6 | static bool ValidateMessage(const char* flagname, const std::string &message) 7 | { 8 | return !message.empty(); 9 | } 10 | DEFINE_validator(message, ValidateMessage); 11 | 12 | int main(int argc, char **argv) 13 | { 14 | gflags::SetUsageMessage("Test CMake configuration of gflags library (gflags-config.cmake)"); 15 | gflags::SetVersionString("0.1"); 16 | gflags::ParseCommandLineFlags(&argc, &argv, true); 17 | std::cout << FLAGS_message << std::endl; 18 | gflags::ShutDownCommandLineFlags(); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /extern/gflags/test/flagfile.1: -------------------------------------------------------------------------------- 1 | --version -------------------------------------------------------------------------------- /extern/gflags/test/flagfile.2: -------------------------------------------------------------------------------- 1 | --foo=bar 2 | --nounused_bool -------------------------------------------------------------------------------- /extern/gflags/test/flagfile.3: -------------------------------------------------------------------------------- 1 | --flagfile=flagfile.2 -------------------------------------------------------------------------------- /extern/gflags/test/gflags_build.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import subprocess 6 | import shutil 7 | 8 | CMAKE = '@CMAKE_COMMAND@' 9 | CMAKE_BUILD_TYPE = '@CMAKE_BUILD_TYPE@' 10 | TMPDIR = '@TMPDIR@' 11 | SRCDIR = '@SRCDIR@' 12 | GFLAGS_DIR = '@gflags_BINARY_DIR@' 13 | 14 | if __name__ == "__main__": 15 | if len(sys.argv) != 4: 16 | sys.stderr.write(' '.join(['usage:', sys.argv[0], ' \n'])) 17 | sys.exit(1) 18 | test_name = sys.argv[1] 19 | srcdir = sys.argv[2] 20 | expect_fail = (sys.argv[3].lower() in ['true', 'yes', 'on', '1']) 21 | bindir = os.path.join(TMPDIR, test_name) 22 | if TMPDIR == '': 23 | sys.stderr.write('Temporary directory not set!\n') 24 | sys.exit(1) 25 | # create build directory 26 | if os.path.isdir(bindir): shutil.rmtree(bindir) 27 | os.makedirs(bindir) 28 | # configure the build tree 29 | if subprocess.call([CMAKE, '-DCMAKE_BUILD_TYPE:STRING='+CMAKE_BUILD_TYPE, 30 | '-Dgflags_DIR:PATH='+GFLAGS_DIR, 31 | '-DTEST_NAME:STRING='+test_name, srcdir], cwd=bindir) != 0: 32 | sys.stderr.write('Failed to configure the build tree!\n') 33 | sys.exit(1) 34 | # build the test project 35 | exit_code = subprocess.call([CMAKE, '--build', bindir, '--config', CMAKE_BUILD_TYPE], cwd=bindir) 36 | if expect_fail == True: 37 | if exit_code == 0: 38 | sys.stderr.write('Build expected to fail, but it succeeded!\n') 39 | sys.exit(1) 40 | else: 41 | sys.stderr.write('Build failed as expected\n') 42 | exit_code = 0 43 | sys.exit(exit_code) 44 | -------------------------------------------------------------------------------- /extern/gflags/test/gflags_declare_flags.cc: -------------------------------------------------------------------------------- 1 | #define GFLAGS_DLL_DECLARE_FLAG 2 | 3 | #include 4 | #include 5 | 6 | DECLARE_string(message); // in gflags_delcare_test.cc 7 | 8 | void print_message(); 9 | void print_message() 10 | { 11 | std::cout << FLAGS_message << std::endl; 12 | } 13 | -------------------------------------------------------------------------------- /extern/gflags/test/gflags_declare_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DEFINE_string(message, "", "The message to print"); 4 | void print_message(); // in gflags_declare_flags.cc 5 | 6 | int main(int argc, char **argv) 7 | { 8 | gflags::SetUsageMessage("Test compilation and use of gflags_declare.h"); 9 | gflags::ParseCommandLineFlags(&argc, &argv, true); 10 | print_message(); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /extern/gflags/test/gflags_strip_flags_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // --- 31 | // Author: csilvers@google.com (Craig Silverstein) 32 | // 33 | // A simple program that uses STRIP_FLAG_HELP. We'll have a shell 34 | // script that runs 'strings' over this program and makes sure 35 | // that the help string is not in there. 36 | 37 | #define STRIP_FLAG_HELP 1 38 | #include 39 | 40 | #include 41 | 42 | using GFLAGS_NAMESPACE::SetUsageMessage; 43 | using GFLAGS_NAMESPACE::ParseCommandLineFlags; 44 | 45 | 46 | DEFINE_bool(test, true, "This text should be stripped out"); 47 | 48 | int main(int argc, char** argv) { 49 | SetUsageMessage("Usage message"); 50 | ParseCommandLineFlags(&argc, &argv, false); 51 | 52 | // Unfortunately, for us, libtool can replace executables with a shell 53 | // script that does some work before calling the 'real' executable 54 | // under a different name. We need the 'real' executable name to run 55 | // 'strings' on it, so we construct this binary to print the real 56 | // name (argv[0]) on stdout when run. 57 | puts(argv[0]); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /extern/gflags/test/gflags_strip_flags_test.cmake: -------------------------------------------------------------------------------- 1 | if (NOT BINARY) 2 | message (FATAL_ERROR "BINARY file to check not specified!") 3 | endif () 4 | file (STRINGS "${BINARY}" strings REGEX "This text should be stripped out") 5 | if (strings) 6 | message (FATAL_ERROR "Text not stripped from binary like it should be: ${BINARY}") 7 | endif () 8 | -------------------------------------------------------------------------------- /extern/gflags/test/gflags_unittest_flagfile: -------------------------------------------------------------------------------- 1 | --test_flag=1 2 | --test_flag=2 3 | -------------------------------------------------------------------------------- /extern/gflags/test/nc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ## gflags negative compilation tests 2 | 3 | cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) 4 | 5 | if (NOT TEST_NAME) 6 | message (FATAL_ERROR "Missing TEST_NAME CMake flag") 7 | endif () 8 | string (TOUPPER ${TEST_NAME} TEST_NAME_UPPER) 9 | 10 | project (gflags_${TEST_NAME}) 11 | 12 | find_package (gflags REQUIRED) 13 | include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/..") 14 | add_definitions (-DTEST_${TEST_NAME_UPPER}) 15 | add_executable (gflags_${TEST_NAME} gflags_nc.cc) 16 | target_link_libraries(gflags_${TEST_NAME} gflags) 17 | -------------------------------------------------------------------------------- /extern/gflags/test/nc/gflags_nc.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | // 32 | // A negative comiple test for gflags. 33 | 34 | #include 35 | 36 | #if defined(TEST_NC_SWAPPED_ARGS) 37 | 38 | DEFINE_bool(some_bool_flag, 39 | "the default value should go here, not the description", 40 | false); 41 | 42 | 43 | #elif defined(TEST_NC_INT_INSTEAD_OF_BOOL) 44 | 45 | DEFINE_bool(some_bool_flag_2, 46 | 0, 47 | "should have been an int32 flag but mistakenly used bool instead"); 48 | 49 | #elif defined(TEST_NC_BOOL_IN_QUOTES) 50 | 51 | 52 | DEFINE_bool(some_bool_flag_3, 53 | "false", 54 | "false in in quotes, which is wrong"); 55 | 56 | #elif defined(TEST_NC_SANITY) 57 | 58 | DEFINE_bool(some_bool_flag_4, 59 | true, 60 | "this is the correct usage of DEFINE_bool"); 61 | 62 | #elif defined(TEST_NC_DEFINE_STRING_WITH_0) 63 | 64 | DEFINE_string(some_string_flag, 65 | 0, 66 | "Trying to construct a string by passing 0 would cause a crash."); 67 | 68 | #endif 69 | 70 | int main(int, char **) 71 | { 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /extern/hsvrgb.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Jan Winkler 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of Universität Bremen nor the names of its 13 | // contributors may be used to endorse or promote products derived from 14 | // this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | 28 | /* Author: Jan Winkler */ 29 | 30 | /*! \brief Convert RGB to HSV color space 31 | 32 | Converts a given set of RGB values `r', `g', `b' into HSV 33 | coordinates. The input RGB values are in the range [0, 1], and the 34 | output HSV values are in the ranges h = [0, 360], and s, v = [0, 35 | 1], respectively. 36 | 37 | \param fR Red component, used as input, range: [0, 1] 38 | \param fG Green component, used as input, range: [0, 1] 39 | \param fB Blue component, used as input, range: [0, 1] 40 | \param fH Hue component, used as output, range: [0, 360] 41 | \param fS Hue component, used as output, range: [0, 1] 42 | \param fV Hue component, used as output, range: [0, 1] 43 | 44 | */ 45 | 46 | #include "hsvrgb.hpp" 47 | 48 | void hsvrgb::RGBtoHSV(double& fR, double& fG, double& fB, double& fH, double& fS, double& fV) { 49 | double fCMax = std::max(std::max(fR, fG), fB); 50 | double fCMin = std::min(std::min(fR, fG), fB); 51 | double fDelta = fCMax - fCMin; 52 | 53 | if(fDelta > 0) { 54 | if(fCMax == fR) { 55 | fH = 60 * (std::fmod(((fG - fB) / fDelta), 6)); 56 | } else if(fCMax == fG) { 57 | fH = 60 * (((fB - fR) / fDelta) + 2); 58 | } else if(fCMax == fB) { 59 | fH = 60 * (((fR - fG) / fDelta) + 4); 60 | } 61 | 62 | if(fCMax > 0) { 63 | fS = fDelta / fCMax; 64 | } else { 65 | fS = 0; 66 | } 67 | 68 | fV = fCMax; 69 | } else { 70 | fH = 0; 71 | fS = 0; 72 | fV = fCMax; 73 | } 74 | 75 | if(fH < 0) { 76 | fH = 360 + fH; 77 | } 78 | } 79 | 80 | 81 | /*! \brief Convert HSV to RGB color space 82 | 83 | Converts a given set of HSV values `h', `s', `v' into RGB 84 | coordinates. The output RGB values are in the range [0, 1], and 85 | the input HSV values are in the ranges h = [0, 360], and s, v = 86 | [0, 1], respectively. 87 | 88 | \param fR Red component, used as output, range: [0, 1] 89 | \param fG Green component, used as output, range: [0, 1] 90 | \param fB Blue component, used as output, range: [0, 1] 91 | \param fH Hue component, used as input, range: [0, 360] 92 | \param fS Hue component, used as input, range: [0, 1] 93 | \param fV Hue component, used as input, range: [0, 1] 94 | 95 | */ 96 | 97 | void hsvrgb::HSVtoRGB(double& fR, double& fG, double& fB, double& fH, double& fS, double& fV) { 98 | double fC = fV * fS; // Chroma 99 | double fHPrime = std::fmod(fH / 60.0, 6); 100 | double fX = fC * (1 - std::fabs(std::fmod(fHPrime, 2) - 1)); 101 | double fM = fV - fC; 102 | 103 | if(0 <= fHPrime && fHPrime < 1) { 104 | fR = fC; 105 | fG = fX; 106 | fB = 0; 107 | } else if(1 <= fHPrime && fHPrime < 2) { 108 | fR = fX; 109 | fG = fC; 110 | fB = 0; 111 | } else if(2 <= fHPrime && fHPrime < 3) { 112 | fR = 0; 113 | fG = fC; 114 | fB = fX; 115 | } else if(3 <= fHPrime && fHPrime < 4) { 116 | fR = 0; 117 | fG = fX; 118 | fB = fC; 119 | } else if(4 <= fHPrime && fHPrime < 5) { 120 | fR = fX; 121 | fG = 0; 122 | fB = fC; 123 | } else if(5 <= fHPrime && fHPrime < 6) { 124 | fR = fC; 125 | fG = 0; 126 | fB = fX; 127 | } else { 128 | fR = 0; 129 | fG = 0; 130 | fB = 0; 131 | } 132 | 133 | fR += fM; 134 | fG += fM; 135 | fB += fM; 136 | } 137 | -------------------------------------------------------------------------------- /extern/tinyply.cpp: -------------------------------------------------------------------------------- 1 | // This software is in the public domain. Where that dedication is not 2 | // recognized, you are granted a perpetual, irrevocable license to copy, 3 | // distribute, and modify this file as you see fit. 4 | // Authored in 2015 by Dimitri Diakopoulos (http://www.dimitridiakopoulos.com) 5 | // https://github.com/ddiakopoulos/tinyply 6 | 7 | #include "tinyply.h" 8 | 9 | using namespace tinyply; 10 | using namespace std; 11 | 12 | ////////////////// 13 | // PLY Property // 14 | ////////////////// 15 | 16 | PlyProperty::PlyProperty(std::istream & is) : isList(false) 17 | { 18 | parse_internal(is); 19 | } 20 | 21 | void PlyProperty::parse_internal(std::istream & is) 22 | { 23 | string type; 24 | is >> type; 25 | if (type == "list") 26 | { 27 | string countType; 28 | is >> countType >> type; 29 | listType = property_type_from_string(countType); 30 | isList = true; 31 | } 32 | propertyType = property_type_from_string(type); 33 | is >> name; 34 | } 35 | 36 | ///////////////// 37 | // PLY Element // 38 | ///////////////// 39 | 40 | PlyElement::PlyElement(std::istream & is) 41 | { 42 | parse_internal(is); 43 | } 44 | 45 | void PlyElement::parse_internal(std::istream & is) 46 | { 47 | is >> name >> size; 48 | } 49 | 50 | ////////////// 51 | // PLY File // 52 | ////////////// 53 | 54 | PlyFile::PlyFile(std::istream & is) 55 | { 56 | if (!parse_header(is)) 57 | { 58 | throw std::runtime_error("file is not ply or encounted junk in header"); 59 | } 60 | } 61 | 62 | bool PlyFile::parse_header(std::istream & is) 63 | { 64 | std::string line; 65 | bool gotMagic = false; 66 | while (std::getline(is, line)) 67 | { 68 | std::istringstream ls(line); 69 | std::string token; 70 | ls >> token; 71 | if (token == "ply" || token == "PLY" || token == "") 72 | { 73 | gotMagic = true; 74 | continue; 75 | } 76 | else if (token == "comment") read_header_text(line, ls, comments, 8); 77 | else if (token == "format") read_header_format(ls); 78 | else if (token == "element") read_header_element(ls); 79 | else if (token == "property") read_header_property(ls); 80 | else if (token == "obj_info") read_header_text(line, ls, objInfo, 9); 81 | else if (token == "end_header") break; 82 | else return false; 83 | } 84 | return true; 85 | } 86 | 87 | void PlyFile::read_header_text(std::string line, std::istream & is, std::vector& place, int erase) 88 | { 89 | place.push_back((erase > 0) ? line.erase(0, erase) : line); 90 | } 91 | 92 | void PlyFile::read_header_format(std::istream & is) 93 | { 94 | std::string s; 95 | (is >> s); 96 | if (s == "binary_little_endian") isBinary = true; 97 | else if (s == "binary_big_endian") isBinary = isBigEndian = true; 98 | } 99 | 100 | void PlyFile::read_header_element(std::istream & is) 101 | { 102 | get_elements().emplace_back(is); 103 | } 104 | 105 | void PlyFile::read_header_property(std::istream & is) 106 | { 107 | get_elements().back().properties.emplace_back(is); 108 | } 109 | 110 | size_t PlyFile::skip_property_binary(const PlyProperty & property, std::istream & is) 111 | { 112 | static std::vector skip(PropertyTable[property.propertyType].stride); 113 | if (property.isList) 114 | { 115 | size_t listSize = 0; 116 | size_t dummyCount = 0; 117 | read_property_binary(property.listType, &listSize, dummyCount, is); 118 | for (size_t i = 0; i < listSize; ++i) is.read(skip.data(), PropertyTable[property.propertyType].stride); 119 | return listSize; 120 | } 121 | else 122 | { 123 | is.read(skip.data(), PropertyTable[property.propertyType].stride); 124 | return 0; 125 | } 126 | } 127 | 128 | void PlyFile::skip_property_ascii(const PlyProperty & property, std::istream & is) 129 | { 130 | std::string skip; 131 | if (property.isList) 132 | { 133 | int listSize; 134 | is >> listSize; 135 | for (int i = 0; i < listSize; ++i) is >> skip; 136 | } 137 | else is >> skip; 138 | } 139 | 140 | void PlyFile::read_property_binary(PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is) 141 | { 142 | static std::vector src(PropertyTable[t].stride); 143 | is.read(src.data(), PropertyTable[t].stride); 144 | 145 | switch (t) 146 | { 147 | case PlyProperty::Type::INT8: ply_cast(dest, src.data(), isBigEndian); break; 148 | case PlyProperty::Type::UINT8: ply_cast(dest, src.data(), isBigEndian); break; 149 | case PlyProperty::Type::INT16: ply_cast(dest, src.data(), isBigEndian); break; 150 | case PlyProperty::Type::UINT16: ply_cast(dest, src.data(), isBigEndian); break; 151 | case PlyProperty::Type::INT32: ply_cast(dest, src.data(), isBigEndian); break; 152 | case PlyProperty::Type::UINT32: ply_cast(dest, src.data(), isBigEndian); break; 153 | case PlyProperty::Type::FLOAT32: ply_cast_float(dest, src.data(), isBigEndian); break; 154 | case PlyProperty::Type::FLOAT64: ply_cast_double(dest, src.data(), isBigEndian); break; 155 | case PlyProperty::Type::INVALID: throw std::invalid_argument("invalid ply property"); 156 | } 157 | destOffset += PropertyTable[t].stride; 158 | } 159 | 160 | void PlyFile::read_property_ascii(PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is) 161 | { 162 | switch (t) 163 | { 164 | case PlyProperty::Type::INT8: *((int8_t *)dest) = ply_read_ascii(is); break; 165 | case PlyProperty::Type::UINT8: *((uint8_t *)dest) = ply_read_ascii(is); break; 166 | case PlyProperty::Type::INT16: ply_cast_ascii(dest, is); break; 167 | case PlyProperty::Type::UINT16: ply_cast_ascii(dest, is); break; 168 | case PlyProperty::Type::INT32: ply_cast_ascii(dest, is); break; 169 | case PlyProperty::Type::UINT32: ply_cast_ascii(dest, is); break; 170 | case PlyProperty::Type::FLOAT32: ply_cast_ascii(dest, is); break; 171 | case PlyProperty::Type::FLOAT64: ply_cast_ascii(dest, is); break; 172 | case PlyProperty::Type::INVALID: throw std::invalid_argument("invalid ply property"); 173 | } 174 | destOffset += PropertyTable[t].stride; 175 | } 176 | 177 | void PlyFile::write_property_ascii(PlyProperty::Type t, std::ostream & os, uint8_t * src, size_t & srcOffset) 178 | { 179 | switch (t) 180 | { 181 | case PlyProperty::Type::INT8: os << static_cast(*reinterpret_cast(src)); break; 182 | case PlyProperty::Type::UINT8: os << static_cast(*reinterpret_cast(src)); break; 183 | case PlyProperty::Type::INT16: os << *reinterpret_cast(src); break; 184 | case PlyProperty::Type::UINT16: os << *reinterpret_cast(src); break; 185 | case PlyProperty::Type::INT32: os << *reinterpret_cast(src); break; 186 | case PlyProperty::Type::UINT32: os << *reinterpret_cast(src); break; 187 | case PlyProperty::Type::FLOAT32: os << *reinterpret_cast(src); break; 188 | case PlyProperty::Type::FLOAT64: os << *reinterpret_cast(src); break; 189 | case PlyProperty::Type::INVALID: throw std::invalid_argument("invalid ply property"); 190 | } 191 | os << " "; 192 | srcOffset += PropertyTable[t].stride; 193 | } 194 | 195 | void PlyFile::write_property_binary(PlyProperty::Type t, std::ostream & os, uint8_t * src, size_t & srcOffset) 196 | { 197 | os.write((char *)src, PropertyTable[t].stride); 198 | srcOffset += PropertyTable[t].stride; 199 | } 200 | 201 | void PlyFile::read(std::istream & is) 202 | { 203 | read_internal(is); 204 | } 205 | 206 | void PlyFile::write(std::ostream & os, bool isBinary) 207 | { 208 | if (isBinary) write_binary_internal(os); 209 | else write_ascii_internal(os); 210 | } 211 | 212 | void PlyFile::write_binary_internal(std::ostream & os) 213 | { 214 | isBinary = true; 215 | write_header(os); 216 | 217 | for (auto & e : elements) 218 | { 219 | for (size_t i = 0; i < e.size; ++i) 220 | { 221 | for (auto & p : e.properties) 222 | { 223 | auto & cursor = userDataTable[make_key(e.name, p.name)]; 224 | if (p.isList) 225 | { 226 | uint8_t listSize[4] = {0, 0, 0, 0}; 227 | memcpy(listSize, &p.listCount, sizeof(uint32_t)); 228 | size_t dummyCount = 0; 229 | write_property_binary(p.listType, os, listSize, dummyCount); 230 | for (int j = 0; j < p.listCount; ++j) 231 | { 232 | write_property_binary(p.propertyType, os, (cursor->data + cursor->offset), cursor->offset); 233 | } 234 | } 235 | else 236 | { 237 | write_property_binary(p.propertyType, os, (cursor->data + cursor->offset), cursor->offset); 238 | } 239 | } 240 | } 241 | } 242 | } 243 | 244 | void PlyFile::write_ascii_internal(std::ostream & os) 245 | { 246 | write_header(os); 247 | 248 | for (auto & e : elements) 249 | { 250 | for (size_t i = 0; i < e.size; ++i) 251 | { 252 | for (auto & p : e.properties) 253 | { 254 | auto & cursor = userDataTable[make_key(e.name, p.name)]; 255 | if (p.isList) 256 | { 257 | os << p.listCount << " "; 258 | for (int j = 0; j < p.listCount; ++j) 259 | { 260 | write_property_ascii(p.propertyType, os, (cursor->data + cursor->offset), cursor->offset); 261 | } 262 | } 263 | else 264 | { 265 | write_property_ascii(p.propertyType, os, (cursor->data + cursor->offset), cursor->offset); 266 | } 267 | } 268 | os << std::endl; 269 | } 270 | } 271 | } 272 | 273 | void PlyFile::write_header(std::ostream & os) 274 | { 275 | const std::locale & fixLoc = std::locale("C"); 276 | os.imbue(fixLoc); 277 | 278 | os << "ply" << std::endl; 279 | if (isBinary) 280 | os << ((isBigEndian) ? "format binary_big_endian 1.0" : "format binary_little_endian 1.0") << std::endl; 281 | else 282 | os << "format ascii 1.0" << std::endl; 283 | 284 | for (const auto & comment : comments) 285 | os << "comment " << comment << std::endl; 286 | 287 | for (auto & e : elements) 288 | { 289 | os << "element " << e.name << " " << e.size << std::endl; 290 | for (const auto & p : e.properties) 291 | { 292 | if (p.isList) 293 | { 294 | os << "property list " << PropertyTable[p.listType].str << " " 295 | << PropertyTable[p.propertyType].str << " " << p.name << std::endl; 296 | } 297 | else 298 | { 299 | os << "property " << PropertyTable[p.propertyType].str << " " << p.name << std::endl; 300 | } 301 | } 302 | } 303 | os << "end_header" << std::endl; 304 | } 305 | 306 | void PlyFile::read_internal(std::istream & is) 307 | { 308 | std::function read; 309 | std::function skip; 310 | if (isBinary) 311 | { 312 | read = [&](PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is) { read_property_binary(t, dest, destOffset, is); }; 313 | skip = [&](const PlyProperty & property, std::istream & is) { skip_property_binary(property, is); }; 314 | } 315 | else 316 | { 317 | read = [&](PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is) { read_property_ascii(t, dest, destOffset, is); }; 318 | skip = [&](const PlyProperty & property, std::istream & is) { skip_property_ascii(property, is); }; 319 | } 320 | 321 | for (auto & element : get_elements()) 322 | { 323 | if (std::find(requestedElements.begin(), requestedElements.end(), element.name) != requestedElements.end()) 324 | { 325 | for (size_t count = 0; count < element.size; ++count) 326 | { 327 | for (auto & property : element.properties) 328 | { 329 | if (auto & cursor = userDataTable[make_key(element.name, property.name)]) 330 | { 331 | if (property.isList) 332 | { 333 | size_t listSize = 0; 334 | size_t dummyCount = 0; 335 | read(property.listType, &listSize, dummyCount, is); 336 | if (cursor->realloc == false) 337 | { 338 | cursor->realloc = true; 339 | resize_vector(property.propertyType, cursor->vector, listSize * element.size, cursor->data); 340 | } 341 | for (size_t i = 0; i < listSize; ++i) 342 | { 343 | read(property.propertyType, (cursor->data + cursor->offset), cursor->offset, is); 344 | } 345 | } 346 | else 347 | { 348 | read(property.propertyType, (cursor->data + cursor->offset), cursor->offset, is); 349 | } 350 | } 351 | else 352 | { 353 | skip(property, is); 354 | } 355 | } 356 | } 357 | } 358 | else continue; 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /img/PointCloudRegistrationTool_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drethage/PointCloudRegistrationTool/21964fb230198c368782f1acfae32e4b280e0ca7/img/PointCloudRegistrationTool_demo.gif -------------------------------------------------------------------------------- /include/Registrator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #ifndef Registrator_hpp 10 | #define Registrator_hpp 11 | 12 | // Standard 13 | #include 14 | 15 | // Boost 16 | #include 17 | 18 | // PCL 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | // PRT 32 | #include "types.hpp" 33 | #include "util.hpp" 34 | 35 | // GFLAGS 36 | #include 37 | DECLARE_string(registration_technique); 38 | DECLARE_double(residual_threshold); 39 | DECLARE_uint64(num_ksearch_neighbors); 40 | DECLARE_double(descriptor_radius); 41 | DECLARE_double(subsampling_radius); 42 | DECLARE_double(consensus_inlier_threshold); 43 | DECLARE_uint64(consensus_max_iterations); 44 | DECLARE_uint64(icp_max_iterations); 45 | DECLARE_double(icp_max_correspondence_distance); 46 | 47 | using namespace PRT; 48 | 49 | class Registrator 50 | { 51 | public: 52 | // Constants 53 | static const std::string DEFAULT_registration_technique; 54 | static const double DEFAULT_residual_threshold; 55 | static const int DEFAULT_num_ksearch_neighbors; 56 | static const double DEFAULT_descriptor_radius; 57 | static const double DEFAULT_subsampling_radius; 58 | static const double DEFAULT_consensus_inlier_threshold; 59 | static const int DEFAULT_consensus_max_iterations; 60 | static const int DEFAULT_icp_max_iterations; 61 | static const double DEFAULT_icp_max_correspondence_distance; 62 | 63 | // Typedefs 64 | typedef boost::shared_ptr< Registrator > Ptr; 65 | 66 | // Constructor 67 | Registrator(); 68 | 69 | /** 70 | Sets the source cloud 71 | The source cloud is that which we aim to align to the source cloud 72 | */ 73 | void setSourceCloud(const PointCloudT::Ptr &cloud); 74 | 75 | /** 76 | Sets the target cloud 77 | The target cloud is that which we aim to align against 78 | */ 79 | void setTargetCloud(const PointCloudT::Ptr &cloud); 80 | 81 | //Setup methods 82 | void setSubsamplingRadius(double r); 83 | void setDescriptorRadius(double r); 84 | void setNumKSearchNeighbors(int n); 85 | void setConsensusInlierThreshold(double t); 86 | void setConsensusMaxIterations(int i); 87 | void setICPMaxCorrespondenceDistance(double d); 88 | void setICPMaxIterations(int i); 89 | 90 | //Computation methods 91 | void performRegistration(const std::string); 92 | void computeResidualColormap(); 93 | int saveResidualColormapPointCloud(std::string &filepath); 94 | 95 | void setResidualThreshold(double residual_threshold); 96 | 97 | //Get methods 98 | Eigen::Matrix4f getCorrespondenceBasedTransformation(); 99 | Eigen::Matrix4f getICPBasedTransformation(); 100 | Eigen::Matrix4f getCombinedTransformation(); 101 | PointCloudT::Ptr getRegisteredCloud(); 102 | PointCloudRGBT::Ptr getRegisteredRGBCloud(); 103 | PointCloudT::Ptr getSourceCloud(); 104 | PointCloudT::Ptr getTargetCloud(); 105 | PointCloudT::Ptr getSourceKeypointsCloud(); 106 | PointCloudT::Ptr getTargetKeypointsCloud(); 107 | DoubleVectorPtr getTargetToRegisteredResiduals(); 108 | DoubleVectorPtr getRegisteredToTargetResiduals(); 109 | double getMaxTargetToRegisteredResidual(); 110 | double getMaxRegisteredToTargetResidual(); 111 | double getFScoreAtThreshold(double threshold = -1); 112 | int saveFinalTransform(const std::string filepath); 113 | void saveFScoreAtThreshold(const std::string filepath, double threshold); 114 | double getResidualThreshold(); 115 | 116 | private: 117 | //Computation methods 118 | void correspondenceBasedRegistration(); 119 | void ICPBasedRegistration(); 120 | void computeNormals(); 121 | void extractKeypoints(); 122 | void computeDescriptors(); 123 | void computeResiduals(); 124 | void findCorrespondences(); 125 | void filterCorrespondences(); 126 | void computeCorrespondenceBasedTransformation(); 127 | 128 | void setRegisteredCloudToDefaultColor(); 129 | 130 | //Data members 131 | PointCloudT::Ptr s_cloud_; //Source Cloud 132 | PointCloudT::Ptr t_cloud_; //Target Cloud 133 | PointCloudT::Ptr r_cloud_; //Source Cloud after Registration 134 | PointCloudRGBT::Ptr r_cloud_rgb_; //Source Cloud after Registration (with RGB attributes) 135 | 136 | NormalCloudT::Ptr s_cloud_normals_; //Source Cloud Normals 137 | NormalCloudT::Ptr t_cloud_normals_; //Target Cloud Normals 138 | 139 | PointCloudT::Ptr s_cloud_keypoints_; //Source Cloud Keypoints 140 | PointCloudT::Ptr t_cloud_keypoints_; //Target Cloud Keypoints 141 | 142 | SHOTDescriptorCloudT::Ptr s_cloud_descriptors_; //Source SHOT Descriptors 143 | SHOTDescriptorCloudT::Ptr t_cloud_descriptors_; //Target SHOT Descriptors 144 | 145 | PointCloudT::Ptr s_cloud_corr_; //Source Cloud Correspondence Points 146 | PointCloudT::Ptr t_cloud_corr_; //Target Cloud Correspondence Points 147 | 148 | pcl::CorrespondencesPtr correspondences_; //Keypoint Correspondences 149 | 150 | DoubleVectorPtr t_r_residuals_; //Residuals from target cloud to registered cloud 151 | DoubleVectorPtr r_t_residuals_; //Residuals from registered cloud to target cloud 152 | double t_r_max_residual_; //Max residual from target cloud to registered cloud 153 | double r_t_max_residual_; //Max residual from registered cloud to target cloud 154 | 155 | Eigen::Matrix4f correspondence_T_; //Transformation matrix estimated from point correspondences 156 | Eigen::Matrix4f icp_T_; //Transformation matrix estimated from ICP 157 | Eigen::Matrix4f combined_T_; //Transformation matrix from both correspondence matching & ICP 158 | 159 | double uniform_sampling_radius_; 160 | double descriptor_radius_; 161 | int num_k_search_neighbors_; 162 | double consensus_inlier_threshold_; 163 | int consensus_max_iterations_; 164 | int icp_max_iterations_; 165 | double icp_max_correspondence_distance_; 166 | 167 | bool is_correspondence_matching_complete_ = false; 168 | bool is_icp_complete_ = false; 169 | bool is_residual_colormap_computed_ = false; 170 | 171 | DoubleVectorPtr colormap_residuals_; 172 | RGB r_color_; 173 | 174 | double residual_threshold_; 175 | 176 | }; 177 | 178 | #endif /* Registrator_hpp */ 179 | -------------------------------------------------------------------------------- /include/Visualizer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #ifndef Visualizer_hpp 10 | #define Visualizer_hpp 11 | 12 | // Standard 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // Boost 20 | #include 21 | 22 | // PCL 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | // VTK 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | // PRT 39 | #include "types.hpp" 40 | #include "util.hpp" 41 | #include "Registrator.hpp" 42 | 43 | using namespace PRT; 44 | 45 | void keyboardEventOccurred (const pcl::visualization::KeyboardEvent& event, void* none); 46 | 47 | class Visualizer 48 | { 49 | public: 50 | //Types 51 | typedef boost::shared_ptr< Visualizer > Ptr; 52 | 53 | //Constructor 54 | Visualizer(const std::string &name); 55 | 56 | //Set methods 57 | void setRegistrator(const Registrator::Ptr ®istrator); 58 | void setHistogramXRange(double min = 0, double max = -1); 59 | 60 | //Toggle switches 61 | void toggleShowKeypoints(); 62 | void toggleShowSource(); 63 | void toggleShowTarget(); 64 | void toggleShowRegistered(); 65 | 66 | //Interactive methods 67 | void updateText(); 68 | void computeResidualHistogram(); 69 | void incrementResidualThreshold(); 70 | void decrementResidualThreshold(); 71 | void saveHistogramImage(std::string &filepath); 72 | 73 | void visualize(); 74 | void closeVisualizer(); 75 | 76 | private: 77 | 78 | Registrator::Ptr registrator_; 79 | pcl::visualization::PCLVisualizer::Ptr viewer_; 80 | PCLPlotterPtr plotter_; 81 | 82 | // Switches 83 | bool show_keypoints_ = false; 84 | bool show_source_ = false; 85 | bool show_target_ = false; 86 | bool show_registered_ = false; 87 | 88 | // Display states 89 | bool keypoints_visible_ = false; 90 | bool s_cloud_visible_ = false; 91 | bool t_cloud_visible_ = false; 92 | bool r_cloud_visible_ = false; 93 | bool histogram_computed_ = false; 94 | bool text_added_ = false; 95 | bool stop_ = false; 96 | 97 | // Colors 98 | RGB s_color_; 99 | RGB t_color_; 100 | RGB r_color_; 101 | RGB keypoints_color_; 102 | 103 | //Sizes 104 | double point_size_; 105 | double keypoint_size_; 106 | 107 | DoubleVectorPtr histogram_residuals_; 108 | 109 | int getNumHistogramBins(); 110 | void resetRegisteredCloud(); 111 | 112 | }; 113 | 114 | #endif /* Visualizer_hpp */ 115 | -------------------------------------------------------------------------------- /include/hsvrgb.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Jan Winkler 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright 10 | // notice, this list of conditions and the following disclaimer in the 11 | // documentation and/or other materials provided with the distribution. 12 | // * Neither the name of Universität Bremen nor the names of its 13 | // contributors may be used to endorse or promote products derived from 14 | // this software without specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | 28 | /* Author: Jan Winkler */ 29 | 30 | #ifndef hsvrgb_hpp 31 | #define hsvrgb_hpp 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace hsvrgb 38 | { 39 | void RGBtoHSV(double& fR, double& fG, double& fB, double& fH, double& fS, double& fV); 40 | void HSVtoRGB(double& fR, double& fG, double& fB, double& fH, double& fS, double& fV); 41 | 42 | } 43 | 44 | #endif // hsvrgb_hpp 45 | -------------------------------------------------------------------------------- /include/tinyply.h: -------------------------------------------------------------------------------- 1 | // This software is in the public domain. Where that dedication is not 2 | // recognized, you are granted a perpetual, irrevocable license to copy, 3 | // distribute, and modify this file as you see fit. 4 | // Authored in 2015 by Dimitri Diakopoulos (http://www.dimitridiakopoulos.com) 5 | // https://github.com/ddiakopoulos/tinyply 6 | 7 | #ifndef tinyply_h 8 | #define tinyply_h 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace tinyply 23 | { 24 | 25 | template T endian_swap(const T & v) { return v; } 26 | template<> inline uint16_t endian_swap(const uint16_t & v) { return (v << 8) | (v >> 8); } 27 | template<> inline uint32_t endian_swap(const uint32_t & v) { return (v << 24) | ((v << 8) & 0x00ff0000) | ((v >> 8) & 0x0000ff00) | (v >> 24); } 28 | template<> inline uint64_t endian_swap(const uint64_t & v) 29 | { 30 | return (((v & 0x00000000000000ffLL) << 56) | 31 | ((v & 0x000000000000ff00LL) << 40) | 32 | ((v & 0x0000000000ff0000LL) << 24) | 33 | ((v & 0x00000000ff000000LL) << 8) | 34 | ((v & 0x000000ff00000000LL) >> 8) | 35 | ((v & 0x0000ff0000000000LL) >> 24) | 36 | ((v & 0x00ff000000000000LL) >> 40) | 37 | ((v & 0xff00000000000000LL) >> 56)); 38 | } 39 | template<> inline int16_t endian_swap(const int16_t & v) { uint16_t r = endian_swap(*(uint16_t*)&v); return *(int16_t*)&r; } 40 | template<> inline int32_t endian_swap(const int32_t & v) { uint32_t r = endian_swap(*(uint32_t*)&v); return *(int32_t*)&r; } 41 | template<> inline int64_t endian_swap(const int64_t & v) { uint64_t r = endian_swap(*(uint64_t*)&v); return *(int64_t*)&r; } 42 | inline float endian_swap_float(const uint32_t & v) { uint32_t r = endian_swap(v); return *(float*)&r; } 43 | inline double endian_swap_double(const uint64_t & v) { uint64_t r = endian_swap(v); return *(double*)&r; } 44 | 45 | struct DataCursor 46 | { 47 | void * vector; 48 | uint8_t * data; 49 | size_t offset; 50 | bool realloc = false; 51 | }; 52 | 53 | class PlyProperty 54 | { 55 | void parse_internal(std::istream & is); 56 | public: 57 | 58 | enum class Type : uint8_t 59 | { 60 | INVALID, 61 | INT8, 62 | UINT8, 63 | INT16, 64 | UINT16, 65 | INT32, 66 | UINT32, 67 | FLOAT32, 68 | FLOAT64 69 | }; 70 | 71 | PlyProperty(std::istream & is); 72 | PlyProperty(Type type, const std::string & name) : propertyType(type), isList(false), name(name) {} 73 | PlyProperty(Type list_type, Type prop_type, const std::string & name, int listCount) : listType(list_type), propertyType(prop_type), isList(true), name(name), listCount(listCount) {} 74 | 75 | Type listType, propertyType; 76 | bool isList; 77 | int listCount = 0; 78 | std::string name; 79 | }; 80 | 81 | inline std::string make_key(const std::string & a, const std::string & b) 82 | { 83 | return (a + "-" + b); 84 | } 85 | 86 | template 87 | void ply_cast(void * dest, const char * src, bool be) 88 | { 89 | *(static_cast(dest)) = (be) ? endian_swap(*(reinterpret_cast(src))) : *(reinterpret_cast(src)); 90 | } 91 | 92 | template 93 | void ply_cast_float(void * dest, const char * src, bool be) 94 | { 95 | *(static_cast(dest)) = (be) ? endian_swap_float(*(reinterpret_cast(src))) : *(reinterpret_cast(src)); 96 | } 97 | 98 | template 99 | void ply_cast_double(void * dest, const char * src, bool be) 100 | { 101 | *(static_cast(dest)) = (be) ? endian_swap_double(*(reinterpret_cast(src))) : *(reinterpret_cast(src)); 102 | } 103 | 104 | template 105 | T ply_read_ascii(std::istream & is) 106 | { 107 | T data; 108 | is >> data; 109 | return data; 110 | } 111 | 112 | template 113 | void ply_cast_ascii(void * dest, std::istream & is) 114 | { 115 | *(static_cast(dest)) = ply_read_ascii(is); 116 | } 117 | 118 | struct PropertyInfo { int stride; std::string str; }; 119 | static std::map PropertyTable 120 | { 121 | { PlyProperty::Type::INT8,{ 1, "char" } }, 122 | { PlyProperty::Type::UINT8,{ 1, "uchar" } }, 123 | { PlyProperty::Type::INT16,{ 2, "short" } }, 124 | { PlyProperty::Type::UINT16,{ 2, "ushort" } }, 125 | { PlyProperty::Type::INT32,{ 4, "int" } }, 126 | { PlyProperty::Type::UINT32,{ 4, "uint" } }, 127 | { PlyProperty::Type::FLOAT32,{ 4, "float" } }, 128 | { PlyProperty::Type::FLOAT64,{ 8, "double" } }, 129 | { PlyProperty::Type::INVALID,{ 0, "INVALID" } } 130 | }; 131 | 132 | inline PlyProperty::Type property_type_from_string(const std::string & t) 133 | { 134 | if (t == "int8" || t == "char") return PlyProperty::Type::INT8; 135 | else if (t == "uint8" || t == "uchar") return PlyProperty::Type::UINT8; 136 | else if (t == "int16" || t == "short") return PlyProperty::Type::INT16; 137 | else if (t == "uint16" || t == "ushort") return PlyProperty::Type::UINT16; 138 | else if (t == "int32" || t == "int") return PlyProperty::Type::INT32; 139 | else if (t == "uint32" || t == "uint") return PlyProperty::Type::UINT32; 140 | else if (t == "float32" || t == "float") return PlyProperty::Type::FLOAT32; 141 | else if (t == "float64" || t == "double") return PlyProperty::Type::FLOAT64; 142 | return PlyProperty::Type::INVALID; 143 | } 144 | 145 | template 146 | inline uint8_t * resize(void * v, size_t newSize) 147 | { 148 | auto vec = static_cast *>(v); 149 | vec->resize(newSize); 150 | return reinterpret_cast(vec->data()); 151 | } 152 | 153 | inline void resize_vector(const PlyProperty::Type t, void * v, size_t newSize, uint8_t *& ptr) 154 | { 155 | switch (t) 156 | { 157 | case PlyProperty::Type::INT8: ptr = resize(v, newSize); break; 158 | case PlyProperty::Type::UINT8: ptr = resize(v, newSize); break; 159 | case PlyProperty::Type::INT16: ptr = resize(v, newSize); break; 160 | case PlyProperty::Type::UINT16: ptr = resize(v, newSize); break; 161 | case PlyProperty::Type::INT32: ptr = resize(v, newSize); break; 162 | case PlyProperty::Type::UINT32: ptr = resize(v, newSize); break; 163 | case PlyProperty::Type::FLOAT32: ptr = resize(v, newSize); break; 164 | case PlyProperty::Type::FLOAT64: ptr = resize(v, newSize); break; 165 | case PlyProperty::Type::INVALID: throw std::invalid_argument("invalid ply property"); 166 | } 167 | } 168 | 169 | template 170 | inline PlyProperty::Type property_type_for_type(std::vector & theType) 171 | { 172 | if (std::is_same::value) return PlyProperty::Type::INT8; 173 | else if (std::is_same::value) return PlyProperty::Type::UINT8; 174 | else if (std::is_same::value) return PlyProperty::Type::INT16; 175 | else if (std::is_same::value) return PlyProperty::Type::UINT16; 176 | else if (std::is_same::value) return PlyProperty::Type::INT32; 177 | else if (std::is_same::value) return PlyProperty::Type::UINT32; 178 | else if (std::is_same::value) return PlyProperty::Type::FLOAT32; 179 | else if (std::is_same::value) return PlyProperty::Type::FLOAT64; 180 | else return PlyProperty::Type::INVALID; 181 | } 182 | 183 | class PlyElement 184 | { 185 | void parse_internal(std::istream & is); 186 | public: 187 | PlyElement(std::istream & istream); 188 | PlyElement(const std::string & name, size_t count) : name(name), size(count) {} 189 | std::string name; 190 | size_t size; 191 | std::vector properties; 192 | }; 193 | 194 | inline int find_element(const std::string key, std::vector & list) 195 | { 196 | for (size_t i = 0; i < list.size(); ++i) 197 | { 198 | if (list[i].name == key) 199 | { 200 | return i; 201 | } 202 | } 203 | return -1; 204 | } 205 | 206 | class PlyFile 207 | { 208 | 209 | public: 210 | 211 | PlyFile() {} 212 | PlyFile(std::istream & is); 213 | 214 | void read(std::istream & is); 215 | void write(std::ostream & os, bool isBinary); 216 | 217 | std::vector & get_elements() { return elements; } 218 | 219 | std::vector comments; 220 | std::vector objInfo; 221 | 222 | template 223 | size_t request_properties_from_element(const std::string & elementKey, std::vector propertyKeys, std::vector & source, const int listCount = 1) 224 | { 225 | if (get_elements().size() == 0) 226 | return 0; 227 | 228 | if (find_element(elementKey, get_elements()) >= 0) 229 | { 230 | if (std::find(requestedElements.begin(), requestedElements.end(), elementKey) == requestedElements.end()) 231 | requestedElements.push_back(elementKey); 232 | } 233 | else return 0; 234 | 235 | // count and verify large enough 236 | auto instance_counter = [&](const std::string & elementKey, const std::string & propertyKey) 237 | { 238 | for (auto e : get_elements()) 239 | { 240 | if (e.name != elementKey) continue; 241 | for (auto p : e.properties) 242 | { 243 | if (p.name == propertyKey) 244 | { 245 | if (PropertyTable[property_type_for_type(source)].stride != PropertyTable[p.propertyType].stride) 246 | throw std::runtime_error("destination vector is wrongly typed to hold this property"); 247 | return e.size; 248 | 249 | } 250 | } 251 | } 252 | return size_t(0); 253 | }; 254 | 255 | // Check if requested key is in the parsed header 256 | std::vector unusedKeys; 257 | for (auto key : propertyKeys) 258 | { 259 | for (auto e : get_elements()) 260 | { 261 | if (e.name != elementKey) continue; 262 | std::vector headerKeys; 263 | for (auto p : e.properties) 264 | { 265 | headerKeys.push_back(p.name); 266 | } 267 | 268 | if (std::find(headerKeys.begin(), headerKeys.end(), key) == headerKeys.end()) 269 | { 270 | unusedKeys.push_back(key); 271 | } 272 | 273 | } 274 | } 275 | 276 | // Not using them? Don't let them affect the propertyKeys count used for calculating array sizes 277 | for (auto k : unusedKeys) 278 | { 279 | propertyKeys.erase(std::remove(propertyKeys.begin(), propertyKeys.end(), k), propertyKeys.end()); 280 | } 281 | if (!propertyKeys.size()) return 0; 282 | 283 | // All requested properties in the userDataTable share the same cursor (thrown into the same flat array) 284 | auto cursor = std::make_shared(); 285 | 286 | std::vector instanceCounts; 287 | 288 | for (auto key : propertyKeys) 289 | { 290 | if (int instanceCount = instance_counter(elementKey, key)) 291 | { 292 | instanceCounts.push_back(instanceCount); 293 | auto result = userDataTable.insert(std::pair>(make_key(elementKey, key), cursor)); 294 | if (result.second == false) 295 | throw std::invalid_argument("property has already been requested: " + key); 296 | } 297 | else continue; 298 | } 299 | 300 | size_t totalInstanceSize = [&]() { size_t t = 0; for (auto c : instanceCounts) { t += c; } return t; }() * listCount; 301 | source.resize(totalInstanceSize); // this satisfies regular properties; `cursor->realloc` is for list types since tinyply uses single-pass parsing 302 | cursor->offset = 0; 303 | cursor->vector = &source; 304 | cursor->data = reinterpret_cast(source.data()); 305 | 306 | if (listCount > 1) 307 | { 308 | cursor->realloc = true; 309 | return (totalInstanceSize / propertyKeys.size()) / listCount; 310 | } 311 | 312 | return totalInstanceSize / propertyKeys.size(); 313 | } 314 | 315 | template 316 | void add_properties_to_element(const std::string & elementKey, const std::vector & propertyKeys, std::vector & source, const int listCount = 1, const PlyProperty::Type listType = PlyProperty::Type::INVALID) 317 | { 318 | auto cursor = std::make_shared(); 319 | cursor->offset = 0; 320 | cursor->vector = &source; 321 | cursor->data = reinterpret_cast(source.data()); 322 | 323 | auto create_property_on_element = [&](PlyElement & e) 324 | { 325 | for (auto key : propertyKeys) 326 | { 327 | PlyProperty::Type t = property_type_for_type(source); 328 | PlyProperty newProp = (listType == PlyProperty::Type::INVALID) ? PlyProperty(t, key) : PlyProperty(listType, t, key, listCount); 329 | userDataTable.insert(std::pair>(make_key(e.name, key), cursor)); 330 | e.properties.push_back(newProp); 331 | } 332 | }; 333 | 334 | int idx = find_element(elementKey, elements); 335 | if (idx >= 0) 336 | { 337 | PlyElement & e = elements[idx]; 338 | create_property_on_element(e); 339 | } 340 | else 341 | { 342 | PlyElement newElement = (listCount == 1) ? PlyElement(elementKey, source.size() / propertyKeys.size()) : PlyElement(elementKey, source.size() / listCount); 343 | create_property_on_element(newElement); 344 | elements.push_back(newElement); 345 | } 346 | } 347 | 348 | private: 349 | 350 | size_t skip_property_binary(const PlyProperty & property, std::istream & is); 351 | void skip_property_ascii(const PlyProperty & property, std::istream & is); 352 | 353 | void read_property_binary(PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is); 354 | void read_property_ascii(PlyProperty::Type t, void * dest, size_t & destOffset, std::istream & is); 355 | void write_property_ascii(PlyProperty::Type t, std::ostream & os, uint8_t * src, size_t & srcOffset); 356 | void write_property_binary(PlyProperty::Type t, std::ostream & os, uint8_t * src, size_t & srcOffset); 357 | 358 | bool parse_header(std::istream & is); 359 | void write_header(std::ostream & os); 360 | 361 | void read_header_format(std::istream & is); 362 | void read_header_element(std::istream & is); 363 | void read_header_property(std::istream & is); 364 | void read_header_text(std::string line, std::istream & is, std::vector & place, int erase = 0); 365 | 366 | void read_internal(std::istream & is); 367 | 368 | void write_ascii_internal(std::ostream & os); 369 | void write_binary_internal(std::ostream & os); 370 | 371 | bool isBinary = false; 372 | bool isBigEndian = false; 373 | 374 | std::map> userDataTable; 375 | 376 | std::vector elements; 377 | std::vector requestedElements; 378 | }; 379 | 380 | } // namesapce tinyply 381 | 382 | #endif // tinyply_h 383 | -------------------------------------------------------------------------------- /include/types.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #ifndef types_hpp 10 | #define types_hpp 11 | 12 | // Standard 13 | #include 14 | 15 | // PCL 16 | #include 17 | #include 18 | #include 19 | 20 | // Boost 21 | #include 22 | 23 | namespace PRT { 24 | 25 | struct filepair_t { 26 | std::string sourcefile; 27 | std::string targetfile; 28 | }; 29 | 30 | struct RGB { 31 | uint8_t r; 32 | uint8_t g; 33 | uint8_t b; 34 | 35 | RGB() : r(0), g(0), b(0) {} 36 | 37 | RGB(const uint8_t r, const uint8_t g, const uint8_t b) : r(r), g(g), b(b) {} 38 | }; 39 | 40 | typedef pcl::PointXYZ PointT; 41 | typedef pcl::PointCloud PointCloudT; 42 | typedef pcl::Normal NormalT; 43 | typedef pcl::PointCloud NormalCloudT; 44 | typedef pcl::SHOT352 SHOTDescriptorT; 45 | typedef pcl::PointCloud SHOTDescriptorCloudT; 46 | typedef pcl::PointXYZRGB PointRGBT; 47 | typedef pcl::PointCloud PointCloudRGBT; 48 | 49 | typedef boost::shared_ptr< pcl::visualization::PCLPlotter > PCLPlotterPtr; 50 | 51 | typedef std::vector FloatVector; 52 | typedef boost::shared_ptr< FloatVector > FloatVectorPtr; 53 | typedef std::vector DoubleVector; 54 | typedef boost::shared_ptr< DoubleVector > DoubleVectorPtr; 55 | typedef std::vector StringVector; 56 | typedef boost::shared_ptr< StringVector > StringVectorPtr; 57 | typedef std::vector FilepairVector; 58 | typedef boost::shared_ptr< FilepairVector > FilepairVectorPtr; 59 | 60 | 61 | } 62 | 63 | #endif /* types_hpp */ 64 | -------------------------------------------------------------------------------- /include/util.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #ifndef util_hpp 10 | #define util_hpp 11 | 12 | // Standard 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | // Boost 22 | #include 23 | 24 | // Eigen 25 | #include 26 | 27 | // PCL 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | // PRT 34 | #include "types.hpp" 35 | #include "hsvrgb.hpp" 36 | #include "tinyply.h" 37 | 38 | // GFLAGS 39 | #include 40 | DECLARE_bool(verbose); 41 | 42 | using namespace PRT; 43 | 44 | namespace util 45 | { 46 | 47 | void print4x4Matrix (const Eigen::Matrix4f & matrix); 48 | double uniformRandom(); 49 | int loadPointCloud(std::string filepath, PointCloudT &cloud); 50 | int writePointCloudToPLY(std::string filepath, PointCloudT &cloud); 51 | int writePointCloudToPLY(std::string filepath, PointCloudRGBT &cloud); 52 | void transformPointCloud(PointCloudT &cloud, double alpha, double beta, double gamma, double tx, double ty, double tz); 53 | void randomTransformPointCloud(PointCloudT::Ptr &cloud); 54 | void hsv2rgb(double& r, double& g, double& b, double& h, double& s, double& v); 55 | void rgb2hsv(double& r, double& g, double& b, double& h, double& s, double& v); 56 | std::string stringTail(const std::string s, const size_t l); 57 | void vectorMin(DoubleVectorPtr &v, double min); 58 | void removeElementsAboveThreshold(DoubleVectorPtr &v, double threshold); 59 | void vectorRescale(DoubleVectorPtr &v, double max_element); 60 | int writeMatrixToFile(const Eigen::MatrixXf &matrix, const std::string filepath); 61 | FilepairVectorPtr readBatchProcessingFile(std::string filepath); 62 | int ensureUniqueFilepath(std::string &filepath); 63 | bool fileExists(const std::string& filepath); 64 | std::string extractFileExtension(const std::string &filepath); 65 | std::string removeFileExtension(const std::string &filepath); 66 | void writeStringToFile(const std::string& filepath, const std::string s); 67 | } 68 | 69 | 70 | #endif /* util_hpp */ 71 | -------------------------------------------------------------------------------- /src/Visualizer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #include "Visualizer.hpp" 10 | 11 | void keyboardEventOccurred (const pcl::visualization::KeyboardEvent& event, void* obj) { 12 | 13 | Visualizer* vis = (Visualizer*) obj; 14 | 15 | if (event.getKeySym () == "s" && event.keyDown ()) 16 | vis->toggleShowSource(); 17 | 18 | if (event.getKeySym () == "t" && event.keyDown ()) 19 | vis->toggleShowTarget(); 20 | 21 | if (event.getKeySym () == "r" && event.keyDown ()) 22 | vis->toggleShowRegistered(); 23 | 24 | if (event.getKeySym () == "k" && event.keyDown ()) 25 | vis->toggleShowKeypoints(); 26 | 27 | if (event.getKeySym () == "Up" && event.keyDown ()) 28 | vis->incrementResidualThreshold(); 29 | 30 | if (event.getKeySym () == "Down" && event.keyDown ()) 31 | vis->decrementResidualThreshold(); 32 | 33 | } 34 | 35 | Visualizer::Visualizer(const std::string &name) { 36 | 37 | viewer_ = pcl::visualization::PCLVisualizer::Ptr(new pcl::visualization::PCLVisualizer(name)); 38 | viewer_->setBackgroundColor(0,0,0); 39 | viewer_->setCameraPosition (-7.5, 0, 7.5, 0, 0, 1, 0); 40 | viewer_->setSize (1024, 768); 41 | viewer_->registerKeyboardCallback (&keyboardEventOccurred, this); 42 | viewer_->setShowFPS(false); 43 | 44 | plotter_ = PCLPlotterPtr(new pcl::visualization::PCLPlotter); 45 | plotter_->setTitle("Residuals Histogram"); 46 | plotter_->setXTitle("Distance (m)"); 47 | plotter_->setYTitle("Frequency"); 48 | plotter_->setShowLegend(false); 49 | 50 | registrator_ = Registrator::Ptr(); 51 | 52 | s_color_ = RGB(0, 0, 255); //Blue 53 | t_color_ = RGB(0, 255, 0); // Green 54 | r_color_ = RGB(255, 0, 0); // Red 55 | keypoints_color_ = RGB(255, 255, 0); // Yellow 56 | 57 | show_source_ = false; 58 | show_target_ = false; 59 | show_registered_ = true; 60 | 61 | histogram_residuals_ = DoubleVectorPtr(new DoubleVector()); 62 | 63 | point_size_ = 1.5; 64 | keypoint_size_ = 3; 65 | } 66 | 67 | void Visualizer::setRegistrator(const Registrator::Ptr ®istrator) { 68 | registrator_ = registrator; 69 | } 70 | 71 | void Visualizer::incrementResidualThreshold() { 72 | registrator_->setResidualThreshold((registrator_->getResidualThreshold() < 1) ? registrator_->getResidualThreshold() + 0.01 : registrator_->getResidualThreshold()); 73 | registrator_->computeResidualColormap(); 74 | 75 | updateText(); 76 | setHistogramXRange(); 77 | computeResidualHistogram(); 78 | resetRegisteredCloud(); 79 | } 80 | 81 | void Visualizer::decrementResidualThreshold() { 82 | registrator_->setResidualThreshold((registrator_->getResidualThreshold() >= .02) ? registrator_->getResidualThreshold() - 0.01 : registrator_->getResidualThreshold()); 83 | registrator_->computeResidualColormap(); 84 | 85 | updateText(); 86 | setHistogramXRange(); 87 | computeResidualHistogram(); 88 | resetRegisteredCloud(); 89 | } 90 | 91 | int Visualizer::getNumHistogramBins() { 92 | return 2 * std::max((int)(registrator_->getResidualThreshold() * 100),1); //One bar represents 0.5cm 93 | } 94 | 95 | void Visualizer::setHistogramXRange(double min, double max) { 96 | 97 | if (max == -1) 98 | max = registrator_->getResidualThreshold(); 99 | 100 | plotter_->setXRange(min, max); 101 | } 102 | 103 | void Visualizer::toggleShowKeypoints() { 104 | show_keypoints_ = !show_keypoints_; 105 | } 106 | 107 | void Visualizer::toggleShowSource() { 108 | show_source_ = !show_source_; 109 | } 110 | 111 | void Visualizer::toggleShowTarget() { 112 | show_target_ = !show_target_; 113 | } 114 | 115 | void Visualizer::toggleShowRegistered() { 116 | show_registered_ = !show_registered_; 117 | } 118 | 119 | void Visualizer::updateText() { 120 | 121 | if (text_added_) { 122 | 123 | std::stringstream ss; 124 | ss << "f-score @ threshold = " << registrator_->getFScoreAtThreshold(registrator_->getResidualThreshold()); 125 | viewer_->updateText(ss.str(), 50, 175, "fscore"); 126 | 127 | ss.str(std::string()); // Clear stringstream 128 | ss << "max residual threshold = " << registrator_->getResidualThreshold() << " (modify: up/down)"; 129 | viewer_->updateText(ss.str(), 50, 200, "max_residual_threshold"); 130 | 131 | } 132 | } 133 | 134 | void Visualizer::resetRegisteredCloud() { 135 | 136 | if (r_cloud_visible_) { 137 | viewer_->removePointCloud("r_cloud"); 138 | r_cloud_visible_ = false; 139 | } 140 | 141 | if (show_registered_) { 142 | pcl::visualization::PointCloudColorHandlerRGBField color(registrator_->getRegisteredRGBCloud()); 143 | viewer_->addPointCloud (registrator_->getRegisteredRGBCloud(), color, "r_cloud"); 144 | r_cloud_visible_ = true; 145 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size_, "r_cloud"); 146 | } 147 | 148 | } 149 | 150 | void Visualizer::computeResidualHistogram() { 151 | 152 | if (histogram_residuals_->size() != registrator_->getRegisteredToTargetResiduals()->size()) 153 | histogram_residuals_->resize(registrator_->getRegisteredToTargetResiduals()->size()); 154 | 155 | std::copy(registrator_->getRegisteredToTargetResiduals()->begin(), registrator_->getRegisteredToTargetResiduals()->end(), histogram_residuals_->begin()); 156 | 157 | util::removeElementsAboveThreshold(histogram_residuals_, registrator_->getResidualThreshold()); //Remove residual values above residual_threshold_ 158 | 159 | if (!histogram_computed_) { 160 | plotter_->clearPlots(); 161 | plotter_->addHistogramData(*histogram_residuals_, getNumHistogramBins()); 162 | } else { 163 | #if VTK_MAJOR_VERSION > 6 164 | plotter_->clearPlots(); 165 | plotter_->addHistogramData(*histogram_residuals_, getNumHistogramBins()); 166 | #endif 167 | } 168 | 169 | histogram_computed_ = true; 170 | } 171 | 172 | void Visualizer::saveHistogramImage(std::string &filepath) { 173 | 174 | if (!histogram_computed_) 175 | computeResidualHistogram(); 176 | 177 | plotter_->spinOnce(); 178 | 179 | vtkWindowToImageFilter* wif = vtkWindowToImageFilter::New(); 180 | wif->Modified(); 181 | wif->SetInput(plotter_->getRenderWindow()); 182 | wif->SetInputBufferTypeToRGB(); 183 | wif->Update(); 184 | 185 | vtkPNGWriter* screenshot_writer = vtkPNGWriter::New(); 186 | 187 | #if VTK_MAJOR_VERSION<6 188 | screenshot_writer->SetInput(wif->GetOutput()); 189 | #else 190 | screenshot_writer->SetInputData(wif->GetOutput()); 191 | #endif 192 | screenshot_writer->SetFileName (filepath.c_str()); 193 | screenshot_writer->Write(); 194 | screenshot_writer->Delete(); 195 | 196 | wif->Delete(); 197 | 198 | #if VTK_MAJOR_VERSION < 6 199 | plotter_->clearPlots(); 200 | plotter_->close(); 201 | plotter_->getRenderWindow()->Delete(); 202 | #endif 203 | 204 | } 205 | 206 | void Visualizer::visualize() { 207 | 208 | if (!histogram_computed_) 209 | computeResidualHistogram(); 210 | 211 | while (!viewer_->wasStopped()) 212 | { 213 | viewer_->spinOnce(); 214 | #if VTK_MAJOR_VERSION > 6 215 | plotter_->spinOnce(); 216 | #endif 217 | 218 | //Registered 219 | if (show_registered_ && !registrator_->getRegisteredRGBCloud()->empty() && !r_cloud_visible_) { 220 | 221 | pcl::visualization::PointCloudColorHandlerRGBField color(registrator_->getRegisteredRGBCloud()); 222 | viewer_->addPointCloud (registrator_->getRegisteredRGBCloud(), color, "r_cloud"); 223 | r_cloud_visible_ = true; 224 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size_, "r_cloud"); 225 | } else if (!show_registered_ && r_cloud_visible_) { 226 | viewer_->removePointCloud("r_cloud"); 227 | r_cloud_visible_ = false; 228 | } 229 | 230 | //Source 231 | if (show_source_ && !registrator_->getSourceCloud()->empty() && !s_cloud_visible_) { 232 | pcl::visualization::PointCloudColorHandlerCustom s_cloud_color_h (registrator_->getSourceCloud(), s_color_.r, s_color_.g, s_color_.b); 233 | viewer_->addPointCloud (registrator_->getSourceCloud(), s_cloud_color_h, "s_cloud"); 234 | s_cloud_visible_ = true; 235 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size_, "s_cloud"); 236 | } else if (!show_source_ && s_cloud_visible_) { 237 | viewer_->removePointCloud("s_cloud"); 238 | s_cloud_visible_ = false; 239 | } 240 | 241 | //Target 242 | if (show_target_ && !registrator_->getTargetCloud()->empty() && !t_cloud_visible_) { 243 | pcl::visualization::PointCloudColorHandlerCustom t_cloud_color_h (registrator_->getTargetCloud(), t_color_.r, t_color_.g, t_color_.b); 244 | viewer_->addPointCloud (registrator_->getTargetCloud(), t_cloud_color_h, "t_cloud"); 245 | t_cloud_visible_ = true; 246 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, point_size_, "t_cloud"); 247 | } else if (!show_target_ && t_cloud_visible_) { 248 | viewer_->removePointCloud("t_cloud"); 249 | t_cloud_visible_ = false; 250 | } 251 | 252 | //Source Keypoints 253 | if (show_keypoints_ && !keypoints_visible_) { 254 | 255 | if (!registrator_->getSourceKeypointsCloud()->empty()) { 256 | pcl::visualization::PointCloudColorHandlerCustom s_cloud_keypoints_color_h (registrator_->getSourceKeypointsCloud(), keypoints_color_.r, keypoints_color_.g, keypoints_color_.b); 257 | viewer_->addPointCloud (registrator_->getSourceKeypointsCloud(), s_cloud_keypoints_color_h, "s_cloud_keypoints"); 258 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, keypoint_size_, "s_cloud_keypoints"); 259 | keypoints_visible_ = true; 260 | } 261 | 262 | if (!registrator_->getSourceKeypointsCloud()->empty()) { 263 | pcl::visualization::PointCloudColorHandlerCustom t_cloud_keypoints_color_h (registrator_->getTargetKeypointsCloud(), keypoints_color_.r, keypoints_color_.g, keypoints_color_.b); 264 | viewer_->addPointCloud (registrator_->getTargetKeypointsCloud(), t_cloud_keypoints_color_h, "t_cloud_keypoints"); 265 | viewer_->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, keypoint_size_, "t_cloud_keypoints"); 266 | keypoints_visible_ = true; 267 | } 268 | 269 | } else if (!show_keypoints_ && keypoints_visible_) { 270 | viewer_->removePointCloud("s_cloud_keypoints"); 271 | viewer_->removePointCloud("t_cloud_keypoints"); 272 | keypoints_visible_ = false; 273 | } 274 | 275 | //Text 276 | if (!text_added_) { 277 | std::string command_panel = "S: toggle source cloud\nT: toggle target cloud\nR: toggle registered cloud\nK: toggle keypoints\nF: adjust center of revolution\nQ: quit"; 278 | viewer_->addText(command_panel, 50, 75, 15, 1, 1, 1, "command_panel"); 279 | 280 | std::stringstream ss; 281 | ss << "f-score @ threshold = " << registrator_->getFScoreAtThreshold(registrator_->getResidualThreshold()); 282 | viewer_->addText(ss.str(), 50, 175, 15, 1, 1, 1, "fscore"); 283 | 284 | ss.str(std::string()); // Clear stringstream 285 | ss << "max residual threshold = " << registrator_->getResidualThreshold() << " (modify: up/down)"; 286 | viewer_->addText(ss.str(), 50, 200, 15, 1, 1, 1, "max_residual_threshold"); 287 | 288 | text_added_ = true; 289 | } 290 | } 291 | 292 | } 293 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #ifdef _OPENMP 10 | #include 11 | #endif 12 | 13 | // Standard 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // PRT 21 | #include "util.hpp" 22 | #include "types.hpp" 23 | #include "Registrator.hpp" 24 | #include "Visualizer.hpp" 25 | 26 | // GFLAGS 27 | #include 28 | 29 | DECLARE_bool(help); 30 | DEFINE_bool(h, false, "Show help"); 31 | DEFINE_bool(gui, false, "launch GUI after registration"); 32 | DEFINE_string(batch_file, "", "path to batch processing file"); 33 | DEFINE_string(transformation_matrix_filepath, "[source_filename]_transform.csv", "filepath to output transformation matrix CSV"); 34 | DEFINE_string(registered_pointcloud_filepath, "[source_filename]_registered.ply", "filepath to output registered point cloud PLY"); 35 | DEFINE_string(residual_histogram_image_filepath, "[source_filename]_histogram.png", "filepath to output histogram PNG"); 36 | DEFINE_string(fscore_filepath, "[source_filename]_fscore.txt", "filepath to output f-score TXT"); 37 | 38 | #ifdef _OPENMP 39 | DEFINE_bool(no_parallel, false, "run single-threaded"); 40 | #endif 41 | 42 | using namespace PRT; 43 | 44 | int main (int argc, char* argv[]) { 45 | 46 | std::string usage_message = "\nUsage:\n\n1. ./point_cloud_registration_tool [options] \n2. ./point_cloud_registration_tool [options] --batch_file \n\nA batch file is a two-column CSV. First column: source point cloud filepaths, second column: target point cloud filepaths.\n\nSee --help for optional arguments\n"; 47 | gflags::SetUsageMessage(usage_message); 48 | 49 | gflags::ParseCommandLineFlags(&argc, &argv, true); 50 | 51 | if (FLAGS_descriptor_radius <= 0) { 52 | std::cout << "Error: Descriptor radius must be a positive value." << std::endl; 53 | return -1; 54 | } 55 | 56 | if (FLAGS_subsampling_radius <= 0) { 57 | std::cout << "Error: Subsampling radius must be a positive value." << std::endl; 58 | return -1; 59 | } 60 | 61 | if (FLAGS_consensus_inlier_threshold <= 0) { 62 | std::cout << "Error: Consensus inlier threshold must be a positive value." << std::endl; 63 | return -1; 64 | } 65 | 66 | if (FLAGS_icp_max_correspondence_distance <= 0) { 67 | std::cout << "Error: Maximum correspondence distance must be a positive value." << std::endl; 68 | return -1; 69 | } 70 | 71 | if (FLAGS_residual_threshold <= 0) { 72 | std::cout << "Error: Residual threshold must be a positive value." << std::endl; 73 | return -1; 74 | } 75 | 76 | if (FLAGS_h) { 77 | FLAGS_help = true; 78 | gflags::HandleCommandLineHelpFlags(); 79 | exit(0); 80 | } 81 | 82 | if (argc < 3 && FLAGS_batch_file.empty()) { 83 | std::cout << usage_message << std::endl; 84 | return 0; 85 | } 86 | 87 | pcl::console::setVerbosityLevel(pcl::console::L_ALWAYS); 88 | 89 | FilepairVectorPtr filepairs; 90 | if (!FLAGS_batch_file.empty()) { 91 | 92 | filepairs = util::readBatchProcessingFile(FLAGS_batch_file); 93 | 94 | if(filepairs->empty()) { 95 | std::cout << "Invalid batch file path, exiting." << std::endl; 96 | return -1; 97 | } 98 | 99 | FLAGS_gui = false; 100 | 101 | } else { 102 | 103 | filepair_t pair; 104 | pair.sourcefile = argv[1]; 105 | pair.targetfile = argv[2]; 106 | filepairs = FilepairVectorPtr(new FilepairVector()); 107 | filepairs->push_back(pair); 108 | 109 | } 110 | 111 | #ifdef _OPENMP 112 | omp_set_nested(true); 113 | if (FLAGS_no_parallel) 114 | omp_set_num_threads(1); 115 | else 116 | if (FLAGS_verbose) 117 | std::cout << "Executing in parallel" << std::endl; 118 | #endif 119 | 120 | for(FilepairVector::size_type i = 0; i < filepairs->size(); i++) { 121 | 122 | PointCloudT::Ptr target_cloud (new PointCloudT); 123 | target_cloud->clear(); 124 | std::string target_cloud_filepath = filepairs->at(i).targetfile; 125 | 126 | PointCloudT::Ptr source_cloud (new PointCloudT); 127 | source_cloud->clear(); 128 | std::string source_cloud_filepath = filepairs->at(i).sourcefile; 129 | bool reads_successful = true; 130 | 131 | if (util::loadPointCloud(source_cloud_filepath, *source_cloud) != 0) { 132 | std::cout << "Invalid input:" << std::endl << source_cloud_filepath << std::endl; 133 | std::cout << "Skipping.." << std::endl; 134 | reads_successful = false; 135 | } 136 | 137 | if (util::loadPointCloud(target_cloud_filepath, *target_cloud) != 0) { 138 | std::cout << "Invalid input:" << std::endl << target_cloud_filepath << std::endl; 139 | std::cout << "Skipping.." << std::endl; 140 | reads_successful = false; 141 | } 142 | 143 | if(!reads_successful) 144 | continue; 145 | 146 | //Extract prefix for output files 147 | std::string prefix = util::removeFileExtension(filepairs->at(i).sourcefile); 148 | 149 | //Set output file paths 150 | std::string transformation_matrix_filepath; 151 | std::string registered_pointcloud_filepath; 152 | std::string residual_histogram_image_filepath; 153 | std::string fscore_filepath; 154 | 155 | if (FLAGS_transformation_matrix_filepath != "[source_filename]_transform.csv") 156 | transformation_matrix_filepath = FLAGS_transformation_matrix_filepath; 157 | else 158 | transformation_matrix_filepath = prefix + "_transform.csv"; 159 | 160 | if (FLAGS_registered_pointcloud_filepath != "[source_filename]_registered.ply") 161 | registered_pointcloud_filepath = FLAGS_registered_pointcloud_filepath; 162 | else 163 | registered_pointcloud_filepath = prefix + "_registered.ply"; 164 | 165 | if (FLAGS_residual_histogram_image_filepath != "[source_filename]_histogram.png") 166 | residual_histogram_image_filepath = FLAGS_residual_histogram_image_filepath; 167 | else 168 | residual_histogram_image_filepath = prefix + "_residual_histogram.png"; 169 | 170 | if (FLAGS_fscore_filepath != "[source_filename]_fscore.txt") 171 | fscore_filepath = FLAGS_fscore_filepath; 172 | else 173 | fscore_filepath = prefix + "_fscore.txt"; 174 | 175 | //Ensure unique output filepaths 176 | if (util::ensureUniqueFilepath(transformation_matrix_filepath) != 0) { 177 | std::cout << "Failed to create transformation matrix file." << std::endl; 178 | continue; 179 | } 180 | 181 | if (util::ensureUniqueFilepath(fscore_filepath) != 0) { 182 | std::cout << "Failed to create f-score file." << std::endl; 183 | continue; 184 | } 185 | 186 | if (util::ensureUniqueFilepath(registered_pointcloud_filepath) != 0) { 187 | std::cout << "Failed to create registered PLY file." << std::endl; 188 | continue; 189 | } 190 | 191 | if (util::ensureUniqueFilepath(residual_histogram_image_filepath) != 0) { 192 | std::cout << "Failed to create residual histogram file." << std::endl; 193 | continue; 194 | } 195 | 196 | //Registration 197 | //Setup 198 | Registrator::Ptr registrator (new Registrator()); 199 | registrator->setNumKSearchNeighbors(FLAGS_num_ksearch_neighbors); 200 | registrator->setDescriptorRadius(FLAGS_descriptor_radius); 201 | registrator->setSubsamplingRadius(FLAGS_subsampling_radius); 202 | registrator->setConsensusInlierThreshold(FLAGS_consensus_inlier_threshold); 203 | registrator->setConsensusMaxIterations(FLAGS_consensus_max_iterations); 204 | registrator->setICPMaxIterations(FLAGS_icp_max_iterations); 205 | registrator->setICPMaxCorrespondenceDistance(FLAGS_icp_max_correspondence_distance); 206 | registrator->setResidualThreshold(FLAGS_residual_threshold); 207 | registrator->setTargetCloud(target_cloud); 208 | registrator->setSourceCloud(source_cloud); 209 | 210 | //Compute 211 | registrator->performRegistration(FLAGS_registration_technique); 212 | 213 | //Save Results 214 | 215 | registrator->saveResidualColormapPointCloud(registered_pointcloud_filepath); 216 | registrator->saveFinalTransform(transformation_matrix_filepath); 217 | registrator->saveFScoreAtThreshold(fscore_filepath, FLAGS_residual_threshold); 218 | 219 | std::cout << "Registration of " << source_cloud_filepath << " finished" << std::endl; 220 | std::cout << "F-score: " << registrator->getFScoreAtThreshold() << std::endl; 221 | std::cout << "Saved to: " << registered_pointcloud_filepath << std::endl; 222 | 223 | if (!FLAGS_gui) 224 | continue; 225 | 226 | //Visualization 227 | Visualizer visualizer ("Point Cloud Registration Tool"); 228 | visualizer.setRegistrator(registrator); 229 | visualizer.saveHistogramImage(residual_histogram_image_filepath); 230 | visualizer.visualize(); 231 | 232 | } 233 | 234 | return 0; 235 | } 236 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Point Cloud Registration Tool 3 | 4 | BSD 2-Clause License 5 | Copyright (c) 2017, Dario Rethage 6 | See LICENSE at package root for full license 7 | */ 8 | 9 | #include "util.hpp" 10 | #define TINYOBJLOADER_IMPLEMENTATION 11 | #include "tiny_obj_loader.h" 12 | 13 | DEFINE_bool(verbose, false, "enable verbosity"); 14 | 15 | namespace util 16 | { 17 | static std::random_device rd; 18 | static std::mt19937 rng(rd()); 19 | std::uniform_int_distribution<> dist (0, 100); 20 | 21 | /** 22 | Print 4x4 in human readable form 23 | */ 24 | void print4x4Matrix (const Eigen::Matrix4f & matrix) 25 | { 26 | printf (" | %6.3f %6.3f %6.3f | \n", matrix (0, 0), matrix (0, 1), matrix (0, 2)); 27 | printf ("R = | %6.3f %6.3f %6.3f | \n", matrix (1, 0), matrix (1, 1), matrix (1, 2)); 28 | printf (" | %6.3f %6.3f %6.3f | \n", matrix (2, 0), matrix (2, 1), matrix (2, 2)); 29 | printf ("t = < %6.3f, %6.3f, %6.3f >\n", matrix (0, 3), matrix (1, 3), matrix (2, 3)); 30 | } 31 | 32 | 33 | /** 34 | Uniformly randomly sample number in the range [0,1] 35 | */ 36 | double uniformRandom() { 37 | return (double)dist(rng) / 100.0; 38 | } 39 | 40 | 41 | /** 42 | Load point cloud from disk 43 | */ 44 | int loadPointCloud(std::string filepath, pcl::PointCloud &cloud) { 45 | 46 | if (filepath.empty()) 47 | return -1; 48 | 49 | std::string file_extension = extractFileExtension(filepath); 50 | std::transform(file_extension.begin(), file_extension.end(), file_extension.begin(), ::tolower); //Convert to lowercase 51 | 52 | if (file_extension.compare(".ply") == 0) { 53 | 54 | try { 55 | 56 | std::ifstream fs(filepath, std::ios::binary); 57 | tinyply::PlyFile ply_file(fs); 58 | std::vector vertices; 59 | 60 | uint32_t vertex_count = ply_file.request_properties_from_element("vertex", { "x", "y", "z" }, vertices); 61 | 62 | if (vertex_count == 0) 63 | return -1; 64 | 65 | ply_file.read(fs); 66 | 67 | cloud.width = vertex_count; 68 | cloud.height = 1; 69 | cloud.is_dense = false; 70 | cloud.points.resize(vertex_count); 71 | 72 | size_t j = 0; 73 | for (size_t i = 0; i < vertices.size(); i+=3, j++) { 74 | cloud.points[j].x = vertices[i]; 75 | cloud.points[j].y = vertices[i+1]; 76 | cloud.points[j].z = vertices[i+2]; 77 | } 78 | 79 | } catch (const std::exception& e) { 80 | return -1; 81 | } 82 | 83 | } else if (file_extension.compare(".obj") == 0) { 84 | 85 | tinyobj::attrib_t attrib; 86 | std::vector shapes; 87 | std::vector materials; 88 | 89 | std::string err; 90 | bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filepath.c_str()); 91 | 92 | if (!err.empty()) { // `err` may contain warning message. 93 | std::cerr << err << std::endl; 94 | } 95 | 96 | if (!ret) { 97 | return -1; 98 | } 99 | 100 | int num_vertices = attrib.vertices.size(); 101 | 102 | cloud.points.resize(num_vertices/3); 103 | cloud.width = cloud.points.size(); 104 | cloud.height = 1; 105 | cloud.is_dense = false; 106 | 107 | int i = 0; 108 | for (size_t v = 0; v < num_vertices; v+=3, i++) 109 | cloud.points[i] = PointT(attrib.vertices[v], attrib.vertices[v+1], attrib.vertices[v+2]); 110 | 111 | } else { 112 | return -1; 113 | } 114 | 115 | if(FLAGS_verbose) { 116 | std::cout << "Loaded point cloud with " << cloud.size() << " points:" << std::endl; 117 | std::cout << filepath << std::endl; 118 | } 119 | 120 | return 0; 121 | } 122 | 123 | 124 | /** 125 | Write XYZ point cloud to disk in PLY format 126 | */ 127 | int writePointCloudToPLY(std::string filepath, PointCloudT &cloud) { 128 | 129 | if (filepath.empty()) 130 | return -1; 131 | 132 | std::string file_extension = extractFileExtension(filepath); 133 | std::transform(file_extension.begin(), file_extension.end(), file_extension.begin(), ::tolower); //Convert to lowercase 134 | 135 | if (file_extension.compare(".ply") != 0) 136 | filepath.append(".ply"); 137 | 138 | if (pcl::io::savePLYFile (filepath, cloud) < 0) 139 | { 140 | std::cout << "Error saving cloud "<< filepath << std::endl; 141 | return -1; 142 | } 143 | 144 | return 0; 145 | 146 | } 147 | 148 | /** 149 | Write XYZRGBA point cloud to disk in PLY or OBJ format 150 | */ 151 | int writePointCloudToPLY(std::string filepath, PointCloudRGBT &cloud) { 152 | 153 | if (filepath.empty()) 154 | return -1; 155 | 156 | std::string file_extension = extractFileExtension(filepath); 157 | std::transform(file_extension.begin(), file_extension.end(), file_extension.begin(), ::tolower); //Convert to lowercase 158 | 159 | if (file_extension.compare(".ply") != 0) 160 | filepath.append(".ply"); 161 | 162 | if (pcl::io::savePLYFile (filepath, cloud) < 0) 163 | { 164 | std::cout << "Error saving cloud "<< filepath << std::endl; 165 | return -1; 166 | } 167 | 168 | return 0; 169 | 170 | } 171 | 172 | 173 | /** 174 | Transform a PointCloud 175 | */ 176 | void transformPointCloud(PointCloudT::Ptr &cloud, double alpha, double beta, double gamma, double tx, double ty, double tz) { 177 | 178 | Eigen::Affine3f T = Eigen::Affine3f::Identity(); 179 | 180 | T.translation() << tx, ty, tz; 181 | T.rotate(Eigen::AngleAxisf(alpha, Eigen::Vector3f::UnitX())); 182 | T.rotate(Eigen::AngleAxisf(beta, Eigen::Vector3f::UnitY())); 183 | T.rotate(Eigen::AngleAxisf(gamma, Eigen::Vector3f::UnitZ())); 184 | 185 | if(FLAGS_verbose) { 186 | std::cout << "Applying Transformation:" << std::endl; 187 | util::print4x4Matrix (T.matrix()); 188 | } 189 | 190 | pcl::transformPointCloud (*cloud, *cloud, T); 191 | 192 | } 193 | 194 | 195 | /** 196 | Transform a PointCloud with randomly chosen parameters 197 | Angles in the range [0,2pi] 198 | Translation in the range [-1,1] 199 | */ 200 | void randomTransformPointCloud(PointCloudT::Ptr &cloud) { 201 | 202 | double alpha = 2.0 * M_PI * uniformRandom(); 203 | double beta = 2.0 * M_PI * uniformRandom(); 204 | double gamma = 2.0 * M_PI * uniformRandom(); 205 | double tx = 2.0*uniformRandom() - 1.0; 206 | double ty = 2.0*uniformRandom() - 1.0; 207 | double tz = 2.0*uniformRandom() - 1.0; 208 | 209 | transformPointCloud(cloud, alpha, beta, gamma, tx, ty, tz); 210 | } 211 | 212 | /** 213 | Converts HSV color to RGB 214 | Everything in [0,1] range except h in [0,360] range 215 | */ 216 | void hsv2rgb(double& r, double& g, double& b, double& h, double& s, double& v) { 217 | hsvrgb::HSVtoRGB(r, g, b, h, s, v); 218 | } 219 | 220 | /** 221 | Converts RGB color to HSV 222 | Everything in [0,1] range except h in [0,360] range 223 | */ 224 | void rgb2hsv(double& r, double& g, double& b, double& h, double& s, double& v) { 225 | hsvrgb::HSVtoRGB(r, g, b, h, s, v); 226 | } 227 | 228 | /** 229 | Return the last l characters of the input string 230 | */ 231 | std::string stringTail(const std::string s, const size_t l) { 232 | if (l >= s.size()) { return s; } 233 | return s.substr(s.size() - l); 234 | } 235 | 236 | /** 237 | Returns a vector with the largest element being 'min' 238 | */ 239 | void vectorMin(DoubleVectorPtr &v, double min) { 240 | 241 | for(DoubleVector::iterator it = v->begin(); it != v->end(); it++) 242 | *it = std::min(*it, min); 243 | 244 | } 245 | 246 | /** 247 | Rescales values in the vector to a [0,1] range 248 | */ 249 | void vectorRescale(DoubleVectorPtr &v, double max_element = -1) { 250 | 251 | if (max_element == -1) 252 | max_element = *std::max_element(v->begin(), v->end()); 253 | 254 | for(DoubleVector::iterator it = v->begin(); it != v->end(); it++) 255 | *it /= max_element; 256 | 257 | } 258 | 259 | 260 | /** 261 | Remove all elements in vector above 'threshold' 262 | */ 263 | void removeElementsAboveThreshold(DoubleVectorPtr &v, double threshold) { 264 | v->erase(std::remove_if(v->begin(), v->end(), boost::bind(std::greater(), _1, threshold)), v->end()); 265 | } 266 | 267 | 268 | /** 269 | Writes an Eigen matrix to disk 270 | */ 271 | int writeMatrixToFile(const Eigen::MatrixXf &matrix, const std::string filepath) { 272 | 273 | Eigen::IOFormat format(Eigen::FullPrecision, 0, ",", "\n", "", "", "", ""); 274 | std::ofstream outfile(filepath); 275 | 276 | if (outfile.is_open()) { 277 | outfile << matrix.format(format); 278 | return 0; 279 | } 280 | return -1; 281 | } 282 | 283 | 284 | /** 285 | Reads in an ascii file containing mesh pairs to be registered 286 | Expects two filepaths per line, comma separated without spaces 287 | First filepath is to the target point cloud, second is to the source point cloud 288 | */ 289 | FilepairVectorPtr readBatchProcessingFile(std::string filepath) { 290 | 291 | FilepairVectorPtr filepairs (new FilepairVector()); 292 | std::ifstream batchfile(filepath); 293 | 294 | if (!batchfile.is_open()) 295 | return filepairs; 296 | 297 | std::string line; 298 | while (std::getline(batchfile, line)) 299 | { 300 | if (line[0] == '#') 301 | continue; 302 | 303 | int comma_pos = line.find(','); 304 | 305 | filepair_t pair; 306 | pair.sourcefile = line.substr(0, comma_pos); 307 | pair.targetfile = line.substr(comma_pos+1, std::string::npos); 308 | filepairs->push_back(pair); 309 | } 310 | 311 | return filepairs; 312 | } 313 | 314 | std::string removeFileExtension(const std::string &filepath) { 315 | 316 | std::size_t ext_begin_pos = filepath.find_last_of('.'); 317 | return filepath.substr(0, ext_begin_pos); 318 | 319 | } 320 | 321 | std::string extractFileExtension(const std::string &filepath) { 322 | 323 | std::size_t ext_begin_pos = filepath.find_last_of('.'); 324 | if (ext_begin_pos == std::string::npos) 325 | return ""; 326 | return filepath.substr(ext_begin_pos, std::string::npos); 327 | 328 | } 329 | 330 | int ensureUniqueFilepath(std::string &filepath) { 331 | 332 | if (!fileExists(filepath)) 333 | return 0; 334 | 335 | std::string filepath_without_ext = removeFileExtension(filepath); 336 | std::string filepath_ext = extractFileExtension(filepath); 337 | 338 | int i = 1; 339 | while(i < 100) { 340 | std::stringstream ss; 341 | ss << filepath_without_ext << "_" << i++ << filepath_ext; 342 | if (!fileExists(ss.str())) { 343 | filepath = ss.str(); 344 | return 0; 345 | } 346 | } 347 | 348 | return -1; 349 | 350 | } 351 | 352 | bool fileExists (const std::string& filepath) { 353 | struct stat buffer; 354 | return (stat (filepath.c_str(), &buffer) == 0); 355 | } 356 | 357 | void writeStringToFile(const std::string& filepath, const std::string s) { 358 | 359 | std::ofstream out(filepath); 360 | out << s; 361 | out.close(); 362 | 363 | } 364 | 365 | } 366 | --------------------------------------------------------------------------------