Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Point cloud loaders (LAS and TXT) #978

Draft
wants to merge 31 commits into
base: release-candidate
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
df9d559
add loaders for las and txt file format (point clouds)
Marina2468 Jul 25, 2022
9eccdfb
fix typo
Marina2468 Jul 25, 2022
afaa7d9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
5e396dd
remove compilation guards
Marina2468 Jul 26, 2022
faa0394
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
b478589
Update src/IO/AsciiPCLoader/asciipcloader.cpp
Marina2468 Jul 26, 2022
9e979c3
constructors set to default
Marina2468 Jul 26, 2022
d171d97
Merge branch 'pcloaders' of github.com:Marina2468/Radium-Engine into …
Marina2468 Jul 26, 2022
3573b19
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
814211f
Update src/IO/AsciiPCLoader/asciipcloader.cpp
Marina2468 Jul 26, 2022
bbf1404
Update src/IO/AsciiPCLoader/asciipcloader.cpp
Marina2468 Jul 26, 2022
1e49cd1
destructors set to default
Marina2468 Jul 26, 2022
2c53183
remove malloc
Marina2468 Jul 26, 2022
211b6f6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
c16169b
group log (remove code duplicate)
Marina2468 Jul 26, 2022
85c7236
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
5b6f991
update color and gps handling
Marina2468 Jul 26, 2022
6f9e1fa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
c21c520
update to load all attribs as custom
Marina2468 Jul 26, 2022
c06f7a0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2022
c974425
update las loader
Marina2468 Jul 27, 2022
769a183
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 27, 2022
2a258b8
fix custom attribs reference issue
Marina2468 Jul 27, 2022
4b470bd
fix colors range
Marina2468 Jul 27, 2022
2f6cfde
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 27, 2022
1ded72e
remove properties' log
Marina2468 Jul 27, 2022
b361d35
Merge branch 'release-candidate' into pcloaders
Marina2468 Jul 27, 2022
d830798
add guards on read + improve char* to double cast
Marina2468 Jul 28, 2022
484848f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 28, 2022
c30f473
initialize to avoid warning
Marina2468 Jul 28, 2022
4fc2c2b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions src/IO/AsciiPCLoader/asciipcloader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <IO/AsciiPCLoader/asciipcloader.hpp>

#include <Core/Asset/FileData.hpp>
#include <Core/Utils/Attribs.hpp> //logs
#include <fstream>
#include <iostream>

using std::ifstream;
using std::make_unique;
using std::runtime_error;
using std::to_string;

const string asciiExt( "txt" );

namespace Ra {
namespace IO {

vector<string> AsciiPointCloudLoader::getFileExtensions() const {
return vector<string>( { "*." + asciiExt } );
}

bool AsciiPointCloudLoader::handleFileExtension( const string& extension ) const {
return extension.compare( asciiExt ) == 0;
}

Ra::Core::Asset::FileData* AsciiPointCloudLoader::loadFile( const string& filename ) {
using Ra::Core::Asset::FileData;
using Ra::Core::Asset::GeometryData;
using Ra::Core::Utils::logERROR;
using Ra::Core::Utils::logINFO;

FileData* fileData = new Ra::Core::Asset::FileData( filename );

if ( !fileData->isInitialized() ) {
delete fileData;
LOG( logINFO ) << "Filedata could not be initialized";
return nullptr;
}

auto startTime = clock();
// a unique name is required by the component messaging system
static int id = 0;
auto geometry =
make_unique<GeometryData>( "TRAJ_PC_" + to_string( ++id ), GeometryData::POINT_CLOUD );
Marina2468 marked this conversation as resolved.
Show resolved Hide resolved
if ( geometry == nullptr ) {
LOG( logERROR ) << "could not create geometry";
return nullptr;
}

geometry->setFrame( Ra::Core::Transform::Identity() );

ifstream stream( filename );
if ( !stream.is_open() ) {
throw runtime_error( "Could not open ifstream to path " + filename );
return nullptr;
}
else {
LOG( logINFO ) << "---Beginning file loading---";
}

/*reading how data is arranged*/
string line;

if ( !std::getline( stream, line ) ) {
delete fileData;
LOG( logINFO ) << "file does not contain ascii data format. aborting";
return nullptr;
}

// retrieving all properties from header line
std::stringstream words( line );
vector<string> tokens;
string temp;
while ( words >> temp ) {
tokens.emplace_back( temp );
};

// making sure X, Y, Z and Time properties are found
int xpos = -1, ypos = -1, zpos = -1;
for ( size_t i = 0; i < tokens.size(); ++i ) {
string token = tokens[i];
if ( xpos == -1 ) {
if ( token.compare( "X" ) == 0 ) { xpos = i; }
}
if ( ypos == -1 ) {
if ( token.compare( "Y" ) == 0 ) { ypos = i; }
}
if ( zpos == -1 ) {
if ( token.compare( "Z" ) == 0 ) { zpos = i; }
}
}

if ( ( xpos == -1 ) || ( ypos == -1 ) || ( zpos == -1 ) ) {
delete fileData;
LOG( logERROR ) << "file does not contain mandatory properties (X, Y, Z, Time). aborting";
return nullptr;
}

Ra::Core::VectorArray<Ra::Core::Vector3>& vertices = geometry->getGeometry().verticesWithLock();

// creating custom attribs for all other properties
vector<Ra::Core::Utils::AttribHandle<Scalar>> attribs;
attribs.reserve( tokens.size() - 3 );

for ( size_t i = 0; i < tokens.size(); ++i ) {
// skipping mandatory attribs
if ( ( (int)i == xpos ) || ( (int)i == ypos ) || ( (int)i == zpos ) ) { continue; }
attribs.emplace_back(
geometry->getGeometry().vertexAttribs().addAttrib<Scalar>( tokens[i] ) );
}

/*recording data*/
vector<double> pointRecord;
int i = 0;
double num;
while ( stream >> num ) {
pointRecord.emplace_back( num );

if ( i == (int)( tokens.size() - 1 ) ) {
vertices.emplace_back( Scalar( pointRecord[xpos] ),
Scalar( pointRecord[ypos] ),
Scalar( pointRecord[zpos] ) );
size_t k = 0;
for ( size_t j = 0; j < tokens.size(); ++j ) {
if ( ( (int)j == xpos ) || ( (int)j == ypos ) || ( (int)j == zpos ) ) { continue; }
geometry->getGeometry()
.vertexAttribs()
.getDataWithLock( attribs[k] )
.emplace_back( Scalar( pointRecord[j] ) );
geometry->getGeometry().vertexAttribs().unlock( attribs[k] );
++k;
}
pointRecord.clear();
}
i = ( i + 1 ) % tokens.size();
}
stream.close();

geometry->getGeometry().verticesUnlock();

// finalizing
fileData->m_geometryData.clear();
fileData->m_geometryData.reserve( 1 );
fileData->m_geometryData.push_back( move( geometry ) );

fileData->m_loadingTime = ( clock() - startTime ) / Scalar( CLOCKS_PER_SEC );

LOG( logINFO ) << "---File loading ended---";

fileData->displayInfo();

fileData->m_processed = true;

return fileData;
}

string AsciiPointCloudLoader::name() const {
return "Plain Text (ASCII)";
}

} // namespace IO
} // namespace Ra
47 changes: 47 additions & 0 deletions src/IO/AsciiPCLoader/asciipcloader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <Core/Asset/FileLoaderInterface.hpp>
#include <IO/RaIO.hpp>

using std::string;
using std::vector;

namespace Ra {
namespace IO {

class RA_IO_API AsciiPointCloudLoader : public Ra::Core::Asset::FileLoaderInterface
{
public:
AsciiPointCloudLoader() = default;
virtual ~AsciiPointCloudLoader() = default;

vector<string> getFileExtensions() const override;
bool handleFileExtension( const std::string& extension ) const override;

/** load vertices properties from ASCII .txt file
*
* expected content in file: header line + data records
*
* header line content : attribute names separated by blanks ( )
*
* example: Time X Y Z Roll Pitch Heading sdX sdY sdZ
*
* X, Y, Z and Time properties (case sensitive) are mandatory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if we could relax the constraint on the time field: it could be useful to load point-clouds with xyz coordinates, even if we don't have the time field.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. now only position properties are mandatory

* for file loading. Failure to find any of these properties
* results in file reading failure
*
* X, Y, Z properties are aggregated in geometry vertex array,
* while all other properties are loaded as custom attribs in
* Radium
*
* @todo add aggregation for normals/colors
* @param [in] filename file path
* @return nullptr if file opening fails, geometry creation
* fails or one of the mandatory properties is not found
*/
Ra::Core::Asset::FileData* loadFile( const std::string& filename ) override;
string name() const override;
};

} // namespace IO
} // namespace Ra
Loading