Commit c04b1e87 authored by aschwarzkopf's avatar aschwarzkopf

[ADD #309] Added colors to building point groups and direct elevation image display.

The buildings detection plugin generally was a mix of many things. These things of
it were split up into these plutins:
  - Elevation image export
  - Points group selector which transforms building groups into a voxel structure
    and exports it to a triangle mesh.

Added features:
  - Elevation image can be output in a triangle mesh
  - Elevation image (file and triangle mesh output) and building outline got colored
    building outline

Code style:
  - Fixed prooblems with documentation (make doc)
  - Purged last code style (make stylecheck)
parent ada4d55a
......@@ -75,7 +75,7 @@ INCLUDE( OpenWalnut )
SETUP_MODULE(
${PROJECT_NAME} # use project name as module(-toolbox) name
"." # where to find the sources
"liblas.so" # no additonal dependencies
"liblas.so" # no additonal dependencies
"" # no sources to exclude
)
......
......@@ -25,13 +25,15 @@
// This file's purpose is to provide a list of modules and additional extensions as entry point for OpenWalnut's module loader.
// Both functAdd your modules here. If you miss this step, OpenWalnut will not be able to load your modules/extensions.
#include <string>
#include <boost/shared_ptr.hpp>
#include <core/kernel/WModule.h>
#include "buildingsDetection/WMBuildingsDetection.h"
#include "elevationImageExport/WMElevationImageExport.h"
#include "pointsCutOutliers/WMPointsCutOutliers.h"
#include "pointsGroupSelector/WMPointsGroupSelector.h"
#include "readLAS/WMReadLAS.h"
// #include "WToolkit.h"
......@@ -49,7 +51,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 WMElevationImageExport ) );
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 WMReadLAS ) );
}
......
......@@ -2,7 +2,7 @@
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2013 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
......
......@@ -2,7 +2,7 @@
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2013 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
......@@ -28,10 +28,10 @@
#include <vector>
#include "core/graphicsEngine/WTriangleMesh.h"
#include "core/dataHandler/WDataSetPoints.h"
#include "structure/WOctNode.h"
#include "structure/WQuadNode.h"
#include "structure/WQuadTree.h"
#include "structure/WOctree.h"
#include "../datastructures/octree/WOctNode.h"
#include "../datastructures/quadtree/WQuadNode.h"
#include "../datastructures/quadtree/WQuadTree.h"
#include "../datastructures/octree/WOctree.h"
/**
* Class that detects buildings using the WDataSetPoints
......
......@@ -2,7 +2,7 @@
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2013 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
......@@ -42,7 +42,7 @@
#include "WMBuildingsDetection.xpm"
#include "WMBuildingsDetection.h"
#include "WBuildingDetector.h"
#include "structure/WOctree.h"
#include "../datastructures/octree/WOctree.h"
// This line is needed by the module loader to actually find your module.
//W_LOADABLE_MODULE( WMBuildingsDetection )
......@@ -52,8 +52,6 @@ WMBuildingsDetection::WMBuildingsDetection():
WModule(),
m_propCondition( new WCondition() )
{
m_tree = new WOctree( 0 );
m_elevationImage = new WQuadTree( 0 );
}
WMBuildingsDetection::~WMBuildingsDetection()
......@@ -83,10 +81,10 @@ void WMBuildingsDetection::connectors()
{
m_input = WModuleInputData< WDataSetPoints >::createAndAdd( shared_from_this(), "input", "The mesh to display" );
m_output = boost::shared_ptr< WModuleOutputData< WTriangleMesh > >(
new WModuleOutputData< WTriangleMesh >( shared_from_this(), "output", "The loaded mesh." ) );
m_outputPointsGrouped = boost::shared_ptr< WModuleOutputData< WDataSetPointsGrouped > >(
new WModuleOutputData< WDataSetPointsGrouped >( shared_from_this(), "Grouped points", "The loaded mesh." ) );
addConnector( m_output );
addConnector( m_outputPointsGrouped );
// addConnector( m_buildings );
WModule::connectors();
}
......@@ -105,12 +103,6 @@ void WMBuildingsDetection::properties()
// ---> Put the code for your properties here. See "src/modules/template/" for an extensively documented example.
m_reloadData = m_properties->addProperty( "Reload data:", "Execute", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
m_stubSize = m_properties->addProperty( "Stub size: ",
"Size of tetraeders that are used to depict points.", 0.6 );
m_stubSize->setMin( 0.0 );
m_stubSize->setMax( 3.0 );
m_contrast = m_properties->addProperty( "Contrast: ",
"Color intensity multiplier.", 2.0 );
m_detailDepth = m_properties->addProperty( "Detail Depth 2^n m: ", "Resulting 2^n meters detail "
"depth for the octree search tree.", 0 );
m_detailDepth->setMin( -3 );
......@@ -118,11 +110,6 @@ void WMBuildingsDetection::properties()
m_detailDepthLabel = m_properties->addProperty( "Detail Depth meters: ", "Resulting detail depth "
"in meters for the octree search tree.", 1.0 );
m_detailDepthLabel->setPurpose( PV_PURPOSE_INFORMATION );
m_showTrianglesInsteadOfOctreeCubes = m_properties->addProperty( "Triangles instead of cubes: ",
"Depicting the input data set points showing the point outline "
"instead of regions depicted as cubes that cover existing points. "
"Enabling this option you must have 32GB RAM depicting a 400MB"
"las file.", false );
m_minSearchDetailDepth = m_properties->addProperty( "Detail Depth min. search: ", "//TODO", 3 );
m_minSearchDetailDepth->setMin( 2 );
......@@ -130,30 +117,6 @@ void WMBuildingsDetection::properties()
m_minSearchCutUntilAbove = m_properties->addProperty( "Cut until above min: ", "//TODO", 4.0 );
m_minSearchCutUntilAbove->setMin( 2.0 );
m_minSearchCutUntilAbove->setMax( 20.0 );
m_selectedShowableBuilding = m_properties->addProperty( "Showable building idx: ",
"Index of the showable building. 0 is the entire dataset. 1 means all "
"buildings without the ground. Other numbers are all each other buildings in "
"one single piece", 1 );
m_selectedShowableBuilding->setMin( 0 );
m_selectedShowableBuilding->setMax( 1 );
boost::shared_ptr< WItemSelection > imageModes( boost::shared_ptr< WItemSelection >( new WItemSelection() ) );
imageModes->addItem( "Minimals", "Minimal elevation values." );
imageModes->addItem( "Maximals", "Maximal elevation values." );
imageModes->addItem( "Point count", "Store point count to each pixel." );
m_elevImageMode = m_properties->addProperty( "Color mode", "Choose one of the available colorings.", imageModes->getSelectorFirst() );
WPropertyHelper::PC_SELECTONLYONE::addTo( m_elevImageMode );
m_minElevImageZ = m_properties->addProperty( "Min. Z value: ",
"Minimal Z value where image intensities begin to rise. Always watch in the "
"info the minimal Z value and enter a similar value.", 0.0 );
m_intensityIncreasesPerMeter = m_properties->addProperty( "Increases per meter: ",
"The bitmap has a range of possible color intensities. This field determines "
"how many increases per meter are done.", 10.0 );
m_elevationImageExportablePath = m_properties->addProperty( "Elev. image:",
"Target file path of the exportable elevation image *.bmp file",
WPathHelper::getAppPath() );
m_exportTriggerProp = m_properties->addProperty( "Write: ", "Export elevation image", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
WModule::properties();
......@@ -185,13 +148,18 @@ void WMBuildingsDetection::moduleMain()
m_moduleState.wait();
boost::shared_ptr< WDataSetPoints > points = m_input->getData();
std::cout << "Execute cycle\r\n";
WItemSelector elevImageModeSelector = m_elevImageMode->get();
// std::cout << "Execute cycle\r\n";
if ( points )
{
WDataSetPoints::VertexArray verts = points->getVertices();
WDataSetPoints::ColorArray colors = points->getColors();
size_t count = verts->size()/3;
WDataSetPoints::VertexArray inputVerts = points->getVertices();
WDataSetPoints::ColorArray inputColors = points->getColors();
WDataSetPointsGrouped::VertexArray outputVerts(
new WDataSetPointsGrouped::VertexArray::element_type() );
WDataSetPointsGrouped::ColorArray outputColors(
new WDataSetPointsGrouped::ColorArray::element_type() );
WDataSetPointsGrouped::GroupArray outputGroups(
new WDataSetPointsGrouped::GroupArray::element_type() );
size_t count = inputVerts->size()/3;
setProgressSettings( count );
WBuildingDetector detector = WBuildingDetector();
......@@ -199,69 +167,42 @@ void WMBuildingsDetection::moduleMain()
m_minSearchCutUntilAbove->get() );
detector.detectBuildings( points );
WOctree* buildingGroups = detector.getBuildingGroups();
size_t groupCount = buildingGroups->getGroupCount();
m_selectedShowableBuilding->setMax( groupCount + 1 );
size_t selectedGroup = m_selectedShowableBuilding->get();
m_detailDepthLabel->set( pow( 2.0, m_detailDepth->get() ) );
m_tree = new WOctree( m_detailDepthLabel->get() );
m_elevationImage = new WQuadTree( m_detailDepthLabel->get() );
m_elevationImage->setExportElevationImageSettings(
m_minElevImageZ->get( true ), m_intensityIncreasesPerMeter->get() );
WQuadTree* boundingBox = new WQuadTree( m_detailDepthLabel->get() ); //TODO(schwarzkopf): replace functions of this field by m_tree
boost::shared_ptr< WTriangleMesh > tmpMesh( new WTriangleMesh( 0, 0 ) );
float a = m_stubSize->get();
float contrast = m_contrast->get();
for ( size_t vertex = 0; vertex < count; vertex++)
{
float x = verts->at( vertex*3 );
float y = verts->at( vertex*3+1 );
float z = verts->at( vertex*3+2 );
float x = inputVerts->at( vertex*3 );
float y = inputVerts->at( vertex*3+1 );
float z = inputVerts->at( vertex*3+2 );
WOctNode* buildingVoxel = buildingGroups->getLeafNode( x, y, z );
if( selectedGroup == 0 || ( buildingVoxel != 0 && (
selectedGroup == 1 || selectedGroup == buildingVoxel->getGroupNr() + 2 ) ) )
if( buildingVoxel != 0 )
{
if( m_showTrianglesInsteadOfOctreeCubes->get() )
{
float r = colors->at( vertex*3 );
float g = colors->at( vertex*3+1 );
float b = colors->at( vertex*3+2 );
osg::Vec4f* color = new osg::Vec4f(
r/400.0f*contrast, g/400.0f*contrast, b/400.0f*contrast, 1.0f );
tmpMesh->addVertex( 0+x, 0+y, 0+z );
tmpMesh->addVertex( a+x, 0+y, 0+z );
tmpMesh->addVertex( 0+x, a+y, 0+z );
tmpMesh->addVertex( 0+x, 0+y, a+z );
size_t body = vertex*4;
tmpMesh->addTriangle( 0+body, 2+body, 1+body );
tmpMesh->addTriangle( 0+body, 1+body, 3+body );
tmpMesh->addTriangle( 0+body, 3+body, 2+body );
tmpMesh->addTriangle( 1+body, 2+body, 3+body );
tmpMesh->setVertexColor( body, *color );
tmpMesh->setVertexColor( body+1, *color );
tmpMesh->setVertexColor( body+2, *color );
tmpMesh->setVertexColor( body+3, *color );
}
m_progressStatus->increment( 1 );
m_tree->registerPoint( x, y, z );
m_elevationImage->registerPoint( x, y, z );
boundingBox->registerPoint( x, y, z );
outputVerts->push_back( x );
outputVerts->push_back( y );
outputVerts->push_back( z );
for( size_t index = vertex*3; index < vertex*3+3; index++ )
outputColors->push_back( inputColors->at( index ) );
outputGroups->push_back( buildingVoxel->getGroupNr() );
}
}
m_tree->groupNeighbourLeafs();
m_output->updateData( m_showTrianglesInsteadOfOctreeCubes->get( true )
?tmpMesh :m_tree->getOutline() );
boost::shared_ptr< WDataSetPointsGrouped > output(
new WDataSetPointsGrouped( outputVerts, outputColors, outputGroups ) );
m_outputPointsGrouped->updateData( output );
m_nbPoints->set( count );
m_xMin->set( m_elevationImage->getRootNode()->getXMin() );
m_xMax->set( m_elevationImage->getRootNode()->getXMax() );
m_yMin->set( m_elevationImage->getRootNode()->getYMin() );
m_yMax->set( m_elevationImage->getRootNode()->getYMax() );
m_zMin->set( m_elevationImage->getRootNode()->getElevationMin() );
m_zMax->set( m_elevationImage->getRootNode()->getElevationMax() );
if( m_exportTriggerProp->get( true ) )
m_elevationImage->exportElevationImage( m_elevationImageExportablePath->get().c_str(),
elevImageModeSelector.getItemIndexOfSelected( 0 ) );
m_exportTriggerProp->set( WPVBaseTypes::PV_TRIGGER_READY, true );
m_xMin->set( boundingBox->getRootNode()->getXMin() );
m_xMax->set( boundingBox->getRootNode()->getXMax() );
m_yMin->set( boundingBox->getRootNode()->getYMin() );
m_yMax->set( boundingBox->getRootNode()->getYMax() );
m_zMin->set( boundingBox->getRootNode()->getElevationMin() );
m_zMax->set( boundingBox->getRootNode()->getElevationMax() );
m_progressStatus->finish();
}
m_reloadData->set( WPVBaseTypes::PV_TRIGGER_READY, true );
......
......@@ -2,7 +2,7 @@
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2013 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
......@@ -42,10 +42,10 @@
#include <osg/ShapeDrawable>
#include <osg/Geode>
#include "core/dataHandler/WDataSetPoints.h"
#include "structure/WOctree.h"
#include "structure/WQuadTree.h"
#include "../datastructures/octree/WOctree.h"
#include "../datastructures/quadtree/WQuadTree.h"
#include "../datastructures/WDataSetPointsGrouped.h"
......@@ -150,9 +150,9 @@ private:
boost::shared_ptr< WModuleInputData< WDataSetPoints > > m_input;
/**
* WDataSetPoints data output as tetraeders.
* WDataSetPointsGrouped data output as point groups depicting each building
*/
boost::shared_ptr< WModuleOutputData< WTriangleMesh > > m_output;
boost::shared_ptr< WModuleOutputData< WDataSetPointsGrouped > > m_outputPointsGrouped;
/**
* The OSG root node for this module. All other geodes or OSG nodes will be attached on this single node.
......@@ -197,16 +197,7 @@ private:
* Info tab property: Maximal z value of input x coordunates.
*/
WPropDouble m_zMax;
/**
* Voxel count that is cut off and kept regarding the ISO value.
*/
WPropDouble m_stubSize;
/**
* Voxel count that is cut off and kept regarding the ISO value.
*/
WPropDouble m_contrast;
/**
* Determines the resolution of the smallest octree nodes in 2^n meters
*/
......@@ -215,40 +206,7 @@ private:
* Determines the resolution of the smallest octree nodes in meters
*/
WPropDouble m_detailDepthLabel;
/**
* Depicting the input data set points showing the point outline instead of regions
* depicted as cubes that cover existing points.
*/
WPropBool m_showTrianglesInsteadOfOctreeCubes;
/**
* Mode of the elevation image to display
* 0: Minimal Z value of each X/Y bin coordinate.
* 1: Maximal Z value of each X/Y bin coordinate.
* 2: Point count of each X/Y bin coordinate.
*/
WPropSelection m_elevImageMode;
/**
* Elevation image export setting.
* All areas below that elevation are depicted using the black color.
*/
WPropDouble m_minElevImageZ;
/**
* Elevation image export setting.
* Count of intensity increases per meter.
*/
WPropDouble m_intensityIncreasesPerMeter;
/**
* Path of the exportable elevation image *.bmp file.
*/
WPropFilename m_elevationImageExportablePath; //!< The mesh will be read from this file.
WPropTrigger m_exportTriggerProp; //!< This property triggers the actual reading,
/**
* This trigger button reloads the data to output.
*/
WPropTrigger m_reloadData; //!< This property triggers the actual reading,
......@@ -265,12 +223,6 @@ private:
*/
WPropDouble m_minSearchCutUntilAbove;
/**
* Property to choose an output building of a voxel group number. Currently 0 is
* cutting nothing and 1 is is showing all buildings altogether.
*/
WPropInt m_selectedShowableBuilding;
/**
* Instance for applying drawable geoms.
*/
......@@ -280,15 +232,6 @@ private:
* Plugin progress status that is shared with the reader.
*/
boost::shared_ptr< WProgress > m_progressStatus;
/**
* Octree node used for the data set points analysis.
*/
WOctree* m_tree;
/**
* This is the elevation image of the whole data set.
* It depicts some statistical Z coordinate information of each X/Y-coordinate.
*/
WQuadTree* m_elevationImage;
};
#endif // WMBUILDINGSDETECTION_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 <algorithm>
#include <string>
#include <vector>
#include "core/common/exceptions/WOutOfBounds.h"
#include "core/common/WAssert.h"
#include "core/common/WColor.h"
#include "core/common/math/linearAlgebra/WPosition.h"
#include "WDataSetPointsGrouped.h"
// prototype instance as singleton
boost::shared_ptr< WPrototyped > WDataSetPointsGrouped::m_prototype = boost::shared_ptr< WPrototyped >();
WDataSetPointsGrouped::WDataSetPointsGrouped( WDataSetPointsGrouped::VertexArray vertices,
WDataSetPointsGrouped::ColorArray colors, WDataSetPointsGrouped::GroupArray groups,
WBoundingBox boundingBox ):
m_vertices( vertices ),
m_colors( colors ),
m_groups( groups ),
m_bb( boundingBox )
{
WAssert( vertices->size() % 3 == 0, "Number of floats in the vertex array must be a multiple of 3" );
if( colors )
{
size_t numPoints = vertices->size() / 3;
WAssert( ( colors->size() / 4 == numPoints ) ||
( colors->size() / 3 == numPoints ) ||
( colors->size() / 1 == numPoints )
, "Number of floats in the color array must be 1,3, or 4 per vertex" );
}
init();
}
WDataSetPointsGrouped::WDataSetPointsGrouped( WDataSetPointsGrouped::VertexArray vertices,
WDataSetPointsGrouped::ColorArray colors, WDataSetPointsGrouped::GroupArray groups ):
m_vertices( vertices ),
m_colors( colors ),
m_groups( groups )
{
WAssert( vertices->size() % 3 == 0, "Number of floats in the vertex array must be a multiple of 3" );
if( colors )
{
size_t numPoints = vertices->size() / 3;
WAssert( ( colors->size() / 4 == numPoints ) ||
( colors->size() / 3 == numPoints ) ||
( colors->size() / 1 == numPoints )
, "Number of floats in the color array must be 1,3, or 4 per vertex" );
}
init( true );
}
WDataSetPointsGrouped::WDataSetPointsGrouped()
{
// dummy construction. Empty point and color list
}
WDataSetPointsGrouped::~WDataSetPointsGrouped()
{
// cleanup
}
void WDataSetPointsGrouped::init( bool calcBB )
{
// no colors specified? Use white as default
if( !m_colors )
{
// Store 1 value for each point (gray scale colors)
m_colors = ColorArray( new ColorArray::element_type( m_vertices->size() / 3, 1.0 ) );
}
// calculate the bounding box if needed
if( calcBB && ( m_vertices->size() != 0 ) )
{
float minX = m_vertices->operator[]( 0 );
float minY = m_vertices->operator[]( 1 );
float minZ = m_vertices->operator[]( 2 );
float maxX = minX;
float maxY = minY;
float maxZ = minZ;
// go through each point
for( size_t pointIdx = 3; pointIdx < m_vertices->size(); pointIdx+=3 )
{
minX = std::min( m_vertices->operator[]( pointIdx + 0 ), minX );
minY = std::min( m_vertices->operator[]( pointIdx + 1 ), minY );
minZ = std::min( m_vertices->operator[]( pointIdx + 2 ), minZ );
maxX = std::max( m_vertices->operator[]( pointIdx + 0 ), maxX );
maxY = std::max( m_vertices->operator[]( pointIdx + 1 ), maxY );
maxZ = std::max( m_vertices->operator[]( pointIdx + 2 ), maxZ );
}
m_bb = WBoundingBox( minX, minY, minZ, maxX, maxY, maxZ );
}
// which colortype do we have?
m_colorType = static_cast< ColorType >( m_colors->size() / ( m_vertices->size() / 3 ) );
}
size_t WDataSetPointsGrouped::size() const
{
return m_vertices->size() / 3;
}
bool WDataSetPointsGrouped::isTexture() const
{
return false;
}
const std::string WDataSetPointsGrouped::getName() const
{
return "WDataSetPointsGrouped";
}
const std::string WDataSetPointsGrouped::getDescription() const
{
return "Dataset which contains points without any topological relation.";
}
boost::shared_ptr< WPrototyped > WDataSetPointsGrouped::getPrototype()
{
if( !m_prototype )
{
m_prototype = boost::shared_ptr< WPrototyped >( new WDataSetPointsGrouped() );
}
return m_prototype;
}
WDataSetPointsGrouped::VertexArray WDataSetPointsGrouped::getVertices() const
{
return m_vertices;
}
WDataSetPointsGrouped::ColorArray WDataSetPointsGrouped::getColors() const
{
return m_colors;
}
WDataSetPointsGrouped::GroupArray WDataSetPointsGrouped::getGroups() const
{
return m_groups;
}
WBoundingBox WDataSetPointsGrouped::getBoundingBox() const
{
return m_bb;
}