UNPKG

route-bounder

Version:

Create bounds between a polyline / set of waypoints. Useful for searching for places along a route.

1 lines 5.72 kB
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface Waypoint {\n latitude: number\n longitude: number\n}\n\nexport interface Bounds {\n north: number\n south: number\n east: number\n west: number\n}\n\nconst calcEarthRadiusMeters = (latitudeRadians: number): number => {\n // Constants based on the WGS84 ellipsoid model\n const equatorialRadius = 6378137.0 // meters\n const flattening = 1 / 298.257223563\n\n // Calculate the radius using the formula\n const radius =\n equatorialRadius /\n Math.sqrt(1 - flattening * Math.sin(latitudeRadians) * Math.sin(latitudeRadians))\n\n return radius\n}\n\nconst calcLonDistance = ({ latitude, longitude }: Waypoint, distance: number): number => {\n const earthRadius = calcEarthRadiusMeters((latitude * Math.PI) / 180) // Calculate radius at given latitude\n const displacementRadians = distance / earthRadius\n\n const newLonRad = (longitude * Math.PI) / 180 + displacementRadians\n const newLonDegrees = ((newLonRad + Math.PI) % (2 * Math.PI)) - Math.PI // Wrap longitude correctly\n\n return (newLonDegrees * 180) / Math.PI\n}\n\nfunction calcVerticalDistance(waypointA: Waypoint, waypointB: Waypoint): number {\n // Convert latitudes to radians\n const lat1Rad = (waypointA.latitude * Math.PI) / 180\n const lat2Rad = (waypointB.latitude * Math.PI) / 180\n\n // Calculate Earth's radii at both latitudes\n const radius1 = calcEarthRadiusMeters(lat1Rad)\n const radius2 = calcEarthRadiusMeters(lat2Rad)\n\n // Calculate the central angle between the points using the Haversine formula\n const centralAngle =\n 2 *\n Math.asin(\n Math.sqrt(\n Math.pow(Math.sin((lat2Rad - lat1Rad) / 2), 2) +\n Math.cos(lat1Rad) *\n Math.cos(lat2Rad) *\n Math.pow(\n Math.sin(\n ((waypointB.longitude - waypointA.longitude) * Math.PI) / 180\n ) / 2,\n 2\n )\n )\n )\n\n // Calculate the vertical distance using the arc length formula\n const verticalDistance = ((radius1 + radius2) * centralAngle) / 2\n\n return verticalDistance\n}\n\n// Create a rectangle whose length covers coordinates A and B with distance padding on each side\nconst calcBounds = (\n { latitude: latA, longitude: lngA }: Waypoint,\n { latitude: latB, longitude: lngB }: Waypoint,\n distance: number\n): Bounds => {\n const startLon = lngA < lngB ? lngA : lngB\n const endLon = lngA > lngB ? lngA : lngB\n\n const southLat = latA < latB ? latA : latB\n const northLat = latA > latB ? latA : latB\n const startWaypoint: Waypoint = { latitude: latA, longitude: startLon }\n const endWaypoint: Waypoint = { latitude: latA, longitude: endLon }\n\n const eastLon = calcLonDistance(startWaypoint, -1 * distance)\n const westLon = calcLonDistance(endWaypoint, distance)\n\n return {\n north: northLat,\n south: southLat,\n east: eastLon,\n west: westLon,\n }\n}\n\n/**\n *\n * @param waypoints A set of waypoints that make up a polyline for a navigational route\n * @param resolution The vertical distance, in meters, that each bound should satisfy.\n * @param distance The horizontal padding that each bound should take up\n * @returns {Bounds[]} An array of bounds centered around the given waypoint path\n */\nconst createRouteBlocker = (\n waypoints: Waypoint[],\n resolution: number,\n distance: number\n): Bounds[] => {\n let startWaypoint = waypoints[0]\n let bounds: Bounds[] = []\n\n for (const waypoint of waypoints) {\n const vertDistance = calcVerticalDistance(startWaypoint, waypoint)\n if (vertDistance >= resolution) {\n bounds.push(calcBounds(startWaypoint, waypoint, distance))\n startWaypoint = waypoint\n }\n }\n\n return bounds\n}\n\nexport default createRouteBlocker\n"],"mappings":";AAYA,IAAM,wBAAwB,CAAC,oBAAoC;AAE/D,QAAM,mBAAmB;AACzB,QAAM,aAAa,IAAI;AAGvB,QAAM,SACF,mBACA,KAAK,KAAK,IAAI,aAAa,KAAK,IAAI,eAAe,IAAI,KAAK,IAAI,eAAe,CAAC;AAEpF,SAAO;AACX;AAEA,IAAM,kBAAkB,CAAC,EAAE,UAAU,UAAU,GAAa,aAA6B;AACrF,QAAM,cAAc,sBAAuB,WAAW,KAAK,KAAM,GAAG;AACpE,QAAM,sBAAsB,WAAW;AAEvC,QAAM,YAAa,YAAY,KAAK,KAAM,MAAM;AAChD,QAAM,iBAAkB,YAAY,KAAK,OAAO,IAAI,KAAK,MAAO,KAAK;AAErE,SAAQ,gBAAgB,MAAO,KAAK;AACxC;AAEA,SAAS,qBAAqB,WAAqB,WAA6B;AAE5E,QAAM,UAAW,UAAU,WAAW,KAAK,KAAM;AACjD,QAAM,UAAW,UAAU,WAAW,KAAK,KAAM;AAGjD,QAAM,UAAU,sBAAsB,OAAO;AAC7C,QAAM,UAAU,sBAAsB,OAAO;AAG7C,QAAM,eACF,IACA,KAAK;AAAA,IACD,KAAK;AAAA,MACD,KAAK,IAAI,KAAK,KAAK,UAAU,WAAW,CAAC,GAAG,CAAC,IACzC,KAAK,IAAI,OAAO,IACZ,KAAK,IAAI,OAAO,IAChB,KAAK;AAAA,QACD,KAAK;AAAA,WACC,UAAU,YAAY,UAAU,aAAa,KAAK,KAAM;AAAA,QAC9D,IAAI;AAAA,QACJ;AAAA,MACJ;AAAA,IACZ;AAAA,EACJ;AAGJ,QAAM,oBAAqB,UAAU,WAAW,eAAgB;AAEhE,SAAO;AACX;AAGA,IAAM,aAAa,CACf,EAAE,UAAU,MAAM,WAAW,KAAK,GAClC,EAAE,UAAU,MAAM,WAAW,KAAK,GAClC,aACS;AACT,QAAM,WAAW,OAAO,OAAO,OAAO;AACtC,QAAM,SAAS,OAAO,OAAO,OAAO;AAEpC,QAAM,WAAW,OAAO,OAAO,OAAO;AACtC,QAAM,WAAW,OAAO,OAAO,OAAO;AACtC,QAAM,gBAA0B,EAAE,UAAU,MAAM,WAAW,SAAS;AACtE,QAAM,cAAwB,EAAE,UAAU,MAAM,WAAW,OAAO;AAElE,QAAM,UAAU,gBAAgB,eAAe,KAAK,QAAQ;AAC5D,QAAM,UAAU,gBAAgB,aAAa,QAAQ;AAErD,SAAO;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,EACV;AACJ;AASA,IAAM,qBAAqB,CACvB,WACA,YACA,aACW;AACX,MAAI,gBAAgB,UAAU,CAAC;AAC/B,MAAI,SAAmB,CAAC;AAExB,aAAW,YAAY,WAAW;AAC9B,UAAM,eAAe,qBAAqB,eAAe,QAAQ;AACjE,QAAI,gBAAgB,YAAY;AAC5B,aAAO,KAAK,WAAW,eAAe,UAAU,QAAQ,CAAC;AACzD,sBAAgB;AAAA,IACpB;AAAA,EACJ;AAEA,SAAO;AACX;AAEA,IAAO,cAAQ;","names":[]}