Upgraded PDAL to 2.1, removed odm_filterpoints module

Former-commit-id: 653d276b20
pull/1161/head
Piero Toffanin 2020-07-07 11:29:25 -04:00
rodzic f501d21d6e
commit 73088aba01
13 zmienionych plików z 59 dodań i 1618 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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})

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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 );
}
}
};

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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");
}

Wyświetl plik

@ -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))

Wyświetl plik

@ -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)