diff options
Diffstat (limited to 'jstests/core/geo_polygon2.js')
-rw-r--r-- | jstests/core/geo_polygon2.js | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/jstests/core/geo_polygon2.js b/jstests/core/geo_polygon2.js new file mode 100644 index 00000000000..c626064f153 --- /dev/null +++ b/jstests/core/geo_polygon2.js @@ -0,0 +1,263 @@ +// +// More tests for N-dimensional polygon querying +// + +// Create a polygon of some shape (no holes) +// using turtle graphics. Basically, will look like a very contorted octopus (quad-pus?) shape. +// There are no holes, but some edges will probably touch. + +var numTests = 4; + +for ( var test = 0; test < numTests; test++ ) { + + Random.srand( 1337 + test ); + + var numTurtles = 4; + var gridSize = [ 20, 20 ]; + var turtleSteps = 500; + var bounds = [ Random.rand() * -1000000 + 0.00001, Random.rand() * 1000000 + 0.00001 ]; + var rotation = Math.PI * Random.rand(); + var bits = Math.floor( Random.rand() * 32 ); + + printjson( { test : test, rotation : rotation, bits : bits }); + + var rotatePoint = function( x, y ) { + + if( y == undefined ){ + y = x[1]; + x = x[0]; + } + + xp = x * Math.cos( rotation ) - y * Math.sin( rotation ); + yp = y * Math.cos( rotation ) + x * Math.sin( rotation ); + + var scaleX = (bounds[1] - bounds[0]) / 360; + var scaleY = (bounds[1] - bounds[0]) / 360; + + x *= scaleX; + y *= scaleY; + + return [xp, yp]; + }; + + var grid = []; + for ( var i = 0; i < gridSize[0]; i++ ) { + grid.push( new Array( gridSize[1] ) ); + } + + grid.toString = function() { + + var gridStr = ""; + for ( var j = grid[0].length - 1; j >= -1; j-- ) { + for ( var i = 0; i < grid.length; i++ ) { + if ( i == 0 ) + gridStr += ( j == -1 ? " " : ( j % 10) ) + ": "; + if ( j != -1 ) + gridStr += "[" + ( grid[i][j] != undefined ? grid[i][j] : " " ) + "]"; + else + gridStr += " " + ( i % 10 ) + " "; + } + gridStr += "\n"; + } + + return gridStr; + }; + + var turtles = []; + for ( var i = 0; i < numTurtles; i++ ) { + + var up = ( i % 2 == 0 ) ? i - 1 : 0; + var left = ( i % 2 == 1 ) ? ( i - 1 ) - 1 : 0; + + turtles[i] = [ + [ Math.floor( gridSize[0] / 2 ), Math.floor( gridSize[1] / 2 ) ], + [ Math.floor( gridSize[0] / 2 ) + left, Math.floor( gridSize[1] / 2 ) + up ] ]; + + grid[turtles[i][1][0]][turtles[i][1][1]] = i; + + } + + grid[Math.floor( gridSize[0] / 2 )][Math.floor( gridSize[1] / 2 )] = "S"; + + // print( grid.toString() ) + + var pickDirections = function() { + + var up = Math.floor( Random.rand() * 3 ); + if ( up == 2 ) + up = -1; + + if ( up == 0 ) { + var left = Math.floor( Random.rand() * 3 ); + if ( left == 2 ) + left = -1; + } else + left = 0; + + if ( Random.rand() < 0.5 ) { + var swap = left; + left = up; + up = swap; + } + + return [ left, up ]; + }; + + for ( var s = 0; s < turtleSteps; s++ ) { + + for ( var t = 0; t < numTurtles; t++ ) { + + var dirs = pickDirections(); + var up = dirs[0]; + var left = dirs[1]; + + var lastTurtle = turtles[t][turtles[t].length - 1]; + var nextTurtle = [ lastTurtle[0] + left, lastTurtle[1] + up ]; + + if ( nextTurtle[0] >= gridSize[0] || + nextTurtle[1] >= gridSize[1] || + nextTurtle[0] < 0 || + nextTurtle[1] < 0 ) + continue; + + if ( grid[nextTurtle[0]][nextTurtle[1]] == undefined ) { + turtles[t].push( nextTurtle ); + grid[nextTurtle[0]][nextTurtle[1]] = t; + } + + } + } + + turtlePaths = []; + for ( var t = 0; t < numTurtles; t++ ) { + + turtlePath = []; + + var nextSeg = function(currTurtle, prevTurtle) { + + var pathX = currTurtle[0] + + if ( currTurtle[1] < prevTurtle[1] ) { + pathX = currTurtle[0] + 1; + pathY = prevTurtle[1] + } else if ( currTurtle[1] > prevTurtle[1] ) { + pathX = currTurtle[0]; + pathY = currTurtle[1]; + } else if ( currTurtle[0] < prevTurtle[0] ) { + pathX = prevTurtle[0]; + pathY = currTurtle[1]; + } else if ( currTurtle[0] > prevTurtle[0] ) { + pathX = currTurtle[0]; + pathY = currTurtle[1] + 1; + } + + // print( " Prev : " + prevTurtle + " Curr : " + currTurtle + " path + // : " + // + [pathX, pathY]); + + return [ pathX, pathY ] + }; + + for ( var s = 1; s < turtles[t].length; s++ ) { + + currTurtle = turtles[t][s]; + prevTurtle = turtles[t][s - 1]; + + turtlePath.push( nextSeg( currTurtle, prevTurtle ) ); + + } + + for ( var s = turtles[t].length - 2; s >= 0; s-- ) { + + currTurtle = turtles[t][s]; + prevTurtle = turtles[t][s + 1]; + + turtlePath.push( nextSeg( currTurtle, prevTurtle ) ); + + } + + // printjson( turtlePath ) + + // End of the line is not inside our polygon. + var lastTurtle = turtles[t][turtles[t].length - 1]; + grid[lastTurtle[0]][lastTurtle[1]] = undefined; + + fixedTurtlePath = []; + for ( var s = 1; s < turtlePath.length; s++ ) { + + if ( turtlePath[s - 1][0] == turtlePath[s][0] && + turtlePath[s - 1][1] == turtlePath[s][1] ) { + continue; + } + + var up = turtlePath[s][1] - turtlePath[s - 1][1]; + var right = turtlePath[s][0] - turtlePath[s - 1][0]; + var addPoint = ( up != 0 && right != 0 ); + + if ( addPoint && up != right ) { + fixedTurtlePath.push( [ turtlePath[s][0], turtlePath[s - 1][1] ] ); + } else if ( addPoint ) { + fixedTurtlePath.push( [ turtlePath[s - 1][0], turtlePath[s][1] ] ); + } + + fixedTurtlePath.push( turtlePath[s] ); + } + + // printjson( fixedTurtlePath ) + + turtlePaths.push( fixedTurtlePath ); + } + + // Uncomment to print polygon shape + // print( grid.toString() ) + + var polygon = []; + for ( var t = 0; t < turtlePaths.length; t++ ) { + for ( var s = 0; s < turtlePaths[t].length; s++ ) { + polygon.push( rotatePoint( turtlePaths[t][s] ) ); + } + } + + // Uncomment to print out polygon + // printjson( polygon ) + + t = db.polytest2; + t.drop(); + + // Test single and multi-location documents + var pointsIn = 0; + var pointsOut = 0; + var allPointsIn = []; + var allPointsOut = []; + + for ( var j = grid[0].length - 1; j >= 0; j-- ) { + for ( var i = 0; i < grid.length; i++ ) { + var point = rotatePoint( [ i + 0.5, j + 0.5 ] ); + + t.insert( { loc : point } ); + if ( grid[i][j] != undefined ){ + allPointsIn.push( point ); + pointsIn++; + } + else{ + allPointsOut.push( point ); + pointsOut++; + } + } + } + + var res = t.ensureIndex({ loc: "2d" }, { bits: 1 + bits, max: bounds[1], min: bounds[0] }); + assert.writeOK( res ); + + t.insert( { loc : allPointsIn } ); + t.insert( { loc : allPointsOut } ); + allPoints = allPointsIn.concat( allPointsOut ); + t.insert( { loc : allPoints } ); + + print( "Points : " ); + printjson( { pointsIn : pointsIn, pointsOut : pointsOut } ); + //print( t.find( { loc : { "$within" : { "$polygon" : polygon } } } ).count() ) + + assert.eq( gridSize[0] * gridSize[1] + 3, t.find().count() ); + assert.eq( 2 + pointsIn, t.find( { loc : { "$within" : { "$polygon" : polygon } } } ).count() ); +} |