[Solved] Pick PlaceNode

classic Classic list List threaded Threaded
9 messages Options
Nikkitta Nikkitta
Reply | Threaded
Open this post in threaded view
|

[Solved] Pick PlaceNode

This post was updated on .
Hi,

I'm trying to implement POI adding and editing.
I use osgEarth::Annotation::PlaceNode as draw type for POI.
Currently with mouse click I can add POIs. Now I want to edit created POI by double clicking it.

My thought was to setName for PlaceNode as "POI/[id]", then use LineSegmentIntersector to get all objects under mouse, and then filter them all with condition on getName().contains("POI/"). After that I could get corresponding POI id from the name.

But the problem is - all PlaceNodes are ignored while searching intersections. Here is my code to find intersections and show all objects names:
bool MouseClickEventHandler::action_editSimplePOI(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
  {
    osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());

    osgUtil::LineSegmentIntersector::Intersections hits;
    if (view->computeIntersections(ea.getX(), ea.getY(), hits))
    {
      int objectID;
      for (std::multiset<osgUtil::LineSegmentIntersector::Intersection>::iterator it = hits.begin(); it != hits.end(); ++it)
      {
        for (osg::Node* node : it->nodePath)
        {
          QString name = QString::fromStdString(node->getName());
          qDebug() << name;
        }
      }
...

As a result I can see lots of nodes names like "osgEarth.RexTerrainEngineNode" or empty ones, but no PlaceNodes.

I've double checked that my PlaceNode getName() method returns correct name.

Is it a common behaviour of PlaceNode? How can I bypass it?
Best regards,
Nikita Petrov
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

Nikita,
Yes, this is normal behavior for PlaceNode. PlaceNode and other annotation types do not render in traditional "scene graph" space; they render as screen-space overlays and are not detectable by an intersection visitor.

I recommend using osgEarth's RTTPicker instead. The "osgearth_pick" example demonstrates it. osgEarth has a global ObjectIndex that supports object identification and picking. Instead of using setName() on your PlaceNode, you would call

osgEarth::Registry::objectIndex()->tagNode(placeNode, owner);

Where "owner" is the object that will be returned when looking up the place node in the index. (In your case, it makes sense for owner==placeNode.)

Hope this helps.
Glenn Waldron / Pelican Mapping
Nikkitta Nikkitta
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

Thanks for reply!
I'm trying to follow your instructions and use RTTPicker, but it is still not working.

For PlaceNode I set name and then:
osgEarth::Util::ObjectID objectID = osgEarth::Registry::objectIndex()->tagNode(visualNode, visualNode);
Assigned objectID looks fine, it increases with each next PlaceNode added.

To install picker I use:
_scene->getViewer()->stopThreading();
picker = new osgEarth::Util::RTTPicker();
_scene->getViewer()->getView(0)->addEventHandler(picker);
picker->addChild(_scene->getMapNode()); // getMapNode() returns _mapNode.get();
picker->setDefaultCallback(new Callbacks::PickerCallback());
_scene->getViewer()->startThreading();

My PickerCallback class:
// PickerCallback.h

namespace Callbacks
{
  //! Changes the name of a marker based on the name of the clustered nodes.
  class PickerCallback : public osgEarth::Util::RTTPicker::Callback
  {
  public:
    PickerCallback() { };

    void onHit(osgEarth::Util::ObjectID id);
    void onMiss();

    // pick whenever the mouse moves.
    bool accept(const osgGA::GUIEventAdapter& ea, const osgGA::GUIActionAdapter& aa)
    {
      return (ea.getEventType() == ea.DOUBLECLICK && ea.getButton() == ea.LEFT_MOUSE_BUTTON);
    }
  };
}

// PickerCallback.cpp
namespace Callbacks
{
  void PickerCallback::onHit(osgEarth::Util::ObjectID id)
  {
    // Check whether it's an annotation:
    osgEarth::Annotation::AnnotationNode* anno = osgEarth::Registry::objectIndex()->get<osgEarth::Annotation::AnnotationNode>(id).get();
    if (anno)
    {
      qDebug() << "AnnotationNode '" << QString::fromStdString(anno->getName()) << "' picked. Actions not implemented.";
    }

    // None of the above.. clear.
    else
    {
      qDebug() << "Unknown ObjectID " << id;
    }
  }
  void PickerCallback::onMiss()
  {
    qDebug() << "Nothing picked.";
  }
}

The thing is when I double click PlaceNodes (call Pick) - onMiss() method is triggered.

What could be the problem?
Best regards,
Nikita Petrov
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

Nikita,
The only suspicious thing I see is your use of osgEarth::Util::ObjectID; it should be osgEarth::ObjectID.
Glenn Waldron / Pelican Mapping
Nikkitta Nikkitta
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

I've made suggested corrections to ObjectID namespace.
Still not working properly :(
Best regards,
Nikita Petrov
Buks van Ellewee Buks van Ellewee
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

I am doing pretty much the same thing as Nikita (using osgEarth 2.9, osg 3.4.1) and getting the same result (only onMiss() called).  The tagNode does not seem to work.  If I add a place node annotation to the .earth file, it works fine.  Obviously I am missing something...  any help would be appreciated.

My RTTPicker installation:
      viewer_->stopThreading();
      picker_ = ref_ptr<RTTPicker>(new RTTPicker());
      picker_->setBuffer( 4 );
      viewer_->addEventHandler( picker_ );
      picker_->addChild(mapNode_);
      picker_->setDefaultCallback( new MyPickCallback() );
      viewer_->startThreading();

Adding a PlaceNode
        ref_ptr<PlaceNode> pn = new PlaceNode( this_->mapNode_,
                                               ipoint,
                                               emitter.name,
                                               *this_->styleSheet_->getStyle( "symbol" ) );
        pn->setDynamic( true );
        node->insertChild( 0, pn );
        Registry::objectIndex()->tagNode(pn, pn);

Regards, Buks
Buks van Ellewee Buks van Ellewee
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

Perhaps another clue to what I may be doing wrong...  I can successfully pick the symbol added via the .earth file until I resize my viewer window.  After that, picking the symbol also only calls onMiss().
Regards, Buks
Buks van Ellewee Buks van Ellewee
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

I found my problem.  Maybe this would also help someone else:  I had a group node (root_) on the viewer level containing the Map Node as a child.  The call to picker_->addChild(mapNode_) should rather be picker_->addChild(root_).  Not really sure why this would be the case though.
Regards, Buks
Nikkitta Nikkitta
Reply | Threaded
Open this post in threaded view
|

Re: Pick PlaceNode

Wow! You're a genius, that works for me too.
Thanks a lot!
Best regards,
Nikita Petrov