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