| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993 |
- // 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 referenceScore = 20;
- ////////////////////////////////////////////////////////////////////////////////
- // Runner
- ////////////////////////////////////////////////////////////////////////////////
- if (typeof (WScript) === "undefined") {
- var WScript = {
- Echo: print
- }
- }
- var print = function () {};
- var performance = performance || {};
- performance.now = (function() {
- return performance.now ||
- performance.mozNow ||
- performance.msNow ||
- performance.oNow ||
- performance.webkitNow ||
- Date.now;
- })();
- function reportResult(score) {
- WScript.Echo("### SCORE: " + (100 * referenceScore / score));
- }
- var top = {};
- top.JetStream = {
- reportResult: reportResult
- };
- ////////////////////////////////////////////////////////////////////////////////
- // util.js
- ////////////////////////////////////////////////////////////////////////////////
- function compareNumbers(a, b) {
- if (a == b)
- return 0;
- if (a < b)
- return -1;
- if (a > b)
- return 1;
-
- // We say that NaN is smaller than non-NaN.
- if (a == a)
- return 1;
- return -1;
- }
- function averageAbovePercentile(numbers, percentile) {
- // Don't change the original array.
- numbers = numbers.slice();
-
- // Sort in ascending order.
- numbers.sort(function(a, b) { return a - b; });
-
- // Now the elements we want are at the end. Keep removing them until the array size shrinks too much.
- // Examples assuming percentile = 99:
- //
- // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore,
- // since then numbers.length / originalLength = 0.99.
- //
- // - numbers.length starts at 1000: we will remove the ten worst.
- //
- // - numbers.length starts at 10: we will remove just the worst.
- var numbersWeWant = [];
- var originalLength = numbers.length;
- while (numbers.length / originalLength > percentile / 100)
- numbersWeWant.push(numbers.pop());
-
- var sum = 0;
- for (var i = 0; i < numbersWeWant.length; ++i)
- sum += numbersWeWant[i];
-
- var result = sum / numbersWeWant.length;
-
- // Do a sanity check.
- if (numbers.length && result < numbers[numbers.length - 1]) {
- throw "Sanity check fail: the worst case result is " + result +
- " but we didn't take into account " + numbers;
- }
-
- return result;
- }
- var currentTime;
- if (this.performance && performance.now)
- currentTime = function() { return performance.now() };
- else if (preciseTime)
- currentTime = function() { return preciseTime() * 1000; };
- else
- currentTime = function() { return 0 + new Date(); };
- //benchmark.js
- function benchmark() {
- var verbosity = 0;
- var numAircraft = 1000;
- var numFrames = 200;
- var expectedCollisions = 14484;
- var percentile = 95;
- var simulator = new Simulator(numAircraft);
- var detector = new CollisionDetector();
- var lastTime = currentTime();
- var results = [];
- for (var i = 0; i < numFrames; ++i) {
- var time = i / 10;
-
- var collisions = detector.handleNewFrame(simulator.simulate(time));
-
- var before = lastTime;
- var after = currentTime();
- lastTime = after;
- var result = {
- time: after - before,
- numCollisions: collisions.length
- };
- if (verbosity >= 2)
- result.collisions = collisions;
- results.push(result);
- }
- if (verbosity >= 1) {
- for (var i = 0; i < results.length; ++i) {
- var string = "Frame " + i + ": " + results[i].time + " ms.";
- if (results[i].numCollisions)
- string += " (" + results[i].numCollisions + " collisions.)";
- print(string);
- if (verbosity >= 2 && results[i].collisions.length)
- print(" Collisions: " + results[i].collisions);
- }
- }
- // Check results.
- var actualCollisions = 0;
- for (var i = 0; i < results.length; ++i)
- actualCollisions += results[i].numCollisions;
- if (actualCollisions != expectedCollisions) {
- throw new Error("Bad number of collisions: " + actualCollisions + " (expected " +
- expectedCollisions + ")");
- }
- // Find the worst 5%
- var times = [];
- for (var i = 0; i < results.length; ++i)
- times.push(results[i].time);
-
- return averageAbovePercentile(times, percentile);
- }
- //call_sign.js
- function CallSign(value) {
- this._value = value;
- }
- CallSign.prototype.compareTo = function(other) {
- return this._value.localeCompare(other._value);
- }
- CallSign.prototype.toString = function() {
- return this._value;
- }
- //collision.js
- function Collision(aircraft, position) {
- this.aircraft = aircraft;
- this.position = position;
- }
- Collision.prototype.toString = function() {
- return "Collision(" + this.aircraft + " at " + this.position + ")";
- };
- //collision_detector.js
- function CollisionDetector() {
- this._state = new RedBlackTree();
- }
- CollisionDetector.prototype.handleNewFrame = function(frame) {
- var motions = [];
- var seen = new RedBlackTree();
-
- for (var i = 0; i < frame.length; ++i) {
- var aircraft = frame[i];
-
- var oldPosition = this._state.put(aircraft.callsign, aircraft.position);
- var newPosition = aircraft.position;
- seen.put(aircraft.callsign, true);
-
- if (!oldPosition) {
- // Treat newly introduced aircraft as if they were stationary.
- oldPosition = newPosition;
- }
-
- motions.push(new Motion(aircraft.callsign, oldPosition, newPosition));
- }
-
- // Remove aircraft that are no longer present.
- var toRemove = [];
- this._state.forEach(function(callsign, position) {
- if (!seen.get(callsign))
- toRemove.push(callsign);
- });
- for (var i = 0; i < toRemove.length; ++i)
- this._state.remove(toRemove[i]);
-
- var allReduced = reduceCollisionSet(motions);
- var collisions = [];
- for (var reductionIndex = 0; reductionIndex < allReduced.length; ++reductionIndex) {
- var reduced = allReduced[reductionIndex];
- for (var i = 0; i < reduced.length; ++i) {
- var motion1 = reduced[i];
- for (var j = i + 1; j < reduced.length; ++j) {
- var motion2 = reduced[j];
- var collision = motion1.findIntersection(motion2);
- if (collision)
- collisions.push(new Collision([motion1.callsign, motion2.callsign], collision));
- }
- }
- }
-
- return collisions;
- };
- //constants.js
- var Constants = {};
- Constants.MIN_X = 0;
- Constants.MIN_Y = 0;
- Constants.MAX_X = 1000;
- Constants.MAX_Y = 1000;
- Constants.MIN_Z = 0;
- Constants.MAX_Z = 10;
- Constants.PROXIMITY_RADIUS = 1;
- Constants.GOOD_VOXEL_SIZE = Constants.PROXIMITY_RADIUS * 2;
- //motion.js
- function Motion(callsign, posOne, posTwo) {
- this.callsign = callsign;
- this.posOne = posOne;
- this.posTwo = posTwo;
- }
- Motion.prototype.toString = function() {
- return "Motion(" + this.callsign + " from " + this.posOne + " to " + this.posTwo + ")";
- };
- Motion.prototype.delta = function() {
- return this.posTwo.minus(this.posOne);
- };
- Motion.prototype.findIntersection = function(other) {
- var init1 = this.posOne;
- var init2 = other.posOne;
- var vec1 = this.delta();
- var vec2 = other.delta();
- var radius = Constants.PROXIMITY_RADIUS;
-
- // this test is not geometrical 3-d intersection test, it takes the fact that the aircraft move
- // into account ; so it is more like a 4d test
- // (it assumes that both of the aircraft have a constant speed over the tested interval)
-
- // we thus have two points, each of them moving on its line segment at constant speed ; we are looking
- // for times when the distance between these two points is smaller than r
-
- // vec1 is vector of aircraft 1
- // vec2 is vector of aircraft 2
-
- // a = (V2 - V1)^T * (V2 - V1)
- var a = vec2.minus(vec1).squaredMagnitude();
-
- if (a != 0) {
- // we are first looking for instances of time when the planes are exactly r from each other
- // at least one plane is moving ; if the planes are moving in parallel, they do not have constant speed
- // if the planes are moving in parallel, then
- // if the faster starts behind the slower, we can have 2, 1, or 0 solutions
- // if the faster plane starts in front of the slower, we can have 0 or 1 solutions
- // if the planes are not moving in parallel, then
- // point P1 = I1 + vV1
- // point P2 = I2 + vV2
- // - looking for v, such that dist(P1,P2) = || P1 - P2 || = r
- // it follows that || P1 - P2 || = sqrt( < P1-P2, P1-P2 > )
- // 0 = -r^2 + < P1 - P2, P1 - P2 >
- // from properties of dot product
- // 0 = -r^2 + <I1-I2,I1-I2> + v * 2<I1-I2, V1-V2> + v^2 *<V1-V2,V1-V2>
- // so we calculate a, b, c - and solve the quadratic equation
- // 0 = c + bv + av^2
- // b = 2 * <I1-I2, V1-V2>
- var b = 2 * init1.minus(init2).dot(vec1.minus(vec2));
- // c = -r^2 + (I2 - I1)^T * (I2 - I1)
- var c = -radius * radius + init2.minus(init1).squaredMagnitude();
- var discr = b * b - 4 * a * c;
- if (discr < 0)
- return null;
- var v1 = (-b - Math.sqrt(discr)) / (2 * a);
- var v2 = (-b + Math.sqrt(discr)) / (2 * a);
- if (v1 <= v2 && ((v1 <= 1 && 1 <= v2) ||
- (v1 <= 0 && 0 <= v2) ||
- (0 <= v1 && v2 <= 1))) {
- // Pick a good "time" at which to report the collision.
- var v;
- if (v1 <= 0) {
- // The collision started before this frame. Report it at the start of the frame.
- v = 0;
- } else {
- // The collision started during this frame. Report it at that moment.
- v = v1;
- }
-
- var result1 = init1.plus(vec1.times(v));
- var result2 = init2.plus(vec2.times(v));
-
- var result = result1.plus(result2).times(0.5);
- if (result.x >= Constants.MIN_X &&
- result.x <= Constants.MAX_X &&
- result.y >= Constants.MIN_Y &&
- result.y <= Constants.MAX_Y &&
- result.z >= Constants.MIN_Z &&
- result.z <= Constants.MAX_Z)
- return result;
- }
- return null;
- }
-
- // the planes have the same speeds and are moving in parallel (or they are not moving at all)
- // they thus have the same distance all the time ; we calculate it from the initial point
-
- // dist = || i2 - i1 || = sqrt( ( i2 - i1 )^T * ( i2 - i1 ) )
-
- var dist = init2.minus(init1).magnitude();
- if (dist <= radius)
- return init1.plus(init2).times(0.5);
-
- return null;
- };
- //red_black_tree.js
- var RedBlackTree = (function(){
- function compare(a, b) {
- return a.compareTo(b);
- }
-
- function treeMinimum(x) {
- while (x.left)
- x = x.left;
- return x;
- }
-
- function treeMaximum(x) {
- while (x.right)
- x = x.right;
- return x;
- }
-
- function Node(key, value) {
- this.key = key;
- this.value = value;
- this.left = null;
- this.right = null;
- this.parent = null;
- this.color = "red";
- }
-
- Node.prototype.successor = function() {
- var x = this;
- if (x.right)
- return treeMinimum(x.right);
- var y = x.parent;
- while (y && x == y.right) {
- x = y;
- y = y.parent;
- }
- return y;
- };
-
- Node.prototype.predecessor = function() {
- var x = this;
- if (x.left)
- return treeMaximum(x.left);
- var y = x.parent;
- while (y && x == y.left) {
- x = y;
- y = y.parent;
- }
- return y;
- };
-
- Node.prototype.toString = function() {
- return this.key + "=>" + this.value + " (" + this.color + ")";
- };
-
- function RedBlackTree() {
- this._root = null;
- }
-
- RedBlackTree.prototype.put = function(key, value) {
- var insertionResult = this._treeInsert(key, value);
- if (!insertionResult.isNewEntry)
- return insertionResult.oldValue;
- var x = insertionResult.newNode;
-
- while (x != this._root && x.parent.color == "red") {
- if (x.parent == x.parent.parent.left) {
- var y = x.parent.parent.right;
- if (y && y.color == "red") {
- // Case 1
- x.parent.color = "black";
- y.color = "black";
- x.parent.parent.color = "red";
- x = x.parent.parent;
- } else {
- if (x == x.parent.right) {
- // Case 2
- x = x.parent;
- this._leftRotate(x);
- }
- // Case 3
- x.parent.color = "black";
- x.parent.parent.color = "red";
- this._rightRotate(x.parent.parent);
- }
- } else {
- // Same as "then" clause with "right" and "left" exchanged.
- var y = x.parent.parent.left;
- if (y && y.color == "red") {
- // Case 1
- x.parent.color = "black";
- y.color = "black";
- x.parent.parent.color = "red";
- x = x.parent.parent;
- } else {
- if (x == x.parent.left) {
- // Case 2
- x = x.parent;
- this._rightRotate(x);
- }
- // Case 3
- x.parent.color = "black";
- x.parent.parent.color = "red";
- this._leftRotate(x.parent.parent);
- }
- }
- }
-
- this._root.color = "black";
- return null;
- };
-
- RedBlackTree.prototype.remove = function(key) {
- var z = this._findNode(key);
- if (!z)
- return null;
-
- // Y is the node to be unlinked from the tree.
- var y;
- if (!z.left || !z.right)
- y = z;
- else
- y = z.successor();
- // Y is guaranteed to be non-null at this point.
- var x;
- if (y.left)
- x = y.left;
- else
- x = y.right;
-
- // X is the child of y which might potentially replace y in the tree. X might be null at
- // this point.
- var xParent;
- if (x) {
- x.parent = y.parent;
- xParent = x.parent;
- } else
- xParent = y.parent;
- if (!y.parent)
- this._root = x;
- else {
- if (y == y.parent.left)
- y.parent.left = x;
- else
- y.parent.right = x;
- }
-
- if (y != z) {
- if (y.color == "black")
- this._removeFixup(x, xParent);
-
- y.parent = z.parent;
- y.color = z.color;
- y.left = z.left;
- y.right = z.right;
-
- if (z.left)
- z.left.parent = y;
- if (z.right)
- z.right.parent = y;
- if (z.parent) {
- if (z.parent.left == z)
- z.parent.left = y;
- else
- z.parent.right = y;
- } else
- this._root = y;
- } else if (y.color == "black")
- this._removeFixup(x, xParent);
-
- return z.value;
- };
-
- RedBlackTree.prototype.get = function(key) {
- var node = this._findNode(key);
- if (!node)
- return null;
- return node.value;
- };
-
- RedBlackTree.prototype.forEach = function(callback) {
- if (!this._root)
- return;
- for (var current = treeMinimum(this._root); current; current = current.successor())
- callback(current.key, current.value);
- };
-
- RedBlackTree.prototype.asArray = function() {
- var result = [];
- this.forEach(function(key, value) {
- result.push({key: key, value: value});
- });
- return result;
- };
-
- RedBlackTree.prototype.toString = function() {
- var result = "[";
- var first = true;
- this.forEach(function(key, value) {
- if (first)
- first = false;
- else
- result += ", ";
- result += key + "=>" + value;
- });
- return result + "]";
- };
-
- RedBlackTree.prototype._findNode = function(key) {
- for (var current = this._root; current;) {
- var comparisonResult = compare(key, current.key);
- if (!comparisonResult)
- return current;
- if (comparisonResult < 0)
- current = current.left;
- else
- current = current.right;
- }
- return null;
- };
-
- RedBlackTree.prototype._treeInsert = function(key, value) {
- var y = null;
- var x = this._root;
- while (x) {
- y = x;
- var comparisonResult = key.compareTo(x.key);
- if (comparisonResult < 0)
- x = x.left;
- else if (comparisonResult > 0)
- x = x.right;
- else {
- var oldValue = x.value;
- x.value = value;
- return {isNewEntry:false, oldValue:oldValue};
- }
- }
- var z = new Node(key, value);
- z.parent = y;
- if (!y)
- this._root = z;
- else {
- if (key.compareTo(y.key) < 0)
- y.left = z;
- else
- y.right = z;
- }
- return {isNewEntry:true, newNode:z};
- };
-
- RedBlackTree.prototype._leftRotate = function(x) {
- var y = x.right;
-
- // Turn y's left subtree into x's right subtree.
- x.right = y.left;
- if (y.left)
- y.left.parent = x;
-
- // Link x's parent to y.
- y.parent = x.parent;
- if (!x.parent)
- this._root = y;
- else {
- if (x == x.parent.left)
- x.parent.left = y;
- else
- x.parent.right = y;
- }
-
- // Put x on y's left.
- y.left = x;
- x.parent = y;
-
- return y;
- };
-
- RedBlackTree.prototype._rightRotate = function(y) {
- var x = y.left;
-
- // Turn x's right subtree into y's left subtree.
- y.left = x.right;
- if (x.right)
- x.right.parent = y;
-
- // Link y's parent to x;
- x.parent = y.parent;
- if (!y.parent)
- this._root = x;
- else {
- if (y == y.parent.left)
- y.parent.left = x;
- else
- y.parent.right = x;
- }
-
- x.right = y;
- y.parent = x;
-
- return x;
- };
-
- RedBlackTree.prototype._removeFixup = function(x, xParent) {
- while (x != this._root && (!x || x.color == "black")) {
- if (x == xParent.left) {
- // Note: the text points out that w cannot be null. The reason is not obvious from
- // simply looking at the code; it comes about from the properties of the red-black
- // tree.
- var w = xParent.right;
- if (w.color == "red") {
- // Case 1
- w.color = "black";
- xParent.color = "red";
- this._leftRotate(xParent);
- w = xParent.right;
- }
- if ((!w.left || w.left.color == "black")
- && (!w.right || w.right.color == "black")) {
- // Case 2
- w.color = "red";
- x = xParent;
- xParent = x.parent;
- } else {
- if (!w.right || w.right.color == "black") {
- // Case 3
- w.left.color = "black";
- w.color = "red";
- this._rightRotate(w);
- w = xParent.right;
- }
- // Case 4
- w.color = xParent.color;
- xParent.color = "black";
- if (w.right)
- w.right.color = "black";
- this._leftRotate(xParent);
- x = this._root;
- xParent = x.parent;
- }
- } else {
- // Same as "then" clause with "right" and "left" exchanged.
-
- var w = xParent.left;
- if (w.color == "red") {
- // Case 1
- w.color = "black";
- xParent.color = "red";
- this._rightRotate(xParent);
- w = xParent.left;
- }
- if ((!w.right || w.right.color == "black")
- && (!w.left || w.left.color == "black")) {
- // Case 2
- w.color = "red";
- x = xParent;
- xParent = x.parent;
- } else {
- if (!w.left || w.left.color == "black") {
- // Case 3
- w.right.color = "black";
- w.color = "red";
- this._leftRotate(w);
- w = xParent.left;
- }
- // Case 4
- w.color = xParent.color;
- xParent.color = "black";
- if (w.left)
- w.left.color = "black";
- this._rightRotate(xParent);
- x = this._root;
- xParent = x.parent;
- }
- }
- }
- if (x)
- x.color = "black";
- };
-
- return RedBlackTree;
- })();
- //reduce_collision_set.js
- 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;
- }
- //simulator.js
- function Simulator(numAircraft) {
- this._aircraft = [];
- for (var i = 0; i < numAircraft; ++i)
- this._aircraft.push(new CallSign("foo" + i));
- }
- Simulator.prototype.simulate = function(time) {
- var frame = [];
- for (var i = 0; i < this._aircraft.length; i += 2) {
- frame.push({
- callsign: this._aircraft[i],
- position: new Vector3D(time, Math.cos(time) * 2 + i * 3, 10)
- });
- frame.push({
- callsign: this._aircraft[i + 1],
- position: new Vector3D(time, Math.sin(time) * 2 + i * 3, 10)
- });
- }
- return frame;
- };
- //vector_2d.js
- function Vector2D(x, y) {
- this.x = x;
- this.y = y;
- }
- Vector2D.prototype.plus = function(other) {
- return new Vector2D(this.x + other.x,
- this.y + other.y);
- };
- Vector2D.prototype.minus = function(other) {
- return new Vector2D(this.x - other.x,
- this.y - other.y);
- };
- Vector2D.prototype.toString = function() {
- return "[" + this.x + ", " + this.y + "]";
- };
- Vector2D.prototype.compareTo = function(other) {
- var result = compareNumbers(this.x, other.x);
- if (result)
- return result;
- return compareNumbers(this.y, other.y);
- };
- //vector_3d.js
- function Vector3D(x, y, z) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
- Vector3D.prototype.plus = function(other) {
- return new Vector3D(this.x + other.x,
- this.y + other.y,
- this.z + other.z);
- };
- Vector3D.prototype.minus = function(other) {
- return new Vector3D(this.x - other.x,
- this.y - other.y,
- this.z - other.z);
- };
- Vector3D.prototype.dot = function(other) {
- return this.x * other.x + this.y * other.y + this.z * other.z;
- };
- Vector3D.prototype.squaredMagnitude = function() {
- return this.dot(this);
- };
- Vector3D.prototype.magnitude = function() {
- return Math.sqrt(this.squaredMagnitude());
- };
- Vector3D.prototype.times = function(amount) {
- return new Vector3D(this.x * amount,
- this.y * amount,
- this.z * amount);
- };
- Vector3D.prototype.as2D = function() {
- return new Vector2D(this.x, this.y);
- };
- Vector3D.prototype.toString = function() {
- return "[" + this.x + ", " + this.y + ", " + this.z + "]";
- };
- //Run the benchmark
- var result = benchmark();
- ////////////////////////////////////////////////////////////////////////////////
- // Runner
- ////////////////////////////////////////////////////////////////////////////////
- top.JetStream.reportResult(result);
|