Forums > Javascript

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

March 26, 2014 | 1: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<0) x = 0;
else if (x>width) x = width;
if (y<0) y = 0;
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:

<code>

– Pasted Max Patch, click to expand. –

</code>


March 26, 2014 | 1: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.


March 27, 2014 | 2: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<0) x = 0;
else if (x>width) x = width;
if (y<0) y = 0;
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


March 27, 2014 | 2:04 am

with ugly formatting…
Tant pis

p


March 27, 2014 | 2:21 am

Thanks Patrick, I’ll check that this evening !

Bonne journée.


March 28, 2014 | 12: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.


March 28, 2014 | 1: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


March 28, 2014 | 6:43 am

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<0) x = 0;
else if (x>width) x = width;
if (y<0) y = 0;
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


Viewing 8 posts - 1 through 8 (of 8 total)