* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Constants } from './constants';
import { CallSign } from './call_sign';
import { Vector3D } from './vector_3d';
const TIMES_NUM: number = 0.5;
const DOT_TWO: number = 2;
const DOT_FOUR: number = 4;
export class Motion {
callSign: CallSign;
posOne: Vector3D;
posTwo: Vector3D;
constructor(callSign: CallSign, posOne: Vector3D, posTwo: Vector3D) {
this.callSign = callSign;
this.posOne = posOne;
this.posTwo = posTwo;
}
toString(): string {
return 'Motion(' + this.callSign + ' from ' + this.posOne + ' to ' + this.posTwo + ')';
}
delta(): Vector3D {
return this.posTwo.minus(this.posOne);
}
findIntersection(other: Motion): Vector3D | null {
let init1 = this.posOne;
let init2 = other.posOne;
let vec1 = this.delta();
let vec2 = other.delta();
let radius = Constants.proximityRadius;
let a = vec2.minus(vec1).squaredMagnitude();
if (a !== 0) {
let b = DOT_TWO * init1.minus(init2).dot(vec1.minus(vec2));
let c = -radius * radius + init2.minus(init1).squaredMagnitude();
let discr = b * b - DOT_FOUR * a * c;
if (discr < 0) {
return null;
}
let v1 = (-b - Math.sqrt(discr)) / (DOT_TWO * a);
let v2 = (-b + Math.sqrt(discr)) / (DOT_TWO * a);
if (v1 <= v2 && ((v1 <= 1 && 1 <= v2) || (v1 <= 0 && 0 <= v2) || (0 <= v1 && v2 <= 1))) {
let v: number = 0;
if (v1 <= 0) {
v = 0;
} else {
v = v1;
}
let result1 = init1.plus(vec1.times(v));
let result2 = init2.plus(vec2.times(v));
let result = result1.plus(result2).times(TIMES_NUM);
if (
result.x >= Constants.minX &&
result.x <= Constants.maxX &&
result.y >= Constants.minY &&
result.y <= Constants.maxY &&
result.z >= Constants.minZ &&
result.z <= Constants.maxZ
) {
return result;
}
}
return null;
}
let dist = init2.minus(init1).magnitude();
if (dist <= radius) {
return init1.plus(init2).times(TIMES_NUM);
}
return null;
}
}