//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2013-2014 Andreas Schwarzkopf, OpenWalnut Community
// 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 .
//
//---------------------------------------------------------------------------
#include
#include // std::ifstream
#include // std::cout
#include
#include
#include "core/kernel/WModule.h"
#include "core/dataHandler/WDataSetScalar.h"
#include "core/graphicsEngine/callbacks/WGELinearTranslationCallback.h"
#include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
#include "core/graphicsEngine/shaders/WGEShader.h"
#include "core/graphicsEngine/WGEGeodeUtils.h"
#include "core/graphicsEngine/WGEManagedGroupNode.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WModuleInputData.h"
#include "WElevationImageOutliner.h"
WElevationImageOutliner::WElevationImageOutliner()
{
m_minElevImageZ = 0;
m_intensityIncreasesPerMeter = 5;
m_vertices = new WQuadTree( 1 );
m_printedQuadrats = new WQuadTree( 1 );
}
WElevationImageOutliner::~WElevationImageOutliner()
{
}
double WElevationImageOutliner::getSurfaceArea2D( WQuadTree* quadTree )
{
return calculateSurfaceForNode2D( quadTree->getRootNode(), quadTree );
}
double WElevationImageOutliner::calculateSurfaceForNode2D( WQuadNode* node, WQuadTree* quadTree )
{
if( node->getRadius() <= quadTree->getDetailLevel() )
{
return node->getRadius() * node->getRadius() * 4;
}
else
{
double area = 0.0;
for ( size_t child = 0; child < 4; child++ )
if ( node->getChild( child ) != 0 )
area += calculateSurfaceForNode2D( node->getChild( child ), quadTree );
return area;
}
}
void WElevationImageOutliner::importElevationImage( WQuadTree* quadTree, size_t elevImageMode )
{
boost::shared_ptr< WTriangleMesh > tmpMesh( new WTriangleMesh( 0, 0 ) );
m_outputMesh = tmpMesh;
m_vertices = new WQuadTree( quadTree->getDetailLevel() );
m_printedQuadrats = new WQuadTree( quadTree->getDetailLevel() );
drawNode( quadTree->getRootNode(), quadTree, elevImageMode );
}
void WElevationImageOutliner::drawNode(
WQuadNode* node, WQuadTree* quadTree, size_t elevImageMode )
{
if( node->getRadius() <= quadTree->getDetailLevel() )
{
double x = node->getCenter( 0 );
double y = node->getCenter( 1 );
double d = quadTree->getDetailLevel() * 2;
WQuadNode* sourceNodes[][3] = { //NOLINT
{ quadTree->getLeafNode( x-d, y-d ), quadTree->getLeafNode( x, y-d ), quadTree->getLeafNode( x+d, y-d ) }, //NOLINT
{ quadTree->getLeafNode( x-d, y ), quadTree->getLeafNode( x, y ), quadTree->getLeafNode( x+d, y ) }, //NOLINT
{ quadTree->getLeafNode( x-d, y+d ), quadTree->getLeafNode( x, y+d ), quadTree->getLeafNode( x+d, y+d ) } }; //NOLINT
for( size_t yIdx = 0; yIdx < 2; yIdx++)
for( size_t xIdx = 0; xIdx < 2; xIdx++)
{
double xOff = static_cast( xIdx )*d-d+x;
double yOff = static_cast( yIdx )*d-d+y;
bool isDone = m_printedQuadrats->getLeafNode( xOff, yOff ) != 0;
if( !isDone )
{
WQuadNode* sourceQuadrat[] = {
sourceNodes[xIdx][yIdx], sourceNodes[xIdx][yIdx+1],
sourceNodes[xIdx+1][yIdx+1], sourceNodes[xIdx+1][yIdx] };
size_t current = 0;
WQuadNode* list[] = {0, 0, 0};
for(int index = 0; index < 4; index++ )
{
if( sourceQuadrat[index] != 0 ) list[current++] = sourceQuadrat[index];
if( current == 3 )
{
size_t vertID0 = getVertexID( list[0], elevImageMode );
size_t vertID1 = getVertexID( list[1], elevImageMode );
size_t vertID2 = getVertexID( list[2], elevImageMode );
m_outputMesh->addTriangle( vertID0, vertID1, vertID2 );
list[1] = list[2];
current--;
}
}
m_printedQuadrats->registerPoint( xOff, yOff, 0 );
}
}
}
else
{
for ( size_t child = 0; child < 4; child++ )
if ( node->getChild( child ) != 0 )
drawNode( node->getChild( child ), quadTree, elevImageMode );
}
}
size_t WElevationImageOutliner::getVertexID(
WQuadNode* node, size_t elevImageMode )
{
double x = node->getCenter( 0 );
double y = node->getCenter( 1 );
WQuadNode* existingNode = m_vertices->getLeafNode( x, y );
if( existingNode != 0 ) return existingNode->getID();
double elevation = elevImageMode != 0 ?node->getValueMax() :node->getValueMin();
if( elevImageMode == 2 ) elevation = node->getPointCount();
m_vertices->registerPoint( x, y, elevation );
existingNode = m_vertices->getLeafNode( x, y );
size_t currentVertex = m_outputMesh->vertSize();
existingNode->setID( currentVertex );
m_outputMesh->addVertex( x, y, m_showElevationInMeshOffset ?elevation :0 );
elevation = ( elevation - m_minElevImageZ ) * m_intensityIncreasesPerMeter;
if( elevation < 0.0 ) elevation = 0.0;
if( elevation > 255.0 ) elevation = 255.0;
elevation /= 255.0;
if( !m_showElevationInMeshColor ) elevation = 128;
osg::Vec4 color = osg::Vec4( elevation, elevation, elevation, 1.0 );
m_outputMesh->setVertexColor( currentVertex, color );
return existingNode->getID();
}
void WElevationImageOutliner::setExportElevationImageSettings( double minElevImageZ, double intensityIncreasesPerMeter )
{
m_minElevImageZ = minElevImageZ;
m_intensityIncreasesPerMeter = intensityIncreasesPerMeter;
}
void WElevationImageOutliner::setShowElevationInMeshColor( bool showElevationInMeshColor )
{
m_showElevationInMeshColor = showElevationInMeshColor;
}
void WElevationImageOutliner::setShowElevationInMeshOffset( bool showElevationInMeshOffset )
{
m_showElevationInMeshOffset = showElevationInMeshOffset;
}
boost::shared_ptr< WTriangleMesh > WElevationImageOutliner::getOutputMesh()
{
return m_outputMesh;
}
void WElevationImageOutliner::highlightBuildingGroups( boost::shared_ptr< WDataSetPointsGrouped > groupedPoints )
{
if( !groupedPoints ) return;
WDataSetPointsGrouped::VertexArray verts = groupedPoints->getVertices();
WDataSetPointsGrouped::GroupArray groups = groupedPoints->getGroups();
size_t count = verts->size()/3;
size_t nulls = 0;
size_t outOfRanges = 0;
for( size_t vertex = 0; vertex < count; vertex++)
{
float x = verts->at( vertex*3 );
float y = verts->at( vertex*3+1 );
WQuadNode* node = m_vertices->getLeafNode( x, y );
if( node != 0 )
{
if( node->getID() < m_outputMesh->vertSize() )
{
size_t group = groups->at( vertex );
osg::Vec4 color = osg::Vec4( WOctree::calcColor( group, 0 ),
WOctree::calcColor( group, 1 ), WOctree::calcColor( group, 2 ), 1.0f );
m_outputMesh->setVertexColor( node->getID(), color );
}
else
{
outOfRanges++;
}
}
else
{
nulls++;
}
}
if( nulls > 0 )
std::cout << "!!!WARNING!!! WElevationImageExporter: " << nulls << " invalid poinnt hits!" << std::endl;
if( outOfRanges > 0 )
std::cout << "!!!WARNING!!! WElevationImageExporter: " << outOfRanges << " out of ranges!" << std::endl;
}