//
// Inventor 2.0 bug fixes that affect correctness of programs that work with
// Nodekits and Hidden Children.
//
// The code in this file fixes problems in the following routines:
// SoPath::getLength()
// SoPickedPoint::getMatrix()
//
// To get the fixes, compile this file into a .o and then link
// the .o before -lInventor_s. The linker may give a warning.
// This is normal and expected.
//
// SoPath::getLength() bug:
// SoPath::getLength and SoPath::getTail can return the wrong answer if the
// path contains hidden children. This happens if nodes are appended
// between subsequent calls to getLength or getTail. The returned value can
// be too large or too far down the path. This error should never cause a
// core dump because in the worst case returned length will be the full
// path length and the returned tail will be the tail of the full path.
// Note that only getLength() needs to be fixed. getTail() will be fixed
// automatically, since its error occurs only because it gets the wrong
// answer from getLength.
//
// SoPickedPoint::getMatrix bug:
// SoPickedPoint::getMatrix does a check to see if the given node is the
// tail of the picked path. If it is the tail, it applies an
// SoGetMatrixAction to the entire path. If not, it builds a path from the
// head down to the given node.
//
// The method should cast the path to an SoFullPath when looking at the
// tail, otherwise if there is a nodekit along the path it will be
// incorrectly applying the action to the full path.
//
#include
#include
#include
#include
int
SoPath::getLength() const
{
// Cast const away...
SoPath *This = (SoPath *)this;
// If we aren't sure how many are public, figure it out:
if (numPublic == -1) {
int lastPublicIndex = 0;
if (minNumPublic > 1)
lastPublicIndex = minNumPublic - 1;
// Last test is for the second to last node.
// If it passes, then lastPublicIndex will be incremented to be the
// final node, which we don't need to test.
for ( ; lastPublicIndex < (getFullLength() - 1) ; lastPublicIndex++) {
// Children of this node will be private, so stop.
if ( ! nodes[lastPublicIndex]->isOfType(SoGroup::getClassTypeId()))
break;
}
This->numPublic = This->minNumPublic = lastPublicIndex + 1;
}
return numPublic;
}
void
SoPickedPoint::getMatrix(SoGetMatrixAction *gma, const SoNode *node) const
{
SoPath *xfPath;
// Construct a path from the root down to this node. Use the given
// path if it's the same
if (node == NULL || node == ((SoFullPath *)path)->getTail())
xfPath = path;
else {
int index = getNodeIndex(node);
xfPath = path->copy(0, index + 1);
xfPath->ref();
}
gma->apply(xfPath);
if (xfPath != path)
xfPath->unref();
}
http://www.sgi.com/tech/Inventor/workarounds/HiddenChildren.C
(possibly inaccurate URL)
01/1995