void Command::adjustCameraPosition() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); if (doc) { Gui::View3DInventor* view = static_cast<Gui::View3DInventor*>(doc->getActiveView()); Gui::View3DInventorViewer* viewer = view->getViewer(); SoCamera* camera = viewer->getCamera(); if (!camera || !camera->isOfType(SoOrthographicCamera::getClassTypeId())) return; // get scene bounding box SoGetBoundingBoxAction action(viewer->getViewportRegion()); action.apply(viewer->getSceneGraph()); SbBox3f box = action.getBoundingBox(); if (box.isEmpty()) return; // get cirumscribing sphere and check if camera is inside SbVec3f cam_pos = camera->position.getValue(); SbVec3f box_cnt = box.getCenter(); SbSphere bs; bs.circumscribe(box); float radius = bs.getRadius(); float distance_to_midpoint = (box_cnt-cam_pos).length(); if (radius >= distance_to_midpoint) { // Move the camera to the edge of the bounding sphere, while still // pointing at the scene. SbVec3f direction = cam_pos - box_cnt; (void) direction.normalize(); // we know this is not a null vector camera->position.setValue(box_cnt + direction * radius); // New distance to mid point distance_to_midpoint = (camera->position.getValue() - box.getCenter()).length(); camera->nearDistance = distance_to_midpoint - radius; camera->farDistance = distance_to_midpoint + radius; camera->focalDistance = distance_to_midpoint; } } }
void ViewProviderInspection::inspectCallback(void * ud, SoEventCallback * n) { Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData()); const SoEvent* ev = n->getEvent(); if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) { const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev); // Mark all incoming mouse button events as handled, especially, to deactivate the selection node n->getAction()->setHandled(); n->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { n->setHandled(); // context-menu QMenu menu; QAction* fl = menu.addAction(QObject::tr("Annotation")); fl->setCheckable(true); fl->setChecked(addflag); QAction* cl = menu.addAction(QObject::tr("Leave info mode")); QAction* id = menu.exec(QCursor::pos()); if (fl == id) { addflag = fl->isChecked(); } else if (cl == id) { // post an event to a proxy object to make sure to avoid problems // when opening a modal dialog QApplication::postEvent( new ViewProviderProxyObject(view->getGLWidget()), new QEvent(QEvent::User)); view->setEditing(false); view->getWidget()->setCursor(QCursor(Qt::ArrowCursor)); view->setRedirectToSceneGraph(false); view->setRedirectToSceneGraphEnabled(false); view->removeEventCallback(SoButtonEvent::getClassTypeId(), inspectCallback); } } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP) { const SoPickedPoint * point = n->getPickedPoint(); if (point == NULL) { Base::Console().Message("No point picked.\n"); return; } n->setHandled(); // check if we have picked one a node of the view provider we are insterested in Gui::ViewProvider* vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(point->getPath())); if (vp && vp->getTypeId().isDerivedFrom(ViewProviderInspection::getClassTypeId())) { ViewProviderInspection* that = static_cast<ViewProviderInspection*>(vp); QString info = that->inspectDistance(point); Gui::getMainWindow()->setPaneText(1,info); if (addflag) ViewProviderProxyObject::addFlag(view, info, point); else Gui::ToolTip::showText(QCursor::pos(), info); } else { // the nearest picked point was not part of the view provider SoRayPickAction action(view->getViewportRegion()); action.setPickAll(TRUE); action.setPoint(mbe->getPosition()); action.apply(view->getSceneManager()->getSceneGraph()); const SoPickedPointList& pps = action.getPickedPointList(); for (int i=0; i<pps.getLength(); ++i) { const SoPickedPoint * point = pps[i]; vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(point->getPath())); if (vp && vp->getTypeId().isDerivedFrom(ViewProviderInspection::getClassTypeId())) { ViewProviderInspection* that = static_cast<ViewProviderInspection*>(vp); QString info = that->inspectDistance(point); Gui::getMainWindow()->setPaneText(1,info); if (addflag) ViewProviderProxyObject::addFlag(view, info, point); else Gui::ToolTip::showText(QCursor::pos(), info); break; } } } } } // toggle between inspection and navigation mode else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { const SoKeyboardEvent * const ke = static_cast<const SoKeyboardEvent *>(ev); if (ke->getState() == SoButtonEvent::DOWN && ke->getKey() == SoKeyboardEvent::ESCAPE) { SbBool toggle = view->isRedirectedToSceneGraph(); view->setRedirectToSceneGraph(!toggle); n->setHandled(); } } }
void MeshFillHole::fileHoleCallback(void * ud, SoEventCallback * n) { MeshFillHole* self = reinterpret_cast<MeshFillHole*>(ud); Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData()); const SoEvent* ev = n->getEvent(); if (ev->getTypeId() == SoLocation2Event::getClassTypeId()) { n->setHandled(); SoRayPickAction rp(view->getViewportRegion()); rp.setPoint(ev->getPosition()); rp.setPickAll(true); if (self->myNumPoints == 0) rp.apply(self->myBoundariesRoot); else rp.apply(self->myBoundaryRoot); SoNode* node = self->getPickedPolygon(rp); if (node) { std::map<SoNode*, TBoundary>::iterator it = self->myPolygons.find(node); if (it != self->myPolygons.end()) { // now check which vertex of the polygon is closest to the ray unsigned long vertex_index; SbVec3f closestPoint; float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint); if (minDist < 1.0f) { if (self->myNumPoints == 0) self->myVertex->point.set1Value(0, closestPoint); else self->myVertex->point.set1Value(1, closestPoint); } } } } else if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) { n->setHandled(); const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev); if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::UP) { if (self->myNumPoints > 1) return; SoRayPickAction rp(view->getViewportRegion()); rp.setPoint(ev->getPosition()); rp.setPickAll(true); if (self->myNumPoints == 0) rp.apply(self->myBoundariesRoot); else rp.apply(self->myBoundaryRoot); SoNode* node = self->getPickedPolygon(rp); if (node) { std::map<SoNode*, TBoundary>::iterator it = self->myPolygons.find(node); if (it != self->myPolygons.end()) { // now check which vertex of the polygon is closest to the ray unsigned long vertex_index; SbVec3f closestPoint; float minDist = self->findClosestPoint(rp.getLine(), it->second, vertex_index, closestPoint); if (minDist < 1.0f) { if (self->myNumPoints == 0) { self->myBoundaryRoot->addChild(node); self->myVertex->point.set1Value(0, closestPoint); self->myNumPoints = 1; self->myVertex1 = vertex_index; } else { // myVertex2 can be equal to myVertex1 which does a full hole-filling self->myBoundaryRoot->removeChild(node); self->myVertex->point.set1Value(1, closestPoint); self->myNumPoints = 2; self->myVertex2 = vertex_index; self->myPolygon = it->second; QTimer::singleShot(300, self, SLOT(closeBridge())); } } } } } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { QMenu menu; QAction* fin = menu.addAction(MeshFillHole::tr("Finish")); QAction* act = menu.exec(QCursor::pos()); if (act == fin) { QTimer::singleShot(300, self, SLOT(finishEditing())); } } } }
void MeshSelection::selectGLCallback(void * ud, SoEventCallback * n) { // When this callback function is invoked we must leave the edit mode Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData()); MeshSelection* self = reinterpret_cast<MeshSelection*>(ud); self->stopInteractiveCallback(view); n->setHandled(); std::vector<SbVec2f> polygon = view->getGLPolygon(); if (polygon.size() < 3) return; if (polygon.front() != polygon.back()) polygon.push_back(polygon.front()); SbVec3f pnt, dir; view->getNearPlane(pnt, dir); Base::Vector3f point (pnt[0],pnt[1],pnt[2]); Base::Vector3f normal(dir[0],dir[1],dir[2]); std::list<ViewProviderMesh*> views = self->getViewProviders(); for (std::list<ViewProviderMesh*>::iterator it = views.begin(); it != views.end(); ++it) { ViewProviderMesh* vp = static_cast<ViewProviderMesh*>(*it); std::vector<unsigned long> faces; const Mesh::MeshObject& mesh = static_cast<Mesh::Feature*>((*it)->getObject())->Mesh.getValue(); const MeshCore::MeshKernel& kernel = mesh.getKernel(); // simply get all triangles under the polygon SoCamera* cam = view->getCamera(); SbViewVolume vv = cam->getViewVolume(); Gui::ViewVolumeProjection proj(vv); vp->getFacetsFromPolygon(polygon, proj, true, faces); if (self->onlyVisibleTriangles) { const SbVec2s& sz = view->getViewportRegion().getWindowSize(); short width,height; sz.getValue(width,height); std::vector<SbVec2s> pixelPoly = view->getPolygon(); SbBox2s rect; for (std::vector<SbVec2s>::iterator it = pixelPoly.begin(); it != pixelPoly.end(); ++it) { const SbVec2s& p = *it; rect.extendBy(SbVec2s(p[0],height-p[1])); } std::vector<unsigned long> rf; rf.swap(faces); std::vector<unsigned long> vf = vp->getVisibleFacetsAfterZoom (rect, view->getViewportRegion(), view->getCamera()); // get common facets of the viewport and the visible one std::sort(vf.begin(), vf.end()); std::sort(rf.begin(), rf.end()); std::back_insert_iterator<std::vector<unsigned long> > biit(faces); std::set_intersection(vf.begin(), vf.end(), rf.begin(), rf.end(), biit); } // if set filter out all triangles which do not point into user direction if (self->onlyPointToUserTriangles) { std::vector<unsigned long> screen; screen.reserve(faces.size()); MeshCore::MeshFacetIterator it_f(kernel); for (std::vector<unsigned long>::iterator it = faces.begin(); it != faces.end(); ++it) { it_f.Set(*it); if (it_f->GetNormal() * normal > 0.0f) { screen.push_back(*it); } } faces.swap(screen); } if (self->addToSelection) vp->addSelection(faces); else vp->removeSelection(faces); } view->render(); }