1

I draw some lines on qglviewer Now i need to computate the shortest way from mouse position to curve

void viewer::mouseMoveEvent(QMouseEvent *e) 
{
qglviewer::Vec xx(e->pos().x(), e->pos().y(), 1);
qglviewer::Vec xxx = this->camera()->unprojectedCoordinatesOf(xx);
float dist1track = std::numeric_limits<float>::max();
for(int i = 0; i < wtrjF.size(); i++)
{
   Atom atom = wtrjF[i];
   for(float t = 0; t < atom.pos.size(); t++)
   {
       if(dist1track > qSqrt(qPow(atom.pos[t][0] - xxx[0], 2) + qPow(atom.pos[t][1] - xxx[1], 2)))
       {
           dist1track = qSqrt(qPow(atom.pos[t][0] - xxx[0], 2) + qPow(atom.pos[t][1] - xxx[1], 2));
           name = atom.wname;
           wid = atom.wid;
           pos = QString::number(atom.pos[0][0]) + "_" + QString::number(atom.pos[0][1]);
       }
   }
}
qDebug()<<name<<dist1track;
}

But its give me wrong curve I think i got wrong coordinates under mouse cursor, but don't know how to fix it. Also tried get coords like:

qglviewer::Vec xx = camera()->pointUnderPixel(e->pos(), found);
qglviewer::Vec xx(e->pos().x(), e->pos().y(), 0);
glReadPixels(e->pos().x(), view[3] - e->pos().y(), 1, 1, GL_DEPTH_COMPONENT, 
GL_FLOAT, &z1);
qglviewer::Vec xx(e->pos().x(), e->pos().y(), z1);

Any advises?

Screen of mouse position

yea, now i draw line from cursor to nearest point. wrong coords

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

0

You should compute the distance from Atom points to the ray formed by the camera origin and the mouse clicked point.

Mouse ray in real world coordinate system Source

Here is an example :

qreal distance_point_to_ray( qglviewer::Vec P, qglviewer::Vec orig, qglviewer::Vec dir ){

    qreal dotP_Ray = (P - orig) * dir; //<-- dot product of P on ray
    qreal dot_dir_dir = dir * dir;   //we need this when dir is not normalized.  

    qreal t0 = dotP_Ray / dot_dir_dir;
    qglviewer::Vec BP = P - (orig + dir * t0 );  //B is the projection of P on ray.

    return sqrt( BP * BP );
}

void viewer::mouseMoveEvent(QMouseEvent *e)
{
    qglviewer::Vec orig, dir;

    //get mouse ray in real world coordinate.
    camera()->convertClickToLine(e->pos(), orig, dir);

    float dist1track = std::numeric_limits<float>::max();
    for(int i = 0; i < wtrjF.size(); i++)
    {
        Atom atom = wtrjF[i];
        for(int t = 0; t < atom.pos.size(); t++)
        {
            //assum that atom.pos is an array of qglviewer::Vec
            float d = distance_point_to_ray( atom.pos[t], orig, dir );

            if(dist1track > d )
            {
                dist1track = d;
                name = atom.wname;
                wid = atom.wid;

                pos = QString("POS: [%1, %2, %3]").arg(atom.pos[t][0], 0, 'g', 3 )
                        .arg(atom.pos[t][1], 0, 'g', 3 )
                        .arg(atom.pos[t][2], 0, 'g', 3 );
            }
        }
    }

    qDebug() << name << dist1track;
}
tunglt
  • 1,022
  • 1
  • 9
  • 16
  • @zloi_templar You are welcome, please mark my answer as accepted :), this makes your question and my answer more visible in SO. – tunglt Dec 26 '18 at 07:59
  • maybe do you know, how to get point under cursor on unproject coords, not distance? – zloi_templar Dec 26 '18 at 08:26
  • When you draw your atoms, you assign each atom an ID, then use pointUnderPixel to get the ID if clicked (as you did in 2e codes), found will return true if one atom is clicked. See the [example](http://libqglviewer.com/examples/select.html). – tunglt Dec 26 '18 at 08:33
  • yea, ty, i use it for my lines. but i need point under cursor without object ( to draw a line from the cursor to the curve, show distance) – zloi_templar Dec 26 '18 at 08:36
  • In fact, you compute the point B of the closest atom as did distance_point_to_ray() : `B = orig + dir*t0;` – tunglt Dec 26 '18 at 08:43
  • ty, you confirmed my assumptions – zloi_templar Dec 26 '18 at 08:57