Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The formula for distance between two points is (javascript):</p> <pre class="lang-js prettyprint-override"><code>var xDiff = ( point1x - point2x ), yDiff = ( point1y - point2y ), distance = Math.sqrt( ( xDiff * xDiff ) + ( yDiff * yDiff ) ); </code></pre> <p>Loop around your "proposed new point", starting at one <code>x-1, y-1 to x+1, y+1</code>. At each point check to see that it's not a forbidden point, not the point you just came from, and not off the boundaries of the map. If it meets all those criteria, use the above formula to measure the distance and add it to an array. At the end of your "1-point out" loop, check if there are any distances in that array. If so, take the smallest one and you're done. If there aren't any, move onto <code>x-2, y-2 to x+2, y+2</code> (2 points out). </p> <p>This will be extremely fast for the small area you are referring to.</p> <p>Demo: <a href="http://jsfiddle.net/ThinkingStiff/V7Bqm/" rel="nofollow">http://jsfiddle.net/ThinkingStiff/V7Bqm/</a></p> <pre class="lang-js prettyprint-override"><code>var X = 0, Y = 1, currentPoint = [5,5], proposedPoint = [5,6], forbiddenPoints = [[5,6],[6,6],[4,7],[5,7],[6,7],[4,8],[5,8]], map = { left:1, top:1, right:10, bottom:10 }; function closestSafePoint( point ) { var x = point[X], y = point[Y], safePoints = []; for( var left = x - 1, top = y - 1, right = x + 1, bottom = y + 1; left &lt;= map.left || top &lt;= map.top || right &lt;= map.right || bottom &lt;= map.bottom; left--, top--, right++, bottom++) { checkHorizontalPoints( safePoints, point, left, right, top ); checkHorizontalPoints( safePoints, point, left, right, bottom ); checkVerticalPoints( safePoints, point, top + 1, bottom - 1, left ); checkVerticalPoints( safePoints, point, top + 1, bottom - 1, right ); safePoints.sort( function( a, b ){ return a[1] - b[1] } ); return safePoints.length ? safePoints[0] : point; }; }; function checkHorizontalPoints( points, fromPoint, startX, endX, y ) { for( var x = startX; x &lt;= endX ; x++ ) { var toPoint = [x, y]; if( !isForbidden( toPoint ) &amp;&amp; !isCurrent( toPoint) &amp;&amp; onMap( toPoint ) ) { points.push( [toPoint, distance( fromPoint, toPoint )] ); }; }; }; function checkVerticalPoints( points, fromPoint, startY, endY, x ) { for( var y = startY; y &lt;= endY ; y++ ) { var toPoint = [x, y]; if( !isForbidden( toPoint ) &amp;&amp; !isCurrent( toPoint) &amp;&amp; onMap( toPoint ) ) { points.push( [toPoint, distance( fromPoint, toPoint )] ); }; }; }; function isForbidden( point ) { for( var index = 0; index &lt; forbiddenPoints.length; index++ ) { if( forbiddenPoints[index].toString() == point.toString() ) return true; }; }; function isCurrent( point ) { return currentPoint.toString() == point.toString() ? true : false; }; function onMap( point ) { var x = point[X], y = point[Y]; return x &gt;= map.left &amp;&amp; y &gt;= map.top &amp;&amp; x &lt;= map.right &amp;&amp; y &lt;= map.bottom; }; function distance( pointA, pointB ) { var xDiff = ( pointA[X] - pointB[X] ), yDiff = ( pointA[Y] - pointB[Y] ); return Math.sqrt( ( xDiff * xDiff ) + ( yDiff * yDiff ) ); }; console.log( 'current: ' + currentPoint + ', ' + 'proposed: ' + proposedPoint + ', ' + 'closest: ' + closestSafePoint( proposedPoint )[0] ); </code></pre> <p>One optimization you could make to this, if you're fairly sure most of your safe spots will be one or two points away is to break out as soon as you get to a point thats distance is the same as the level you're on. So if you're on loop one, and you get a point that is distance = 1, stop, since you'll never get closer than that.</p> <p>UPDATE: I noticed you added "same trajectory" to your question. But in one of the comments, you also say it can't jump over the forbidden area. Those statements seem to conflict.</p> <p>Same trajectory is a little more tricky and requires some trig. Check out my demo of circular divs at <a href="http://jsfiddle.net/ThinkingStiff/uLu7v/" rel="nofollow">http://jsfiddle.net/ThinkingStiff/uLu7v/</a>. There is a "point on ray" function halfway down at:</p> <pre><code>$this.siblings( ".circle" ).each( function() </code></pre> <p>This calculates the distance to move the surrounding circles on a ray away from the selected circle. This could be used to calculate a point on your trajectory. But, I think my original function is actually what you're looking for and you didn't mean same trajectory.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload