mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
The text labels are always visible, also through geometry. The line closest to label text was set to no depth test, probably to match the text visibility. This is changed by this commit, and the top line will be hidden by reservoir geometry. Introduced by https://github.com/OPM/ResInsight/issues/266
775 lines
26 KiB
C++
775 lines
26 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 "RiaApplication.h"
|
|
#include "RiaColorTools.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_gridBoxModel = new cvf::ModelBasicList;
|
|
|
|
m_scaleZ = 1.0;
|
|
m_displayModelOffset = cvf::Vec3d::ZERO;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setScaleZ(double scaleZ)
|
|
{
|
|
m_scaleZ = scaleZ;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::setDisplayModelOffset(cvf::Vec3d offset)
|
|
{
|
|
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);
|
|
|
|
m_domainCoordsBoundingBox = expandedBB;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::createGridBoxParts()
|
|
{
|
|
computeDisplayCoords();
|
|
|
|
createGridBoxFaceParts();
|
|
createGridBoxLegendParts();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
void RivGridBoxGenerator::updateFromCamera(const cvf::Camera* camera)
|
|
{
|
|
m_gridBoxModel->removeAllParts();
|
|
|
|
if (m_gridBoxFaceParts.size() == 0) 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;
|
|
}
|
|
}
|
|
|
|
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();
|
|
|
|
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::Font* standardFont = RiaApplication::instance()->standardFont();
|
|
|
|
geo->setFont(standardFont);
|
|
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);
|
|
m_gridLegendColor = RiaColorTools::constrastColor(backgroundColor);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
///
|
|
//--------------------------------------------------------------------------------------------------
|
|
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()));
|
|
}
|
|
}
|