Commit e5431dda authored by Andreas Schwarzkopf's avatar Andreas Schwarzkopf

[FIX #371] Heavy committing related to validation of the approach of Lari/Habib 2014

 * Modules purged
 *   - Points group selector
 *
 * Altered modules
 *   - Points - Transform: Can now save and load point data using files
 *
 * Modules created:
 *   - Point Groups - Validator
 *       - Is done in order to validate groups against reference groups
 *   - Point Groups - Transform
 *       - Can save and load grouped point data using files
 *       - Also can merge grouped point data sets and subtract point sets
 *       - Still has all features to replace "Point group selector" completely
parent 883eac38
......@@ -33,9 +33,10 @@
#include "buildingsDetection/WMBuildingsDetection.h"
#include "treeDetectionByPCA/WMTreeDetectionByPCA.h"
#include "elevationImageExport/WMElevationImageExport.h"
#include "pointGroupsTransform/WMPointGroupsTransform.h"
#include "pointsTransform/WMPointsTransform.h"
#include "pointsCutOutliers/WMPointsCutOutliers.h"
#include "pointsGroupSelector/WMPointsGroupSelector.h"
#include "pointGroupsValidator/WMPointGroupsValidator.h"
#include "readLAS/WMReadLAS.h"
#include "surfaceDetectionByLari/WMSurfaceDetectionByLari.h"
#include "surfaceDetectionByPCL/WMSurfaceDetectionByPCL.h"
......@@ -62,8 +63,9 @@ extern "C" void WLoadModule( WModuleList& m ) // NOLINT
m.push_back( boost::shared_ptr< WModule >( new WMBuildingsDetection ) );
m.push_back( boost::shared_ptr< WModule >( new WMTreeDetectionByPCA ) );
m.push_back( boost::shared_ptr< WModule >( new WMElevationImageExport ) );
m.push_back( boost::shared_ptr< WModule >( new WMPointGroupsTransform ) );
m.push_back( boost::shared_ptr< WModule >( new WMPointsCutOutliers ) );
m.push_back( boost::shared_ptr< WModule >( new WMPointsGroupSelector ) );
m.push_back( boost::shared_ptr< WModule >( new WMPointGroupsValidator ) );
m.push_back( boost::shared_ptr< WModule >( new WMPointsTransform ) );
m.push_back( boost::shared_ptr< WModule >( new WMReadLAS ) );
m.push_back( boost::shared_ptr< WModule >( new WMSurfaceDetectionByLari ) );
......
......@@ -196,6 +196,14 @@ void WMBuildingsDetection::moduleMain()
outputGroups->push_back( buildingVoxel->getGroupNr() );
}
}
if( outputVerts->size() == 0)
{
for( size_t dimension = 0; dimension < 3; dimension++ )
outputVerts->push_back( 0.0 );
for( size_t colorChannel = 0; colorChannel < 3; colorChannel++ )
outputColors->push_back( 0.0 );
outputGroups->push_back( 0 );
}
boost::shared_ptr< WDataSetPointsGrouped > output(
new WDataSetPointsGrouped( outputVerts, outputColors, outputGroups ) );
m_outputPointsGrouped->updateData( output );
......
......@@ -28,10 +28,10 @@
#include <vector>
#include "../../common/datastructures/quadtree/WQuadNode.h"
#include "../../common/datastructures/quadtree/WQuadTree.h"
#include "../../common/datastructures/octree/WOctree.h"
#include "../../common/datastructures/WDataSetPointsGrouped.h"
#include "../../datastructures/quadtree/WQuadNode.h"
#include "../../datastructures/quadtree/WQuadTree.h"
#include "../../datastructures/octree/WOctree.h"
#include "../../datastructures/WDataSetPointsGrouped.h"
/**
* Image object. Currently it's used for saving bmp files.
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <iostream>
#include "WGroupEdit.h"
WGroupEdit::WGroupEdit()
{
m_mergeGroups = false;
}
WGroupEdit::~WGroupEdit()
{
}
void WGroupEdit::initProocessBegin()
{
m_groupSizes.resize( 0 );
m_groupSizes.reserve( 0 );
m_lastGroupID = 0;
WDataSetPointsGrouped::VertexArray newVertices(
new WDataSetPointsGrouped::VertexArray::element_type() );
m_vertices = newVertices;
WDataSetPointsGrouped::ColorArray newColors(
new WDataSetPointsGrouped::ColorArray::element_type() );
m_colors = newColors;
WDataSetPointsGrouped::GroupArray newGroups(
new WDataSetPointsGrouped::GroupArray::element_type() );
m_groups = newGroups;
}
void WGroupEdit::setMergeGroups( bool mergeGroups )
{
m_mergeGroups = mergeGroups;
}
void WGroupEdit::setGroupSizeThreshold( size_t groupSizeThreshold )
{
m_groupSizeThreshold = groupSizeThreshold;
}
void WGroupEdit::mergeGroupSet( boost::shared_ptr< WDataSetPointsGrouped > points )
{
size_t groupIDOffset = m_lastGroupID == 0 ?0 :m_lastGroupID + 1;
if( !points )
return;
WDataSetPointsGrouped::VertexArray vertices = points->getVertices();
WDataSetPointsGrouped::ColorArray colors = points->getColors();
WDataSetPointsGrouped::GroupArray groups = points->getGroups();
for( size_t index = 0; index < vertices->size(); index++ )
m_vertices->push_back( vertices->at( index ) );
for( size_t index = 0; index < colors->size(); index++ )
m_colors->push_back( colors->at( index ) );
for( size_t index = 0; index < groups->size(); index++ )
{
size_t groupID = groups->at( index );
if( !m_mergeGroups )
groupID += groupIDOffset;
m_groups->push_back( groupID );
if( groupID > m_lastGroupID )
m_lastGroupID = groupID;
if( isValidGroupID( groupID ) )
{
double currentSize = m_groupSizes.size();
if( groupID >= currentSize )
{
m_groupSizes.reserve( groupID + 1 );
m_groupSizes.resize( groupID + 1 );
for( size_t newGroup = currentSize; newGroup <= groupID; newGroup++ )
m_groupSizes[newGroup] = 0;
}
m_groupSizes[groupID] = m_groupSizes[groupID] + 1;
}
}
}
double WGroupEdit::getVertex( size_t pointIndex, size_t dimension )
{
return m_vertices->at( pointIndex * 3 + dimension );
}
double WGroupEdit::getColor( size_t pointIndex, size_t colorChannel )
{
return m_colors->at( pointIndex * 3 + colorChannel );
}
size_t WGroupEdit::getOldGroupID( size_t pointIndex )
{
return m_groups->at( pointIndex );
}
size_t WGroupEdit::getNewGroupID( size_t pointIndex )
{
size_t originalGroupID = getOldGroupID( pointIndex );
if( !isValidGroupID( originalGroupID ) || !isPointCollected( pointIndex ) )
return originalGroupID;
return m_groupIDMap[originalGroupID];
}
bool WGroupEdit::isPointCollected( size_t pointIndex )
{
size_t originalGroupID = getOldGroupID( pointIndex );
if( !isValidGroupID( originalGroupID ) )
return false;
return m_groupSizes[originalGroupID] >= m_groupSizeThreshold;
}
size_t WGroupEdit::getInputPointCount()
{
return m_vertices->size() / 3;
}
size_t WGroupEdit::getLastGroupID()
{
return m_lastGroupID;
}
size_t WGroupEdit::getGroupSize( size_t origGroupID )
{
return m_groupSizes[origGroupID];
}
void WGroupEdit::modifyGroupIDs()
{
m_groupIDMap.reserve( m_groupSizes.size() );
m_groupIDMap.resize( m_groupSizes.size() );
size_t currentID = 0;
for( size_t index = 0; index < m_groupSizes.size(); index++ )
if( m_groupSizes[index] >= m_groupSizeThreshold )
m_groupIDMap[index] = currentID++;
m_lastGroupID = currentID - 1;
}
bool WGroupEdit::isValidGroupID( size_t groupID )
{
return groupID < 1000 * 1000 * 100;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WGROUPEDIT_H
#define WGROUPEDIT_H
#include <vector>
#include "../../datastructures/WDataSetPointsGrouped.h"
using std::cout;
using std::endl;
using std::vector;
/**
* Class to edit groups of WDataSetPointsGrouped.
* Its main purposes are:
* - Merging point sets with group IDs
* - Helps to remove groups below a group count threshold
* - When merging WDataSetPointsGrouped group IDs can eigher be kept by
* setMergeGroups( true ) or continuously counted adding each dataset.using
* setMergeGroups( false )
*
* Workflow:
* - initProcessBegin()
* - setMergeGroups()
* - setGroupSizeThreshold()
* - Execute mergeGroupSet() for at least one grouped point dataset.
* - modifyGroupIDs()
* - traverse all getInputPointCount() points. Add new vertices, colors and groups
* using your own class if isPointCollected() is true for the corresponding index.
* - New data is getVertex(), getColor() and getNewGroupID()
*/
class WGroupEdit
{
public:
/**
* Creates the group edit instance
*/
explicit WGroupEdit();
/**
* Destroys the group edit instance
*/
virtual ~WGroupEdit();
/**
* Initializes the group edit process.
*/
void initProocessBegin();
/**
* Sets whether group IDs should be kept or continuously counted up when a new
* grouped point set is added.
* \param mergeGroups Choose false in order to disconnect groups from those groups
* of previous datasets. Choosing true group IDs will remain the
* same if the group size threshold is 0.
*/
void setMergeGroups( bool mergeGroups );
/**
* Sets the minimal group size. Groups below that point count are signaled not to be
* added. Further group IDs are changed changed that way so that no group until the
* last one remains without points.
* \param groupSizeThreshold Minimal group size that is proposed to be added to the
* final dataset.
*/
void setGroupSizeThreshold( size_t groupSizeThreshold );
/**
* Merges points to previously added points. This method is also used tu add grouped
* points for the first time.
* \param points Points with group ID to be added.
*/
void mergeGroupSet( boost::shared_ptr< WDataSetPointsGrouped > points );
/**
* returns the last group ID that is generated for the new merged dataset.
* \return Last group ID of the new merged point dataset.
*/
size_t getLastGroupID();
/**
* Returns the point count of a group.
* \param origGroupID Point group ID of the original dataset to get the point count
* of. Warning - The original group ID changes after using
* setMergeGroups( false ).
* \return Point count of a group.
*/
size_t getGroupSize( size_t origGroupID );
/**
* Returns a vertex of a corresponding point within the merged dataset.
* Points with a group sizw below a threshold still remain using that function. Use
* isPointCollected() to determine whether to add a point in your code.
* \param pointIndex Point index of the merged dataset.
* \param dimension Dimension (X/Y/Z or 0/1/2) or the corresponding coordinate.
* \return Value that belongs to a coordinate value X, Y or Z of a point.
*/
double getVertex( size_t pointIndex, size_t dimension );
/**
* Returns a color of a corresponding point within the merged dataset.
* Points with a group sizw below a threshold still remain using that function. Use
* isPointCollected() to determine whether to add a point in your code.
* \param pointIndex Point index of the merged dataset.
* \param colorChannel Color channel (red/green/blue or 0/1/2) or the corresponding
* coordinate.
* \return Value that belongs to color channel of a point.
*/
double getColor( size_t pointIndex, size_t colorChannel );
/**
* Returns an original group ID of a point. Group IDs are changed after the first
* merged dataset if setMergeGroups( false ) was applied.
* Points with a group sizw below a threshold still remain using that function. Use
* isPointCollected() to determine whether to add a point in your code.
* \param pointIndex Point index of the merged dataset.
* \return Group ID of the original dataset.
*/
size_t getOldGroupID( size_t pointIndex );
/**
* Returns a new group ID. It is further changed if the group size threshold is
* above 0. Further no ID remains without points.
* Points with a group sizw below a threshold still remain using that function. Use
* isPointCollected() to determine whether to add a point in your code.
* \param pointIndex Point index of the merged dataset.
* \return New group ID.
*/
size_t getNewGroupID( size_t pointIndex );
/**
* Tells whether a point is collected by means if the point group size threshold.
* \param pointIndex Point index of the merged dataset.
* \return Point should be added to the final dataset by means of the group size
* threshold or not.
*/
bool isPointCollected( size_t pointIndex );
/**
* Gets point count of all points that were entered to be merged. Group size
* threshold does not play a role here.
* \return Point count without means of group point count threshold.
*/
size_t getInputPointCount();
/**
* Creates an array which shows a map from old to new group IDs. Array index is the
* old group ID. The map has finally no groups without point using a group size
* threshold above 0.
*/
void modifyGroupIDs();
private:
/**
* This is a method that decides whether a group ID is valid or not. Points with a
* group ID above an index are not regarded. Very big IDs lead to very big arrays of
* group sizes and group maps.
* //TODO(aschwarzkopf): Use a hashset for groups later or something else to solve that problem.
* \param groupID Group ID to be validated.
* \return Group ID is valid or not.
*/
bool isValidGroupID( size_t groupID );
/**
* Array that depicts group sizes. The group ID is the array index. Values are point
* counts of each group.
* //TODO(aschwarzkopf): Solve that problem that big IDs lead to big arrays with
* too many unused IDs.
*/
vector<size_t> m_groupSizes;
/**
* Map that links an old group ID with a new one. Old group ID is the array index.
* The new group ID is its value.
* //TODO(aschwarzkopf): Solve that problem that big IDs lead to big arrays with
* too many unused IDs.
*/
vector<size_t> m_groupIDMap;
/**
* Last new group ID.
*/
size_t m_lastGroupID;
/**
* Input point coordinates.
*/
WDataSetPointsGrouped::VertexArray m_vertices;
/**
* Colors of the input point data set that are also passed through.
*/
WDataSetPointsGrouped::ColorArray m_colors;
/**
* Input point groups.
*/
WDataSetPointsGrouped::GroupArray m_groups;
/**
* Determines whether group IDs should be bigger than those of previous datasets or
* remain. before applying the group size threshold.
*/
bool m_mergeGroups;
/**
* Group point count threshold that is applied. Groups with a point count below that
* value are proposed to be removed. Having a threshold above 0 group IDs are
* modified that way so that no ID remains with a zero point count.
*/
size_t m_groupSizeThreshold;
};
#endif // WGROUPEDIT_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <vector>
#include "WPointSaver.h"
WPointSaver::WPointSaver()
{
m_hasGroupInfo = false;
m_filePath = new stringstream();
m_containsData = false;
}
WPointSaver::~WPointSaver()
{
}
WDataSetPointsGrouped::VertexArray WPointSaver::getVertices()
{
return m_verts;
}
WDataSetPointsGrouped::VertexArray WPointSaver::getColors()
{
return m_colors;
}
WDataSetPointsGrouped::GroupArray WPointSaver::getGroups()
{
return m_groups;
}
bool WPointSaver::loadWDataSetPoints()
{
m_hasGroupInfo = false;
return load();
}
bool WPointSaver::loadWDataSetPointsGrouped()
{
m_hasGroupInfo = true;
return load();
}
void WPointSaver::saveWDataSetPoints( WDataSetPointsGrouped::VertexArray vertices, WDataSetPointsGrouped::ColorArray colors )
{
m_verts = vertices;
m_colors = colors;
m_hasGroupInfo = false;
m_containsData = true;
save();
}
void WPointSaver::saveWDataSetPointsGrouped( WDataSetPointsGrouped::VertexArray vertices,
WDataSetPointsGrouped::ColorArray colors, WDataSetPointsGrouped::GroupArray groups )
{
m_verts = vertices;
m_colors = colors;
m_groups = groups;
m_hasGroupInfo = true;
m_containsData = true;
save();
}
void WPointSaver::setFilePath( const char* path )
{
delete m_filePath;
m_filePath = new stringstream();
*m_filePath << path;
}
double WPointSaver::parseDouble( vector<char> charVector )
{
stringstream numberStream;
for( size_t index = 0; index < charVector.size(); index++ )
numberStream << charVector[index];
const string numberString = numberStream.str();
istringstream stream( numberString );
double number;
stream >> number;
return number;
}
size_t WPointSaver::parseSizeT( vector<char> charVector )
{
stringstream numberStream;
for( size_t index = 0; index < charVector.size(); index++ )
numberStream << charVector[index];
const string numberString = numberStream.str();
istringstream stream( numberString );
size_t number;
stream >> number;
return number;
}
bool WPointSaver::containsData()
{
return m_containsData;
}
bool WPointSaver::correctFilePathByExtension()
{
if( m_filePath->str().length() == 0 )
return false;
const char* extension = m_hasGroupInfo ?EXTENSION_WDATASETPOINTSGROUPED :EXTENSION_WDATASETPOINTS;
if( !pathEndsWith( extension, m_filePath ) )
*m_filePath << extension;
return true;
}
bool WPointSaver::pathEndsWith( const char* nameTail, stringstream* filePath )
{
const string tmp = filePath->str();
const char* pathChars = tmp.c_str();
stringstream extensionStream;
extensionStream << nameTail;
size_t pathLength = filePath->str().length();
size_t tailLength = extensionStream.str().length();
if( pathLength < tailLength )
return false;
for(size_t index = 0; index < tailLength; index++)
if(pathChars[pathLength+index-tailLength] != nameTail[index])
return false;
return true;
}
bool WPointSaver::load()
{
cout << "WPointSaver::load() - Start" << endl;
WDataSetPointsGrouped::VertexArray outVertices(
new WDataSetPointsGrouped::VertexArray::element_type() );
WDataSetPointsGrouped::ColorArray outColors(
new WDataSetPointsGrouped::ColorArray::element_type() );
WDataSetPointsGrouped::GroupArray outGroups(
new WDataSetPointsGrouped::GroupArray::element_type() );
m_verts = outVertices;
m_colors = outColors;
m_groups = outGroups;
const char* extension = m_hasGroupInfo ?EXTENSION_WDATASETPOINTSGROUPED :EXTENSION_WDATASETPOINTS;
const string tmp = m_filePath->str();
const char* path = tmp.c_str();
const size_t variablesPerLine = m_hasGroupInfo ?7 :6;