[vtk-developers] vtkGlyph3D & range clamping

John Platt jcplatt at lineone.net
Wed May 11 18:20:05 EDT 2005


Hi,

 

Maybe I've missed something but I seem to spend a lot of time modifying
filters to normalise the input data at the time of execution. Here's an
example of bodging the scale factor so the warp is always shown a fixed
size.

 

void vtkWarpScalarEx::Execute()

{

    vtkDataArray* inScalars =
this->GetInput()->GetPointData()->GetScalars(
this->InputScalarsSelection );

    double scaleFactor = this->ScaleFactor;

    if ( inScalars )

      {

      double maxNorm = inScalars->GetMaxNorm();

      if ( maxNorm > 0.0 )

        this->SetScaleFactor( scaleFactor/maxNorm );

      }

    vtkWarpScalar::Execute();

    this->SetScaleFactor( scaleFactor );

}

 

Mapping attribute data to the range to [0,1] doesn't always solve the
problem either, particularly when computing a scale factor for sizing
glyphs. For example, suppose there are sphere glyphs representing masses
M1 < M2 and M2 is to be displayed a fixed size. Normalising scalars
(say) to [0, 1] will leave M1 zero size. Provision for this kind of
functionality requires independent access to the attribute data limits.
Here is a solution for the mass problem using UpperClampToMaxNormOn().

 

vtkGlyph3D.h

==========

 

Replace 

 

  // Description:

  // Specify range to map scalar values into.

  vtkSetVector2Macro(Range,double);

  vtkGetVectorMacro(Range,double,2);

 

By

 

  // Description:

  // Specify the range for clamping the scalar values (or vector
magnitude if

  // ScaleByVector() is enabled). Scalars outside this range are set to
the

  // end points and then normalised to [0-1]. Glyphs for points with
scalars

  // less than or equal to Range[0] with therefore not be visible. This
range is

  // only used with ClampingOn()

  vtkSetVector2Macro(Range,double);

  vtkGetVectorMacro(Range,double,2);

 

  vtkSetMacro(LowerClampToMinNorm,int);

  vtkBooleanMacro(LowerClampToMinNorm,int);

  vtkGetMacro(LowerClampToMinNorm,int);

 

  vtkSetMacro(UpperClampToMaxNorm,int);

  vtkBooleanMacro(UpperClampToMaxNorm,int);

  vtkGetMacro(UpperClampToMaxNorm,int);

 

Insert

 

  int LowerClampToMinNorm; // Use the min norm of the attribute data as
the lower clamp

  int UpperClampToMaxNorm; // Use the max norm of the attribute data as
the upper clamp

 

 

vtkGlyph3D.cxx (Revision: 1.112)

========================

 

vtkGlyph3D::vtkGlyph3D()

 

Insert

 

  this->LowerClampToMinNorm = 0;

  this->UpperClampToMaxNorm = 0;

 

vtkGlyph3D::Execute()

 

Remove

 

  // Check input for consistency

  //

  if ( (den = this->Range[1] - this->Range[0]) == 0.0 )

    {

    den = 1.0;

    }

 

After 

 

  else

    {

    haveVectors = 0;

    }

 

Insert

 

  // Set the range for clamping the data scale factors.

  if ( this->Clamping && ( this->LowerClampToMinNorm ||
this->UpperClampToMaxNorm ) )

    {

    double* inRange = NULL;

    if ( inScalars && this->ScaleMode == VTK_SCALE_BY_SCALAR )

      {

      inRange = inScalars->GetRange();

      }

    else if ( haveVectors )

      {

      if ( this->VectorMode == VTK_USE_NORMAL )

        {

        inRange = inNormals->GetRange( -1 );

        }

      else

        {

        inRange = inVectors->GetRange( -1 );

        }

      }

    if ( inRange && LowerClampToMinNorm ) this->Range[0] = inRange[0];

    if ( inRange && UpperClampToMaxNorm ) this->Range[1] = inRange[1];

    }

 

  if ( (den = this->Range[1] - this->Range[0]) == 0.0 ) den = 1.0;

 

 

vtkGlyph3D::PrintSelf()

 

Replace 

 

  os << indent << "Range: (" << this->Range[0] << ", " << this->Range[1]
<< ")\n";

 

By

 

  os << indent << "Range: (";

  this->LowerClampToMinNorm ? os << "Min norm,"   : os << this->Range[0]
<< ",";

  this->UpperClampToMaxNorm ? os << "Max norm)\n" : os << this->Range[1]
<< ")\n";

 

If this kind of functionality is useful I will add it to bug tracker as
a feature request.

 

Where the clamping and normalisation are not combined, it would be
useful to have methods like

 

            ScaleByMinNorm()/ScaleByMaxNorm()

            SetLowerClamp( lower )/SetUpperClamp( upper )

            MapToRange( lower, upper )

 

Using MapToRange( 0, 1 ) on vtkMapper would allow scalars of any range
to be colour mapped red through blue without having to call SetRange()
with actual attribute values. This would go some way to lessening the
assumption that the data range is known in advance.

 

Thanks for your consideration.

 

John Platt.

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20050511/df2750d4/attachment.html>


More information about the vtk-developers mailing list