Fix #1951 by rounding all floats passed to Bounds.initialize() and
LonLat.initialize() to 14 significant figures. Added an OpenLayers.Util.toFloat() function, and changed the LonLat constructor and the Bounds constructor to truncate all float parameters to 14 significant figures to avoid numeric comparison errors caused by floating point precision loss. See the comments around the definition of OpenLayers.Util.DEFAULT_PRECISION for how it works. Also refactored Bounds.intersectBounds() for readability, and added a Bounds.touchesBounds() in the process. After tweaking the tests for Layer.SphericalMercator and Format.WKT (because they were expecting too many significant figures), all tests pass. git-svn-id: http://svn.openlayers.org/trunk/openlayers@9022 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<script type="text/javascript">
|
||||
var bounds;
|
||||
function test_Bounds_constructor (t) {
|
||||
t.plan( 17 );
|
||||
t.plan( 21 );
|
||||
|
||||
bounds = new OpenLayers.Bounds();
|
||||
t.ok( bounds instanceof OpenLayers.Bounds, "new OpenLayers.Bounds returns Bounds object" );
|
||||
@@ -36,6 +36,14 @@
|
||||
var center = new OpenLayers.LonLat(5,3);
|
||||
var boundsCenter = bounds.getCenterLonLat();
|
||||
t.ok( boundsCenter.equals(center), "bounds.getCenterLonLat() has correct value" );
|
||||
|
||||
// This is an actual use case with Mercator projection at global scale
|
||||
bounds = new OpenLayers.Bounds(-40075016.67999999,-20037508.339999992,
|
||||
40075016.67999999,20037508.339999992);
|
||||
t.eq( bounds.left, -40075016.68, "bounds.left adjusted for floating precision");
|
||||
t.eq( bounds.bottom, -20037508.34, "bounds.bottom adjusted for floating precision");
|
||||
t.eq( bounds.right, 40075016.68, "bounds.right adjusted for floating precision");
|
||||
t.eq( bounds.top, 20037508.34, "bounds.top adjusted for floating precision");
|
||||
}
|
||||
|
||||
function test_Bounds_constructorFromStrings(t) {
|
||||
@@ -91,13 +99,13 @@
|
||||
var ring = poly.components[0];
|
||||
t.eq(ring.components.length, 5,
|
||||
"four sided polygon created");
|
||||
t.eq(ring.components[0].x, minx,
|
||||
t.eq(ring.components[0].x, OpenLayers.Util.toFloat(minx),
|
||||
"bounds left preserved");
|
||||
t.eq(ring.components[0].y, miny,
|
||||
t.eq(ring.components[0].y, OpenLayers.Util.toFloat(miny),
|
||||
"bounds bottom preserved");
|
||||
t.eq(ring.components[2].x, maxx,
|
||||
t.eq(ring.components[2].x, OpenLayers.Util.toFloat(maxx),
|
||||
"bounds left preserved");
|
||||
t.eq(ring.components[2].y, maxy,
|
||||
t.eq(ring.components[2].y, OpenLayers.Util.toFloat(maxy),
|
||||
"bounds bottom preserved");
|
||||
}
|
||||
|
||||
@@ -157,7 +165,7 @@
|
||||
}
|
||||
|
||||
function test_Bounds_intersectsBounds(t) {
|
||||
t.plan( 17 );
|
||||
t.plan( 19 );
|
||||
|
||||
var aBounds = new OpenLayers.Bounds(-180, -90, 180, 90);
|
||||
|
||||
@@ -194,6 +202,13 @@
|
||||
t.eq( aBounds.intersectsBounds(bBounds, true), false, "(" + aBounds.toBBOX() + ") does not intersect (" + bBounds.toBBOX() + "), inclusive is true" );
|
||||
t.eq( aBounds.intersectsBounds(bBounds, false), false, "(" + aBounds.toBBOX() + ") does not intersect (" + bBounds.toBBOX() + "), inclusive is false" );
|
||||
|
||||
// This is an actual use case with Mercator tiles at global scale
|
||||
var merc_aBounds = new OpenLayers.Bounds(-40075016.67999999,20037508.339999992,
|
||||
-20037508.339999992,40075016.67999999),
|
||||
merc_bBounds = new OpenLayers.Bounds(-20037508.34,-20037508.34,
|
||||
20037508.34,20037508.34);
|
||||
t.eq( merc_aBounds.intersectsBounds(merc_bBounds, true), true, "intersect shouldn't fall prey to floating point errors, inclusive is true");
|
||||
t.eq( merc_aBounds.intersectsBounds(merc_bBounds, false), false, "intersect shouldn't fall prey to floating point errors, inclusive is false");
|
||||
}
|
||||
|
||||
function test_Bounds_containsBounds(t) {
|
||||
@@ -282,7 +297,7 @@
|
||||
var boundsA = new OpenLayers.Bounds(1,2,3,4);
|
||||
var boundsB = new OpenLayers.Bounds(1,2,3,4);
|
||||
var boundsC = new OpenLayers.Bounds(1,5,3,4);
|
||||
|
||||
|
||||
t.ok( boundsA.equals(boundsB), "equals() returns true on two equal bounds." );
|
||||
t.ok( !boundsA.equals(boundsC), "equals() returns false on two different bounds." );
|
||||
t.ok( !boundsA.equals(null), "equals() returns false on comparison to null");
|
||||
|
||||
@@ -6,12 +6,17 @@
|
||||
var lonlat;
|
||||
|
||||
function test_LonLat_constructor (t) {
|
||||
t.plan( 4 );
|
||||
t.plan( 6 );
|
||||
lonlat = new OpenLayers.LonLat(6, 5);
|
||||
t.ok( lonlat instanceof OpenLayers.LonLat, "new OpenLayers.LonLat returns LonLat object" );
|
||||
t.eq( lonlat.CLASS_NAME, "OpenLayers.LonLat", "lonlat.CLASS_NAME is set correctly");
|
||||
t.eq( lonlat.lon, 6, "lonlat.lon is set correctly");
|
||||
t.eq( lonlat.lat, 5, "lonlat.lat is set correctly");
|
||||
|
||||
// possible global Mercator projection values
|
||||
lonlat = new OpenLayers.LonLat(20037508.33999999, -20037508.33999999);
|
||||
t.eq( lonlat.lon, 20037508.34, "lonlat.lon rounds correctly");
|
||||
t.eq( lonlat.lat, -20037508.34, "lonlat.lat rounds correctly");
|
||||
}
|
||||
|
||||
function test_LonLat_constructorFromStrings (t) {
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
|
||||
var points = {
|
||||
src: new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-87.9, 41.9)),
|
||||
dest: new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-9784983.239366667, 5146011.678566458))
|
||||
dest: new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-9784983.2393667, 5146011.6785665))
|
||||
};
|
||||
|
||||
var format = new OpenLayers.Format.WKT({
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
t.eq(sw.lon, -180, "Southwest lon correct");
|
||||
t.eq(ne.lon, 180, "Northeast lon correct");
|
||||
|
||||
t.eq(sw.lat, -85.05112877980659, "Southwest lat correct");
|
||||
t.eq(ne.lat, 85.05112877980660, "Northeast lat correct");
|
||||
t.eq(sw.lat, -85.051128779807, "Southwest lat correct");
|
||||
t.eq(ne.lat, 85.051128779807, "Northeast lat correct");
|
||||
}
|
||||
|
||||
function strToFixed(str, dig) {
|
||||
|
||||
@@ -806,6 +806,16 @@
|
||||
|
||||
}
|
||||
|
||||
function test_toFloat(t) {
|
||||
t.plan(2);
|
||||
// actual possible computed Mercator tile coordinates, more or less
|
||||
var a1=40075016.67999999, b1=-20037508.33999999,
|
||||
a2=40075016.68, b2=-20037508.34;
|
||||
t.eq(OpenLayers.Util.toFloat(a1), OpenLayers.Util.toFloat(a2),
|
||||
"toFloat rounds large floats correctly #1");
|
||||
t.eq(OpenLayers.Util.toFloat(b1), OpenLayers.Util.toFloat(b2),
|
||||
"toFloat rounds large floats correctly #2");
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Reference in New Issue
Block a user