demoSegmentation.cpp
/// example showing how to use opalsSegmentation
/// and access its results based on the segment manager
#include "opals/Exception.hpp"
#include "opals/ParamList.hpp"
#include "opals/ModuleDeleter.hpp"
#include "opals/ISegmentation.hpp"
#include "DM/IDatamanager.hpp"
#include "DM/IPolyline.hpp"
#include <iostream>
#include <iomanip>
#include <memory>
#include "opals/IImport.hpp"
#include "opals/INormals.hpp"
void output_addinfo(const DM::IAddInfo &info)
{
//output all attribute values within an addinfo object
std::cout << "attributes: ";
if (!info.columns())
std::cout << "NONE";
else
{
for (unsigned i = 0; i < info.columns(); i++)
{
if (i > 0)
std::cout << ", ";
std::cout << info.name(i) << "=";
if (info.isNull(i))
std::cout << "NULL";
else
{
switch (info.type(i))
{
std::cout << info.getInt32(i);
break;
std::cout << info.getUInt32(i);
break;
std::cout << info.getInt8(i);
break;
std::cout << info.getUInt8(i);
break;
std::cout << info.getInt16(i);
break;
std::cout << info.getUInt16(i);
break;
std::cout << info.getFloat(i);
break;
std::cout << info.getDouble(i);
break;
std::cout << info.getInt64(i);
break;
std::cout << info.getCStr(i);
break;
}
}
}
}
std::cout << std::endl;
}
void preprocessing(opals::Path name)
{
std::shared_ptr<opals::IImport> imp(opals::IImport::New(), opals::ModuleDeleter());
opals::Vector<opals::VectorOrRasterFile> infiles{1, name + ".laz"};
imp->opts().inFile().set(infiles);
imp->opts().tileSize().set(100);
imp->opts().filter().set("generic[z>265]");
imp->run();
imp.reset();
std::shared_ptr<opals::INormals> normals(opals::INormals::New(), opals::ModuleDeleter());
normals->opts().inFile().set(name + ".odm");
normals->opts().normalsAlg().set(opals::NormalsAlgorithm::simplePlane);
normals->opts().neighbours().set(8);
normals->opts().searchMode().set(opals::SearchMode::d2);
normals->opts().searchRadius().set(1);
normals->run();
}
int main(int argc, char** argv)
{
int errorCode = 0;
try {
//ATTENTION: programm needs to be excecuted within the opals demo directory or
// copy strip21.laz in your current directory
// necessary preprocessing steps
preprocessing("strip21");
//perform segmentation using plane extraction mode and alpha shape computation
std::shared_ptr<opals::ISegmentation> module( opals::ISegmentation::New(), opals::ModuleDeleter() );
module->opts().inFile().set("strip21.odm");
opals::Vector< float > radius(1, 1.0);
module->opts().searchRadius().set(radius);
module->opts().minSegSize().set(50);
module->opts().method().set(opals::SegmentationMethod::planeExtraction);
module->opts().planeExtraction().maxDist().set(0.2);
module->opts().planeExtraction().maxSigma().set(0.15);
module->opts().planeExtraction().seedCalculator().set("NormalSigma0<0.02 AND Z > 275 ? NormalSigma0 : invalid");
filters[0] = "Region[529568.8 5338773.5 529863 5338773.9 529862.6 5338642.4 529706 5338685.4 529569.1 5338753.8]";
module->opts().filter().set(filters);
module->opts().alphaRadius().set(1);
module->opts().sort().set(opals::SegmentSort::descendingPSize);
module->run();
// get segmentation manager(gives access to the segment objects)
opals::SharedPtr<opals::ISegmentManager> segManager = module->opts().segments().get();
// DM::IDatamanager::load(const char *filename, bool readOnly = false, bool threadSafety = true);
DM::DatamanagerHandle odm = DM::IDatamanager::load("strip21.odm", true, false);
DM::PointIndexHandle pi = odm->getPointIndex(); // get point index object of odm
std::cout << "The segmentation process has found " << segManager->sizeSegments() << " segment(s)" << std::endl;
unsigned max_pt_output = 5;
// iterate over all segments and output relevant segments properties
auto segs = segManager->getSegments();
for (auto it = segs.begin(); it != segs.end(); ++it)
{
const opals::ISegment &seg = **it;
//print basic segment information
std::cout << std::fixed << std::setprecision(3);
std::cout << "Segment-Nr " << seg.getID() << "\t " << seg.sizePoints() << " points; "
<< "COG (" << seg.getCoG()->x() << " / " << seg.getCoG()->y() << " / " << seg.getCoG()->z() << ")" << std::endl;
// get plane parameters
assert(planeParams.size() == 5);
std::cout << std::fixed << std::setprecision(4);
std::cout << "\tplane parameters: a=" << planeParams[0] << " b=" << planeParams[1] << " c=" << planeParams[2]
<< " d=" << planeParams[3] << std::setprecision(3) << " (sigma0=" << planeParams[4] << ")" << std::endl;
// get alpha shape(can be empty in case the computation failed)
if (alphaShape)
{
std::cout << "\talpha shape consists of " << alphaShape->sizePart() << " parts:" << std::endl;
unsigned idx = 0;
for (auto itPart = alphaShape->beginPart(); itPart != alphaShape->endPart(); ++itPart, ++idx)
{
const DM::IPolyline::IPart &part = *itPart;
std::cout << "\t\t" << idx << " part has " << part.sizePoint() << " points";
output_addinfo(part.info());
}
}
// get segment point ids and print the first "max_pt_output" points
std::cout << "\touput the first " << max_pt_output << " points: " << std::endl;
auto ptIds = seg.getPoints();
unsigned idx = 0;
for (auto it = ptIds.begin(); it != ptIds.end(); ++it, ++idx)
{
DM::PointHandle pt = pi->getPoint(*it);
std::cout << "\t\t" << idx << std::setprecision(3) << ".point (" << pt->x() << " / " << pt->y() << " / " << pt->z() << ")" << std::endl;
if (idx + 1 >= max_pt_output)
break;
}
}
}
{
//in this case an error occurred, output error message
errorCode = e.errorCode();
std::cout << e.errorMessage() << std::endl;
}
return errorCode;
}
virtual opals::Vector< opals::ISegment * > getSegments() const =0
get vector of all segments. the lifetime of the segments is attached to the manager....
@ d2
Search based on 2D coordinates (x and y) only.
const char * errorMessage() const
returns the actual error message
ErrorCode::Enum errorCode() const
returns the error code
@ planeExtraction
This method detects planar surface segments with the use of normal vectors.
A functor that may be used for memory management of modules allocated on the heap usage: e....
Definition: ModuleDeleter.hpp:15
@ int16
name: "int16". 2 byte, integer
@ int32
name: "int32". 4 byte, signed integer
AddInfo objects store a set of attributes.
Definition: M/c++_api/inc/DM/IAddInfo.hpp:14
@ uint16
name: "uint16". 2 byte, unsigned integer
Segment interface.
Definition: ISegmentManager.hpp:20
@ int8
name: "int8". 1 byte, signed integer
@ uint32
name: "uint32". 4 byte, unsigned integer
smart pointer class for opals objects
Definition: SharedPtr.hpp:33
A file/directory path.
Definition: Path.hpp:26
virtual const opals::Vector< double > & getPlaneParams() const =0
get plane parameters (a,b,c,d and sigma0) of the extracted plane (in plane extraction mode only....
@ double_
name: "double". 8 byte, real
@ descendingPSize
sort descending by point per segment
@ float_
name: "float". 4 byte, real
@ odm
OPALS Datamanager file.
virtual const DM::PolylineHandle & getAlphaShape() const =0
get alpha shape of segment (only available in plane extraction mode and set alpha radius)
T * get() const noexcept
get pointer to controlled object
Definition: SharedPtr.hpp:72
virtual unsigned getID() const =0
returns id of segment
static IDatamanager * load(const char *filename, bool readOnly=false, bool threadSafety=true)
Definition: IPolyline.hpp:21
@ int64
name: "int64". 8 byte, signed integer
@ info
Some progress that may be interesting in everyday-use.
@ alphaShape
alpha shape ( strictly simple boundary polygon with dished parts but without holes)
virtual int64_t sizeSegments() const =0
get number of segments
@ simplePlane
performs a simple plane fit
Mimics std::vector<T>
Definition: fwd.hpp:18
@ string
name: "string". c string of arbitrary size
Smart pointer class using reference counting with support for DM objects (see ObjectBase)
Definition: Handle.hpp:75
virtual const DM::PointHandle & getCoG() const =0
get center of gravity of segment points
virtual opals::Vector< int64_t > getPoints() const =0
get point id vector of segment
@ uint8
name: "uint8". 1 byte, unsigned integer
The base class of all exceptions thrown by opals.
Definition: c++_api/inc/opals/Exception.hpp:170
virtual size_t sizePoints() const =0
number of points that have been assigned to segment