137 lines
5.6 KiB
JavaScript
137 lines
5.6 KiB
JavaScript
// 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.
|
|
|
|
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;
|
|
};
|
|
|