Find which points from a multitouch are closest to each corner


    Aug 21 2014 | 5:32 pm
    Hey there, working on a multitouch thing for live projection. The idea is that there are four points on the multitouch which correspond to a cornerpin object. Essentially you can map out a quad live. Problem is, I don't trust the operators to know which child on the multitouch is correct, so I'd like to take that out of the equation. I'm guessing the best way would be to compare each touch to a corner, and then have a series of gate objects to direct them to the proper "bottom_left" type message on cornerpin. Thoughts?

    • Aug 21 2014 | 9:38 pm
      the quick-n-dirty method to use is by doing taxicab geometry to find each distance: http://en.wikipedia.org/wiki/Taxicab_geometry
      This gives you a single number as the distance, and shortest distance wins. It might help if you purposefully made the system a little sluggish, so that you don't get flicker in the center states... perhaps look at http://en.wikipedia.org/wiki/Hysteresis , too.
    • Aug 21 2014 | 9:42 pm
      Was hoping for a nice MAX object that did it for me, which is usually the case after banging my head against the wall ;-) And thank you for your suggestion, I think the flicker thing is a good point. I ended up doing it in LUA; I'm more of a linear programmer.
      this.inlets = 4
      this.outlets = 4
      
      function list(x1, y1, x2, y2, x3, y3, x4, y4)
      	v = {}				-- vector array
      	v[1] = {x1, y1}
      	v[2] = {x2, y2}
      	v[3] = {x3, y3}
      	v[4] = {x4, y4}
      		
      	-- find TL point
      	local bestFit = 100	-- arbitrary starting value to compare to
      	for i=1,4 do	-- loop 4 times
            local d = distance (v[i][1], v[i][2], 0, 0)
      	  if d < bestFit then
      	    TL = {v[i][1], v[i][2]}	-- assign top left corner
      		bestFit = d
      	  end
          end
      
      	-- find TR
      	local bestFit = 100	-- arbitrary starting value to compare to
      	for i=1,4 do	-- loop 4 times
            local d = distance (v[i][1], v[i][2], 1.0, 0.0)
      	  if d < bestFit then
      	    TR = {v[i][1], v[i][2]}	-- assign top left corner
      		bestFit = d
      	  end
          end
      	
      	-- find BR
      	bestFit = 100	-- arbitrary starting value to compare to
      	for i=1,4 do	-- loop 4 times
            local d = distance (v[i][1], v[i][2], 1.0, 1.0)
      	  if d < bestFit then
      	    BR = {v[i][1], v[i][2]}	-- assign top left corner
      		bestFit = d
      	  end
          end
      
      	-- find BR
      	bestFit = 100	-- arbitrary starting value to compare to
      	for i=1,4 do	-- loop 4 times
            local d = distance (v[i][1], v[i][2], 0.0, 1.0)
      	  if d < bestFit then
      	    BL = {v[i][1], v[i][2]}	-- assign top left corner
      		bestFit = d
      	  end
          end
      
      	outlet(0,TL)
      	outlet(1,TR)
      	outlet(2,BR)
      	outlet(3,BL)
      end
      
      function distance ( x1, y1, x2, y2 )
          local dx = x1 - x2
          local dy = y1 - y2
          return math.sqrt ( dx * dx + dy * dy )
      end
      
    • Aug 21 2014 | 9:57 pm
      ah, okay, sometimes it's hard to ascern the skill of the patcher guy/girl online here ;)
      so yeah, in a "proper scenario" you do the pythagorean formula (like you did at the bottom) and then test for fit. In max we have the lovely "zl sort" which'll happily let you skip about 30 lines of code after you've calculated the distances.
    • Aug 22 2014 | 8:04 pm
      @PrismSpecs: note that if you're concerned about performance, you could skip the call to math.sqrt() in your distance() function. It is a simple fact of arithmetic that for non-negative numbers, x< y iff x^2 < y^2.
      If you do this, you might want to rename the function distance-squared() or distance2().