kopia lustrzana https://github.com/OpenDroneMap/ODM
rodzic
f501d21d6e
commit
73088aba01
|
@ -8,15 +8,14 @@ ExternalProject_Add(${_proj_name}
|
|||
STAMP_DIR ${_SB_BINARY_DIR}/stamp
|
||||
#--Download step--------------
|
||||
DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}
|
||||
URL https://github.com/PDAL/PDAL/archive/1.9.1.zip
|
||||
URL https://github.com/PDAL/PDAL/archive/2.1.0.zip
|
||||
#--Update/Patch step----------
|
||||
UPDATE_COMMAND ""
|
||||
#--Configure step-------------
|
||||
SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name}
|
||||
CMAKE_ARGS
|
||||
-BUILD_PGPOINTCLOUD_TESTS=OFF
|
||||
-BUILD_PLUGIN_PCL=ON
|
||||
-BUILD_PLUGIN_PGPOINTCLOUD=ON
|
||||
-DBUILD_PGPOINTCLOUD_TESTS=OFF
|
||||
-DBUILD_PLUGIN_PGPOINTCLOUD=OFF
|
||||
-DBUILD_PLUGIN_CPD=OFF
|
||||
-DBUILD_PLUGIN_GREYHOUND=OFF
|
||||
-DBUILD_PLUGIN_HEXBIN=ON
|
||||
|
|
|
@ -7,7 +7,6 @@ endif()
|
|||
add_subdirectory(odm_georef)
|
||||
add_subdirectory(odm_orthophoto)
|
||||
add_subdirectory(odm_cleanmesh)
|
||||
add_subdirectory(odm_filterpoints)
|
||||
|
||||
if (ODM_BUILD_SLAM)
|
||||
add_subdirectory(odm_slam)
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
project(odm_filterpoints)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
# Add compiler options.
|
||||
add_definitions(-Wall -Wextra -Wconversion -pedantic -std=c++11)
|
||||
|
||||
# PDAL and jsoncpp
|
||||
find_package(PDAL REQUIRED CONFIG)
|
||||
include_directories(${PDAL_INCLUDE_DIRS})
|
||||
include_directories("${PROJECT_SOURCE_DIR}/../../SuperBuild/src/pdal/vendor/jsoncpp/dist")
|
||||
link_directories(${PDAL_LIBRARY_DIRS})
|
||||
add_definitions(${PDAL_DEFINITIONS})
|
||||
|
||||
# Add source directory
|
||||
aux_source_directory("./src" SRC_LIST)
|
||||
|
||||
# Add exectuteable
|
||||
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||
|
||||
# Link
|
||||
target_link_libraries(${PROJECT_NAME} jsoncpp ${PDAL_LIBRARIES})
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CMD_LINE_PARSER_INCLUDED
|
||||
#define CMD_LINE_PARSER_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef WIN32
|
||||
int strcasecmp( const char* c1 , const char* c2 );
|
||||
#endif // WIN32
|
||||
|
||||
class cmdLineReadable
|
||||
{
|
||||
public:
|
||||
bool set;
|
||||
char *name;
|
||||
cmdLineReadable( const char *name );
|
||||
virtual ~cmdLineReadable( void );
|
||||
virtual int read( char** argv , int argc );
|
||||
virtual void writeValue( char* str ) const;
|
||||
};
|
||||
|
||||
template< class Type > void cmdLineWriteValue( Type t , char* str );
|
||||
template< class Type > void cmdLineCleanUp( Type* t );
|
||||
template< class Type > Type cmdLineInitialize( void );
|
||||
template< class Type > Type cmdLineCopy( Type t );
|
||||
template< class Type > Type cmdLineStringToType( const char* str );
|
||||
|
||||
template< class Type >
|
||||
class cmdLineParameter : public cmdLineReadable
|
||||
{
|
||||
public:
|
||||
Type value;
|
||||
cmdLineParameter( const char *name );
|
||||
cmdLineParameter( const char *name , Type v );
|
||||
~cmdLineParameter( void );
|
||||
int read( char** argv , int argc );
|
||||
void writeValue( char* str ) const;
|
||||
bool expectsArg( void ) const { return true; }
|
||||
};
|
||||
|
||||
template< class Type , int Dim >
|
||||
class cmdLineParameterArray : public cmdLineReadable
|
||||
{
|
||||
public:
|
||||
Type values[Dim];
|
||||
cmdLineParameterArray( const char *name, const Type* v=NULL );
|
||||
~cmdLineParameterArray( void );
|
||||
int read( char** argv , int argc );
|
||||
void writeValue( char* str ) const;
|
||||
bool expectsArg( void ) const { return true; }
|
||||
};
|
||||
|
||||
template< class Type >
|
||||
class cmdLineParameters : public cmdLineReadable
|
||||
{
|
||||
public:
|
||||
int count;
|
||||
Type *values;
|
||||
cmdLineParameters( const char* name );
|
||||
~cmdLineParameters( void );
|
||||
int read( char** argv , int argc );
|
||||
void writeValue( char* str ) const;
|
||||
bool expectsArg( void ) const { return true; }
|
||||
};
|
||||
|
||||
void cmdLineParse( int argc , char **argv, cmdLineReadable** params );
|
||||
char* FileExtension( char* fileName );
|
||||
char* LocalFileName( char* fileName );
|
||||
char* DirectoryName( char* fileName );
|
||||
char* GetFileExtension( const char* fileName );
|
||||
char* GetLocalFileName( const char* fileName );
|
||||
char** ReadWords( const char* fileName , int& cnt );
|
||||
|
||||
#include "CmdLineParser.inl"
|
||||
#endif // CMD_LINE_PARSER_INCLUDED
|
|
@ -1,300 +0,0 @@
|
|||
/* -*- C++ -*-
|
||||
Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer. Redistributions in binary form must reproduce
|
||||
the above copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
Neither the name of the Johns Hopkins University nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN64 )
|
||||
inline int strcasecmp( const char* c1 , const char* c2 ){ return _stricmp( c1 , c2 ); }
|
||||
#endif // WIN32 || _WIN64
|
||||
|
||||
template< > void cmdLineCleanUp< int >( int* t ){ *t = 0; }
|
||||
template< > void cmdLineCleanUp< float >( float* t ){ *t = 0; }
|
||||
template< > void cmdLineCleanUp< double >( double* t ){ *t = 0; }
|
||||
template< > void cmdLineCleanUp< char* >( char** t ){ if( *t ) free( *t ) ; *t = NULL; }
|
||||
template< > int cmdLineInitialize< int >( void ){ return 0; }
|
||||
template< > float cmdLineInitialize< float >( void ){ return 0.f; }
|
||||
template< > double cmdLineInitialize< double >( void ){ return 0.; }
|
||||
template< > char* cmdLineInitialize< char* >( void ){ return NULL; }
|
||||
template< > void cmdLineWriteValue< int >( int t , char* str ){ sprintf( str , "%d" , t ); }
|
||||
template< > void cmdLineWriteValue< float >( float t , char* str ){ sprintf( str , "%f" , t ); }
|
||||
template< > void cmdLineWriteValue< double >( double t , char* str ){ sprintf( str , "%f" , t ); }
|
||||
template< > void cmdLineWriteValue< char* >( char* t , char* str ){ if( t ) sprintf( str , "%s" , t ) ; else str[0]=0; }
|
||||
template< > int cmdLineCopy( int t ){ return t; }
|
||||
template< > float cmdLineCopy( float t ){ return t; }
|
||||
template< > double cmdLineCopy( double t ){ return t; }
|
||||
#if defined( WIN32 ) || defined( _WIN64 )
|
||||
template< > char* cmdLineCopy( char* t ){ return _strdup( t ); }
|
||||
#else // !WIN32 && !_WIN64
|
||||
template< > char* cmdLineCopy( char* t ){ return strdup( t ); }
|
||||
#endif // WIN32 || _WIN64
|
||||
template< > int cmdLineStringToType( const char* str ){ return atoi( str ); }
|
||||
template< > float cmdLineStringToType( const char* str ){ return float( atof( str ) ); }
|
||||
template< > double cmdLineStringToType( const char* str ){ return double( atof( str ) ); }
|
||||
#if defined( WIN32 ) || defined( _WIN64 )
|
||||
template< > char* cmdLineStringToType( const char* str ){ return _strdup( str ); }
|
||||
#else // !WIN32 && !_WIN64
|
||||
template< > char* cmdLineStringToType( const char* str ){ return strdup( str ); }
|
||||
#endif // WIN32 || _WIN64
|
||||
|
||||
|
||||
/////////////////////
|
||||
// cmdLineReadable //
|
||||
/////////////////////
|
||||
#if defined( WIN32 ) || defined( _WIN64 )
|
||||
inline cmdLineReadable::cmdLineReadable( const char *name ) : set(false) { this->name = _strdup( name ); }
|
||||
#else // !WIN32 && !_WIN64
|
||||
inline cmdLineReadable::cmdLineReadable( const char *name ) : set(false) { this->name = strdup( name ); }
|
||||
#endif // WIN32 || _WIN64
|
||||
|
||||
inline cmdLineReadable::~cmdLineReadable( void ){ if( name ) free( name ) ; name = NULL; }
|
||||
inline int cmdLineReadable::read( char** , int ){ set = true ; return 0; }
|
||||
inline void cmdLineReadable::writeValue( char* str ) const { str[0] = 0; }
|
||||
|
||||
//////////////////////
|
||||
// cmdLineParameter //
|
||||
//////////////////////
|
||||
template< class Type > cmdLineParameter< Type >::~cmdLineParameter( void ) { cmdLineCleanUp( &value ); }
|
||||
template< class Type > cmdLineParameter< Type >::cmdLineParameter( const char *name ) : cmdLineReadable( name ){ value = cmdLineInitialize< Type >(); }
|
||||
template< class Type > cmdLineParameter< Type >::cmdLineParameter( const char *name , Type v ) : cmdLineReadable( name ){ value = cmdLineCopy< Type >( v ); }
|
||||
template< class Type >
|
||||
int cmdLineParameter< Type >::read( char** argv , int argc )
|
||||
{
|
||||
if( argc>0 )
|
||||
{
|
||||
cmdLineCleanUp< Type >( &value ) , value = cmdLineStringToType< Type >( argv[0] );
|
||||
set = true;
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
template< class Type >
|
||||
void cmdLineParameter< Type >::writeValue( char* str ) const { cmdLineWriteValue< Type >( value , str ); }
|
||||
|
||||
|
||||
///////////////////////////
|
||||
// cmdLineParameterArray //
|
||||
///////////////////////////
|
||||
template< class Type , int Dim >
|
||||
cmdLineParameterArray< Type , Dim >::cmdLineParameterArray( const char *name , const Type* v ) : cmdLineReadable( name )
|
||||
{
|
||||
if( v ) for( int i=0 ; i<Dim ; i++ ) values[i] = cmdLineCopy< Type >( v[i] );
|
||||
else for( int i=0 ; i<Dim ; i++ ) values[i] = cmdLineInitialize< Type >();
|
||||
}
|
||||
template< class Type , int Dim >
|
||||
cmdLineParameterArray< Type , Dim >::~cmdLineParameterArray( void ){ for( int i=0 ; i<Dim ; i++ ) cmdLineCleanUp< Type >( values+i ); }
|
||||
template< class Type , int Dim >
|
||||
int cmdLineParameterArray< Type , Dim >::read( char** argv , int argc )
|
||||
{
|
||||
if( argc>=Dim )
|
||||
{
|
||||
for( int i=0 ; i<Dim ; i++ ) cmdLineCleanUp< Type >( values+i ) , values[i] = cmdLineStringToType< Type >( argv[i] );
|
||||
set = true;
|
||||
return Dim;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
template< class Type , int Dim >
|
||||
void cmdLineParameterArray< Type , Dim >::writeValue( char* str ) const
|
||||
{
|
||||
char* temp=str;
|
||||
for( int i=0 ; i<Dim ; i++ )
|
||||
{
|
||||
cmdLineWriteValue< Type >( values[i] , temp );
|
||||
temp = str+strlen( str );
|
||||
}
|
||||
}
|
||||
///////////////////////
|
||||
// cmdLineParameters //
|
||||
///////////////////////
|
||||
template< class Type >
|
||||
cmdLineParameters< Type >::cmdLineParameters( const char* name ) : cmdLineReadable( name ) , values(NULL) , count(0) { }
|
||||
template< class Type >
|
||||
cmdLineParameters< Type >::~cmdLineParameters( void )
|
||||
{
|
||||
if( values ) delete[] values;
|
||||
values = NULL;
|
||||
count = 0;
|
||||
}
|
||||
template< class Type >
|
||||
int cmdLineParameters< Type >::read( char** argv , int argc )
|
||||
{
|
||||
if( values ) delete[] values;
|
||||
values = NULL;
|
||||
|
||||
if( argc>0 )
|
||||
{
|
||||
count = atoi(argv[0]);
|
||||
if( count <= 0 || argc <= count ) return 1;
|
||||
values = new Type[count];
|
||||
if( !values ) return 0;
|
||||
for( int i=0 ; i<count ; i++ ) values[i] = cmdLineStringToType< Type >( argv[i+1] );
|
||||
set = true;
|
||||
return count+1;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
template< class Type >
|
||||
void cmdLineParameters< Type >::writeValue( char* str ) const
|
||||
{
|
||||
char* temp=str;
|
||||
for( int i=0 ; i<count ; i++ )
|
||||
{
|
||||
cmdLineWriteValue< Type >( values[i] , temp );
|
||||
temp = str+strlen( str );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline char* FileExtension( char* fileName )
|
||||
{
|
||||
char* temp = fileName;
|
||||
for( unsigned int i=0 ; i<strlen(fileName) ; i++ ) if( fileName[i]=='.' ) temp = &fileName[i+1];
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline char* GetFileExtension( const char* fileName )
|
||||
{
|
||||
char* fileNameCopy;
|
||||
char* ext=NULL;
|
||||
char* temp;
|
||||
|
||||
fileNameCopy=new char[strlen(fileName)+1];
|
||||
assert(fileNameCopy);
|
||||
strcpy(fileNameCopy,fileName);
|
||||
temp=strtok(fileNameCopy,".");
|
||||
while(temp!=NULL)
|
||||
{
|
||||
if(ext!=NULL){delete[] ext;}
|
||||
ext=new char[strlen(temp)+1];
|
||||
assert(ext);
|
||||
strcpy(ext,temp);
|
||||
temp=strtok(NULL,".");
|
||||
}
|
||||
delete[] fileNameCopy;
|
||||
return ext;
|
||||
}
|
||||
inline char* GetLocalFileName( const char* fileName )
|
||||
{
|
||||
char* fileNameCopy;
|
||||
char* name=NULL;
|
||||
char* temp;
|
||||
|
||||
fileNameCopy=new char[strlen(fileName)+1];
|
||||
assert(fileNameCopy);
|
||||
strcpy(fileNameCopy,fileName);
|
||||
temp=strtok(fileNameCopy,"\\");
|
||||
while(temp!=NULL){
|
||||
if(name!=NULL){delete[] name;}
|
||||
name=new char[strlen(temp)+1];
|
||||
assert(name);
|
||||
strcpy(name,temp);
|
||||
temp=strtok(NULL,"\\");
|
||||
}
|
||||
delete[] fileNameCopy;
|
||||
return name;
|
||||
}
|
||||
inline char* LocalFileName( char* fileName )
|
||||
{
|
||||
char* temp = fileName;
|
||||
for( int i=0 ; i<(int)strlen(fileName) ; i++ ) if( fileName[i] =='\\' ) temp = &fileName[i+1];
|
||||
return temp;
|
||||
}
|
||||
inline char* DirectoryName( char* fileName )
|
||||
{
|
||||
for( int i=int( strlen(fileName) )-1 ; i>=0 ; i-- )
|
||||
if( fileName[i] =='\\' )
|
||||
{
|
||||
fileName[i] = 0;
|
||||
return fileName;
|
||||
}
|
||||
fileName[0] = 0;
|
||||
return fileName;
|
||||
}
|
||||
|
||||
inline void cmdLineParse( int argc , char **argv , cmdLineReadable** params )
|
||||
{
|
||||
while( argc>0 )
|
||||
{
|
||||
if( argv[0][0]=='-' )
|
||||
{
|
||||
cmdLineReadable* readable=NULL;
|
||||
for( int i=0 ; params[i]!=NULL && readable==NULL ; i++ ) if( !strcasecmp( params[i]->name , argv[0]+1 ) ) readable = params[i];
|
||||
if( readable )
|
||||
{
|
||||
int j = readable->read( argv+1 , argc-1 );
|
||||
argv += j , argc -= j;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr , "[WARNING] Invalid option: %s\n" , argv[0] );
|
||||
for( int i=0 ; params[i]!=NULL ; i++ ) printf( "\t-%s\n" , params[i]->name );
|
||||
}
|
||||
}
|
||||
else fprintf( stderr , "[WARNING] Parameter name should be of the form -<name>: %s\n" , argv[0] );
|
||||
++argv , --argc;
|
||||
}
|
||||
}
|
||||
|
||||
inline char** ReadWords(const char* fileName,int& cnt)
|
||||
{
|
||||
char** names;
|
||||
char temp[500];
|
||||
FILE* fp;
|
||||
|
||||
fp=fopen(fileName,"r");
|
||||
if(!fp){return NULL;}
|
||||
cnt=0;
|
||||
while(fscanf(fp," %s ",temp)==1){cnt++;}
|
||||
fclose(fp);
|
||||
|
||||
names=new char*[cnt];
|
||||
if(!names){return NULL;}
|
||||
|
||||
fp=fopen(fileName,"r");
|
||||
if(!fp){
|
||||
delete[] names;
|
||||
cnt=0;
|
||||
return NULL;
|
||||
}
|
||||
cnt=0;
|
||||
while(fscanf(fp," %s ",temp)==1){
|
||||
names[cnt]=new char[strlen(temp)+1];
|
||||
if(!names){
|
||||
for(int j=0;j<cnt;j++){delete[] names[j];}
|
||||
delete[] names;
|
||||
cnt=0;
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(names[cnt],temp);
|
||||
cnt++;
|
||||
}
|
||||
fclose(fp);
|
||||
return names;
|
||||
}
|
|
@ -1,454 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2015, Peter J. Gadomski <pete.gadomski@gmail.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
// Modified to not cast to double and to use certain type identifier ("float" vs "float32")
|
||||
|
||||
#include "FloatPlyReader.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <pdal/PDALUtils.hpp>
|
||||
#include <pdal/PointView.hpp>
|
||||
#include <pdal/util/IStream.hpp>
|
||||
|
||||
namespace pdal
|
||||
{
|
||||
|
||||
|
||||
FloatPlyReader::FloatPlyReader() : m_vertexElt(nullptr)
|
||||
{}
|
||||
|
||||
|
||||
std::string FloatPlyReader::readLine()
|
||||
{
|
||||
m_line.clear();
|
||||
if (m_lines.size())
|
||||
{
|
||||
m_line = m_lines.top();
|
||||
m_lines.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
std::getline(*m_stream, m_line);
|
||||
} while (m_line.empty() && m_stream->good());
|
||||
}
|
||||
Utils::trimTrailing(m_line);
|
||||
m_linePos = Utils::extract(m_line, 0,
|
||||
[](char c){ return !std::isspace(c); });
|
||||
return std::string(m_line, 0, m_linePos);
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::pushLine()
|
||||
{
|
||||
m_lines.push(m_line);
|
||||
}
|
||||
|
||||
|
||||
std::string FloatPlyReader::nextWord()
|
||||
{
|
||||
std::string s;
|
||||
std::string::size_type cnt = Utils::extractSpaces(m_line, m_linePos);
|
||||
m_linePos += cnt;
|
||||
if (m_linePos == m_line.size())
|
||||
return s;
|
||||
|
||||
cnt = Utils::extract(m_line, m_linePos,
|
||||
[](char c){ return !std::isspace(c); });
|
||||
s = std::string(m_line, m_linePos, cnt);
|
||||
m_linePos += cnt;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractMagic()
|
||||
{
|
||||
std::string first = readLine();
|
||||
if (first != "ply")
|
||||
throwError("File isn't a PLY file. 'ply' not found.");
|
||||
if (m_linePos != m_line.size())
|
||||
throwError("Text found following 'ply' keyword.");
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractEnd()
|
||||
{
|
||||
std::string first = readLine();
|
||||
if (first != "end_header")
|
||||
throwError("'end_header' expected but found line beginning with '" +
|
||||
first + "' instead.");
|
||||
if (m_linePos != m_line.size())
|
||||
throwError("Text found following 'end_header' keyword.");
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractFormat()
|
||||
{
|
||||
std::string word = readLine();
|
||||
if (word != "format")
|
||||
throwError("Expected format line not found in PLY file.");
|
||||
|
||||
word = nextWord();
|
||||
if (word == "ascii")
|
||||
m_format = Format::Ascii;
|
||||
else if (word == "binary_big_endian")
|
||||
m_format = Format::BinaryBe;
|
||||
else if (word == "binary_little_endian")
|
||||
m_format = Format::BinaryLe;
|
||||
else
|
||||
throwError("Unrecognized PLY format: '" + word + "'.");
|
||||
|
||||
word = nextWord();
|
||||
if (word != "1.0")
|
||||
throwError("Unsupported PLY version: '" + word + "'.");
|
||||
}
|
||||
|
||||
|
||||
Dimension::Type FloatPlyReader::getType(const std::string& name)
|
||||
{
|
||||
static std::map<std::string, Dimension::Type> types =
|
||||
{
|
||||
{ "int8", Dimension::Type::Signed8 },
|
||||
{ "uint8", Dimension::Type::Unsigned8 },
|
||||
{ "int16", Dimension::Type::Signed16 },
|
||||
{ "uint16", Dimension::Type::Unsigned16 },
|
||||
{ "int32", Dimension::Type::Signed32 },
|
||||
{ "uint32", Dimension::Type::Unsigned32 },
|
||||
{ "float32", Dimension::Type::Float },
|
||||
{ "float64", Dimension::Type::Double },
|
||||
|
||||
{ "char", Dimension::Type::Signed8 },
|
||||
{ "uchar", Dimension::Type::Unsigned8 },
|
||||
{ "short", Dimension::Type::Signed16 },
|
||||
{ "ushort", Dimension::Type::Unsigned16 },
|
||||
{ "int", Dimension::Type::Signed32 },
|
||||
{ "uint", Dimension::Type::Unsigned32 },
|
||||
{ "float", Dimension::Type::Float },
|
||||
{ "double", Dimension::Type::Double }
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return types.at(name);
|
||||
}
|
||||
catch (std::out_of_range&)
|
||||
{}
|
||||
return Dimension::Type::None;
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractProperty(Element& element)
|
||||
{
|
||||
std::string word = nextWord();
|
||||
Dimension::Type type = getType(word);
|
||||
|
||||
if (type != Dimension::Type::None)
|
||||
{
|
||||
std::string name = nextWord();
|
||||
if (name.empty())
|
||||
throwError("No name for property of element '" +
|
||||
element.m_name + "'.");
|
||||
element.m_properties.push_back(
|
||||
std::unique_ptr<Property>(new SimpleProperty(name, type)));
|
||||
}
|
||||
else if (word == "list")
|
||||
{
|
||||
if (element.m_name == "vertex")
|
||||
throwError("List properties are not supported for the 'vertex' "
|
||||
"element.");
|
||||
|
||||
word = nextWord();
|
||||
Dimension::Type countType = getType(word);
|
||||
if (countType == Dimension::Type::None)
|
||||
throwError("No valid count type for list property of element '" +
|
||||
element.m_name + "'.");
|
||||
word = nextWord();
|
||||
Dimension::Type listType = getType(word);
|
||||
if (listType == Dimension::Type::None)
|
||||
throwError("No valid list type for list property of element '" +
|
||||
element.m_name + "'.");
|
||||
std::string name = nextWord();
|
||||
if (name.empty())
|
||||
throwError("No name for property of element '" +
|
||||
element.m_name + "'.");
|
||||
element.m_properties.push_back(
|
||||
std::unique_ptr<Property>(new ListProperty(name, countType,
|
||||
listType)));
|
||||
}
|
||||
else
|
||||
throwError("Invalid property type '" + word + "'.");
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractProperties(Element& element)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string word = readLine();
|
||||
if (word == "comment" || word == "obj_info")
|
||||
continue;
|
||||
else if (word == "property")
|
||||
extractProperty(element);
|
||||
else
|
||||
{
|
||||
pushLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FloatPlyReader::extractElement()
|
||||
{
|
||||
std::string word = readLine();
|
||||
if (word == "comment" || word == "obj_info")
|
||||
return true;
|
||||
else if (word == "end_header")
|
||||
{
|
||||
pushLine();
|
||||
return false;
|
||||
}
|
||||
else if (word == "element")
|
||||
{
|
||||
std::string name = nextWord();
|
||||
if (name.empty())
|
||||
throwError("Missing element name.");
|
||||
long count = std::stol(nextWord());
|
||||
if (count < 0)
|
||||
throwError("Invalid count for element '" + name + "'.");
|
||||
m_elements.emplace_back(name, count);
|
||||
extractProperties(m_elements.back());
|
||||
return true;
|
||||
}
|
||||
throwError("Invalid keyword '" + word + "' when expecting an element.");
|
||||
return false; // quiet compiler
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::extractHeader()
|
||||
{
|
||||
m_elements.clear();
|
||||
extractMagic();
|
||||
extractFormat();
|
||||
while (extractElement())
|
||||
;
|
||||
extractEnd();
|
||||
m_dataPos = m_stream->tellg();
|
||||
|
||||
for (Element& elt : m_elements)
|
||||
if (elt.m_name == "vertex")
|
||||
m_vertexElt = &elt;
|
||||
if (!m_vertexElt)
|
||||
throwError("Can't read PLY file without a 'vertex' element.");
|
||||
}
|
||||
|
||||
|
||||
std::string FloatPlyReader::getName() const
|
||||
{
|
||||
return "FloatPlyReader";
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::initialize()
|
||||
{
|
||||
m_stream = Utils::openFile(m_filename, true);
|
||||
if (!m_stream)
|
||||
throwError("Couldn't open '" + m_filename + "'.");
|
||||
extractHeader();
|
||||
Utils::closeFile(m_stream);
|
||||
m_stream = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::addDimensions(PointLayoutPtr layout)
|
||||
{
|
||||
// Override XYZ
|
||||
// layout->registerDim(Dimension::Id::X);
|
||||
// layout->registerDim(Dimension::Id::Y);
|
||||
// layout->registerDim(Dimension::Id::Z);
|
||||
|
||||
for (auto& elt : m_elements)
|
||||
{
|
||||
if (elt.m_name == "vertex")
|
||||
{
|
||||
for (auto& prop : elt.m_properties)
|
||||
{
|
||||
auto vprop = static_cast<SimpleProperty *>(prop.get());
|
||||
layout->registerOrAssignDim(vprop->m_name, vprop->m_type);
|
||||
vprop->setDim(
|
||||
layout->registerOrAssignDim(vprop->m_name, vprop->m_type));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
throwError("No 'vertex' element in header.");
|
||||
}
|
||||
|
||||
|
||||
bool FloatPlyReader::readProperty(Property *prop, PointRef& point)
|
||||
{
|
||||
if (!m_stream->good())
|
||||
return false;
|
||||
prop->read(m_stream, m_format, point);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::SimpleProperty::read(std::istream *stream,
|
||||
FloatPlyReader::Format format, PointRef& point)
|
||||
{
|
||||
if (format == Format::Ascii)
|
||||
{
|
||||
double d;
|
||||
*stream >> d;
|
||||
point.setField(m_dim, d);
|
||||
}
|
||||
else if (format == Format::BinaryLe)
|
||||
{
|
||||
ILeStream in(stream);
|
||||
Everything e = Utils::extractDim(in, m_type);
|
||||
point.setField(m_dim, m_type, &e);
|
||||
}
|
||||
else if (format == Format::BinaryBe)
|
||||
{
|
||||
IBeStream in(stream);
|
||||
Everything e = Utils::extractDim(in, m_type);
|
||||
point.setField(m_dim, m_type, &e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Right now we don't support list properties for point data. We just
|
||||
// read the data and throw it away.
|
||||
void FloatPlyReader::ListProperty::read(std::istream *stream,
|
||||
FloatPlyReader::Format format, PointRef& point)
|
||||
{
|
||||
if (format == Format::Ascii)
|
||||
{
|
||||
size_t cnt;
|
||||
*stream >> cnt;
|
||||
|
||||
double d;
|
||||
while (cnt--)
|
||||
*stream >> d;
|
||||
}
|
||||
else if (format == Format::BinaryLe)
|
||||
{
|
||||
ILeStream istream(stream);
|
||||
Everything e = Utils::extractDim(istream, m_countType);
|
||||
size_t cnt = (size_t)Utils::toDouble(e, m_countType);
|
||||
cnt *= Dimension::size(m_listType);
|
||||
istream.seek(cnt, std::ios_base::cur);
|
||||
}
|
||||
else if (format == Format::BinaryBe)
|
||||
{
|
||||
IBeStream istream(stream);
|
||||
Everything e = Utils::extractDim(istream, m_countType);
|
||||
size_t cnt = (size_t)Utils::toDouble(e, m_countType);
|
||||
cnt *= Dimension::size(m_listType);
|
||||
istream.seek(cnt, std::ios_base::cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::readElement(Element& elt, PointRef& point)
|
||||
{
|
||||
for (auto& prop : elt.m_properties)
|
||||
if (!readProperty(prop.get(), point))
|
||||
throwError("Error reading data for point/element " +
|
||||
std::to_string(point.pointId()) + ".");
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::ready(PointTableRef table)
|
||||
{
|
||||
m_stream = Utils::openFile(m_filename, true);
|
||||
if (m_stream)
|
||||
m_stream->seekg(m_dataPos);
|
||||
for (Element& elt : m_elements)
|
||||
{
|
||||
if (&elt == m_vertexElt)
|
||||
break;
|
||||
|
||||
// We read an element into point 0. Since the element's properties
|
||||
// weren't registered as dimensions, we'll try to write the data
|
||||
// to a NULL dimension, which is a noop.
|
||||
// This essentially just gets us to the vertex element.
|
||||
// In binary mode, this is all silliness, since we should be able
|
||||
// to seek right where we want to go, but in text mode, you've got
|
||||
// to go through the data.
|
||||
PointRef point(table, 0);
|
||||
for (PointId idx = 0; idx < elt.m_count; ++idx)
|
||||
readElement(elt, point);
|
||||
}
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
|
||||
bool FloatPlyReader::processOne(PointRef& point)
|
||||
{
|
||||
if (m_index < m_vertexElt->m_count)
|
||||
{
|
||||
readElement(*m_vertexElt, point);
|
||||
m_index++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// We're just reading the vertex element here.
|
||||
point_count_t FloatPlyReader::read(PointViewPtr view, point_count_t num)
|
||||
{
|
||||
point_count_t cnt(0);
|
||||
|
||||
PointRef point(view->point(0));
|
||||
for (PointId idx = 0; idx < m_vertexElt->m_count && idx < num; ++idx)
|
||||
{
|
||||
point.setPointId(idx);
|
||||
processOne(point);
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
void FloatPlyReader::done(PointTableRef table)
|
||||
{
|
||||
Utils::closeFile(m_stream);
|
||||
}
|
||||
|
||||
} // namespace pdal
|
|
@ -1,156 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2015, Peter J. Gadomski <pete.gadomski@gmail.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <pdal/io/PlyReader.hpp>
|
||||
#include <pdal/PointTable.hpp>
|
||||
#include <pdal/PointView.hpp>
|
||||
#include <pdal/Options.hpp>
|
||||
#include <pdal/Filter.hpp>
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include <pdal/Dimension.hpp>
|
||||
#include <pdal/Reader.hpp>
|
||||
#include <pdal/StageFactory.hpp>
|
||||
|
||||
namespace pdal
|
||||
{
|
||||
|
||||
class PDAL_DLL FloatPlyReader : public Reader
|
||||
{
|
||||
public:
|
||||
std::string getName() const;
|
||||
|
||||
typedef std::map<std::string, Dimension::Id> DimensionMap;
|
||||
|
||||
FloatPlyReader();
|
||||
|
||||
private:
|
||||
enum class Format
|
||||
{
|
||||
Ascii,
|
||||
BinaryLe,
|
||||
BinaryBe
|
||||
};
|
||||
|
||||
struct Property
|
||||
{
|
||||
Property(const std::string& name) : m_name(name)
|
||||
{}
|
||||
virtual ~Property()
|
||||
{}
|
||||
|
||||
std::string m_name;
|
||||
|
||||
virtual void setDim(Dimension::Id id)
|
||||
{}
|
||||
virtual void read(std::istream *stream, FloatPlyReader::Format format,
|
||||
PointRef& point) = 0;
|
||||
};
|
||||
|
||||
struct SimpleProperty : public Property
|
||||
{
|
||||
SimpleProperty(const std::string& name, Dimension::Type type) :
|
||||
Property(name), m_type(type), m_dim(Dimension::Id::Unknown)
|
||||
{}
|
||||
|
||||
Dimension::Type m_type;
|
||||
Dimension::Id m_dim;
|
||||
|
||||
virtual void read(std::istream *stream, FloatPlyReader::Format format,
|
||||
PointRef& point) override;
|
||||
virtual void setDim(Dimension::Id id) override
|
||||
{ m_dim = id; }
|
||||
};
|
||||
|
||||
struct ListProperty : public Property
|
||||
{
|
||||
ListProperty(const std::string& name, Dimension::Type countType,
|
||||
Dimension::Type listType) : Property(name), m_countType(countType),
|
||||
m_listType(listType)
|
||||
{}
|
||||
|
||||
Dimension::Type m_countType;
|
||||
Dimension::Type m_listType;
|
||||
|
||||
virtual void read(std::istream *stream, FloatPlyReader::Format format,
|
||||
PointRef& point) override;
|
||||
};
|
||||
|
||||
struct Element
|
||||
{
|
||||
Element(const std::string name, size_t count) :
|
||||
m_name(name), m_count(count)
|
||||
{}
|
||||
|
||||
std::string m_name;
|
||||
size_t m_count;
|
||||
std::vector<std::unique_ptr<Property>> m_properties;
|
||||
};
|
||||
|
||||
Format m_format;
|
||||
std::string m_line;
|
||||
std::string::size_type m_linePos;
|
||||
std::stack<std::string> m_lines;
|
||||
std::istream *m_stream;
|
||||
std::istream::streampos m_dataPos;
|
||||
std::vector<Element> m_elements;
|
||||
PointId m_index;
|
||||
Element *m_vertexElt;
|
||||
|
||||
virtual void initialize();
|
||||
virtual void addDimensions(PointLayoutPtr layout);
|
||||
virtual void ready(PointTableRef table);
|
||||
virtual point_count_t read(PointViewPtr view, point_count_t num);
|
||||
virtual void done(PointTableRef table);
|
||||
virtual bool processOne(PointRef& point);
|
||||
|
||||
std::string readLine();
|
||||
void pushLine();
|
||||
std::string nextWord();
|
||||
void extractMagic();
|
||||
void extractEnd();
|
||||
void extractFormat();
|
||||
Dimension::Type getType(const std::string& name);
|
||||
void extractProperty(Element& element);
|
||||
void extractProperties(Element& element);
|
||||
bool extractElement();
|
||||
void extractHeader();
|
||||
void readElement(Element& elt, PointRef& point);
|
||||
bool readProperty(Property *prop, PointRef& point);
|
||||
};
|
||||
|
||||
} // namespace pdal
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include "CmdLineParser.h"
|
||||
|
||||
struct Logger{
|
||||
bool verbose;
|
||||
const char* outputFile;
|
||||
|
||||
Logger(){
|
||||
this->verbose = false;
|
||||
this->outputFile = NULL;
|
||||
}
|
||||
|
||||
void operator() ( const char* format , ... )
|
||||
{
|
||||
if( outputFile )
|
||||
{
|
||||
FILE* fp = fopen( outputFile , "a" );
|
||||
va_list args;
|
||||
va_start( args , format );
|
||||
vfprintf( fp , format , args );
|
||||
fclose( fp );
|
||||
va_end( args );
|
||||
}
|
||||
if( verbose )
|
||||
{
|
||||
va_list args;
|
||||
va_start( args , format );
|
||||
vprintf( format , args );
|
||||
va_end( args );
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,276 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2015, Peter J. Gadomski <pete.gadomski@gmail.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
// Modified to output certain property names in normalized format ("nx", "ny", ... instead of "normalx", "normaly", etc.)
|
||||
|
||||
#include "ModifiedPlyWriter.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <pdal/util/OStream.hpp>
|
||||
#include <pdal/util/ProgramArgs.hpp>
|
||||
|
||||
namespace pdal
|
||||
{
|
||||
|
||||
std::string ModifiedPlyWriter::getName() const { return "ModifiedPlyWriter"; }
|
||||
|
||||
|
||||
ModifiedPlyWriter::ModifiedPlyWriter()
|
||||
{}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::addArgs(ProgramArgs& args)
|
||||
{
|
||||
args.add("filename", "Output filename", m_filename).setPositional();
|
||||
args.add("storage_mode", "PLY Storage Mode", m_format, Format::Ascii);
|
||||
args.add("dims", "Dimension names", m_dimNames);
|
||||
args.add("faces", "Write faces", m_faces);
|
||||
m_precisionArg = &args.add("precision", "Output precision", m_precision, 3);
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::prepared(PointTableRef table)
|
||||
{
|
||||
if (m_precisionArg->set() && m_format != Format::Ascii)
|
||||
throwError("Option 'precision' can only be set of the 'storage_mode' "
|
||||
"is ascii.");
|
||||
if (m_dimNames.size())
|
||||
{
|
||||
for (auto& name : m_dimNames)
|
||||
{
|
||||
auto id = table.layout()->findDim(name);
|
||||
if (id == Dimension::Id::Unknown)
|
||||
throwError("Unknown dimension '" + name + "' in provided "
|
||||
"dimension list.");
|
||||
m_dims.push_back(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dims = table.layout()->dims();
|
||||
for (auto dim : m_dims)
|
||||
m_dimNames.push_back(Utils::tolower(table.layout()->dimName(dim)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ModifiedPlyWriter::getType(Dimension::Type type) const
|
||||
{
|
||||
static std::map<Dimension::Type, std::string> types =
|
||||
{
|
||||
{ Dimension::Type::Signed8, "char" },
|
||||
{ Dimension::Type::Unsigned8, "uchar" },
|
||||
{ Dimension::Type::Signed16, "short" },
|
||||
{ Dimension::Type::Unsigned16, "ushort" },
|
||||
{ Dimension::Type::Signed32, "int" },
|
||||
{ Dimension::Type::Unsigned32, "uint" },
|
||||
{ Dimension::Type::Float, "float" },
|
||||
{ Dimension::Type::Double, "double" }
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return types.at(type);
|
||||
}
|
||||
catch (std::out_of_range&)
|
||||
{
|
||||
throwError("Can't write dimension of type '" +
|
||||
Dimension::interpretationName(type) + "'.");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::writeHeader(PointLayoutPtr layout) const
|
||||
{
|
||||
*m_stream << "ply" << std::endl;
|
||||
*m_stream << "format " << m_format << " 1.0" << std::endl;
|
||||
*m_stream << "comment Generated by odm_filterpoints" << std::endl;
|
||||
*m_stream << "element vertex " << pointCount() << std::endl;
|
||||
|
||||
auto ni = m_dimNames.begin();
|
||||
for (auto dim : m_dims)
|
||||
{
|
||||
std::string name = *ni++;
|
||||
std::string typeString = getType(layout->dimType(dim));
|
||||
|
||||
// Normalize certain property names
|
||||
if (name == "normalx" || name == "normal_x") name = "nx";
|
||||
if (name == "normaly" || name == "normal_y") name = "ny";
|
||||
if (name == "normalz" || name == "normal_z") name = "nz";
|
||||
|
||||
if (name == "diffuse_red") name = "red";
|
||||
if (name == "diffuse_green") name = "green";
|
||||
if (name == "diffuse_blue") name = "blue";
|
||||
|
||||
*m_stream << "property " << typeString << " " << name << std::endl;
|
||||
}
|
||||
if (m_faces)
|
||||
{
|
||||
*m_stream << "element face " << faceCount() << std::endl;
|
||||
*m_stream << "property list uchar uint vertex_indices" << std::endl;
|
||||
}
|
||||
*m_stream << "end_header" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::ready(PointTableRef table)
|
||||
{
|
||||
if (pointCount() > (std::numeric_limits<uint32_t>::max)())
|
||||
throwError("Can't write PLY file. Only " +
|
||||
std::to_string((std::numeric_limits<uint32_t>::max)()) +
|
||||
" points supported.");
|
||||
|
||||
m_stream = Utils::createFile(m_filename, true);
|
||||
if (m_format == Format::Ascii && m_precisionArg->set())
|
||||
{
|
||||
*m_stream << std::fixed;
|
||||
m_stream->precision(m_precision);
|
||||
}
|
||||
writeHeader(table.layout());
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::write(const PointViewPtr data)
|
||||
{
|
||||
m_views.push_back(data);
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::writeValue(PointRef& point, Dimension::Id dim,
|
||||
Dimension::Type type)
|
||||
{
|
||||
if (m_format == Format::Ascii)
|
||||
{
|
||||
double d = point.getFieldAs<double>(dim);
|
||||
*m_stream << d;
|
||||
}
|
||||
else if (m_format == Format::BinaryLe)
|
||||
{
|
||||
OLeStream out(m_stream);
|
||||
Everything e;
|
||||
point.getField((char *)&e, dim, type);
|
||||
Utils::insertDim(out, type, e);
|
||||
}
|
||||
else if (m_format == Format::BinaryBe)
|
||||
{
|
||||
OBeStream out(m_stream);
|
||||
Everything e;
|
||||
point.getField((char *)&e, dim, type);
|
||||
Utils::insertDim(out, type, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::writePoint(PointRef& point, PointLayoutPtr layout)
|
||||
{
|
||||
for (auto it = m_dims.begin(); it != m_dims.end();)
|
||||
{
|
||||
Dimension::Id dim = *it;
|
||||
writeValue(point, dim, layout->dimType(dim));
|
||||
++it;
|
||||
if (m_format == Format::Ascii && it != m_dims.end())
|
||||
*m_stream << " ";
|
||||
}
|
||||
if (m_format == Format::Ascii)
|
||||
*m_stream << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void ModifiedPlyWriter::writeTriangle(const Triangle& t, size_t offset)
|
||||
{
|
||||
if (m_format == Format::Ascii)
|
||||
{
|
||||
*m_stream << "3 " << (t.m_a + offset) << " " <<
|
||||
(t.m_b + offset) << " " << (t.m_c + offset) << std::endl;
|
||||
}
|
||||
else if (m_format == Format::BinaryLe)
|
||||
{
|
||||
OLeStream out(m_stream);
|
||||
unsigned char count = 3;
|
||||
uint32_t a = (uint32_t)(t.m_a + offset);
|
||||
uint32_t b = (uint32_t)(t.m_b + offset);
|
||||
uint32_t c = (uint32_t)(t.m_c + offset);
|
||||
out << count << a << b << c;
|
||||
}
|
||||
else if (m_format == Format::BinaryBe)
|
||||
{
|
||||
OBeStream out(m_stream);
|
||||
unsigned char count = 3;
|
||||
uint32_t a = (uint32_t)(t.m_a + offset);
|
||||
uint32_t b = (uint32_t)(t.m_b + offset);
|
||||
uint32_t c = (uint32_t)(t.m_c + offset);
|
||||
out << count << a << b << c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Deferring write until this time allows both points and faces from multiple
|
||||
// point views to be written.
|
||||
void ModifiedPlyWriter::done(PointTableRef table)
|
||||
{
|
||||
for (auto& v : m_views)
|
||||
{
|
||||
PointRef point(*v, 0);
|
||||
for (PointId idx = 0; idx < v->size(); ++idx)
|
||||
{
|
||||
point.setPointId(idx);
|
||||
writePoint(point, table.layout());
|
||||
}
|
||||
}
|
||||
if (m_faces)
|
||||
{
|
||||
PointId offset = 0;
|
||||
for (auto& v : m_views)
|
||||
{
|
||||
TriangularMesh *mesh = v->mesh();
|
||||
if (mesh)
|
||||
{
|
||||
for (size_t id = 0; id < mesh->size(); ++id)
|
||||
{
|
||||
const Triangle& t = (*mesh)[id];
|
||||
writeTriangle(t, offset);
|
||||
}
|
||||
}
|
||||
offset += v->size();
|
||||
}
|
||||
}
|
||||
Utils::closeFile(m_stream);
|
||||
m_stream = nullptr;
|
||||
getMetadata().addList("filename", m_filename);
|
||||
}
|
||||
|
||||
} // namespace pdal
|
|
@ -1,116 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Copyright (c) 2015, Peter J. Gadomski <pete.gadomski@gmail.com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
|
||||
* names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
****************************************************************************/
|
||||
|
||||
#include <pdal/PointView.hpp>
|
||||
#include <pdal/Writer.hpp>
|
||||
|
||||
namespace pdal
|
||||
{
|
||||
|
||||
class Triangle;
|
||||
|
||||
class PDAL_DLL ModifiedPlyWriter : public Writer
|
||||
{
|
||||
public:
|
||||
enum class Format
|
||||
{
|
||||
Ascii,
|
||||
BinaryLe,
|
||||
BinaryBe
|
||||
};
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
ModifiedPlyWriter();
|
||||
|
||||
private:
|
||||
virtual void addArgs(ProgramArgs& args);
|
||||
virtual void prepared(PointTableRef table);
|
||||
virtual void ready(PointTableRef table);
|
||||
virtual void write(const PointViewPtr data);
|
||||
virtual void done(PointTableRef table);
|
||||
|
||||
std::string getType(Dimension::Type type) const;
|
||||
void writeHeader(PointLayoutPtr layout) const;
|
||||
void writeValue(PointRef& point, Dimension::Id dim, Dimension::Type type);
|
||||
void writePoint(PointRef& point, PointLayoutPtr layout);
|
||||
void writeTriangle(const Triangle& t, size_t offset);
|
||||
|
||||
std::ostream *m_stream;
|
||||
std::string m_filename;
|
||||
Format m_format;
|
||||
bool m_faces;
|
||||
StringList m_dimNames;
|
||||
Dimension::IdList m_dims;
|
||||
int m_precision;
|
||||
Arg *m_precisionArg;
|
||||
std::vector<PointViewPtr> m_views;
|
||||
};
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, ModifiedPlyWriter::Format& f)
|
||||
{
|
||||
std::string s;
|
||||
std::getline(in, s);
|
||||
Utils::trim(s);
|
||||
Utils::tolower(s);
|
||||
if (s == "ascii" || s == "default")
|
||||
f = ModifiedPlyWriter::Format::Ascii;
|
||||
else if (s == "little endian" || s == "binary_little_endian")
|
||||
f = ModifiedPlyWriter::Format::BinaryLe;
|
||||
else if (s == "big endian" || s == "binary_big_endian")
|
||||
f = ModifiedPlyWriter::Format::BinaryBe;
|
||||
else
|
||||
in.setstate(std::ios_base::failbit);
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const ModifiedPlyWriter::Format& f)
|
||||
{
|
||||
switch (f)
|
||||
{
|
||||
case ModifiedPlyWriter::Format::Ascii:
|
||||
out << "ascii";
|
||||
break;
|
||||
case ModifiedPlyWriter::Format::BinaryLe:
|
||||
out << "binary_little_endian";
|
||||
break;
|
||||
case ModifiedPlyWriter::Format::BinaryBe:
|
||||
out << "binary_big_endian";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <pdal/filters/OutlierFilter.hpp>
|
||||
#include <pdal/filters/RangeFilter.hpp>
|
||||
#include <pdal/filters/SampleFilter.hpp>
|
||||
#include "CmdLineParser.h"
|
||||
#include "Logger.h"
|
||||
#include "FloatPlyReader.hpp"
|
||||
#include "ModifiedPlyWriter.hpp"
|
||||
|
||||
Logger logWriter;
|
||||
|
||||
cmdLineParameter< char* >
|
||||
InputFile( "inputFile" ) ,
|
||||
OutputFile( "outputFile" );
|
||||
cmdLineParameter< float >
|
||||
StandardDeviation( "sd" ) ,
|
||||
MeanK ( "meank" ) ,
|
||||
Confidence ( "confidence" ) ,
|
||||
Sample ( "sample" );
|
||||
cmdLineReadable
|
||||
Verbose( "verbose" );
|
||||
|
||||
cmdLineReadable* params[] = {
|
||||
&InputFile , &OutputFile , &StandardDeviation, &MeanK, &Confidence, &Sample, &Verbose ,
|
||||
NULL
|
||||
};
|
||||
|
||||
void help(char *ex){
|
||||
std::cout << "Usage: " << ex << std::endl
|
||||
<< "\t -" << InputFile.name << " <input PLY point cloud>" << std::endl
|
||||
<< "\t -" << OutputFile.name << " <output PLY point cloud>" << std::endl
|
||||
<< "\t [-" << StandardDeviation.name << " <standard deviation threshold>]" << std::endl
|
||||
<< "\t [-" << MeanK.name << " <mean number of neighbors >]" << std::endl
|
||||
<< "\t [-" << Confidence.name << " <lower bound filter for confidence property>]" << std::endl
|
||||
|
||||
<< "\t [-" << Verbose.name << "]" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
void logArgs(cmdLineReadable* params[], Logger& logWriter){
|
||||
logWriter("Running with parameters:\n");
|
||||
char str[1024];
|
||||
for( int i=0 ; params[i] ; i++ ){
|
||||
if( params[i]->set ){
|
||||
params[i]->writeValue( str );
|
||||
if( strlen( str ) ) logWriter( "\t--%s %s\n" , params[i]->name , str );
|
||||
else logWriter( "\t--%s\n" , params[i]->name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
cmdLineParse( argc-1 , &argv[1] , params );
|
||||
if( !InputFile.set || !OutputFile.set ) help(argv[0]);
|
||||
if( !StandardDeviation.set ) StandardDeviation.value = 2.0;
|
||||
if( !MeanK.set ) MeanK.value = 8;
|
||||
|
||||
logWriter.verbose = Verbose.set;
|
||||
logArgs(params, logWriter);
|
||||
|
||||
logWriter("Filtering point cloud...\n");
|
||||
|
||||
pdal::Options inPlyOpts;
|
||||
inPlyOpts.add("filename", InputFile.value);
|
||||
|
||||
pdal::PointTable table;
|
||||
pdal::FloatPlyReader plyReader;
|
||||
pdal::Stage *currentStage = &plyReader;
|
||||
plyReader.setOptions(inPlyOpts);
|
||||
|
||||
pdal::RangeFilter confidenceFilter;
|
||||
if (Confidence.set){
|
||||
logWriter("Filtering confidence\n");
|
||||
|
||||
pdal::Options confidenceFilterOpts;
|
||||
float confidenceValue = std::min(1.0f, std::max(Confidence.value, 0.0f));
|
||||
std::ostringstream confidenceLimit;
|
||||
confidenceLimit << "confidence[" << confidenceValue << ":1]";
|
||||
confidenceFilterOpts.add("limits", confidenceLimit.str());
|
||||
|
||||
confidenceFilter.setInput(*currentStage);
|
||||
currentStage = &confidenceFilter;
|
||||
confidenceFilter.setOptions(confidenceFilterOpts);
|
||||
}
|
||||
|
||||
pdal::SampleFilter sampleFilter;
|
||||
if (Sample.set && Sample.value > 0.0f){
|
||||
logWriter("Radius sampling\n");
|
||||
pdal::Options sampleFilterOpts;
|
||||
sampleFilterOpts.add("radius", Sample.value);
|
||||
sampleFilter.setOptions(sampleFilterOpts);
|
||||
sampleFilter.setInput(*currentStage);
|
||||
currentStage = &sampleFilter;
|
||||
}
|
||||
|
||||
pdal::Options outlierOpts;
|
||||
outlierOpts.add("method", "statistical");
|
||||
outlierOpts.add("mean_k", MeanK.value);
|
||||
outlierOpts.add("multiplier", StandardDeviation.value);
|
||||
|
||||
pdal::OutlierFilter outlierFilter;
|
||||
outlierFilter.setInput(*currentStage);
|
||||
outlierFilter.setOptions(outlierOpts);
|
||||
|
||||
pdal::Options rangeOpts;
|
||||
rangeOpts.add("limits", "Classification![7:7]"); // Remove outliers
|
||||
|
||||
pdal::RangeFilter rangeFilter;
|
||||
rangeFilter.setInput(outlierFilter);
|
||||
rangeFilter.setOptions(rangeOpts);
|
||||
|
||||
pdal::Options outPlyOpts;
|
||||
outPlyOpts.add("storage_mode", "little endian");
|
||||
outPlyOpts.add("filename", OutputFile.value);
|
||||
|
||||
pdal::ModifiedPlyWriter plyWriter;
|
||||
plyWriter.setOptions(outPlyOpts);
|
||||
plyWriter.setInput(rangeFilter);
|
||||
plyWriter.prepare(table);
|
||||
plyWriter.execute(table);
|
||||
|
||||
logWriter("Done!\n");
|
||||
}
|
|
@ -7,7 +7,26 @@ from opendm import entwine
|
|||
from opendm import io
|
||||
from pipes import quote
|
||||
|
||||
def filter(input_point_cloud, output_point_cloud, standard_deviation=2.5, meank=16, confidence=None, sample_radius=0, verbose=False):
|
||||
def ply_has_normals(input_ply):
|
||||
if not os.path.exists(input_ply):
|
||||
return False
|
||||
|
||||
# Read PLY header, check if point cloud has normals
|
||||
has_normals = False
|
||||
with open(input_ply, 'r') as f:
|
||||
line = f.readline().strip().lower()
|
||||
i = 0
|
||||
while line != "end_header" and i < 100:
|
||||
line = f.readline().strip().lower()
|
||||
props = line.split(" ")
|
||||
if len(props) == 3 and props[0] == "property" and props[2] in ["nx", "normalx", "normal_x"]:
|
||||
has_normals = True
|
||||
break
|
||||
i += 1
|
||||
|
||||
return has_normals
|
||||
|
||||
def filter(input_point_cloud, output_point_cloud, standard_deviation=2.5, meank=16, sample_radius=0, verbose=False):
|
||||
"""
|
||||
Filters a point cloud
|
||||
"""
|
||||
|
@ -21,40 +40,53 @@ def filter(input_point_cloud, output_point_cloud, standard_deviation=2.5, meank=
|
|||
shutil.copy(input_point_cloud, output_point_cloud)
|
||||
return
|
||||
|
||||
if standard_deviation > 0 and meank > 0:
|
||||
log.ODM_INFO("Filtering point cloud (statistical, meanK {}, standard deviation {})".format(meank, standard_deviation))
|
||||
|
||||
if confidence:
|
||||
log.ODM_INFO("Keeping only points with > %s confidence" % confidence)
|
||||
filters = []
|
||||
|
||||
if sample_radius > 0:
|
||||
log.ODM_INFO("Sampling points around a %sm radius" % sample_radius)
|
||||
filters.append('sample')
|
||||
|
||||
filter_program = os.path.join(context.odm_modules_path, 'odm_filterpoints')
|
||||
if not os.path.exists(filter_program):
|
||||
log.ODM_WARNING("{} program not found. Will skip filtering, but this installation should be fixed.")
|
||||
shutil.copy(input_point_cloud, output_point_cloud)
|
||||
return
|
||||
if standard_deviation > 0 and meank > 0:
|
||||
log.ODM_INFO("Filtering point cloud (statistical, meanK {}, standard deviation {})".format(meank, standard_deviation))
|
||||
filters.append('outlier')
|
||||
|
||||
if len(filters) > 0:
|
||||
filters.append('range')
|
||||
|
||||
dims = "x=float,y=float,z=float,"
|
||||
if ply_has_normals(input_point_cloud):
|
||||
dims += "nx=float,ny=float,nz=float,"
|
||||
dims += "red=uchar,blue=uchar,green=uchar"
|
||||
|
||||
filterArgs = {
|
||||
'bin': filter_program,
|
||||
'inputFile': input_point_cloud,
|
||||
'outputFile': output_point_cloud,
|
||||
'sd': standard_deviation,
|
||||
'meank': meank,
|
||||
'verbose': '-verbose' if verbose else '',
|
||||
'confidence': '-confidence %s' % confidence if confidence else '',
|
||||
'sample': max(0, sample_radius)
|
||||
'stages': " ".join(filters),
|
||||
'dims': dims
|
||||
}
|
||||
|
||||
system.run('{bin} -inputFile {inputFile} '
|
||||
'-outputFile {outputFile} '
|
||||
'-sd {sd} '
|
||||
'-meank {meank} '
|
||||
'-sample {sample} '
|
||||
'{confidence} {verbose} '.format(**filterArgs))
|
||||
cmd = ("pdal translate -i \"{inputFile}\" "
|
||||
"-o \"{outputFile}\" "
|
||||
"{stages} "
|
||||
"--writers.ply.sized_types=false "
|
||||
"--writers.ply.storage_mode='little endian' "
|
||||
"--writers.ply.dims=\"{dims}\" "
|
||||
"").format(**filterArgs)
|
||||
|
||||
if 'sample' in filters:
|
||||
cmd += "--filters.sample.radius={} ".format(sample_radius)
|
||||
|
||||
if 'outlier' in filters:
|
||||
cmd += ("--filters.outlier.method='statistical' "
|
||||
"--filters.outlier.mean_k={} "
|
||||
"--filters.outlier.multiplier={} ").format(meank, standard_deviation)
|
||||
|
||||
if 'range' in filters:
|
||||
# Remove outliers
|
||||
cmd += "--filters.range.limits='Classification![7:7]' "
|
||||
|
||||
system.run(cmd)
|
||||
|
||||
# Remove input file, swap temp file
|
||||
if not os.path.exists(output_point_cloud):
|
||||
log.ODM_WARNING("{} not found, filtering has failed.".format(output_point_cloud))
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ class ODMFilterPoints(types.ODM_Stage):
|
|||
|
||||
point_cloud.filter(inputPointCloud, tree.filtered_point_cloud,
|
||||
standard_deviation=args.pc_filter,
|
||||
confidence=None,
|
||||
sample_radius=args.pc_sample,
|
||||
verbose=args.verbose)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue