Fish - FiberLib for VISH 0.3
Fish - The Fiber Bundle API for the Vish Visualization Shell
FragmentBoxes.cpp

Draw a bounding box for a Grid object residing in the fiber bundle.

Draw a bounding box for a Grid object residing in the fiber bundle.Refinement representations and field fragments are supported (which constitutes AMR).

For each coordinate field, the bounding box is stored with the field and thus re-used if possible. Also, there might be an field in the same data represention be specified. The bounding box information of this field is then shown in addition. This field may consist of various fragments, such that multiple bounding boxes are shown. The bounding box information is cached at each field fragment.

If values in field coordinates are changed, this is not recognized. Code doing so would have to clear the field's FragmentBoxes interface.

#include <bone/BundleInput.hpp>
#include <bone/GridObject.hpp>
#include <bone/FishField.hpp>
#include <bone/FieldObject.hpp>
#include <ocean/shrimp/Options.hpp>
#include <ocean/shrimp/VObjectStatus.hpp>
#include <ocean/GLvish/BoundingBox.hpp>
#include <ocean/GLvish/GLFonts.hpp>
#include <ocean/Anemonia/FloatOrigin.hpp>
#include <eagle/PhysicalSpace.hpp>
#include <eye/retina/VFieldRenderObject.hpp>
#include <baseop/ExpandBBox.hpp>
using namespace Wizt;
using namespace Fiber;
using namespace Eagle;
/**@example FragmentBoxes.cpp
Draw a bounding box for a Grid object residing in the fiber bundle.
Refinement representations and field fragments are supported (which
constitutes AMR).
For each coordinate field, the bounding box is stored with the field
and thus re-used if possible. Also, there might be an field in the
same data represention be specified. The bounding box information of
this field is then shown in addition. This field may consist of
various fragments, such that multiple bounding boxes are shown.
The bounding box information is cached at each field fragment.
If values in field coordinates are changed, this is not recognized.
Code doing so would have to clear the field's FragmentBoxes interface.
*/
namespace
{
/**
Display boxes for all the fragments of fiber bundle's field.
@author werner
*/
class VFragmentBoxes : public VFieldRenderObject
, public Fish<Fiber::Skeleton>
, public FloatOrigin
{
public:
enum { NumberOfInputFields = 1 };
struct FieldState : State, FieldFragmentIterator
{
/// Internally used for apply()
RefPtr<Field> CurrentCoords;
/// The bounding box for the entire field
RefPtr<BoundingBox> FieldBBox;
double MinBBoxRadius, MaxBBoxRadius;
struct PerFragmentInfo
{
RefPtr<BoundingBox> BBox;
RefPtr<FragmentID> fragID;
PerFragmentInfo(const RefPtr<BoundingBox>&theBBox,
const RefPtr<FragmentID> &theFragID,
const WeakPtr<CreativeArrayBase>&theDataPtr)
: BBox(theBBox)
, fragID(theFragID)
, DataPtr(theDataPtr)
{}
};
///
void clear()
{
FieldBBox = new BoundingBox();
BBoxes.clear();
}
bool apply(const RefPtr<FragmentID>&f, const RefPtr<CreativeArrayBase>&CAB) override;
};
RefPtr<State> newState() const override
{
return new FieldState();
}
in<Options> inOptions;
in<rgba_float_t> inColor,
inUnloadedColor,
inFontColor;
TypedSlot<double> Thickness,
inFontScale;
VFragmentBoxes(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
, inOptions(this, "options", Options("+autoscale +showtext"))
, inColor(this,"color", rgba_float_t(0.4, 0.12, 0.65, 1.0), 1)
, inUnloadedColor(this,"uncolor", rgba_float_t(0.3, 0.3, 0.3, 1.0), 2)
, inFontColor(this, "fontcolor", rgba_float_t(0.9, 0.9, 0.9, 1.0), 1)
, Thickness(this, "thickness", 20, 5.0)
, inFontScale(this, "fontscale", 1.0, 1)
{}
bool update(VRequest&R, double precision) override;
bool renderGL(VGLRenderContext&Context) const override;
};
/*
Bounding box field state iterator callback function:
Called for each fragment of an (optional) field.
Determines the bounding box for the respective field fragments
using the global coordinate information.
*/
bool VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&fid, const RefPtr<CreativeArrayBase>&FragmentDataCreator)
{
using namespace Eagle::PhysicalSpace;
if (!CurrentCoords)
{
printf("bool VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&, CreativeArrayBase&): NO COORDINATES!\n" );
return false;
}
if (RefPtr<BoundingBox> BBox = getFragmentBBox(fid, FragmentDataCreator, *CurrentCoords) )
{
double R = BBox->getRadius();
if (BBoxes.size()<1)
{
MinBBoxRadius = MaxBBoxRadius = R;
}
else
{
if (R<MinBBoxRadius) MinBBoxRadius = R;
if (R>MaxBBoxRadius) MaxBBoxRadius = R;
}
BBoxes.push_back( PerFragmentInfo(BBox,
fid,
FragmentDataCreator)
);
assert( FieldBBox );
FieldBBox->insert( *BBox );
}
return true;
}
/*
Update function: evaluates the current parameter settings
and determines the bounding box information for the entire
representation, plus the field fragments if a field is
specified.
*/
bool VFragmentBoxes::update(VRequest&Context, double precision)
{
struct DataExtractor : LevelIterator
{
int FieldInstancesFound;
RefPtr<FieldState> S;
string Fieldname;
DataExtractor()
: FieldInstancesFound(0)
{}
bool apply(const Info<Skeleton>&iS,
int Level,
const RefPtr<Fiber::Grid>&GridWithCoarsetRefinementLevel,
const RefPtr<ValuePool>&Context) override
{
RefPtr<Fiber::Representation> CartesianLevelRep = iS.getCartesianRepresentation();
// assert( CartesianLevelRep );
if(!CartesianLevelRep)
{
cout << "VFragmentBoxes::DataExtractor::apply() No CartesianLevelRep found!! Skipping fragment!" << endl;
return true;
}
RefPtr<Field> Coords = CartesianLevelRep->Positions();
S->CurrentCoords = Coords;
if (RefPtr<Field> DataField = (*CartesianLevelRep)(Fieldname) )
{
FieldInstancesFound ++;
// printf("LEVEL %d\n", Level);
// CartesianLevelRep.speak("CartesianLevelRep");
DataField->iterate( *S );
}
return true;
}
}
DE;
DE.S = myState(Context);
DE.S->clear();
DE.Fieldname = getFieldname(Context);
IterateLevels(DE, Context);
if (DE.S->FieldBBox)
DE.S->FieldBBox->updateBall();
setBoundingBall(Context, DE.S->FieldBBox);
// printf(" ConnectionAge(): %d inFontScale->ValueAge(Context) %d\n",
// int(ConnectionAge().time_value()),
// int(inFontScale->ValueAge(Context).time_value()));
if (ConnectionAge().isYoungerThan( inFontScale->ValueAge(Context) ) )
{
double R = DE.S->FieldBBox->getRadius();
inFontScale.setProperty("max", R);
}
Options opt;
inOptions << Context >> opt;
if (opt("autoscale"))
{
double ProposedFontScale = DE.S->MinBBoxRadius*0.1;
inFontScale << Context <<= ProposedFontScale;
}
if (DE.FieldInstancesFound)
{
"Showing " + String( int(DE.S->BBoxes.size() ) ) + " fragment boxes for "
+ String( DE.FieldInstancesFound ) + " field instances. "
"Bounding box radii vary from " + String(DE.S->MinBBoxRadius) +
" to " + String(DE.S->MaxBBoxRadius) + " ."
);
}
else
{
return setStatusError( Context, "No instances of the given field \"" + DE.Fieldname + "\" found.");
}
}
/**
The OpenGL render routine.
Retrieves the field state information, draws the
global bounding box of the coordinate field,
plus local bounding boxes for all fragments of the
specified fields.
*/
bool VFragmentBoxes::renderGL(VGLRenderContext&Context) const
{
RefPtr<FieldState> myState = getState(Context);
if (!myState)
return false;
RefPtr<BoundingBox> MyBBox = myState->FieldBBox;
Eagle::tvector3 TranslationVector;
auto T = getCoordinateTranslation(Context, TranslationVector);
using namespace Eagle::PhysicalSpace;
Options opt;
inOptions << Context >> opt;
double width = 20;
Thickness << Context >> width;
if (width<=0.0)
width = 1.0;
glLineWidth(width/10.0);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glPointSize(width/10.0);
glDisable(GL_LIGHTING);
glEnable( GL_DEPTH_TEST );
#if 0
glColor3f( 0.6, 0.7, 0.9);
if (MyBBox && !MyBBox->empty() )
glDraw( *MyBBox );
#endif
glDisable( GL_BLEND );
rgba_float_t LoadedColor(0.6, 0.7, 0.9, 1.0);
inColor << Context >> LoadedColor;
rgba_float_t UnloadedColor(0.3, 0.3, 0.3, 1.0);
inUnloadedColor << Context >> UnloadedColor;
rgba_float_t FontColor(0.9, 0.9, 0.9, 1.0);
inFontColor << Context >> FontColor;
RefPtr<GLFontManager::Font>
MyFont = Context.getFont();
if( MyFont) MyFont->setSize(1);
glMatrixMode(GL_MODELVIEW);
glEnable( GL_NORMALIZE );
double FontScale = 0.5;
inFontScale << Context >> FontScale;
for(unsigned i=0; i<myState->BBoxes.size(); i++)
{
if (!myState->BBoxes[ i ].BBox )
continue;
BoundingBox&CurrentBBox = *myState->BBoxes[ i ].BBox;
if (myState->BBoxes[i].DataPtr &&
myState->BBoxes[i].DataPtr->hasData() )
{
glColor( LoadedColor );
}
else
glColor( UnloadedColor );
glDrawBox( CurrentBBox.mincoord() - TranslationVector,
CurrentBBox.maxcoord() - TranslationVector );
if (opt("showtext") && FontScale>0.0 && MyFont && myState->BBoxes[i].fragID)
{
glColor( FontColor );
glPushMatrix();
glTranslate( CurrentBBox.center() - TranslationVector );
glScaled(FontScale, FontScale, FontScale );
MyFont->render( myState->BBoxes[i].fragID->Name().c_str() );
glPopMatrix();
}
}
return true;
}
using namespace Panthalassa;
MyFragmentBoxesCreator(
Category("Display") /
VIdentifier("FragmentBoxes"),
} // namespace
_Expr< _ValFunClos< _ValArray, _Tp >, _Tp > apply(_Tp __func(_Tp)) const
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
ostream cout
constexpr void clear() noexcept
point_t & center()
const point_t & mincoord() const
const point_t & maxcoord() const
bool setProperty(const string &theName, const Type &theValue) const
Base class for objects rendering fields on a fiber bundle.
Definition VFieldRenderObject.hpp:23
string String(const T &Val)
FlagList Options
Given a fragmented field of curvilinear coordinates, (3D array of coordinates), build a uniform Grid ...
Definition FAQ.dox:2
Wizt::VCreatorProperty< Wizt::VCreatorProperties::CATEGORY > Category
note: cannot derive from FloatingSkeletonRenderer as long as independent base class TriangleRenderer ...
void glDrawBox(const Eagle::PhysicalSpace::point &Min, const Eagle::PhysicalSpace::point &Max)
void glDraw(const Eagle::BoundingBox &BB)
DEFAULT_OBJECT
Definition Lytica.hpp:7
Definition GridInspector.hpp:13
Generic template namespace class for results of find() functions throughout the Bundle.
Definition Info.hpp:17
bool setStatusInfo(const RefPtr< ValuePool > &Context, const string &what) const