/*************************************************************************** * Copyright (c) 2007 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include #endif #include #include #include #include #include #include #include #include #include #include #include #include "SoFCBoundingBox.h" using namespace Gui; SO_NODE_SOURCE(SoFCBoundingBox); // vertices used to create a box static const int32_t bBoxVerts[8][3] = { {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1} }; // indexes used to create the edges static const int32_t bBoxEdges[36] = { 0,1,-1, 1,2,-1, 2,3,-1, 3,0,-1, 4,5,-1, 5,6,-1, 6,7,-1, 7,4,-1, 0,4,-1, 1,5,-1, 2,6,-1, 3,7,-1 }; void SoFCBoundingBox::initClass () { SO_NODE_INIT_CLASS(SoFCBoundingBox, SoShape, "Shape"); } SoFCBoundingBox::SoFCBoundingBox () { SO_NODE_CONSTRUCTOR(SoFCBoundingBox); SO_NODE_ADD_FIELD(minBounds, (-1.0, -1.0, -1.0)); SO_NODE_ADD_FIELD(maxBounds, ( 1.0, 1.0, 1.0)); SO_NODE_ADD_FIELD(coordsOn, (true)); SO_NODE_ADD_FIELD(dimensionsOn, (true)); root = new SoSeparator(); SoSeparator *bboxSep = new SoSeparator(); bboxCoords = new SoCoordinate3(); bboxCoords->point.setNum(8); bboxSep->addChild(bboxCoords); root->addChild(bboxSep); // the lines of the box bboxLines = new SoIndexedLineSet(); bboxLines->coordIndex.setNum(36); bboxLines->coordIndex.setValues(0, 36, bBoxEdges); bboxSep->addChild(bboxLines); // create the text nodes, including a transform for each vertice offset textSep = new SoSeparator(); for (int i = 0; i < 8; i++) { SoSeparator *temp = new SoSeparator(); SoTransform *trans = new SoTransform(); temp->addChild(trans); SoText2* text = new SoText2(); text->justification.setValue(SoText2::CENTER); temp->addChild(text); textSep->addChild(temp); } // create the text nodes, including a transform for each dimension dimSep = new SoSeparator(); for (int i = 0; i < 3; i++) { SoSeparator *temp = new SoSeparator(); SoTransform *trans = new SoTransform(); temp->addChild(trans); SoText2* text = new SoText2(); text->justification.setValue(SoText2::CENTER); temp->addChild(text); dimSep->addChild(temp); } root->addChild(textSep); root->addChild(dimSep); root->ref(); } SoFCBoundingBox::~SoFCBoundingBox () { root->unref(); } void SoFCBoundingBox::GLRender (SoGLRenderAction *action) { SbVec3f corner[2], ctr, *vptr; SbBool coord, dimension; // grab the current state //SoState *state = action->getState(); if (!shouldGLRender(action)) return; // get the latest values from the fields corner[0] = minBounds.getValue(); corner[1] = maxBounds.getValue(); coord = coordsOn.getValue(); dimension = dimensionsOn.getValue(); // set the coordinates for the LineSet to point to vptr = bboxCoords->point.startEditing(); for (int i = 0; i < 8; i++) { for (int j = 0; j < 3; j++) { vptr[i][j] = corner[bBoxVerts[i][j]][j]; } } // if coord is true then set the text nodes if (coord) { ctr = (corner[1] - corner[0]) / 2.0f; for (int i = 0; i < 8; i++) { // create the string for the text std::stringstream str; str.precision(2); str.setf(std::ios::fixed | std::ios::showpoint); str << "(" << vptr[i][0] << "," << vptr[i][1] << "," << vptr[i][2] << ")"; SoSeparator *sep = (SoSeparator *)textSep->getChild(i); SoTransform *trans = (SoTransform *)sep->getChild(0); trans->translation.setValue(vptr[i].getValue()); SoText2* t = (SoText2 *)sep->getChild(1); t->string.setValue(str.str().c_str()); } textSep->ref(); if (root->findChild(textSep) < 0) root->addChild(textSep); } else { if (root->findChild(textSep) >= 0) root->removeChild(textSep); } // if dimension is true then set the text nodes if (dimension) { ctr = (corner[1] - corner[0]) / 2.0f; for (int i = 0; i < 3; i++) { // create the string for the text std::stringstream str; str.precision(2); str.setf(std::ios::fixed | std::ios::showpoint); str << (2.0f * ctr[i]); SoSeparator *sep = (SoSeparator *)dimSep->getChild(i); SoTransform *trans = (SoTransform *)sep->getChild(0); SbVec3f point = corner[0]; point[i] += ctr[i]; trans->translation.setValue(point.getValue()); SoText2* t = (SoText2 *)sep->getChild(1); t->string.setValue(str.str().c_str()); } dimSep->ref(); if (root->findChild(dimSep) < 0) root->addChild(dimSep); } else { if (root->findChild(dimSep) >= 0) root->removeChild(dimSep); } bboxCoords->point.finishEditing(); // Avoid shading SoState * state = action->getState(); state->push(); SoLazyElement::setLightModel(state, SoLazyElement::BASE_COLOR); root->GLRender(action); state->pop(); } void SoFCBoundingBox::generatePrimitives (SoAction *action) { } void SoFCBoundingBox::computeBBox (SoAction *action, SbBox3f &box, SbVec3f ¢er) { center = (minBounds.getValue() + maxBounds.getValue()) / 2.0f; box.setBounds(minBounds.getValue(), maxBounds.getValue()); } void SoFCBoundingBox::finish() { atexit_cleanup(); } // --------------------------------------------------------------- SO_NODE_SOURCE(SoSkipBoundingGroup); /*! Constructor. */ SoSkipBoundingGroup::SoSkipBoundingGroup() { SO_NODE_CONSTRUCTOR(SoSkipBoundingGroup); SO_NODE_ADD_FIELD(mode, (INCLUDE_BBOX)); SO_NODE_DEFINE_ENUM_VALUE(Modes, INCLUDE_BBOX); SO_NODE_DEFINE_ENUM_VALUE(Modes, EXCLUDE_BBOX); SO_NODE_SET_SF_ENUM_TYPE (mode, Modes); } /*! Destructor. */ SoSkipBoundingGroup::~SoSkipBoundingGroup() { } void SoSkipBoundingGroup::initClass(void) { SO_NODE_INIT_CLASS(SoSkipBoundingGroup,SoGroup,"Group"); } void SoSkipBoundingGroup::finish() { atexit_cleanup(); } void SoSkipBoundingGroup::getBoundingBox(SoGetBoundingBoxAction *action) { if (mode.getValue() == INCLUDE_BBOX) inherited::getBoundingBox(action); }