1import { directionScoreAdjust, distanceScoreAdjust, mode, timeScoreAdjust } from '../env.js'; 2import { ENUatLLAtoXYZmodified, LLAdeltaToENU, LLAdeltaToXYZ, LLAtoXYZ, addVec, distanceBetweenTwoLines, dot, haversineDist, normalise, scaleVec } from "./math.js"; 3 4 5export function projectedMovement(movementENU, deviceOrientation) { 6 const rightness = dot(movementENU, deviceOrientation.right); 7 const upness = dot(movementENU, deviceOrientation.up); 8 9 return normalise([rightness, upness]); 10} 11 12const distanceScore = (distance) => Math.exp(-distance / distanceScoreAdjust); // high if the point is close to the user 13 14 15// score a point based on alignment with the device forward direction 16const directionScore = (point, direction) => { 17 return Math.exp(-directionScoreAdjust * Math.acos(dot(normalise(point), direction))); // high if the point is in the direction of direction 18}; 19 20 21// score a point based on how long since it was created 22const timeScore = (pointTime, now) => Math.exp(-(now - pointTime) / timeScoreAdjust); // high if the point time is close to now 23 24 25// score a point based on alignment between projected movement direction and apparent contrail direction 26const movementScore = (movementENU, deviceOrientation, projectedDirection) => 27 Math.abs( 28 dot( 29 projectedDirection, 30 projectedMovement(movementENU, deviceOrientation) 31 ) 32 ); // high if movement delta is in the projected direction 33 34 35export async function getPointScore(pointData, nextPointData, contrailData) { 36 // assign a match quality score to a point 37 38 // get point attributes needed for scoring 39 const pointTime = pointData[0]; 40 const pointAge = contrailData.unixSeconds - pointTime; 41 const pointLLA = addVec( 42 [pointData[1], pointData[2], pointData[3]], 43 scaleVec(contrailData.windDLLA, pointAge) 44 ); 45 const pointENU = LLAdeltaToENU(pointLLA, contrailData.userLLA); 46 const result = { 47 t: pointTime, 48 LLA: pointLLA, 49 ENU: pointENU, 50 score: -1, 51 scoreDetails: [0, 0, 0, 0], 52 }; 53 54 const distanceOfPoint = haversineDist(pointLLA, contrailData.userLLA); 55 56 // if there is no next point, return the result 57 if (!nextPointData) return result; 58 59 // point is too low to have a contrail form 60 if (pointLLA[2] < contrailData.minAltitude) 61 return result; 62 63 // point is below horizon, can't be on the contrail the user saw 64 if (pointENU[2] < 0) return result; 65 66 // calculate movement to next point 67 const nextPointLLA = addVec( 68 [nextPointData[1], nextPointData[2], nextPointData[3]], 69 scaleVec(contrailData.windDLLA, pointAge) 70 ); 71 const movementENU = LLAdeltaToENU(nextPointLLA, pointLLA); 72 73 const flightPathXYZ = LLAdeltaToXYZ(nextPointLLA, pointLLA); 74 const phoneForwardXYZ = ENUatLLAtoXYZmodified( 75 contrailData.deviceOrientation.forward, 76 contrailData.userLLA 77 ); 78 const flightPointXYZ = LLAtoXYZ(pointLLA); 79 const phonePointXYZ = LLAtoXYZ(contrailData.userLLA); 80 81 const distance = distanceBetweenTwoLines(phonePointXYZ, phoneForwardXYZ, flightPointXYZ, flightPathXYZ); 82 83 console.log("distance: ", distance); 84 85 // wallace's score 86 const distSco = distanceScore(distance); 87 // oscar's score 88 const dirSco = directionScore( 89 pointENU, 90 contrailData.deviceOrientation.forward 91 ); 92 const timSco = timeScore(pointTime, contrailData.unixSeconds); 93 const movSco = movementScore( 94 movementENU, 95 contrailData.deviceOrientation, 96 contrailData.projectedDirection 97 ); 98 99 // calculate the point's score and return the result 100 result.scoreDetails[0] = distSco; 101 result.scoreDetails[1] = timSco; 102 result.scoreDetails[2] = movSco; 103 // extra variable used in testing, but no longer in use 104 result.scoreDetails[3] = 1; 105 if (mode === 'debug') console.log("dir, tim, mov (distance): ", result.scoreDetails, ", (", distance, ")"); 106 result.score = result.scoreDetails.reduce((a, b) => a * b, 1); 107 108 return result; 109}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.