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>
namespace
{
, public Fish<Fiber::Skeleton>
{
public:
enum { NumberOfInputFields = 1 };
struct FieldState : State, FieldFragmentIterator
{
RefPtr<Field> CurrentCoords;
RefPtr<BoundingBox> FieldBBox;
double MinBBoxRadius, MaxBBoxRadius;
struct PerFragmentInfo
{
RefPtr<BoundingBox> BBox;
RefPtr<FragmentID> fragID;
PerFragmentInfo(const RefPtr<BoundingBox>&theBBox,
const RefPtr<FragmentID> &theFragID,
: BBox(theBBox)
, fragID(theFragID)
, DataPtr(theDataPtr)
{}
};
void 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;
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 VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&fid, const RefPtr<CreativeArrayBase>&FragmentDataCreator)
{
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;
}
{
struct DataExtractor : LevelIterator
{
int FieldInstancesFound;
RefPtr<FieldState> S;
string Fieldname;
DataExtractor()
: FieldInstancesFound(0)
{}
int Level,
const RefPtr<Fiber::Grid>&GridWithCoarsetRefinementLevel,
const RefPtr<ValuePool>&
Context)
override
{
RefPtr<Fiber::Representation> CartesianLevelRep = iS.getCartesianRepresentation();
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 ++;
DataField->iterate( *S );
}
return true;
}
}
DE;
DE.S->clear();
DE.Fieldname = getFieldname(
Context);
if (DE.S->FieldBBox)
DE.S->FieldBBox->updateBall();
setBoundingBall(
Context, DE.S->FieldBBox);
if (ConnectionAge().isYoungerThan( inFontScale->ValueAge(
Context) ) )
{
double R = DE.S->FieldBBox->getRadius();
}
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.");
}
}
{
RefPtr<FieldState> myState = getState(
Context);
if (!myState)
return false;
RefPtr<BoundingBox> MyBBox = myState->FieldBBox;
Eagle::tvector3 TranslationVector;
auto T = getCoordinateTranslation(
Context, TranslationVector);
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() )
#endif
glDisable( GL_BLEND );
inColor << Context >> LoadedColor;
inUnloadedColor << Context >> UnloadedColor;
inFontColor << Context >> FontColor;
RefPtr<GLFontManager::Font>
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;
if (myState->BBoxes[i].DataPtr &&
myState->BBoxes[i].DataPtr->hasData() )
{
glColor( LoadedColor );
}
else
glColor( UnloadedColor );
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;
}
MyFragmentBoxesCreator(
VIdentifier("FragmentBoxes"),
}
_Expr< _ValFunClos< _ValArray, _Tp >, _Tp > apply(_Tp __func(_Tp)) const
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
constexpr void clear() noexcept
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)
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)
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