kopia lustrzana https://github.com/OpenDroneMap/ODM
commit
25a246dbae
|
@ -16,7 +16,7 @@ RUN apt-get install --no-install-recommends -y git cmake python-pip build-essent
|
||||||
libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libflann-dev \
|
libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libflann-dev \
|
||||||
libproj-dev libxext-dev liblapack-dev libeigen3-dev libvtk5-dev python-networkx libgoogle-glog-dev libsuitesparse-dev libboost-filesystem-dev libboost-iostreams-dev \
|
libproj-dev libxext-dev liblapack-dev libeigen3-dev libvtk5-dev python-networkx libgoogle-glog-dev libsuitesparse-dev libboost-filesystem-dev libboost-iostreams-dev \
|
||||||
libboost-regex-dev libboost-python-dev libboost-date-time-dev libboost-thread-dev python-pyproj python-empy python-nose python-pyside python-pyexiv2 python-scipy \
|
libboost-regex-dev libboost-python-dev libboost-date-time-dev libboost-thread-dev python-pyproj python-empy python-nose python-pyside python-pyexiv2 python-scipy \
|
||||||
jhead liblas-bin python-matplotlib libatlas-base-dev libgmp-dev libmpfr-dev swig2.0 python-wheel libboost-log-dev libjsoncpp-dev
|
libexiv2-dev liblas-bin python-matplotlib libatlas-base-dev libgmp-dev libmpfr-dev swig2.0 python-wheel libboost-log-dev libjsoncpp-dev
|
||||||
|
|
||||||
RUN apt-get remove libdc1394-22-dev
|
RUN apt-get remove libdc1394-22-dev
|
||||||
RUN pip install --upgrade pip
|
RUN pip install --upgrade pip
|
||||||
|
|
15
configure.sh
15
configure.sh
|
@ -6,6 +6,12 @@ install() {
|
||||||
export PYTHONPATH=$RUNPATH/SuperBuild/install/lib/python2.7/dist-packages:$RUNPATH/SuperBuild/src/opensfm:$PYTHONPATH
|
export PYTHONPATH=$RUNPATH/SuperBuild/install/lib/python2.7/dist-packages:$RUNPATH/SuperBuild/src/opensfm:$PYTHONPATH
|
||||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RUNPATH/SuperBuild/install/lib
|
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RUNPATH/SuperBuild/install/lib
|
||||||
|
|
||||||
|
if [[ $2 =~ ^[0-9]+$ ]] ; then
|
||||||
|
processes=$2
|
||||||
|
else
|
||||||
|
processes=$(nproc)
|
||||||
|
fi
|
||||||
|
|
||||||
## Before installing
|
## Before installing
|
||||||
echo "Updating the system"
|
echo "Updating the system"
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
|
@ -84,7 +90,7 @@ install() {
|
||||||
echo "Installing OpenDroneMap Dependencies"
|
echo "Installing OpenDroneMap Dependencies"
|
||||||
sudo apt-get install -y -qq python-pyexiv2 \
|
sudo apt-get install -y -qq python-pyexiv2 \
|
||||||
python-scipy \
|
python-scipy \
|
||||||
jhead \
|
libexiv2-dev \
|
||||||
liblas-bin
|
liblas-bin
|
||||||
|
|
||||||
echo "Installing lidar2dems Dependencies"
|
echo "Installing lidar2dems Dependencies"
|
||||||
|
@ -97,12 +103,12 @@ install() {
|
||||||
echo "Compiling SuperBuild"
|
echo "Compiling SuperBuild"
|
||||||
cd ${RUNPATH}/SuperBuild
|
cd ${RUNPATH}/SuperBuild
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
cmake .. && make -j$(nproc)
|
cmake .. && make -j$processes
|
||||||
|
|
||||||
echo "Compiling build"
|
echo "Compiling build"
|
||||||
cd ${RUNPATH}
|
cd ${RUNPATH}
|
||||||
mkdir -p build && cd build
|
mkdir -p build && cd build
|
||||||
cmake .. && make -j$(nproc)
|
cmake .. && make -j$processes
|
||||||
|
|
||||||
echo "Configuration Finished"
|
echo "Configuration Finished"
|
||||||
}
|
}
|
||||||
|
@ -123,7 +129,7 @@ reinstall() {
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage:"
|
echo "Usage:"
|
||||||
echo "bash configure.sh <install|update|uninstall|help>"
|
echo "bash configure.sh <install|update|uninstall|help> [nproc]"
|
||||||
echo "Subcommands:"
|
echo "Subcommands:"
|
||||||
echo " install"
|
echo " install"
|
||||||
echo " Installs all dependencies and modules for running OpenDroneMap"
|
echo " Installs all dependencies and modules for running OpenDroneMap"
|
||||||
|
@ -133,6 +139,7 @@ usage() {
|
||||||
echo " Removes SuperBuild and build modules. Does not uninstall dependencies"
|
echo " Removes SuperBuild and build modules. Does not uninstall dependencies"
|
||||||
echo " help"
|
echo " help"
|
||||||
echo " Displays this message"
|
echo " Displays this message"
|
||||||
|
echo "[nproc] is an optional argument that can set the number of processes for the make -j tag. By default it uses $(nproc)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $1 =~ ^(install|reinstall|uninstall|usage)$ ]]; then
|
if [[ $1 =~ ^(install|reinstall|uninstall|usage)$ ]]; then
|
||||||
|
|
|
@ -14,7 +14,7 @@ RUN apt-get install --no-install-recommends -y git cmake python-pip build-essent
|
||||||
libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libflann-dev \
|
libgtk2.0-dev libavcodec-dev libavformat-dev libswscale-dev python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libflann-dev \
|
||||||
libproj-dev libxext-dev liblapack-dev libeigen3-dev libvtk5-dev python-networkx libgoogle-glog-dev libsuitesparse-dev libboost-filesystem-dev libboost-iostreams-dev \
|
libproj-dev libxext-dev liblapack-dev libeigen3-dev libvtk5-dev python-networkx libgoogle-glog-dev libsuitesparse-dev libboost-filesystem-dev libboost-iostreams-dev \
|
||||||
libboost-regex-dev libboost-python-dev libboost-date-time-dev libboost-thread-dev python-pyproj python-empy python-nose python-pyside python-pyexiv2 python-scipy \
|
libboost-regex-dev libboost-python-dev libboost-date-time-dev libboost-thread-dev python-pyproj python-empy python-nose python-pyside python-pyexiv2 python-scipy \
|
||||||
jhead liblas-bin python-matplotlib libatlas-base-dev libgmp-dev libmpfr-dev swig2.0 python-wheel libboost-log-dev libjsoncpp-dev
|
libexiv2-dev liblas-bin python-matplotlib libatlas-base-dev libgmp-dev libmpfr-dev swig2.0 python-wheel libboost-log-dev libjsoncpp-dev
|
||||||
|
|
||||||
RUN apt-get remove libdc1394-22-dev
|
RUN apt-get remove libdc1394-22-dev
|
||||||
RUN pip install --upgrade pip
|
RUN pip install --upgrade pip
|
||||||
|
|
|
@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 2.8)
|
||||||
set(PROJ4_INCLUDE_DIR "/usr/include/" CACHE "PROJ4_INCLUDE_DIR" "Path to the proj4 inlcude directory")
|
set(PROJ4_INCLUDE_DIR "/usr/include/" CACHE "PROJ4_INCLUDE_DIR" "Path to the proj4 inlcude directory")
|
||||||
|
|
||||||
find_library(PROJ4_LIBRARY "libproj.so" PATHS "/usr/lib" "/usr/lib/x86_64-linux-gnu")
|
find_library(PROJ4_LIBRARY "libproj.so" PATHS "/usr/lib" "/usr/lib/x86_64-linux-gnu")
|
||||||
|
find_library(EXIV2_LIBRARY "libexiv2.so" PATHS "/usr/lib" "/usr/lib/x86_64-linux-gnu")
|
||||||
|
|
||||||
# Add compiler options.
|
# Add compiler options.
|
||||||
add_definitions(-Wall -Wextra)
|
add_definitions(-Wall -Wextra)
|
||||||
|
@ -16,4 +17,5 @@ add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||||
|
|
||||||
# Link
|
# Link
|
||||||
target_link_libraries(${PROJECT_NAME} ${PROJ4_LIBRARY})
|
target_link_libraries(${PROJECT_NAME} ${PROJ4_LIBRARY})
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${EXIV2_LIBRARY})
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <exiv2/exiv2.hpp>
|
||||||
|
|
||||||
// Proj4
|
// Proj4
|
||||||
#include <proj_api.h>
|
#include <proj_api.h>
|
||||||
|
@ -168,32 +169,42 @@ void UtmExtractor::extractUtm()
|
||||||
std::string imageFilename;
|
std::string imageFilename;
|
||||||
std::vector<Coord> coords;
|
std::vector<Coord> coords;
|
||||||
while (getline(imageListStream, imageFilename)) {
|
while (getline(imageListStream, imageFilename)) {
|
||||||
// Run jhead on image to extract EXIF data to temporary file
|
|
||||||
std::string commandLine = "jhead -v " + imagesPath_ + "/" + imageFilename + " > extract_utm_output.txt";
|
|
||||||
system(commandLine.c_str());
|
|
||||||
|
|
||||||
// Read temporary EXIF data file
|
|
||||||
std::ifstream jheadDataStream;
|
|
||||||
jheadDataStream.open("extract_utm_output.txt");
|
|
||||||
if (!jheadDataStream.good()) {
|
|
||||||
throw UtmExtractorException("Failed to open temporary jhead data file extract_utm_output.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete temporary file
|
|
||||||
remove("extract_utm_output.txt");
|
|
||||||
|
|
||||||
// Parse jhead output
|
// Read image and load metadata
|
||||||
double lon, lat, alt;
|
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(imagesPath_ + "/" + imageFilename);
|
||||||
if (!parsePosition(jheadDataStream, lon, lat, alt)) {
|
if (image.get() == 0) {
|
||||||
throw UtmExtractorException("Failed parsing GPS position.");
|
std::string error(imageFilename);
|
||||||
jheadDataStream.close();
|
error += ": Image cannot be read";
|
||||||
|
throw Exiv2::Error(1, error);
|
||||||
}
|
}
|
||||||
jheadDataStream.close();
|
else {
|
||||||
|
image->readMetadata();
|
||||||
|
|
||||||
// Convert to UTM
|
Exiv2::ExifData &exifData = image->exifData();
|
||||||
double x, y, z;
|
if (exifData.empty()) {
|
||||||
convert(lon, lat, alt, x, y, z, utmZone, hemisphere);
|
std::string error(imageFilename);
|
||||||
coords.push_back(Coord(x, y, z));
|
error += ": No Exif data found in the file";
|
||||||
|
throw Exiv2::Error(1, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse exif data for positional data
|
||||||
|
double lon, lat, alt = 0.0;
|
||||||
|
|
||||||
|
parsePosition(exifData, lon, lat, alt);
|
||||||
|
|
||||||
|
if (lon == 0.0 || lat == 0.0 || alt == 0.0) {
|
||||||
|
std::string error("Failed parsing GPS position for " + imageFilename);
|
||||||
|
throw UtmExtractorException(error);
|
||||||
|
}
|
||||||
|
// Convert to UTM
|
||||||
|
double x, y, z = 0.0;
|
||||||
|
convert(lon, lat, alt, x, y, z, utmZone, hemisphere);
|
||||||
|
if (x == 0.0 || y == 0.0 || z == 0.0) {
|
||||||
|
std::string error("Failed to convert GPS position to UTM for " + imageFilename);
|
||||||
|
throw UtmExtractorException(error);
|
||||||
|
}
|
||||||
|
coords.push_back(Coord(x, y, z));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
imageListStream.close();
|
imageListStream.close();
|
||||||
|
|
||||||
|
@ -223,17 +234,15 @@ void UtmExtractor::extractUtm()
|
||||||
}
|
}
|
||||||
|
|
||||||
outputCoordStream.close();
|
outputCoordStream.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UtmExtractor::convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere)
|
void UtmExtractor::convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere)
|
||||||
{
|
{
|
||||||
x = y = z = 0.0;
|
|
||||||
|
|
||||||
// Create WGS84 longitude/latitude coordinate system
|
// Create WGS84 longitude/latitude coordinate system
|
||||||
projPJ pjLatLon = pj_init_plus("+proj=latlong +datum=WGS84");
|
projPJ pjLatLon = pj_init_plus("+proj=latlong +datum=WGS84");
|
||||||
if (!pjLatLon) {
|
if (!pjLatLon) {
|
||||||
throw UtmExtractorException("Couldn't create WGS84 coordinate system with PROJ.4.");
|
throw UtmExtractorException("Couldn't create WGS84 coordinate system with PROJ.4.");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate UTM zone if it's set to magic 99
|
// Calculate UTM zone if it's set to magic 99
|
||||||
|
@ -255,7 +264,6 @@ bool UtmExtractor::convert(const double &lon, const double &lat, const double &a
|
||||||
projPJ pjUtm = pj_init_plus(("+proj=utm +datum=WGS84 +zone=" + ostr.str()).c_str());
|
projPJ pjUtm = pj_init_plus(("+proj=utm +datum=WGS84 +zone=" + ostr.str()).c_str());
|
||||||
if (!pjUtm) {
|
if (!pjUtm) {
|
||||||
throw UtmExtractorException("Couldn't create UTM coordinate system with PROJ.4.");
|
throw UtmExtractorException("Couldn't create UTM coordinate system with PROJ.4.");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to radians
|
// Convert to radians
|
||||||
|
@ -267,87 +275,54 @@ bool UtmExtractor::convert(const double &lon, const double &lat, const double &a
|
||||||
int res = pj_transform(pjLatLon, pjUtm, 1, 1, &x, &y, &z);
|
int res = pj_transform(pjLatLon, pjUtm, 1, 1, &x, &y, &z);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
throw UtmExtractorException("Failed to transform coordinates");
|
throw UtmExtractorException("Failed to transform coordinates");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UtmExtractor::parsePosition(std::ifstream &jheadStream, double &lon, double &lat, double &alt)
|
void UtmExtractor::parsePosition(Exiv2::ExifData &exifData, double &lon, double &lat, double &alt)
|
||||||
{
|
{
|
||||||
lon = lat = alt = 0.0;
|
Exiv2::Exifdatum& latitudeTag = exifData["Exif.GPSInfo.GPSLatitude"];
|
||||||
|
Exiv2::Exifdatum& latitudeRef = exifData["Exif.GPSInfo.GPSLatitudeRef"];
|
||||||
|
Exiv2::Exifdatum& longitudeTag = exifData["Exif.GPSInfo.GPSLongitude"];
|
||||||
|
Exiv2::Exifdatum& longitudeRef = exifData["Exif.GPSInfo.GPSLongitudeRef"];
|
||||||
|
Exiv2::Exifdatum& altitudeTag = exifData["Exif.GPSInfo.GPSAltitude"];
|
||||||
|
Exiv2::Exifdatum& altitudeRef = exifData["Exif.GPSInfo.GPSAltitudeRef"];
|
||||||
|
|
||||||
// Parse position
|
// Latitude: parse into a double
|
||||||
std::string str;
|
if (latitudeTag.count() < 3)
|
||||||
std::string latStr, lonStr, altStr;
|
throw UtmExtractorException("Image is missing GPS Latitude data");
|
||||||
while (std::getline(jheadStream, str))
|
else {
|
||||||
{
|
Exiv2::URational rLat[] = {latitudeTag.toRational(0), latitudeTag.toRational(1), latitudeTag.toRational(2)};
|
||||||
const char* latitudeTag = "GPS Latitude : ";
|
bool south = (strcmp(latitudeRef.toString().c_str(), "S") == 0);
|
||||||
size_t index = str.find(latitudeTag);
|
double degrees, minutes, seconds;
|
||||||
if (index != std::string::npos)
|
|
||||||
{
|
|
||||||
latStr = str.substr(index + std::strlen(latitudeTag));
|
|
||||||
size_t find = latStr.find_first_of("0123456789");
|
|
||||||
if(std::string::npos == find)
|
|
||||||
{
|
|
||||||
throw UtmExtractorException("Image is missing GPS Latitude data");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
degrees = (double)rLat[0].first / (double)rLat[0].second;
|
||||||
|
minutes = (double)rLat[1].first / (double)rLat[1].second / 60.0;
|
||||||
const char* longitudeTag = "GPS Longitude: ";
|
seconds = (double)rLat[2].first / (double)rLat[2].second / 3600.0;
|
||||||
index = str.find(longitudeTag);
|
lat = (south ? -1 : 1) * (degrees + minutes + seconds);
|
||||||
if (index != std::string::npos)
|
|
||||||
{
|
|
||||||
lonStr = str.substr(index + std::strlen(longitudeTag));
|
|
||||||
size_t find = lonStr.find_first_of("0123456789");
|
|
||||||
if(std::string::npos == find)
|
|
||||||
{
|
|
||||||
throw UtmExtractorException("Image is missing GPS Longitude data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* altitudeTag = "GPS Altitude :";
|
|
||||||
index = str.find(altitudeTag);
|
|
||||||
if (index != std::string::npos)
|
|
||||||
{
|
|
||||||
altStr = str.substr(index + std::strlen(altitudeTag));
|
|
||||||
size_t find = altStr.find_first_of("0123456789");
|
|
||||||
if(std::string::npos == find)
|
|
||||||
{
|
|
||||||
throw UtmExtractorException("Image is missing GPS Altitude data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lonStr.empty() || latStr.empty()) {
|
// Longitude
|
||||||
throw UtmExtractorException("No valid GPS position found");
|
if (longitudeTag.count() < 3)
|
||||||
return false;
|
throw UtmExtractorException("Image is missing GPS Longitude data");
|
||||||
|
else {
|
||||||
|
Exiv2::URational rLon[] = {longitudeTag.toRational(0), longitudeTag.toRational(1), longitudeTag.toRational(2)};
|
||||||
|
bool west = (strcmp(longitudeRef.toString().c_str(), "W") == 0);
|
||||||
|
double degrees, minutes, seconds;
|
||||||
|
|
||||||
|
degrees = (double)rLon[0].first / (double)rLon[0].second;
|
||||||
|
minutes = (double)rLon[1].first / (double)rLon[1].second / 60.0;
|
||||||
|
seconds = (double)rLon[2].first / (double)rLon[2].second / 3600.0;
|
||||||
|
lon = (west ? -1 : 1) * (degrees + minutes + seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse longitude
|
// Altitude
|
||||||
std::string hemisphere;
|
if (altitudeTag.count() < 1)
|
||||||
double degrees, minutes, seconds;
|
throw UtmExtractorException("Image is missing GPS Altitude data");
|
||||||
std::istringstream istr(lonStr);
|
else {
|
||||||
char degChar = 'd', minChar = 'm', secChar = 's';
|
Exiv2::URational rAlt = altitudeTag.toRational(0);
|
||||||
istr >> hemisphere >> degrees >> degChar >> minutes >> minChar >> seconds >> secChar;
|
bool below = (altitudeRef.count() >= 1 && altitudeRef.toLong() == 1);
|
||||||
lon = (hemisphere == "W" ? -1 : 1) * (degrees + minutes/60.0 + seconds/3600.0);
|
alt = (below ? -1 : 1) * (double) rAlt.first / (double) rAlt.second;
|
||||||
|
|
||||||
// Parse latitude
|
|
||||||
istr.clear();
|
|
||||||
istr.str(latStr);
|
|
||||||
istr >> hemisphere >> degrees >> degChar >> minutes >> minChar >> seconds >> secChar;
|
|
||||||
lat = (hemisphere == "S" ? -1 : 1) * (degrees + minutes/60.0 + seconds/3600.0);
|
|
||||||
|
|
||||||
if (!altStr.empty())
|
|
||||||
{
|
|
||||||
char meterUnitChar;
|
|
||||||
istr.clear();
|
|
||||||
istr.str(altStr);
|
|
||||||
istr >> alt >> meterUnitChar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtmExtractor::printHelp()
|
void UtmExtractor::printHelp()
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
#include "Logger.hpp"
|
#include "Logger.hpp"
|
||||||
|
#include <exiv2/exiv2.hpp>
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \breif The Coord struct Class used in UtmExtractor to extract GPS positions from images and ODM output
|
* \breif The Coord struct Class used in UtmExtractor to extract GPS positions from images and ODM output
|
||||||
|
@ -55,7 +57,7 @@ private:
|
||||||
*
|
*
|
||||||
* \returns True if successful (otherwise output parameters are 0)
|
* \returns True if successful (otherwise output parameters are 0)
|
||||||
*/
|
*/
|
||||||
static bool convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere);
|
static void convert(const double &lon, const double &lat, const double &alt, double &x, double &y, double &z, int &utmZone, char &hemisphere);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Static method that parses a GPS position from jhead data.
|
* \brief Static method that parses a GPS position from jhead data.
|
||||||
|
@ -67,7 +69,7 @@ private:
|
||||||
*
|
*
|
||||||
* \returns True if successful (otherwise output parameters are 0)
|
* \returns True if successful (otherwise output parameters are 0)
|
||||||
*/
|
*/
|
||||||
static bool parsePosition(std::ifstream &jheadStream, double &lon, double &lat, double &alt);
|
static void parsePosition(Exiv2::ExifData &exifData, double &lon, double &lat, double &alt);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief printHelp Prints help, explaining usage. Can be shown by calling the program with arguments: "-help".
|
* \brief printHelp Prints help, explaining usage. Can be shown by calling the program with arguments: "-help".
|
||||||
|
|
Ładowanie…
Reference in New Issue