javascript - Calculate minimum value not between set of ranges -


given array of circles (x,y,r values), want place new point, such has fixed/known y-coordinate (shown horizontal line), , close possible center not within of existing circles. in example images, point in red result.

circles have known radius , y-axis attribute, easy calculate points intersect horizontal line @ known y value. efficiency important, don't want have try bunch of x coords , test them against each item in circles array. there way work out optimal x coordinate mathematically? appreciated. way, i'm writing in javascript using raphael.js library (because 1 supports ie8) - more of logic problem language doesn't matter. enter image description here

basically equation of circle (x - cx)2 + (y - cy)2 = r2. therefore can find intersection points between circle , x axis substituting y 0. after have simple quadratic equation solve: x2 - 2cxx + cx2 + cy2 - r2 = 0 . have 3 possible outcomes:

  • no intersection - determinant irrational number (nan in javascript), ignore result;
  • one intersection - both solutions match, use [value, value];
  • two intersections - both solutions different, use [value1, value2].

sort newly calculated intersection intervals, try merge them possible. take in mind in every program language there approximation, therefore need define delta value dot approximation , take consideration when merging intervals.

when intervals merged can generate x coordinates subtracting/adding same delta value beginning/end of every interval. , lastly points, 1 closest 0 answer.

here example o(n log n) complexity oriented rather towards readability. i've used 1*10-10 delta :

var circles = [     {x:0, y:0, r:1},     {x:2.5, y:0, r:1},     {x:-1, y:0.5, r:1},     {x:2, y:-0.5, r:1},     {x:-2, y:0, r:1},     {x:10, y:10, r:1} ];  console.log(getclosestpoint(circles, 1e-10));    function getclosestpoint(circles, delta) {     var intervals = [],         len = circles.length,          i, result;     (i = 0; < len; i++)     {         result = getxintersection(circles[i])         if (result)         {             intervals.push(result);         }     }      intervals = intervals.sort(function(a, b){         return a.from - b.from;     });     if (intervals.length <= 0) return 0;     intervals = mergeintervals(intervals, delta);      var points = getclosestpoints(intervals, delta);     points = points.sort(function(a, b){         return math.abs(a) - math.abs(b);     });     return points[0]; }  function getxintersection(circle) {     var d = math.sqrt(circle.r * circle.r - circle.y * circle.y);     return isnan(d) ? null : {from: circle.x - d, to: circle.x + d}; }  function mergeintervals(intervals, delta) {     var curr = intervals[0],         result = [],         len = intervals.length, i;     (i = 1 ; < len ; i++)     {         if (intervals[i].from <= curr.to + delta)         {             curr.to = math.max(curr.to, intervals[i].to);         } else {             result.push(curr);             curr = intervals[i];         }     }     result.push(curr);     return result; }  function getclosestpoints(intervals, delta) {     var result = [],          len = intervals.length, i;     (i = 0 ; < len ; i++)     {         result.push( intervals[i].from - delta );         result.push( intervals[i].to + delta );     }     return result; } 

Comments

Popular posts from this blog

css - SVG using textPath a symbol not rendering in Firefox -

Java 8 + Maven Javadoc plugin: Error fetching URL -

order - Notification for user in user account opencart -