Mouse doesn't always grab the closest point using click and drag within jsui


    Mar 26 2014 | 8:02 pm
    Hello,
    In a jsui I am trying to grab the point closest to the mouse pointer upon mouseclick in order to drag it.
    However it seems that quite often the mouse grabs a point which is not the closest one.
    What's wrong with my code ?
    Thank you in advance for helping.
    inlets = 1;
    outlets = 4;
    sketch.ortho3d(); //like default3d but uses orthographic projection
    var vbrgb = [0.9,0.9,0.9,1.];
    var outer = [0.8,0.8,0.0,1.];
    var vlrgb = [0.5,0.0,0.0,1.];
    var inner = [0.0,0.0,0.0,1.];
    var w = [[-0.5,-0.5,0],[0.5,-0.5,0],[0.5,0.5,0],[-0.5,0.5,0]]; // array of four points - as world coordinates
    var vx = [0.2,0.4,0.6, 0.8];
    var vy = [0.2,0.4, 0.6, 0.8];
    var vradius = 0.05;
    var closestPoint = 0; // id of point closest to mouse position
    var maxdist ; // maximal distance from mouse to point
    // process arguments
    if (jsarguments.length>1)
    outer[0] = jsarguments[1]/255.;
    if (jsarguments.length>2)
    outer[1] = jsarguments[2]/255.;
    if (jsarguments.length>3)
    outer[2] = jsarguments[3]/255.;
    if (jsarguments.length>4)
    vbrgb[0] = jsarguments[4]/255.;
    if (jsarguments.length>5)
    vbrgb[1] = jsarguments[5]/255.;
    if (jsarguments.length>6)
    vbrgb[2] = jsarguments[6]/255.;
    if (jsarguments.length>7)
    vradius = jsarguments[1];
    draw();
    function draw()
    {
    var str;
    with (sketch) {
    glclearcolor(vbrgb);
    glclear();
    for(var i = 0; i < 4 ; i++) {
    moveto(w[i]);
    glcolor(outer);
    sphere(vradius);
    glcolor(vlrgb);
    linesegment(w[i], w[(i+1) % 4]);
    }
    }
    }
    function bang()
    {
    draw();
    refresh();
    }
    function fsaa(v)
    {
    sketch.fsaa = v;
    bang();
    }
    function onresize(w,h)
    {
    draw();
    refresh();
    }
    onresize.local = 1; //private
    function onclick(x,y)
    {
    maxdist = 1000000;
    ondrag(x,y);
    }
    function ondrag(x,y)
    {
    var width = box.rect[2] - box.rect[0];
    var height = box.rect[3] - box.rect[1];
    var distance;
    if (x else if (x>width) x = width;
    if (y else if (y>height) y = height;
    for(var k = 0; k < 4; k++) {
    // checks distance from point to stored point
    distance = Math.abs(x/width - vx[k]) * Math.abs(y/height - vy[k]); // sqrt not extracted as we don't need the actual value
    if (distance < maxdist) {
    maxdist = distance;
    closestPoint=k;
    }
    }
    w[closestPoint] = sketch.screentoworld(x,y);
    vx[closestPoint] = x/width;
    vy[closestPoint] = 1- y/height;
    for (var i = 0; i < 4 ; i++) {
    outlet(i,vx[i], vy[i]);
    }
    notifyclients();
    bang();
    }
    ondrag.local = 1; //private
    Patcher code:

    • Mar 26 2014 | 8:06 pm
      By the way I can't get my code to be displayed as such, a /code tag is inserted automatically in the middle of the script althought I have put one at the end.
    • Mar 27 2014 | 9:00 am
      I had difficulties to open the js file: the "-" (minus sign) were replaced with "—" (dashes) when surrounded by spaces. Probably a forum issue.
      Anyway I found 3 problems (but maybe I didn't understand what you do):
      1_ bad initialization of your vx/vy values
      2_ distance is the square root of the SUM of the squares
      3_ new value of vy
      This seems to work:
      inlets = 1;
      outlets = 4;
      sketch.ortho3d(); //like default3d but uses orthographic projection
      var vbrgb = [0.9,0.9,0.9,1.];
      var outer = [0.8,0.8,0.0,1.];
      var vlrgb = [0.5,0.0,0.0,1.];
      var inner = [0.0,0.0,0.0,1.];
      var w = [[-0.5,-0.5,0],[0.5,-0.5,0],[0.5,0.5,0],[-0.5,0.5,0]]; // array of four points – as world coordinates
      var vx = [0.2,0.8,0.8, 0.2]; // ##### 1 #####
      var vy = [0.8,0.8, 0.2, 0.2]; // ##### 1 #####
      var vradius = 0.05;
      var closestPoint = 0; // id of point closest to mouse position
      var maxdist ; // maximal distance from mouse to point
      // process arguments
      if (jsarguments.length>1)
      outer[0] = jsarguments[1]/255.;
      if (jsarguments.length>2)
      outer[1] = jsarguments[2]/255.;
      if (jsarguments.length>3)
      outer[2] = jsarguments[3]/255.;
      if (jsarguments.length>4)
      vbrgb[0] = jsarguments[4]/255.;
      if (jsarguments.length>5)
      vbrgb[1] = jsarguments[5]/255.;
      if (jsarguments.length>6)
      vbrgb[2] = jsarguments[6]/255.;
      if (jsarguments.length>7)
      vradius = jsarguments[1];
      draw();
      function draw()
      {
      var str;
      with (sketch) {
      glclearcolor(vbrgb);
      glclear();
      for(var i = 0; i < 4 ; i++) {
      moveto(w[i]);
      glcolor(outer);
      sphere(vradius);
      glcolor(vlrgb);
      linesegment(w[i], w[(i+1) % 4]);
      }
      }
      }
      function bang()
      {
      draw();
      refresh();
      }
      function fsaa(v)
      {
      sketch.fsaa = v;
      bang();
      }
      function onresize(w,h)
      {
      draw();
      refresh();
      }
      onresize.local = 1; //private
      function onclick(x,y)
      {
      maxdist = 1000000;
      ondrag(x,y);
      }
      function ondrag(x,y)
      {
      var width = box.rect[2] - box.rect[0];
      var height = box.rect[3] - box.rect[1];
      var distance;
      if (x else if (x>width) x = width;
      if (y else if (y>height) y = height;
      for(var k = 0; k < 4; k++) {
      // checks distance from point to stored point
      //distance = Math.abs(x/width - vx[k]) + Math.abs(y/height - vy[k]); // ##### 2 #####
      distance = (x/width - vx[k])*(x/width - vx[k]) + (y/height - vy[k])*(y/height - vy[k]); // sqrt not extracted as we don’t need the actual value
      outlet(k, vx[k], vy[k],x/width, y/height,distance, maxdist);
      if (distance < maxdist) {
      maxdist = distance;
      closestPoint=k;
      }
      }
      w[closestPoint] = sketch.screentoworld(x,y);
      vx[closestPoint] = x/width;
      //vy[closestPoint] = 1- y/height;
      vy[closestPoint] = y/height; // ##### 3 #####
      for (var i = 0; i < 4 ; i++) {
      // outlet(i,vx[i], vy[i]);
      }
      notifyclients();
      bang();
      }
      ondrag.local = 1; //private
    • Mar 27 2014 | 9:04 am
      with ugly formatting…
      Tant pis
      p
    • Mar 27 2014 | 9:21 am
      Thanks Patrick, I'll check that this evening !
      Bonne journée.
    • Mar 28 2014 | 7:43 am
      I understand corrections #2 (Pythagorean theorem, should have been obvious - how stupid I was) and #3 but I don't get your idea with #1.
    • Mar 28 2014 | 8:30 am
      Maybe I didn't understand correctly how you use those vx and vy variables.
      But as they seem to represent the positions, I just tried to match the initial positions of the 4 dots defined in the w array.
      Doesn't the code work the way you want?
      p
    • Mar 28 2014 | 1:43 pm
      Sure it does ! :-))
      Now I am trying to displau the shape another way because the final shape will be in 3D.
      Therefore I am using the glulookat command and the way the shape is displayed is fine. However I have problems of closest neighbor selection again. Should I apply a transform on my mouse position after having translated it to world coordinates so that it compensates the glulookat transform ?
      The additional blue spheres are there to check the orientation.
      inlets = 1;
      outlets = 4;
      sketch.ortho3d();
      sketch.glulookat(1.,8.,1.,0.,0.,0.,0.,0.,1.); //eye (camera) - center (point camera points to) - up
      var vbrgb = [0.9,0.9,0.9,1.];
      var outer = [0.8,0.8,0.0,1.];
      var vlrgb = [0.5,0.0,0.0,1.];
      var centercolor = [0.0,0.5,0.75,1.];
      var reperescolor = [0.5,0.87,1.,1.];
      var center =[0.,0.,0.];
      var reperes =[[0.,1.,0.],[0.,2.,0.],[0.,3.,0.],[0.,4.,0.],[0.,5.,0.]];
      var w = [[-0.5,-0.5,0],[0.5,-0.5,0],[0.5,0.5,0],[-0.5,0.5,0]]; // array of four points – as world coordinates
      var vx = [0.2,0.8,0.8, 0.2]; // ##### 1 #####
      var vy = [0.8,0.8, 0.2, 0.2]; // ##### 1 #####
      var vradius = 0.05;
      var closestPoint = 0; // id of point closest to mouse position
      var maxdist ; // maximal distance from mouse to point
      // process arguments
      if (jsarguments.length>1)
      outer[0] = jsarguments[1]/255.;
      if (jsarguments.length>2)
      outer[1] = jsarguments[2]/255.;
      if (jsarguments.length>3)
      outer[2] = jsarguments[3]/255.;
      if (jsarguments.length>4)
      vbrgb[0] = jsarguments[4]/255.;
      if (jsarguments.length>5)
      vbrgb[1] = jsarguments[5]/255.;
      if (jsarguments.length>6)
      vbrgb[2] = jsarguments[6]/255.;
      if (jsarguments.length>7)
      vradius = jsarguments[1];
      draw();
      function draw()
      {
      var str;
      with (sketch) {
      glclearcolor(vbrgb);
      glclear();
      moveto(center);
      glcolor(centercolor);
      sphere(vradius);
      linesegment(center, reperes[0]);
      for(var i = 0; i < 5 ; i++) {
      moveto(reperes[i]);
      glcolor(reperescolor);
      sphere(vradius);
      if (i < 4) {
      glcolor(vlrgb);
      linesegment(reperes[i], reperes[i+1]);
      }
      }
      for(var i = 0; i < 4 ; i++) {
      moveto(w[i]);
      glcolor(outer);
      sphere(vradius);
      glcolor(vlrgb);
      linesegment(w[i], w[(i+1) % 4]);
      }
      }
      }
      function bang()
      {
      draw();
      refresh();
      }
      function fsaa(v)
      {
      sketch.fsaa = v;
      bang();
      }
      function myview(a,b,c,d,e,f,g,h,i) {
      sketch.glulookat(a,b,c,d,e,f,g,h,i);
      bang()
      }
      function onresize(w,h)
      {
      draw();
      refresh();
      }
      onresize.local = 1; //private
      //
      function onclick(x,y)
      {
      maxdist = 1000000;
      ondrag(x,y);
      }
      function ondrag(x,y)
      {
      var width = box.rect[2] - box.rect[0];
      var height = box.rect[3] - box.rect[1];
      var distance;
      //
      if (x else if (x>width) x = width;
      if (y else if (y>height) y = height;
      //post("sketch.screentoworld(x,y) : "+sketch.screentoworld(x,y)+"\n");
      for(var k = 0; k < 4; k++) {
      // checks distance from point to stored point
      distance = (x/width - vx[k])*(x/width - vx[k]) + (y/height - vy[k])*(y/height - vy[k]); // sqrt not extracted as we don’t need the actual value
      if (distance < maxdist) {
      maxdist = distance;
      closestPoint=k;
      }
      outlet(closestPoint, vx[closestPoint], vy[closestPoint],distance, maxdist);
      }
      w[closestPoint] = sketch.screentoworld(x,y);
      vx[closestPoint] = x/width;
      vy[closestPoint] = y/height; // ##### 3 #####
      for (var i = 0; i < 4 ; i++) {
      // outlet(i,vx[i], vy[i]);
      }
      notifyclients();
      bang();
      }
      ondrag.local = 1; //private