Example #1
0
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();
}