diff --git a/src/ol/render/webgl/polygonreplay.js b/src/ol/render/webgl/polygonreplay.js index 80809c234e..7c442f8a0f 100644 --- a/src/ol/render/webgl/polygonreplay.js +++ b/src/ol/render/webgl/polygonreplay.js @@ -88,17 +88,33 @@ if (ol.ENABLE_WEBGL) { for (i = 0, ii = holeFlatCoordinates.length; i < ii; ++i) { var holeList = { list: new ol.structs.LinkedList(), - maxX: undefined + maxX: undefined, + rtree: new ol.structs.RBush() }; holeLists.push(holeList); holeList.maxX = this.processFlatCoordinates_(holeFlatCoordinates[i], - stride, holeList.list, rtree, false); + stride, holeList.list, holeList.rtree, false); } holeLists.sort(function(a, b) { return b.maxX - a.maxX; }); for (i = 0; i < holeLists.length; ++i) { - this.bridgeHole_(holeLists[i].list, holeLists[i].maxX, outerRing, maxX, rtree); + var currList = holeLists[i].list; + var start = currList.firstItem(); + var currItem = start; + var intersection; + do { + if (this.getIntersections_(currItem, rtree).length) { + intersection = true; + break; + } + currItem = currList.nextItem(); + } while (start !== currItem); + if (!intersection) { + this.classifyPoints_(currList, holeLists[i].rtree, true); + this.bridgeHole_(currList, holeLists[i].maxX, outerRing, maxX, rtree); + rtree.concat(holeLists[i].rtree); + } } } this.classifyPoints_(outerRing, rtree, false); @@ -215,7 +231,6 @@ if (ol.ENABLE_WEBGL) { */ ol.render.webgl.PolygonReplay.prototype.bridgeHole_ = function(hole, holeMaxX, list, listMaxX, rtree) { - this.classifyPoints_(hole, rtree, true); var seg = hole.firstItem(); while (seg.p1.x !== holeMaxX) { seg = hole.nextItem(); @@ -761,7 +776,7 @@ if (ol.ENABLE_WEBGL) { var ends = polygonGeometry.getEnds(); var stride = polygonGeometry.getStride(); if (ends.length > 0) { - var flatCoordinates = polygonGeometry.getFlatCoordinates(); + var flatCoordinates = polygonGeometry.getFlatCoordinates().map(Number); var outerRing = ol.geom.flat.transform.translate(flatCoordinates, 0, ends[0], stride, -this.origin[0], -this.origin[1]); if (outerRing.length) { diff --git a/src/ol/structs/rbush.js b/src/ol/structs/rbush.js index 0828832452..f802507dad 100644 --- a/src/ol/structs/rbush.js +++ b/src/ol/structs/rbush.js @@ -215,3 +215,14 @@ ol.structs.RBush.prototype.getExtent = function(opt_extent) { var data = this.rbush_.data; return ol.extent.createOrUpdate(data.minX, data.minY, data.maxX, data.maxY, opt_extent); }; + + +/** + * @param {ol.structs.RBush} rbush R-Tree. + */ +ol.structs.RBush.prototype.concat = function(rbush) { + this.rbush_.load(rbush.rbush_.all()); + for (var i in rbush.items_) { + this.items_[i | 0] = rbush.items_[i | 0]; + } +}; diff --git a/test/spec/ol/structs/rbush.test.js b/test/spec/ol/structs/rbush.test.js index 1e9741ce83..2ff46ab541 100644 --- a/test/spec/ol/structs/rbush.test.js +++ b/test/spec/ol/structs/rbush.test.js @@ -313,4 +313,29 @@ describe('ol.structs.RBush', function() { }); + describe('#concat', function() { + + it('concatenates two RBush objects', function() { + var obj1 = {}; + var obj2 = {}; + var rBush2 = new ol.structs.RBush(); + rBush.insert([0, 0, 1, 1], obj1); + rBush2.insert([0, 0, 2, 2], obj2); + rBush.concat(rBush2); + expect(rBush.getExtent()).to.eql([0, 0, 2, 2]); + expect(rBush.getAll().length).to.be(2); + }); + + it('preserves the concatenated object\'s references', function() { + var obj1 = {}; + var obj2 = {}; + var rBush2 = new ol.structs.RBush(); + rBush.insert([0, 0, 1, 1], obj1); + rBush2.insert([0, 0, 2, 2], obj2); + rBush.concat(rBush2); + rBush.update([0, 0, 3, 3], obj2); + expect(rBush.getExtent()).to.eql([0, 0, 3, 3]); + }); + }); + });