Ngl: picking atoms using backbone or licorice representations

Created on 29 Mar 2017  路  15Comments  路  Source: nglviewer/ngl

Hi, I am experimenting with a widget to add distance representations after clicking on atoms.
When the molecule is displayed in backbone or licorice, it can be very difficult to actually click on an atom, and the corresponding bond is indeed reported back by the signal mechanism.

I could use the atom proxies provided by the reported bond proxy to get the actual atom, but how can I guess which atom is the closest to the mouse pointer?
I suppose it might be possible, knowing both atoms coordinates, to compute their screen projections coordinates' and compare their respective distance to the mouse pointer's.

My questions are:

  • is this picking atom problem remediable?
  • if not, is there a built-in procedure to get atoms x-y coordinates in the viewer?

All 15 comments

As an aside, I'm really keen to have some kind of "click to add distance measure" functionality (as in #46). Can I ask how you are doing it at the moment?

Sure.
You can have a look at my prototype on https://libmol.org (research on the PDB is not functional)
To activate distance mesurement, you have to click on the [distance] button in the toolbar (top right corner) and activate the functionality.
Cursor style is set to "crosshair".
stage.signal.clicked.add(nameOfTheMethod)
the code is a mess but can be accessed at https://github.com/ppillot/libmol/blob/master/src/store/index.js between lines 119-209

The method receives a response object after a click. If an atom is clicked, it is added to an accumulator. After a second atom has been clicked, the distance label is displayed. I keep a list of all the measurements made so that they could be removed.
A measure is rejected if the second click doesn't happen on an atom. I need to check for a second click on the same atom to discard the measurement too.
I am also trying to implement a way to give users feedback about a measure being started (highlighting the pointed and hovered atoms).

Cool, looks nice!

Nice.

In answer to your second question, @arose probably knows a neater way, but I've been using this to try and get my head around how atomic coords map to x,y screen coords:

  var rg = stage.viewer.rotationGroup;
  var tg = stage.viewer.translationGroup;

  function handler( o ){

    if( o.atom === undefined ){ return; }

    var v = o.position.clone();

    v.add( tg.position );
    v.applyMatrix4( rg.matrix );

    v.project( stage.viewer.camera );

    var canvasX = ( v.x + 1 ) * stage.viewer.width / 2;
    var canvasY = ( v.y + 1 ) * stage.viewer.height / 2

    console.log( "Reported canvasPosition: "  + o.canvasPosition.x + "," + o.canvasPosition.y );
    console.log( "Projected Position: " + v.x + "," + v.y );
    console.log( "Calc'd Canvas position:" + canvasX + "," + canvasY ); // Hopefully this is close in value to the first logged line!

  }


  stage.signals.hovered.add( handler );

Having a general method somewhere for doing this would be handy (it might already exist?). It might also need to take into account pixelRatio?

Thanks Fred! This is exactly what I needed!

We could provide the atom of the bond that is closest to where the user clicked. Code should go into controls/picking-controls.js.

Having a general method somewhere for doing this would be handy (it might already exist?).

There are a few aspect that need to be taken into account for this to work generally

  • There could be a transformation matrix from an assembly
  • I want to introduce per component transformation matrices

Not sure how and where to provide a useful method for that

It might also need to take into account pixelRatio?

Yes it does

We could provide the atom of the bond that is closest to where the user clicked. Code should go into controls/picking-controls.js.

Sounds like the best option.
I've had a look at this file and I must aknowledge that I don't know how I could do it from this code. It seems that the code to get the picked object is in viewer/viewer.js and refers to Groups defined in three.js. Can you provide pointers to where I could start from?

There are a few aspect that need to be taken into account for this to work generally

  • There could be a transformation matrix from an assembly
  • I want to introduce per component transformation matrices

Not sure how and where to provide a useful method for that

Maybe viewer.getCanvasPosition( myVector3 )? (assuming user has handled assembly and per-component transformation). But if bond clicked/hovered event returns the nearest atom then for now I guess YAGNI.

In answer to your second question, @arose probably knows a neater way, but I've been using this to try and get my head around how atomic coords map to x,y screen coords
I've included it in my code and it works beautifully: I can now pick an atom by clicking on its side of a bond

Hey, I refactored how picking is handled but it should not break anything. Instead of a plain object you now get a PickingProxy which also has a property .closestBondAtom. Also, you can now pick Shape objects.

It looks great! Thanks Alex!
Unfortunately it seems that stage.signals.hovered got broken in the process. It only returns undefined...

does hovering works for you here: http://arose.github.io/ngldev/?example=slice it is the latest prerelease build

It does!

After further experimentation, I found out that what broke my code was an undefined return value when the background is hovered, whereas previously an object with undefined properties (such as atom, bond, etc...) was returned.

By the way, I've made a jsfiddle for quick testing using rawgit to get the latest ngl.js on github: https://jsfiddle.net/ppillot/mu95zmx1/

Thanks Alex for solving this issue!

And for the record, there is now a native method to get the 2D viewer coordinates of an atom: stage.viewerControls.getPositionOnCanvas( myAtomReference )

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fredludlow picture fredludlow  路  3Comments

pconesa picture pconesa  路  5Comments

biharck picture biharck  路  6Comments

thomashopf picture thomashopf  路  6Comments

sbliven picture sbliven  路  3Comments