/*===========================================================================*\ * * * OpenFlipper * * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * * www.openflipper.org * * * *---------------------------------------------------------------------------* * This file is part of OpenFlipper. * * * * OpenFlipper is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenFlipper 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenFlipper. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Author$ * * $Date$ * * * \*===========================================================================*/ //============================================================================= // // CLASS CoordsysNode - IMPLEMENTATION // //============================================================================= //== INCLUDES ================================================================= #include "CoordsysNode.hh" #include #include #include #include //== NAMESPACES =============================================================== namespace ACG { namespace SceneGraph { //== IMPLEMENTATION ========================================================== CoordsysNode::CoordsysNode(BaseNode* _parent, std::string _name, CoordsysMode _mode, ProjectionMode _projectionMode) : BaseNode(_parent, _name), mode_(_mode), projectionMode_(_projectionMode) { const double bodyRadius = 0.004; const double topRadius = 0.01; const int slices = 10; const int stacks = 10; sphere_ = new ACG::GLSphere(slices,stacks); cylinder_ = new ACG::GLCylinder(slices, stacks, bodyRadius,false,false); cone_ = new ACG::GLCone(slices, stacks, 0, topRadius , false,true); disk_ = new ACG::GLDisk(slices, 10, 0.0f, bodyRadius); } CoordsysNode::~CoordsysNode() { if (sphere_) delete sphere_; if (cylinder_) delete cylinder_; if (cone_) delete cone_; if (disk_) delete disk_; } void CoordsysNode:: boundingBox(Vec3d& /*_bbMin*/, Vec3d& /*_bbMax*/) { //_bbMin.minimize( Vect3f ) } //---------------------------------------------------------------------------- DrawModes::DrawMode CoordsysNode:: availableDrawModes() const { return ( DrawModes::POINTS | DrawModes::POINTS_SHADED | DrawModes::POINTS_COLORED ); } //---------------------------------------------------------------------------- void CoordsysNode:: drawCoordsys( GLState& _state) { const double arrowLength = 0.03; const double bodyLength = 0.06; const double sphereRadius = 0.01; ACG::Vec4f matCol(0.5f, 0.5f, 0.5f, 1.0f); // Origin glColor4f(0.5, 0.5, 0.5 , 1.0); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (matCol * 0.5f).data()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matCol.data()); sphere_->draw(_state,sphereRadius); // X-Axis glColor4f(1.0, 0.0, 0.0, 1.0); matCol[0] = 1.0f; matCol[1] = 0.0f; matCol[2] = 0.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (matCol * 0.5f).data()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matCol.data()); _state.push_modelview_matrix (); _state.rotate (-90, 0, 1, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); // Y-Axis glColor4f(0.0, 1.0, 0.0, 1.0); matCol[0] = 0.0f; matCol[1] = 1.0f; matCol[2] = 0.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (matCol * 0.2f).data()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matCol.data()); _state.push_modelview_matrix (); _state.rotate (90, 1, 0, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); // Z-Axis glColor4f(0.0, 0.0, 1.0, 1.0); matCol[0] = 0.0f; matCol[1] = 0.0f; matCol[2] = 1.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (matCol * 0.5f).data()); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matCol.data()); _state.push_modelview_matrix (); _state.rotate (180, 0, 1, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); } void CoordsysNode::drawCoordsys(IRenderer* _renderer, RenderObject* _baseRO) { // save model view matrix GLMatrixf mModelView = _baseRO->modelview; const double arrowLength = 0.03; const double bodyLength = 0.06; const double sphereRadius = 0.01; // Origin _baseRO->debugName = "coordsys.sphere"; _baseRO->emissive = Vec3f(1.0f, 1.0f, 1.0f); sphere_->addToRenderer(_renderer, _baseRO, sphereRadius); // X-Axis _baseRO->debugName = "coordsys.x.axis"; _baseRO->emissive = Vec3f(1.0f, 0.0f, 0.0f); _baseRO->modelview = mModelView; _baseRO->modelview.rotate (-90, 0, 1, 0); _baseRO->modelview.translate ( 0, 0, -bodyLength ); cylinder_->addToRenderer(_renderer, _baseRO, bodyLength); _baseRO->debugName = "coordsys.x.head"; _baseRO->modelview.translate ( 0, 0, -arrowLength ); cone_->addToRenderer(_renderer, _baseRO, arrowLength); // Y-Axis _baseRO->debugName = "coordsys.y.axis"; _baseRO->emissive = Vec3f(0.0f, 1.0f, 0.0f); _baseRO->modelview = mModelView; _baseRO->modelview.rotate (90, 1, 0, 0); _baseRO->modelview.translate ( 0, 0, -bodyLength ); cylinder_->addToRenderer(_renderer, _baseRO, bodyLength); _baseRO->debugName = "coordsys.y.head"; _baseRO->modelview.translate ( 0, 0, -arrowLength ); cone_->addToRenderer(_renderer, _baseRO, arrowLength); // Z-Axis _baseRO->debugName = "coordsys.z.axis"; _baseRO->emissive = Vec3f(0.0f, 0.0f, 1.0f); _baseRO->modelview = mModelView; _baseRO->modelview.rotate (180, 0, 1, 0); _baseRO->modelview.translate ( 0, 0, -bodyLength ); cylinder_->addToRenderer(_renderer, _baseRO, bodyLength); _baseRO->debugName = "coordsys.z.head"; _baseRO->modelview.translate ( 0, 0, -arrowLength ); cone_->addToRenderer(_renderer, _baseRO, arrowLength); } //============================================================================ void CoordsysNode::drawCoordsysPick( GLState& _state) { const double arrowLength = 0.03; const double bodyLength = 0.06; const double sphereRadius = 0.01; // Origin _state.pick_set_name (1); sphere_->draw(_state,sphereRadius); // X-Axis _state.pick_set_name (2); _state.push_modelview_matrix (); _state.rotate (-90, 0, 1, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); // Y-Axis _state.pick_set_name (3); _state.push_modelview_matrix (); _state.rotate (90, 1, 0, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); // Z-Axis _state.pick_set_name (4); _state.push_modelview_matrix (); _state.rotate (180, 0, 1, 0); _state.translate ( 0, 0, -bodyLength ); cylinder_->draw(_state,bodyLength); _state.translate ( 0, 0, -arrowLength ); cone_->draw(_state,arrowLength); _state.pop_modelview_matrix (); } //============================================================================ void CoordsysNode:: draw(GLState& _state , const DrawModes::DrawMode& /*_drawMode*/) { GLenum prev_depth = _state.depthFunc(); GLboolean colorMask[4]; glGetBooleanv (GL_COLOR_WRITEMASK, colorMask); // Push Modelview-Matrix _state.push_modelview_matrix(); Vec4f lastBaseColor = _state.base_color(); glPushAttrib( GL_LIGHTING_BIT ); // STACK_ATTRIBUTES <- LIGHTING_ATTRIBUTE ACG::GLState::enable(GL_LIGHTING); glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ; ACG::GLState::enable(GL_COLOR_MATERIAL); ACG::GLState::shadeModel(GL_SMOOTH); GLfloat zeroVec[4] = {0.0f}; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zeroVec); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zeroVec); // Init state - changes when mode_ != POSITION Vec3d pos3D(0.0,0.0,0.0); if ( mode_ == SCREENPOS ) { int left, bottom, width, height; double aspect = _state.aspect(); _state.get_viewport(left, bottom, width, height); // Projection reset _state.push_projection_matrix(); _state.reset_projection(); if (projectionMode_ == PERSPECTIVE_PROJECTION) _state.perspective(45.0, aspect, 0.8, 20.0); else _state.ortho(-0.65*aspect, 0.65*aspect, -0.65, 0.65, 0.8, 20.0); _state.push_modelview_matrix(); _state.reset_modelview(); float rel_size = 50.0; float projdist = sqrt ( (width*height) / rel_size ); float posx = left + width - projdist ; float posy = bottom + height - projdist ; // get our desired coordsys position in scene coordinates pos3D = _state.unproject (Vec3d (posx, posy, 0.5)); _state.pop_modelview_matrix(); // reset scene translation // we want only the scene rotation to rotate the coordsys GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; _state.set_modelview (modelview); _state.translate (pos3D[0], pos3D[1], pos3D[2], MULT_FROM_LEFT); // clear the depth buffer behind the coordsys ACG::GLState::depthRange (1.0, 1.0); ACG::GLState::depthFunc (GL_ALWAYS); drawCoordsys(_state); ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (GL_LESS); // draw coordsys drawCoordsys(_state); // set depth buffer to 0 so that nothing can paint over cordsys ACG::GLState::depthRange (0.0, 0.0); ACG::GLState::depthFunc (GL_ALWAYS); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_state); ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (prev_depth); glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]); // Projection reload _state.pop_projection_matrix(); } else if (mode_ == POSITION) { /* mode_ == POSITION */ GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; _state.set_modelview (modelview); // clear depth buffer in coordsys region ACG::GLState::depthRange (1.0, 1.0); ACG::GLState::depthFunc (GL_ALWAYS); // Koordinatensystem zeichnen drawCoordsys(_state); // draw coordsys in normal mode ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (GL_LESS); // Koordinatensystem zeichnen drawCoordsys(_state); // set depth buffer to 0 so that nothing can paint over cordsys ACG::GLState::depthRange (0.0, 0.0); ACG::GLState::depthFunc (GL_ALWAYS); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_state); // reset to default ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (prev_depth); glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]); } glPopAttrib(); glColor4fv(lastBaseColor.data()); // Reload old configuration _state.pop_modelview_matrix(); } void CoordsysNode::getRenderObjects( IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat ) { // Init state - changes when mode_ != POSITION Vec3d pos3D(0.0,0.0,0.0); _state.push_modelview_matrix(); // init base renderobject RenderObject ro; ro.initFromState(&_state); ro.setMaterial(_mat); ro.depthTest = true; ro.depthWrite = true; if ( mode_ == SCREENPOS ) { int left, bottom, width, height; double aspect = _state.aspect(); _state.get_viewport(left, bottom, width, height); // Projection reset _state.push_projection_matrix(); _state.reset_projection(); if (projectionMode_ == PERSPECTIVE_PROJECTION) _state.perspective(45.0, aspect, 0.8, 20.0); else _state.ortho(-0.65*aspect, 0.65*aspect, -0.65, 0.65, 0.8, 20.0); _state.push_modelview_matrix(); _state.reset_modelview(); float rel_size = 50.0; float projdist = sqrt ( (width*height) / rel_size ); float posx = left + width - projdist ; float posy = bottom + height - projdist ; // get our desired coordsys position in scene coordinates pos3D = _state.unproject (Vec3d (posx, posy, 0.5)); _state.pop_modelview_matrix(); // reset scene translation // we want only the scene rotation to rotate the coordsys GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; _state.set_modelview (modelview); _state.translate (pos3D[0], pos3D[1], pos3D[2], MULT_FROM_LEFT); // grab new transforms ro.proj = _state.projection(); ro.modelview = _state.modelview(); // colored by emission only ro.shaderDesc.shadeMode = SG_SHADE_UNLIT; ro.shaderDesc.clearTextures(); ro.shaderDesc.vertexColors = false; // clear the depth buffer behind the coordsys ro.priority = -4; ro.depthRange = Vec2f(1.0f, 1.0f); ro.depthFunc = GL_ALWAYS; drawCoordsys(_renderer, &ro); // regrab of transforms needed, drawCoordsys overwrites this ro.modelview = _state.modelview(); ro.priority = -3; ro.depthRange = Vec2f(0.0f, 1.0f); ro.depthFunc = GL_LESS; // draw coordsys drawCoordsys(_renderer, &ro); // set depth buffer to 0 so that nothing can paint over cordsys ro.modelview = _state.modelview(); ro.priority = -2; ro.depthRange = Vec2f(0.0, 0.0); ro.depthFunc = GL_ALWAYS; ro.glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_renderer, &ro); // Projection reload _state.pop_projection_matrix(); } else if (mode_ == POSITION) { /* mode_ == POSITION */ GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; _state.set_modelview (modelview); // clear depth buffer in coordsys region ACG::GLState::depthRange (1.0, 1.0); ACG::GLState::depthFunc (GL_ALWAYS); // Koordinatensystem zeichnen drawCoordsys(_renderer, &ro); // draw coordsys in normal mode ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (GL_LESS); // Koordinatensystem zeichnen drawCoordsys(_renderer, &ro); // set depth buffer to 0 so that nothing can paint over cordsys ACG::GLState::depthRange (0.0, 0.0); ACG::GLState::depthFunc (GL_ALWAYS); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_renderer, &ro); } _state.pop_modelview_matrix(); } void CoordsysNode:: setMode(const CoordsysMode _mode) { mode_ = _mode; } void CoordsysNode:: setProjectionMode(const ProjectionMode _mode) { projectionMode_ = _mode; } void CoordsysNode:: setPosition(const Vec3f& _pos) { pos3f_ = _pos; } CoordsysNode::CoordsysMode CoordsysNode:: getMode() const { return mode_; } CoordsysNode::ProjectionMode CoordsysNode:: getProjectionMode() const { return projectionMode_; } void CoordsysNode::pick(GLState& _state, PickTarget _target) { GLenum prev_depth = _state.depthFunc(); if (_target == PICK_ANYTHING) { GLdouble mat[16]; // Push Modelview-Matrix _state.push_modelview_matrix(); _state.pick_set_maximum (5); _state.pick_set_name (0); // Init state - changes when mode_ != POSITION Vec3d pos3D(0.0,0.0,0.0); if ( mode_ == SCREENPOS ) { int left, bottom, width, height; double aspect = _state.aspect(); _state.get_viewport(left, bottom, width, height); // Projection reset _state.push_projection_matrix(); _state.reset_projection(); if (projectionMode_ == PERSPECTIVE_PROJECTION) _state.perspective(45.0, aspect, 0.8, 20.0); else _state.ortho(-0.65*aspect, 0.65*aspect, -0.65, 0.65, 0.8, 20.0); _state.push_modelview_matrix(); _state.reset_modelview(); float rel_size = 50.0; float projdist = sqrt ( (width*height) / rel_size ); float posx = left + width - projdist ; float posy = bottom + height - projdist ; // get our desired coordsys position in scene coordinates pos3D = _state.unproject (Vec3d (posx, posy, 0.5)); _state.pop_modelview_matrix(); // reset scene translation GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; _state.set_modelview (modelview); _state.translate (pos3D[0], pos3D[1], pos3D[2], MULT_FROM_LEFT); // We don't have access to the pick matrix used during selection buffer picking // so we can't draw our pick area circle in this case if (_state.color_picking ()) { // clear depth buffer behind coordsys node clearPickArea(_state, true, 1.0); // Koordinatensystem zeichnen drawCoordsysPick(_state); // set depth buffer to 0.0 so that nothing can paint above clearPickArea(_state, false, 0.0); } else { // clear depth buffer in coordsys region ACG::GLState::depthRange (1.0, 1.0); ACG::GLState::depthFunc (GL_ALWAYS); // Koordinatensystem zeichnen drawCoordsys(_state); // draw coordsys in normal mode ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (GL_LESS); // Koordinatensystem zeichnen drawCoordsys(_state); // set depth buffer to 0 so tah nothing can paint over cordsys ACG::GLState::depthRange (0.0, 0.0); ACG::GLState::depthFunc (GL_ALWAYS); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_state); // reset to default ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (prev_depth); glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } // Projection reload _state.pop_projection_matrix(); } else if (mode_ == POSITION) { /* mode_ == POSITION */ // The selection buffer picking method might have set a // pick matrix that has been multiplied with the projection matrix. // This is the only way to get the gl pick matrix again glMatrixMode(GL_PROJECTION); glPushMatrix (); glMultMatrixd( _state.inverse_projection().get_raw_data()); glGetDoublev(GL_PROJECTION_MATRIX, mat); glPopMatrix (); GLMatrixd pickMat (mat); glMatrixMode(GL_MODELVIEW); GLMatrixd modelview = _state.modelview(); modelview(0,3) = 0.0; modelview(1,3) = 0.0; modelview(2,3) = 0.0; // We don't have access to the pick matrix used during selection buffer picking // so we can't draw our pick area circle in this case if (_state.color_picking ()) { // clear depth buffer behind coordsys node clearPickArea(_state, true, 1.0); // Koordinatensystem zeichnen drawCoordsysPick(_state); // set depth buffer to 0.0 so that nothing can paint above clearPickArea(_state, false, 0.0); } else { // clear depth buffer in coordsys region ACG::GLState::depthRange (1.0, 1.0); ACG::GLState::depthFunc (GL_ALWAYS); // Koordinatensystem zeichnen drawCoordsys(_state); // draw coordsys in normal mode ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (GL_LESS); // Koordinatensystem zeichnen drawCoordsys(_state); // set depth buffer to 0 so tah nothing can paint over cordsys ACG::GLState::depthRange (0.0, 0.0); ACG::GLState::depthFunc (GL_ALWAYS); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); // Koordinatensystem zeichnen drawCoordsys(_state); // reset to default ACG::GLState::depthRange (0.0, 1.0); ACG::GLState::depthFunc (prev_depth); glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } // Reload old configuration _state.pop_modelview_matrix(); } } //---------------------------------------------------------------------------- void CoordsysNode::clearPickArea(GLState& _state, bool _draw, GLfloat _depth) { GLenum prev_depth = _state.depthFunc(); std::vector points; Vec2f center; float radius; int left, bottom, width, height; _state.get_viewport(left, bottom, width, height); GLboolean colorMask[4]; glGetBooleanv (GL_COLOR_WRITEMASK, colorMask); // respect sphere radius Vec3d proj = _state.project (Vec3d (-0.01, -0.01, -0.01)); points.push_back (Vec2f (proj[0], proj[1])); proj = _state.project (Vec3d (0.1, 0.0, 0.0)); points.push_back (Vec2f (proj[0], proj[1])); proj = _state.project (Vec3d (0.0, 0.1, 0.0)); points.push_back (Vec2f (proj[0], proj[1])); proj = _state.project (Vec3d (0.0, 0.0, 0.1)); points.push_back (Vec2f (proj[0], proj[1])); // get bounding circle of projected 4 points of the coord node boundingCircle(points, center, radius); _state.push_projection_matrix(); _state.reset_projection(); _state.ortho (left, left + width, bottom, bottom + height, 0.0, 1.0); _state.push_modelview_matrix(); _state.reset_modelview(); ACG::GLState::depthFunc (GL_ALWAYS); ACG::GLState::depthRange (_depth, _depth); _state.translate (center[0], center[1], -0.5); if (_draw) _state.pick_set_name (0); else glColorMask(false, false, false, false); // 10% more to ensure everything is in disk_->setInnerRadius(0.0f); disk_->setOuterRadius(radius * 1.1f); disk_->draw(_state); ACG::GLState::depthFunc (prev_depth); _state.pop_modelview_matrix(); _state.pop_projection_matrix(); ACG::GLState::depthRange (0.0, 1.0); if (!_draw) glColorMask (colorMask[0], colorMask[1], colorMask[2], colorMask[3]); } //---------------------------------------------------------------------------- void CoordsysNode::boundingCircle(std::vector &_in, Vec2f &_center, float &_radius) { if (_in.empty()) return; if (_in.size () < 2) { _center = _in[0]; _radius = 0.0f; return; } bool found = false; // try all circumcircles of all possible lines for (unsigned int i = 0; i < _in.size () - 1; i++) for (unsigned int j = i + 1; j < _in.size (); j++) { Vec2f cen = (_in[i] + _in[j]) * 0.5; float rad = (_in[i] - cen).length (); bool allin = true; for (unsigned int k = 0; k < _in.size (); k++) if (k != i && k != j && (_in[k] - cen).length () > rad) { allin = false; break; } if (!allin) continue; if (found) { if (rad < _radius) { _center = cen; _radius = rad; } } else { found = true; _center = cen; _radius = rad; } } if (found) return; // try all circumcircles of all possible triangles for (unsigned int i = 0; i < _in.size () - 2; i++) for (unsigned int j = i + 1; j < _in.size () - 1; j++) for (unsigned int k = j + 1; k < _in.size (); k++) { float v = ((_in[k][0]-_in[j][0])*((_in[i][0]*_in[i][0])+(_in[i][1]*_in[i][1]))) + ((_in[i][0]-_in[k][0])*((_in[j][0]*_in[j][0])+(_in[j][1]*_in[j][1]))) + ((_in[j][0]-_in[i][0])*((_in[k][0]*_in[k][0])+(_in[k][1]*_in[k][1]))); float u = ((_in[j][1]-_in[k][1])*((_in[i][0]*_in[i][0])+(_in[i][1]*_in[i][1]))) + ((_in[k][1]-_in[i][1])*((_in[j][0]*_in[j][0])+(_in[j][1]*_in[j][1]))) + ((_in[i][1]-_in[j][1])*((_in[k][0]*_in[k][0])+(_in[k][1]*_in[k][1]))); float d = (_in[i][0]*_in[j][1])+(_in[j][0]*_in[k][1])+(_in[k][0]*_in[i][1]) - (_in[i][0]*_in[k][1])-(_in[j][0]*_in[i][1])-(_in[k][0]*_in[j][1]); Vec2f cen(0.5 * (u/d), 0.5 * (v/d)); float rad = (_in[i] - cen).length (); bool allin = true; for (unsigned int l = 0; l < _in.size (); l++) if (l != i && l != j && l != k && (_in[l] - cen).length () > rad) { allin = false; break; } if (!allin) continue; if (found) { if (rad < _radius) { _center = cen; _radius = rad; } } else { found = true; _center = cen; _radius = rad; } } } //============================================================================= } // namespace SceneGraph } // namespace ACG //=============================================================================