diff --git a/mibpov.js b/mibpov.js index 2f3810d..3161d93 100644 --- a/mibpov.js +++ b/mibpov.js @@ -646,19 +646,35 @@ let cachedVoronoiDiagram = null; function getVoronoiDiagram(points, recalculate) { // Calculate bounding box, defaults to heat/humidity limits ... let vbbox = {xl: limit_heat_min, xr: limit_heat_max, yb: limit_humidity_max, yt: limit_humidity_min}; - const BUFFER_ZONE = 1; + // ... unless a point is out of bounds, // then we increase the bounding box size + + // Calculate by how much to extend the + // bounding box for the given value. + let getBufferZone = function(value) { + // This essentially calculates the "order of magnitude" + // in base-2. + return 2**Math.floor(Math.log2(Math.abs(value))); + + // The reason why we do this is due to floating-point arithmetic. + // If we’d add/subtract a constant offset (like 1) from the value, + // the offset might disappear if the value is very large, + // due to floating point rounding, thus effectively adding/subtracting 0. + // This scaling makes sure we'll apply an offset that is + // "in the ballpark" of the origin value + } + for (let p of points) { if (p.heat < vbbox.xl) { - vbbox.xl = p.heat - BUFFER_ZONE; + vbbox.xl = p.heat - getBufferZone(p.heat); } else if (p.heat > vbbox.xr) { - vbbox.xr = p.heat + BUFFER_ZONE; + vbbox.xr = p.heat + getBufferZone(p.heat); } if (p.humidity < vbbox.yt) { - vbbox.yt = p.humidity - BUFFER_ZONE; + vbbox.yt = p.humidity - getBufferZone(p.humidity); } else if (p.humidity > vbbox.yb) { - vbbox.yb = p.humidity + BUFFER_ZONE; + vbbox.yb = p.humidity + getBufferZone(p.humidity); } } if ((cachedVoronoiDiagram === null) || recalculate) {