// this example uses one KDTable in two different ways. There is a one-time call to // kNearestRows to gather the nearest points for every point. Then, for each mouse move, // there is a call to kNearestRows to find the nearest point to the cursor. dim = 200; // how many random points to create xx = J( dim, 1, 5 + 90 * Random uniform() ); yy = J( dim, 1, 5 + 90 * Random uniform() ); data = xx || yy; // matrix needed to generate KDTable is built by concatenating the coordinates table = KDTable( data ); // this builds a KDTable from the data, do it once because it takes time {nearRows, dist} = table << kNearestRows( 9 ); // pre-locate 9 nearest points to every point. mutant spider! creepy = 0; // a little less creepy, by default // creepy notes: this might be creepier still if the 9 nearest neighbors were re-looked-up // with respect to the *cursor*. In this example, the 9 nearest neighbors are with respect to // the *data point* nearest the cursor. This causes ALL the spider legs to move to different // data points at the same time, which isn't what spiders do. See the cloud example. exx = 50; // initial location of exy = 50; // mouse handle hand = J( 1, 2, 0 ); // handle script keeps hand matrix up-to-date hand[1] = exx; // the hand matrix is sent to kdtable on every move hand[2] = exy; // to find the closest point to the handle {rows, dist} = table << kNearestRows( 1, hand ); // point near cursor iCursor = rows[1]; // remember the point nearest the cursor/handle New Window( "Drag handle to find neighbors", cb = Check Box( {"Creepy"}, creepy = cb << Get(); g< 0, // got one. draw the spider legs If( creepy == 0, if ( exx < 30 & exy > 70, textcolor("red");text( {2,97}, "check box")); x = [0, 0]; x[1] = xx[iCursor]; // x and y are each two elements; the point near the cursor is in y = [0, 0]; y[1] = yy[iCursor]; // the first element. the following loop fills in the second point... , x = [0, 0]; x[1] = exx;// x and y are each two elements; the point near the cursor is in y = [0, 0]; y[1] = exy;// the first element. the following loop fills in the second point... ); For( iNear = 1, iNear <= ncols(nearRows), iNear++, // nearRows has the indexes of the points near the cursor x[2] = xx[nearRows[iCursor,iNear]]; // each of the near by points has needs a blue line segment from y[2] = yy[nearRows[iCursor,iNear]]; // cursor to itself Pen Color( "Blue" ); Pen Size( 3 ); Line( x, y ); ); ); if ( exx ==50 & exy==50, textcolor("red");text( {50,50}, " <--drag square box")); // work around issue where handle is black on black background Marker( combinestates(Color State( if(g<