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

Scalar fields now rely on an internal offset to properly manage double/large values #116

Merged
merged 4 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
37 changes: 12 additions & 25 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ option( CCCORELIB_SHARED
"Compile CCCoreLib as a shared library"
ON
)
option( CCCORELIB_SCALAR_DOUBLE
"Define ScalarType as double (instead of float)"
OFF
)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

Expand Down Expand Up @@ -119,24 +115,15 @@ target_compile_definitions( CCCoreLib
"$<$<CONFIG:DEBUG>:CC_DEBUG>"
)

if ( CCCORELIB_SCALAR_DOUBLE )
target_compile_definitions( CCCoreLib
PUBLIC
CC_CORE_LIB_USES_DOUBLE
)
else()
target_compile_definitions( CCCoreLib
PUBLIC
CC_CORE_LIB_USES_FLOAT
)
endif()

# Nanoflann
option(NANOFLANN_BUILD_BENCHMARKS "" OFF)
option(NANOFLANN_BUILD_EXAMPLES "" OFF)
option(NANOFLANN_BUILD_TESTS "" OFF)
add_subdirectory( extern/nanoflann EXCLUDE_FROM_ALL )
target_link_libraries( CCCoreLib PUBLIC nanoflann::nanoflann )
target_link_libraries( CCCoreLib
PUBLIC
nanoflann::nanoflann
)

# Windows-specific flags
if ( WIN32 )
Expand Down Expand Up @@ -177,12 +164,12 @@ if ( CCCORELIB_USE_TBB )
if ( ${TBB_VERSION} VERSION_GREATER 2021.0.0 )
target_link_libraries( CCCoreLib
PUBLIC
TBB::tbb
TBB::tbb
)
else()
target_link_libraries( CCCoreLib
PUBLIC
${TBB_IMPORTED_TARGETS}
${TBB_IMPORTED_TARGETS}
)
endif()
target_compile_definitions( CCCoreLib
Expand Down Expand Up @@ -237,15 +224,15 @@ if ( CCCORELIB_USE_QT_CONCURRENT )
REQUIRED
)

set_target_properties( CCCoreLib PROPERTIES
AUTOMOC OFF
AUTORCC OFF
AUTOUIC OFF
)
set_target_properties( CCCoreLib PROPERTIES
AUTOMOC OFF
AUTORCC OFF
AUTOUIC OFF
)

target_link_libraries( CCCoreLib
PUBLIC
Qt5::Concurrent
Qt5::Concurrent
)

target_compile_definitions( CCCoreLib
Expand Down
2 changes: 1 addition & 1 deletion include/CCConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ namespace CCCoreLib
};

//! Min number of points to compute local models (see CC_LOCAL_MODEL_TYPES)
constexpr unsigned CC_LOCAL_MODEL_MIN_SIZE[] = {
constexpr unsigned CC_LOCAL_MODEL_MIN_SIZE[] {
1, //!< for single point model (i.e. no model ;)
3, //!< for least Square best fitting plane
3, //!< for Delaunay triangulation (2.5D)
Expand Down
6 changes: 0 additions & 6 deletions include/CCTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,4 @@
using PointCoordinateType = float;

//! Type of a single scalar field value
#if defined CC_CORE_LIB_USES_DOUBLE
using ScalarType = double;
#elif defined CC_CORE_LIB_USES_FLOAT
using ScalarType = float;
#else
static_assert(false, "type for ScalarType has not been declared");
#endif
42 changes: 35 additions & 7 deletions include/GenericDistribution.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
#pragma once

//Local
#include "CCCoreLib.h"
#include "CCTypes.h"

//system
#include <vector>
#include "ScalarField.h"

namespace CCCoreLib
{
Expand Down Expand Up @@ -39,8 +35,40 @@ namespace CCCoreLib
**/
virtual bool isValid() const { return m_isValid; }

//! Scalar values container
using ScalarContainer = std::vector<ScalarType>;
//! Scalar values container interface
struct ScalarContainer
{
virtual size_t size() const = 0;
virtual ScalarType getValue(size_t index) const = 0;
};

//! Wrapper of a CCCoreLib's scalar field as a Scalar values container
struct SFAsScalarContainer : ScalarContainer
{
SFAsScalarContainer(const ScalarField& sf)
: ScalarContainer()
, m_sf(sf)
{}

inline size_t size() const override { return m_sf.size(); }
inline ScalarType getValue(size_t index) const override { return m_sf.getValue(index); }

const CCCoreLib::ScalarField& m_sf;
};

//! Wrapper of a std::vector as a Scalar values container
struct VectorAsScalarContainer : ScalarContainer
{
VectorAsScalarContainer(const std::vector<ScalarType>& vector)
: ScalarContainer()
, m_vector(vector)
{}

inline size_t size() const override { return m_vector.size(); }
inline ScalarType getValue(size_t index) const override { return m_vector[index]; }

const std::vector<ScalarType>& m_vector;
};

//! Computes the distribution parameters from a set of values
/** \param values a set of scalar values
Expand Down
38 changes: 29 additions & 9 deletions include/PointCloudTpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,27 @@ namespace CCCoreLib
}

unsigned n = size();
for (unsigned i = 0; i < n; ++i)

if (0 != n)
{
action(m_points[i], (*currentOutScalarFieldArray)[i]);
double previousOffset = currentOutScalarFieldArray->getOffset();
if (n == currentOutScalarFieldArray->size())
{
// if we are going to change ALL the values, we can also apply the functor on the offset
double firstValue = currentOutScalarFieldArray->getValue(0);
action(m_points.front(), firstValue);
if (ScalarField::ValidValue(firstValue))
{
currentOutScalarFieldArray->setOffset(firstValue);
}
}

for (unsigned i = 0; i < n; ++i)
{
ScalarType value = previousOffset + currentOutScalarFieldArray->getLocalValue(i); // warning, the offset has been changed, we can't use getValue anymore
action(m_points[i], value);
currentOutScalarFieldArray->setValue(i, value);
}
}
}

Expand Down Expand Up @@ -244,7 +262,7 @@ namespace CCCoreLib
//if something fails, we restore the previous size for already processed SFs!
for (std::size_t j = 0; j < i; ++j)
{
m_scalarFields[j]->resize(oldCount);
m_scalarFields[j]->resizeSafe(oldCount);
m_scalarFields[j]->computeMinAndMax();
}
//we can assume that newNumberOfPoints > oldCount, so it should always be ok
Expand Down Expand Up @@ -348,23 +366,25 @@ namespace CCCoreLib
/** \param index a scalar field index
\return a pointer to a string structure (null-terminated array of characters), or 0 if the index is invalid.
**/
const char* getScalarFieldName(int index) const
const std::string getScalarFieldName(int index) const
{
return (index >= 0 && index < static_cast<int>(m_scalarFields.size()) ? m_scalarFields[index]->getName() : 0);
return (index >= 0 && index < static_cast<int>(m_scalarFields.size()) ? m_scalarFields[index]->getName() : std::string{});
}

//! Returns the index of a scalar field represented by its name
/** \param name a scalar field name
\return an index (-1 if the scalar field couldn't be found)
**/
int getScalarFieldIndexByName(const char* name) const
int getScalarFieldIndexByName(const std::string& name) const
{
std::size_t sfCount = m_scalarFields.size();
for (std::size_t i = 0; i < sfCount; ++i)
{
//we don't accept two SF with the same name!
if (strcmp(m_scalarFields[i]->getName(), name) == 0)
if (0 == m_scalarFields[i]->getName().compare(name))
{
return static_cast<int>(i);
}
}

return -1;
Expand Down Expand Up @@ -414,7 +434,7 @@ namespace CCCoreLib
\param uniqueName scalar field name (must be unique)
\return index of this new scalar field (or -1 if an error occurred)
**/
virtual int addScalarField(const char* uniqueName)
virtual int addScalarField(const std::string& uniqueName)
{
//we don't accept two SF with the same name!
if (getScalarFieldIndexByName(uniqueName) >= 0)
Expand Down Expand Up @@ -455,7 +475,7 @@ namespace CCCoreLib
\param newName new name
\return success
**/
bool renameScalarField(int index, const char* newName)
bool renameScalarField(int index, const std::string& newName)
{
if (getScalarFieldIndexByName(newName) < 0)
{
Expand Down
42 changes: 20 additions & 22 deletions include/RegistrationTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ namespace CCCoreLib
const CCVector3& referenceGravityCenter,
ScaledTransformation& outTrans );

//! Computes RMS between two clouds given a transformation and a scale
/** Warning: both clouds must have the same size (and at least 3 points)
RMS = Sqrt ( Sum( square_norm( Pr - s*R*Pl+T ) ) / count )
\param lCloud left cloud {Pl}
\param rCloud right cloud {Pr}
\param trans transformation: Pr = s.R.Pl + T
\return RMS (or -1.0 if an error occurred)
**/
static double ComputeRMS( GenericCloud* lCloud,
GenericCloud* rCloud,
const ScaledTransformation& trans);

protected:

//! ICP Registration procedure with optional scale estimation
Expand Down Expand Up @@ -92,32 +104,18 @@ namespace CCCoreLib
{
public:

//! Returns "absolute orientation" (scale + transformation) between two set of (unordered) points
/** Warning: both clouds must have the same size (and at least 3 points)
Output transformation is from the left (L) to the right (R) coordinate system
\param lCloud left cloud {Pl}
\param rCloud right cloud {Pr}
\param trans resulting transformation: Pr = s.R.Pl + T
\param fixedScale force scale parameter to 1.0
//! Returns the transformation (scale + transformation) between two sets of (unordered) points
/** \warning Both clouds must have the same size (and at least 3 points)
\param[in] toBeAlignedPoints the points to be aligned
\param[in] referencePoints the fixed/static points
\param[out] trans resulting transformation: Pr = s.R.Pl + T
\param[in] fixedScale force scale parameter to 1.0
\return success
**/
static bool FindAbsoluteOrientation(GenericCloud* lCloud,
GenericCloud* rCloud,
static bool FindAbsoluteOrientation(GenericCloud* toBeAlignedPoints,
GenericCloud* referencePoints,
ScaledTransformation& trans,
bool fixedScale = false);

//! Computes RMS between two clouds given a transformation and a scale
/** Warning: both clouds must have the same size (and at least 3 points)
RMS = Sqrt ( Sum( square_norm( Pr - s*R*Pl+T ) ) / count )
\param lCloud left cloud {Pl}
\param rCloud right cloud {Pr}
\param trans transformation: Pr = s.R.Pl + T
\return RMS (or -1.0 if an error occurred)
**/
static double ComputeRMS( GenericCloud* lCloud,
GenericCloud* rCloud,
const ScaledTransformation& trans);

};

//! ICP point cloud registration algorithm (Besl et al.).
Expand Down
Loading
Loading