mirror of
https://github.com/OPM/ResInsight.git
synced 2025-01-08 23:23:01 -06:00
820 lines
29 KiB
C++
820 lines
29 KiB
C++
/////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2015- Statoil ASA
|
|
// Copyright (C) 2015- Ceetron Solutions AS
|
|
//
|
|
// ResInsight is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// ResInsight 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 General Public License at <http://www.gnu.org/licenses/gpl.html>
|
|
// for more details.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RivGridBoxGenerator.h"
|
|
|
|
#include "RiaColorTools.h"
|
|
#include "RiaFontCache.h"
|
|
#include "RiaGuiApplication.h"
|
|
#include "RiaPreferences.h"
|
|
|
|
#include "RivPartPriority.h"
|
|
#include "RivPatchGenerator.h"
|
|
|
|
#include "cafEffectGenerator.h"
|
|
|
|
#include "cvfCamera.h"
|
|
#include "cvfDrawableText.h"
|
|
#include "cvfFixedAtlasFont.h"
|
|
#include "cvfGeometryBuilderDrawableGeo.h"
|
|
#include "cvfGeometryBuilderFaceList.h"
|
|
#include "cvfMeshEdgeExtractor.h"
|
|
#include "cvfPrimitiveSetIndexedUInt.h"
|
|
#include "cvfRenderStateDepth.h"
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
RivGridBoxGenerator::RivGridBoxGenerator()
|
|
: m_gridColor( cvf::Color3f::LIGHT_GRAY )
|
|
, m_gridLegendColor( cvf::Color3f::BLACK )
|
|
, m_needsRegeneration( true )
|
|
{
|
|
m_gridBoxModel = new cvf::ModelBasicList();
|
|
m_gridBoxModel->setName( "GridBoxModel" );
|
|
|
|
m_scaleZ = 1.0;
|
|
m_displayModelOffset = cvf::Vec3d::ZERO;
|
|
|
|
m_fontPointSize = caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultSceneFontSize() );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setScaleZ( double scaleZ )
|
|
{
|
|
if ( m_scaleZ != scaleZ ) m_needsRegeneration = true;
|
|
|
|
m_scaleZ = scaleZ;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setDisplayModelOffset( cvf::Vec3d offset )
|
|
{
|
|
if ( m_displayModelOffset != offset ) m_needsRegeneration = true;
|
|
|
|
m_displayModelOffset = offset;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setGridBoxDomainCoordBoundingBox( const cvf::BoundingBox& incomingBB )
|
|
{
|
|
double expandFactor = 0.05;
|
|
|
|
// Use ScalarMapperDiscreteLinear to find human readable tick mark positions for grid box sub division coordinate
|
|
// values Expand the range for ScalarMapperDiscreteLinear until the geometry bounding box has a generated tick mark
|
|
// coords both below minimum and above maximum bounding box coords
|
|
|
|
cvf::BoundingBox bb;
|
|
if ( incomingBB.isValid() )
|
|
{
|
|
bb = incomingBB;
|
|
}
|
|
else
|
|
{
|
|
bb.add( cvf::Vec3d::ZERO );
|
|
}
|
|
|
|
cvf::Vec3d min = bb.min();
|
|
cvf::Vec3d max = bb.max();
|
|
|
|
size_t levelCount = 6;
|
|
|
|
{
|
|
bool majorTickValuesCoversDomainValues = false;
|
|
while ( !majorTickValuesCoversDomainValues )
|
|
{
|
|
m_domainCoordsXValues.clear();
|
|
|
|
cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
|
|
linDiscreteScalarMapper.setRange( min.x(), max.x() );
|
|
linDiscreteScalarMapper.setLevelCount( levelCount, true );
|
|
linDiscreteScalarMapper.majorTickValues( &m_domainCoordsXValues );
|
|
|
|
majorTickValuesCoversDomainValues = true;
|
|
|
|
if ( m_domainCoordsXValues[1] > bb.min().x() )
|
|
{
|
|
min.x() = min.x() - bb.extent().x() * expandFactor;
|
|
max.x() = max.x() + bb.extent().x() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
|
|
if ( m_domainCoordsXValues[m_domainCoordsXValues.size() - 1] < bb.max().x() )
|
|
{
|
|
min.x() = min.x() - bb.extent().x() * expandFactor;
|
|
max.x() = max.x() + bb.extent().x() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
bool majorTickValuesCoversDomainValues = false;
|
|
while ( !majorTickValuesCoversDomainValues )
|
|
{
|
|
m_domainCoordsYValues.clear();
|
|
|
|
cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
|
|
linDiscreteScalarMapper.setRange( min.y(), max.y() );
|
|
linDiscreteScalarMapper.setLevelCount( levelCount, true );
|
|
linDiscreteScalarMapper.majorTickValues( &m_domainCoordsYValues );
|
|
|
|
majorTickValuesCoversDomainValues = true;
|
|
|
|
if ( m_domainCoordsYValues[1] > bb.min().y() )
|
|
{
|
|
min.y() = min.y() - bb.extent().y() * expandFactor;
|
|
max.y() = max.y() + bb.extent().y() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
|
|
if ( m_domainCoordsYValues[m_domainCoordsYValues.size() - 1] < bb.max().y() )
|
|
{
|
|
min.y() = min.y() - bb.extent().y() * expandFactor;
|
|
max.y() = max.y() + bb.extent().y() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
bool majorTickValuesCoversDomainValues = false;
|
|
while ( !majorTickValuesCoversDomainValues )
|
|
{
|
|
m_domainCoordsZValues.clear();
|
|
|
|
cvf::ScalarMapperDiscreteLinear linDiscreteScalarMapper;
|
|
linDiscreteScalarMapper.setRange( min.z(), max.z() );
|
|
linDiscreteScalarMapper.setLevelCount( levelCount, true );
|
|
linDiscreteScalarMapper.majorTickValues( &m_domainCoordsZValues );
|
|
|
|
majorTickValuesCoversDomainValues = true;
|
|
|
|
if ( m_domainCoordsZValues[1] > bb.min().z() )
|
|
{
|
|
min.z() = min.z() - bb.extent().z() * expandFactor;
|
|
max.z() = max.z() + bb.extent().z() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
|
|
if ( m_domainCoordsZValues[m_domainCoordsZValues.size() - 1] < bb.max().z() )
|
|
{
|
|
min.z() = min.z() - bb.extent().z() * expandFactor;
|
|
max.z() = max.z() + bb.extent().z() * expandFactor;
|
|
majorTickValuesCoversDomainValues = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
cvf::BoundingBox expandedBB;
|
|
expandedBB.add( min );
|
|
expandedBB.add( max );
|
|
|
|
if ( !m_domainCoordsBoundingBox.isValid() || m_domainCoordsBoundingBox.min() != expandedBB.min() ||
|
|
m_domainCoordsBoundingBox.max() != expandedBB.max() )
|
|
{
|
|
m_needsRegeneration = true;
|
|
}
|
|
|
|
m_domainCoordsBoundingBox = expandedBB;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::createGridBoxParts()
|
|
{
|
|
if ( m_needsRegeneration )
|
|
{
|
|
computeDisplayCoords();
|
|
|
|
createGridBoxFaceParts();
|
|
createGridBoxLegendParts();
|
|
m_needsRegeneration = false;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setGridLabelFontSize( int fontSize )
|
|
{
|
|
if ( m_fontPointSize != fontSize )
|
|
{
|
|
m_fontPointSize = fontSize;
|
|
m_needsRegeneration = true;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::updateFromCamera( const cvf::Camera* camera )
|
|
{
|
|
m_gridBoxModel->removeAllParts();
|
|
|
|
if ( m_gridBoxFaceParts.empty() ) return;
|
|
|
|
std::vector<bool> faceVisibility( 6, false );
|
|
for ( size_t i = POS_X; i <= NEG_Z; i++ )
|
|
{
|
|
bool isFaceVisible = false;
|
|
cvf::Vec3f sideNorm = sideNormalOutwards( (FaceType)i );
|
|
|
|
if ( camera->projection() == cvf::Camera::PERSPECTIVE )
|
|
{
|
|
cvf::Vec3d camToSide = camera->position() - pointOnSide( (FaceType)i );
|
|
camToSide.normalize();
|
|
|
|
isFaceVisible = sideNorm.dot( cvf::Vec3f( camToSide ) ) < 0.0;
|
|
}
|
|
else
|
|
{
|
|
cvf::Vec3d camToSide = camera->direction();
|
|
isFaceVisible = sideNorm.dot( cvf::Vec3f( camToSide ) ) > 0.0;
|
|
}
|
|
|
|
if ( isFaceVisible )
|
|
{
|
|
m_gridBoxModel->addPart( m_gridBoxFaceParts[i].p() );
|
|
faceVisibility[i] = true;
|
|
}
|
|
}
|
|
|
|
if ( !m_gridBoxLegendParts.empty() )
|
|
{
|
|
std::vector<bool> edgeVisibility( 12, false );
|
|
computeEdgeVisibility( faceVisibility, edgeVisibility );
|
|
|
|
CVF_ASSERT( m_gridBoxLegendParts.size() == ( NEG_X_NEG_Y + 1 ) * 2 );
|
|
for ( size_t i = POS_Z_POS_X; i <= NEG_X_NEG_Y; i++ )
|
|
{
|
|
if ( edgeVisibility[i] )
|
|
{
|
|
// We have two parts for each edge - line and text
|
|
m_gridBoxModel->addPart( m_gridBoxLegendParts[2 * i].p() );
|
|
m_gridBoxModel->addPart( m_gridBoxLegendParts[2 * i + 1].p() );
|
|
}
|
|
}
|
|
}
|
|
|
|
m_gridBoxModel->updateBoundingBoxesRecursive();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::computeEdgeVisibility( const std::vector<bool>& faceVisibility, std::vector<bool>& edgeVisibility )
|
|
{
|
|
CVF_ASSERT( faceVisibility.size() == NEG_Z + 1 );
|
|
CVF_ASSERT( edgeVisibility.size() == NEG_X_NEG_Y + 1 );
|
|
|
|
// POS Z
|
|
if ( faceVisibility[POS_Z] ^ faceVisibility[POS_X] )
|
|
{
|
|
edgeVisibility[POS_Z_POS_X] = true;
|
|
}
|
|
if ( faceVisibility[POS_Z] ^ faceVisibility[NEG_X] )
|
|
{
|
|
edgeVisibility[POS_Z_NEG_X] = true;
|
|
}
|
|
if ( faceVisibility[POS_Z] ^ faceVisibility[POS_Y] )
|
|
{
|
|
edgeVisibility[POS_Z_POS_Y] = true;
|
|
}
|
|
if ( faceVisibility[POS_Z] ^ faceVisibility[NEG_Y] )
|
|
{
|
|
edgeVisibility[POS_Z_NEG_Y] = true;
|
|
}
|
|
|
|
// NEG Z
|
|
if ( faceVisibility[NEG_Z] ^ faceVisibility[POS_X] )
|
|
{
|
|
edgeVisibility[NEG_Z_POS_X] = true;
|
|
}
|
|
if ( faceVisibility[NEG_Z] ^ faceVisibility[NEG_X] )
|
|
{
|
|
edgeVisibility[NEG_Z_NEG_X] = true;
|
|
}
|
|
if ( faceVisibility[NEG_Z] ^ faceVisibility[POS_Y] )
|
|
{
|
|
edgeVisibility[NEG_Z_POS_Y] = true;
|
|
}
|
|
if ( faceVisibility[NEG_Z] ^ faceVisibility[NEG_Y] )
|
|
{
|
|
edgeVisibility[NEG_Z_NEG_Y] = true;
|
|
}
|
|
|
|
// POS X
|
|
if ( faceVisibility[POS_X] ^ faceVisibility[POS_Y] )
|
|
{
|
|
edgeVisibility[POS_X_POS_Y] = true;
|
|
}
|
|
if ( faceVisibility[POS_X] ^ faceVisibility[NEG_Y] )
|
|
{
|
|
edgeVisibility[POS_X_NEG_Y] = true;
|
|
}
|
|
|
|
// NEG X
|
|
if ( faceVisibility[NEG_X] ^ faceVisibility[POS_Y] )
|
|
{
|
|
edgeVisibility[NEG_X_POS_Y] = true;
|
|
}
|
|
if ( faceVisibility[NEG_X] ^ faceVisibility[NEG_Y] )
|
|
{
|
|
edgeVisibility[NEG_X_NEG_Y] = true;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Model* RivGridBoxGenerator::model()
|
|
{
|
|
return m_gridBoxModel.p();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::createGridBoxFaceParts()
|
|
{
|
|
m_gridBoxFaceParts.clear();
|
|
|
|
CVF_ASSERT( m_displayCoordsBoundingBox.isValid() );
|
|
CVF_ASSERT( m_displayCoordsXValues.size() > 0 );
|
|
CVF_ASSERT( m_displayCoordsYValues.size() > 0 );
|
|
CVF_ASSERT( m_displayCoordsZValues.size() > 0 );
|
|
|
|
cvf::Vec3d min = m_displayCoordsBoundingBox.min();
|
|
cvf::Vec3d max = m_displayCoordsBoundingBox.max();
|
|
|
|
for ( int face = POS_X; face <= NEG_Z; face++ )
|
|
{
|
|
// TODO: move out of loop
|
|
RivPatchGenerator patchGen;
|
|
|
|
if ( face == POS_X )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( max.x(), 0.0, 0.0 ) );
|
|
patchGen.setAxes( cvf::Vec3d::Y_AXIS, cvf::Vec3d::Z_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsYValues, m_displayCoordsZValues );
|
|
}
|
|
else if ( face == NEG_X )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( min.x(), 0.0, 0.0 ) );
|
|
patchGen.setAxes( cvf::Vec3d::Y_AXIS, cvf::Vec3d::Z_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsYValues, m_displayCoordsZValues );
|
|
}
|
|
else if ( face == POS_Y )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( 0.0, max.y(), 0.0 ) );
|
|
patchGen.setAxes( cvf::Vec3d::X_AXIS, cvf::Vec3d::Z_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsXValues, m_displayCoordsZValues );
|
|
}
|
|
else if ( face == NEG_Y )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( 0.0, min.y(), 0.0 ) );
|
|
patchGen.setAxes( cvf::Vec3d::X_AXIS, cvf::Vec3d::Z_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsXValues, m_displayCoordsZValues );
|
|
}
|
|
else if ( face == POS_Z )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( 0.0, 0.0, max.z() ) );
|
|
patchGen.setAxes( cvf::Vec3d::X_AXIS, cvf::Vec3d::Y_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsXValues, m_displayCoordsYValues );
|
|
}
|
|
else if ( face == NEG_Z )
|
|
{
|
|
patchGen.setOrigin( cvf::Vec3d( 0.0, 0.0, min.z() ) );
|
|
patchGen.setAxes( cvf::Vec3d::X_AXIS, cvf::Vec3d::Y_AXIS );
|
|
patchGen.setSubdivisions( m_displayCoordsXValues, m_displayCoordsYValues );
|
|
}
|
|
else
|
|
{
|
|
CVF_ASSERT( false );
|
|
}
|
|
|
|
cvf::GeometryBuilderFaceList builder;
|
|
patchGen.generate( &builder );
|
|
cvf::ref<cvf::Vec3fArray> vertexArray = builder.vertices();
|
|
cvf::ref<cvf::UIntArray> faceList = builder.faceList();
|
|
|
|
{
|
|
// Box mesh
|
|
cvf::MeshEdgeExtractor ee;
|
|
ee.addFaceList( *faceList );
|
|
|
|
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
|
|
geo->setVertexArray( vertexArray.p() );
|
|
geo->addPrimitiveSet( new cvf::PrimitiveSetIndexedUInt( cvf::PT_LINES, ee.lineIndices().p() ) );
|
|
|
|
cvf::ref<cvf::Part> part = new cvf::Part;
|
|
part->setName( "Grid box " );
|
|
part->setDrawable( geo.p() );
|
|
|
|
part->updateBoundingBox();
|
|
|
|
cvf::ref<cvf::Effect> eff;
|
|
caf::MeshEffectGenerator effGen( m_gridColor );
|
|
eff = effGen.generateCachedEffect();
|
|
|
|
part->setEffect( eff.p() );
|
|
|
|
m_gridBoxFaceParts.push_back( part.p() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::createGridBoxLegendParts()
|
|
{
|
|
m_gridBoxLegendParts.clear();
|
|
|
|
CVF_ASSERT( m_displayCoordsBoundingBox.isValid() );
|
|
CVF_ASSERT( m_displayCoordsXValues.size() > 0 );
|
|
CVF_ASSERT( m_displayCoordsYValues.size() > 0 );
|
|
CVF_ASSERT( m_displayCoordsZValues.size() > 0 );
|
|
|
|
for ( int edge = POS_Z_POS_X; edge <= NEG_X_NEG_Y; edge++ )
|
|
{
|
|
cvf::Collection<cvf::Part> parts;
|
|
|
|
createLegend( (EdgeType)edge, &parts );
|
|
|
|
for ( size_t i = 0; i < parts.size(); i++ )
|
|
{
|
|
m_gridBoxLegendParts.push_back( parts.at( i ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Vec3d RivGridBoxGenerator::displayModelCoordFromDomainCoord( const cvf::Vec3d& domainCoord ) const
|
|
{
|
|
cvf::Vec3d coord = domainCoord - m_displayModelOffset;
|
|
coord.z() *= m_scaleZ;
|
|
|
|
return coord;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::createLegend( EdgeType edge, cvf::Collection<cvf::Part>* parts )
|
|
{
|
|
cvf::Vec3d posMin = cvf::Vec3d::ZERO;
|
|
cvf::Vec3d posMax = cvf::Vec3d::ZERO;
|
|
|
|
cvf::Vec3d min = m_displayCoordsBoundingBox.min();
|
|
cvf::Vec3d max = m_displayCoordsBoundingBox.max();
|
|
|
|
if ( min == max )
|
|
{
|
|
return;
|
|
}
|
|
|
|
AxisType axis = X_AXIS;
|
|
|
|
cvf::Vec3f tickMarkDir = cvf::Vec3f::X_AXIS;
|
|
|
|
switch ( edge )
|
|
{
|
|
case RivGridBoxGenerator::POS_Z_POS_X:
|
|
axis = Y_AXIS;
|
|
posMin.set( max.x(), min.y(), max.z() );
|
|
posMax.set( max.x(), max.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_Z, POS_X );
|
|
break;
|
|
case RivGridBoxGenerator::POS_Z_NEG_X:
|
|
axis = Y_AXIS;
|
|
posMin.set( min.x(), min.y(), max.z() );
|
|
posMax.set( min.x(), max.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_Z, NEG_X );
|
|
break;
|
|
case RivGridBoxGenerator::POS_Z_POS_Y:
|
|
axis = X_AXIS;
|
|
posMin.set( min.x(), max.y(), max.z() );
|
|
posMax.set( max.x(), max.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_Z, POS_Y );
|
|
break;
|
|
case RivGridBoxGenerator::POS_Z_NEG_Y:
|
|
axis = X_AXIS;
|
|
posMin.set( min.x(), min.y(), max.z() );
|
|
posMax.set( max.x(), min.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_Z, NEG_Y );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_Z_POS_X:
|
|
axis = Y_AXIS;
|
|
posMin.set( max.x(), min.y(), min.z() );
|
|
posMax.set( max.x(), max.y(), min.z() );
|
|
tickMarkDir = cornerDirection( NEG_Z, POS_X );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_Z_NEG_X:
|
|
axis = Y_AXIS;
|
|
posMin.set( min.x(), min.y(), min.z() );
|
|
posMax.set( min.x(), max.y(), min.z() );
|
|
tickMarkDir = cornerDirection( NEG_Z, NEG_X );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_Z_POS_Y:
|
|
axis = X_AXIS;
|
|
posMin.set( min.x(), max.y(), min.z() );
|
|
posMax.set( max.x(), max.y(), min.z() );
|
|
tickMarkDir = cornerDirection( NEG_Z, POS_Y );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_Z_NEG_Y:
|
|
axis = X_AXIS;
|
|
posMin.set( min.x(), min.y(), min.z() );
|
|
posMax.set( max.x(), min.y(), min.z() );
|
|
tickMarkDir = cornerDirection( NEG_Z, NEG_Y );
|
|
break;
|
|
case RivGridBoxGenerator::POS_X_POS_Y:
|
|
axis = Z_AXIS;
|
|
posMin.set( max.x(), max.y(), min.z() );
|
|
posMax.set( max.x(), max.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_X, POS_Y );
|
|
break;
|
|
case RivGridBoxGenerator::POS_X_NEG_Y:
|
|
axis = Z_AXIS;
|
|
posMin.set( max.x(), min.y(), min.z() );
|
|
posMax.set( max.x(), min.y(), max.z() );
|
|
tickMarkDir = cornerDirection( POS_X, NEG_Y );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_X_POS_Y:
|
|
axis = Z_AXIS;
|
|
posMin.set( min.x(), max.y(), min.z() );
|
|
posMax.set( min.x(), max.y(), max.z() );
|
|
tickMarkDir = cornerDirection( NEG_X, POS_Y );
|
|
break;
|
|
case RivGridBoxGenerator::NEG_X_NEG_Y:
|
|
axis = Z_AXIS;
|
|
posMin.set( min.x(), min.y(), min.z() );
|
|
posMax.set( min.x(), min.y(), max.z() );
|
|
tickMarkDir = cornerDirection( NEG_X, NEG_Y );
|
|
break;
|
|
default:
|
|
CVF_TIGHT_ASSERT( false );
|
|
break;
|
|
}
|
|
|
|
std::vector<double>* displayCoordsTickValues = nullptr;
|
|
std::vector<double>* domainCoordsTickValues = nullptr;
|
|
|
|
if ( axis == X_AXIS )
|
|
{
|
|
displayCoordsTickValues = &m_displayCoordsXValues;
|
|
domainCoordsTickValues = &m_domainCoordsXValues;
|
|
}
|
|
else if ( axis == Y_AXIS )
|
|
{
|
|
displayCoordsTickValues = &m_displayCoordsYValues;
|
|
domainCoordsTickValues = &m_domainCoordsYValues;
|
|
}
|
|
else if ( axis == Z_AXIS )
|
|
{
|
|
displayCoordsTickValues = &m_displayCoordsZValues;
|
|
domainCoordsTickValues = &m_domainCoordsZValues;
|
|
}
|
|
|
|
CVF_ASSERT( displayCoordsTickValues );
|
|
CVF_ASSERT( domainCoordsTickValues );
|
|
|
|
size_t numVerts = ( displayCoordsTickValues->size() ) * 2;
|
|
size_t numLines = ( displayCoordsTickValues->size() ) + 1;
|
|
|
|
cvf::ref<cvf::Vec3fArray> vertices = new cvf::Vec3fArray;
|
|
vertices->reserve( numVerts );
|
|
|
|
cvf::ref<cvf::UIntArray> indices = new cvf::UIntArray;
|
|
indices->reserve( 2 * numLines );
|
|
|
|
float tickLength = static_cast<float>( m_displayCoordsBoundingBox.extent().length() / 100.0 );
|
|
|
|
cvf::Vec3f point = cvf::Vec3f( posMin );
|
|
cvf::Vec3f tickPoint;
|
|
|
|
// Tick marks
|
|
for ( size_t i = 0; i < displayCoordsTickValues->size(); ++i )
|
|
{
|
|
point[axis] = static_cast<float>( displayCoordsTickValues->at( i ) );
|
|
|
|
vertices->add( point );
|
|
tickPoint = point + tickLength * tickMarkDir;
|
|
;
|
|
vertices->add( tickPoint );
|
|
|
|
if ( i == 0 || i == displayCoordsTickValues->size() - 1 )
|
|
{
|
|
// Do not show tick mark at ends of legend
|
|
// Add to list of indices to keep surrounding code unchanged
|
|
indices->add( 2 * static_cast<cvf::uint>( i ) );
|
|
indices->add( 2 * static_cast<cvf::uint>( i ) );
|
|
}
|
|
else
|
|
{
|
|
indices->add( 2 * static_cast<cvf::uint>( i ) );
|
|
indices->add( 2 * static_cast<cvf::uint>( i ) + 1 );
|
|
}
|
|
}
|
|
|
|
// Backbone of legend
|
|
indices->add( 0 );
|
|
indices->add( static_cast<cvf::uint>( numVerts ) - 2 );
|
|
|
|
{
|
|
// Legend lines
|
|
|
|
cvf::ref<cvf::DrawableGeo> geo = new cvf::DrawableGeo;
|
|
geo->setVertexArray( vertices.p() );
|
|
|
|
cvf::ref<cvf::PrimitiveSetIndexedUInt> primSet = new cvf::PrimitiveSetIndexedUInt( cvf::PT_LINES );
|
|
primSet->setIndices( indices.p() );
|
|
geo->addPrimitiveSet( primSet.p() );
|
|
|
|
cvf::ref<cvf::Part> part = new cvf::Part;
|
|
part->setName( "Legend lines" );
|
|
part->setDrawable( geo.p() );
|
|
part->updateBoundingBox();
|
|
|
|
cvf::ref<cvf::Effect> eff;
|
|
caf::MeshEffectGenerator effGen( m_gridLegendColor );
|
|
eff = effGen.generateUnCachedEffect();
|
|
|
|
part->setPriority( RivPartPriority::PartType::Text );
|
|
part->setEffect( eff.p() );
|
|
|
|
parts->push_back( part.p() );
|
|
}
|
|
|
|
{
|
|
// Text labels
|
|
|
|
cvf::ref<cvf::DrawableText> geo = new cvf::DrawableText;
|
|
|
|
cvf::ref<cvf::Font> font = RiaGuiApplication::instance()->defaultSceneFont();
|
|
if ( caf::FontTools::absolutePointSize( RiaPreferences::current()->defaultSceneFontSize() ) != m_fontPointSize )
|
|
{
|
|
font = RiaFontCache::getFont( m_fontPointSize );
|
|
}
|
|
geo->setFont( font.p() );
|
|
geo->setTextColor( m_gridLegendColor );
|
|
geo->setCheckPosVisible( false );
|
|
geo->setDrawBackground( false );
|
|
geo->setDrawBorder( false );
|
|
|
|
// Do not draw legend labels at first/last tick mark
|
|
for ( size_t idx = 1; idx < domainCoordsTickValues->size() - 1; idx++ )
|
|
{
|
|
double legendValue = domainCoordsTickValues->at( idx );
|
|
if ( axis == Z_AXIS )
|
|
{
|
|
legendValue = -domainCoordsTickValues->at( idx );
|
|
}
|
|
|
|
cvf::int64 integerValue = static_cast<cvf::int64>( legendValue );
|
|
cvf::String numberText = cvf::String( "%1" ).arg( integerValue );
|
|
|
|
geo->addText( numberText, vertices->get( idx * 2 + 1 ) + ( 0.5f * tickLength ) * tickMarkDir );
|
|
}
|
|
|
|
cvf::ref<cvf::Part> part = new cvf::Part;
|
|
part->setName( "Legend text" );
|
|
part->setDrawable( geo.p() );
|
|
part->updateBoundingBox();
|
|
|
|
caf::TextEffectGenerator textGen;
|
|
cvf::ref<cvf::Effect> eff = textGen.generateCachedEffect();
|
|
part->setEffect( eff.p() );
|
|
|
|
parts->push_back( part.p() );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Vec3f RivGridBoxGenerator::sideNormalOutwards( FaceType face )
|
|
{
|
|
switch ( face )
|
|
{
|
|
case RivGridBoxGenerator::POS_X:
|
|
return cvf::Vec3f::X_AXIS;
|
|
case RivGridBoxGenerator::NEG_X:
|
|
return -cvf::Vec3f::X_AXIS;
|
|
case RivGridBoxGenerator::POS_Y:
|
|
return cvf::Vec3f::Y_AXIS;
|
|
case RivGridBoxGenerator::NEG_Y:
|
|
return -cvf::Vec3f::Y_AXIS;
|
|
case RivGridBoxGenerator::POS_Z:
|
|
return cvf::Vec3f::Z_AXIS;
|
|
case RivGridBoxGenerator::NEG_Z:
|
|
return -cvf::Vec3f::Z_AXIS;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return cvf::Vec3f::ZERO;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Vec3d RivGridBoxGenerator::pointOnSide( FaceType face )
|
|
{
|
|
switch ( face )
|
|
{
|
|
case RivGridBoxGenerator::POS_X:
|
|
case RivGridBoxGenerator::POS_Y:
|
|
case RivGridBoxGenerator::POS_Z:
|
|
return cvf::Vec3d( m_displayCoordsBoundingBox.max() );
|
|
|
|
case RivGridBoxGenerator::NEG_X:
|
|
case RivGridBoxGenerator::NEG_Y:
|
|
case RivGridBoxGenerator::NEG_Z:
|
|
return cvf::Vec3d( m_displayCoordsBoundingBox.min() );
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return cvf::Vec3d::ZERO;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
cvf::Vec3f RivGridBoxGenerator::cornerDirection( FaceType face1, FaceType face2 )
|
|
{
|
|
cvf::Vec3f dir = sideNormalOutwards( face1 ) + sideNormalOutwards( face2 );
|
|
dir.normalize();
|
|
|
|
return dir;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::updateFromBackgroundColor( const cvf::Color3f& backgroundColor )
|
|
{
|
|
m_gridColor = RiaColorTools::computeOffsetColor( backgroundColor, 0.3f );
|
|
cvf::Color3f contrastColor = RiaColorTools::contrastColor( backgroundColor );
|
|
|
|
if ( contrastColor != m_gridLegendColor ) m_needsRegeneration = true;
|
|
|
|
m_gridLegendColor = contrastColor;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::computeDisplayCoords()
|
|
{
|
|
m_displayCoordsBoundingBox.reset();
|
|
m_displayCoordsXValues.clear();
|
|
m_displayCoordsYValues.clear();
|
|
m_displayCoordsZValues.clear();
|
|
|
|
m_displayCoordsBoundingBox.add( displayModelCoordFromDomainCoord( m_domainCoordsBoundingBox.min() ) );
|
|
m_displayCoordsBoundingBox.add( displayModelCoordFromDomainCoord( m_domainCoordsBoundingBox.max() ) );
|
|
|
|
for ( size_t i = 0; i < m_domainCoordsXValues.size(); i++ )
|
|
{
|
|
m_displayCoordsXValues.push_back( m_domainCoordsXValues[i] - m_displayModelOffset.x() );
|
|
}
|
|
|
|
for ( size_t i = 0; i < m_domainCoordsYValues.size(); i++ )
|
|
{
|
|
m_displayCoordsYValues.push_back( m_domainCoordsYValues[i] - m_displayModelOffset.y() );
|
|
}
|
|
|
|
for ( size_t i = 0; i < m_domainCoordsZValues.size(); i++ )
|
|
{
|
|
m_displayCoordsZValues.push_back( m_scaleZ * ( m_domainCoordsZValues[i] - m_displayModelOffset.z() ) );
|
|
}
|
|
}
|