// Copyright (c) 2001-2010, Purdue University. All rights reserved. // Copyright (C) 2015 Apple Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of the Purdue University nor the // names of its contributors may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. var drawMotionOnVoxelMap = (function() { var voxelSize = Constants.GOOD_VOXEL_SIZE; var horizontal = new Vector2D(voxelSize, 0); var vertical = new Vector2D(0, voxelSize); function voxelHash(position) { var xDiv = (position.x / voxelSize) | 0; var yDiv = (position.y / voxelSize) | 0; var result = new Vector2D(); result.x = voxelSize * xDiv; result.y = voxelSize * yDiv; if (position.x < 0) result.x -= voxelSize; if (position.y < 0) result.y -= voxelSize; return result; } return function(voxelMap, motion) { var seen = new RedBlackTree(); function putIntoMap(voxel) { var array = voxelMap.get(voxel); if (!array) voxelMap.put(voxel, array = []); array.push(motion); } function isInVoxel(voxel) { if (voxel.x > Constants.MAX_X || voxel.x < Constants.MIN_X || voxel.y > Constants.MAX_Y || voxel.y < Constants.MIN_Y) return false; var init = motion.posOne; var fin = motion.posTwo; var v_s = voxelSize; var r = Constants.PROXIMITY_RADIUS / 2; var v_x = voxel.x; var x0 = init.x; var xv = fin.x - init.x; var v_y = voxel.y; var y0 = init.y; var yv = fin.y - init.y; var low_x, high_x; low_x = (v_x - r - x0) / xv; high_x = (v_x + v_s + r - x0) / xv; if (xv < 0) { var tmp = low_x; low_x = high_x; high_x = tmp; } var low_y, high_y; low_y = (v_y - r - y0) / yv; high_y = (v_y + v_s + r - y0) / yv; if (yv < 0) { var tmp = low_y; low_y = high_y; high_y = tmp; } if (false) { print("v_x = " + v_x + ", x0 = " + x0 + ", xv = " + xv + ", v_y = " + v_y + ", y0 = " + y0 + ", yv = " + yv + ", low_x = " + low_x + ", low_y = " + low_y + ", high_x = " + high_x + ", high_y = " + high_y); } return (((xv == 0 && v_x <= x0 + r && x0 - r <= v_x + v_s) /* no motion in x */ || ((low_x <= 1 && 1 <= high_x) || (low_x <= 0 && 0 <= high_x) || (0 <= low_x && high_x <= 1))) && ((yv == 0 && v_y <= y0 + r && y0 - r <= v_y + v_s) /* no motion in y */ || ((low_y <= 1 && 1 <= high_y) || (low_y <= 0 && 0 <= high_y) || (0 <= low_y && high_y <= 1))) && (xv == 0 || yv == 0 || /* no motion in x or y or both */ (low_y <= high_x && high_x <= high_y) || (low_y <= low_x && low_x <= high_y) || (low_x <= low_y && high_y <= high_x))); } function recurse(nextVoxel) { if (!isInVoxel(nextVoxel, motion)) return; if (seen.put(nextVoxel, true)) return; putIntoMap(nextVoxel); recurse(nextVoxel.minus(horizontal)); recurse(nextVoxel.plus(horizontal)); recurse(nextVoxel.minus(vertical)); recurse(nextVoxel.plus(vertical)); recurse(nextVoxel.minus(horizontal).minus(vertical)); recurse(nextVoxel.minus(horizontal).plus(vertical)); recurse(nextVoxel.plus(horizontal).minus(vertical)); recurse(nextVoxel.plus(horizontal).plus(vertical)); } recurse(voxelHash(motion.posOne)); }; })(); function reduceCollisionSet(motions) { var voxelMap = new RedBlackTree(); for (var i = 0; i < motions.length; ++i) drawMotionOnVoxelMap(voxelMap, motions[i]); var result = []; voxelMap.forEach(function(key, value) { if (value.length > 1) result.push(value); }); return result; }