Merge pull request #6858 from GaborFarkas/webgl_vector_improvements

Webgl vector improvements
This commit is contained in:
Frédéric Junod
2017-06-12 09:23:15 +02:00
committed by GitHub
4 changed files with 145 additions and 69 deletions
+12 -9
View File
@@ -324,16 +324,19 @@ if (ol.ENABLE_WEBGL) {
*/ */
ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) { ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
var indexCount = this.indices.length; var indexCount = this.indices.length;
var lineStringGeometries = multiLineStringGeometry.getLineStrings(); var ends = multiLineStringGeometry.getEnds();
ends.unshift(0);
var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
var stride = multiLineStringGeometry.getStride();
var i, ii; var i, ii;
for (i = 0, ii = lineStringGeometries.length; i < ii; ++i) { if (ends.length > 1) {
var flatCoordinates = lineStringGeometries[i].getFlatCoordinates(); for (i = 1, ii = ends.length; i < ii; ++i) {
var stride = lineStringGeometries[i].getStride(); if (this.isValid_(flatCoordinates, ends[i - 1], ends[i], stride)) {
if (this.isValid_(flatCoordinates, 0, flatCoordinates.length, stride)) { var lineString = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1], ends[i],
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length, stride, -this.origin[0], -this.origin[1]);
stride, -this.origin[0], -this.origin[1]); this.drawCoordinates_(
this.drawCoordinates_( lineString, 0, lineString.length, stride);
flatCoordinates, 0, flatCoordinates.length, stride); }
} }
} }
if (this.indices.length > indexCount) { if (this.indices.length > indexCount) {
+97 -60
View File
@@ -88,20 +88,39 @@ if (ol.ENABLE_WEBGL) {
for (i = 0, ii = holeFlatCoordinates.length; i < ii; ++i) { for (i = 0, ii = holeFlatCoordinates.length; i < ii; ++i) {
var holeList = { var holeList = {
list: new ol.structs.LinkedList(), list: new ol.structs.LinkedList(),
maxX: undefined maxX: undefined,
rtree: new ol.structs.RBush()
}; };
holeLists.push(holeList); holeLists.push(holeList);
holeList.maxX = this.processFlatCoordinates_(holeFlatCoordinates[i], holeList.maxX = this.processFlatCoordinates_(holeFlatCoordinates[i],
stride, holeList.list, rtree, false); stride, holeList.list, holeList.rtree, false);
} }
holeLists.sort(function(a, b) { holeLists.sort(function(a, b) {
return b.maxX - a.maxX; return b.maxX[0] === a.maxX[0] ? a.maxX[1] - b.maxX[1] : b.maxX[0] - a.maxX[0];
}); });
for (i = 0; i < holeLists.length; ++i) { 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);
if (this.bridgeHole_(currList, holeLists[i].maxX[0], outerRing, maxX[0], rtree)) {
rtree.concat(holeLists[i].rtree);
this.classifyPoints_(outerRing, rtree, false);
}
}
} }
} else {
this.classifyPoints_(outerRing, rtree, false);
} }
this.classifyPoints_(outerRing, rtree, false);
this.triangulate_(outerRing, rtree); this.triangulate_(outerRing, rtree);
}; };
@@ -114,13 +133,13 @@ if (ol.ENABLE_WEBGL) {
* @param {ol.structs.LinkedList} list Linked list. * @param {ol.structs.LinkedList} list Linked list.
* @param {ol.structs.RBush} rtree R-Tree of the polygon. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
* @param {boolean} clockwise Coordinate order should be clockwise. * @param {boolean} clockwise Coordinate order should be clockwise.
* @return {number} Maximum X value. * @return {Array.<number>} X and Y coords of maximum X value.
*/ */
ol.render.webgl.PolygonReplay.prototype.processFlatCoordinates_ = function( ol.render.webgl.PolygonReplay.prototype.processFlatCoordinates_ = function(
flatCoordinates, stride, list, rtree, clockwise) { flatCoordinates, stride, list, rtree, clockwise) {
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates, var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates,
0, flatCoordinates.length, stride); 0, flatCoordinates.length, stride);
var i, ii, maxX; var i, ii, maxXX, maxXY;
var n = this.vertices.length / 2; var n = this.vertices.length / 2;
/** @type {ol.WebglPolygonVertex} */ /** @type {ol.WebglPolygonVertex} */
var start; var start;
@@ -133,13 +152,17 @@ if (ol.ENABLE_WEBGL) {
if (clockwise === isClockwise) { if (clockwise === isClockwise) {
start = this.createPoint_(flatCoordinates[0], flatCoordinates[1], n++); start = this.createPoint_(flatCoordinates[0], flatCoordinates[1], n++);
p0 = start; p0 = start;
maxX = flatCoordinates[0]; maxXX = flatCoordinates[0];
maxXY = flatCoordinates[1];
for (i = stride, ii = flatCoordinates.length; i < ii; i += stride) { for (i = stride, ii = flatCoordinates.length; i < ii; i += stride) {
p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++); p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
segments.push(this.insertItem_(p0, p1, list)); segments.push(this.insertItem_(p0, p1, list));
extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x), extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
Math.max(p0.y, p1.y)]); Math.max(p0.y, p1.y)]);
maxX = flatCoordinates[i] > maxX ? flatCoordinates[i] : maxX; if (flatCoordinates[i] > maxXX) {
maxXX = flatCoordinates[i];
maxXY = flatCoordinates[i + 1];
}
p0 = p1; p0 = p1;
} }
segments.push(this.insertItem_(p1, start, list)); segments.push(this.insertItem_(p1, start, list));
@@ -149,13 +172,17 @@ if (ol.ENABLE_WEBGL) {
var end = flatCoordinates.length - stride; var end = flatCoordinates.length - stride;
start = this.createPoint_(flatCoordinates[end], flatCoordinates[end + 1], n++); start = this.createPoint_(flatCoordinates[end], flatCoordinates[end + 1], n++);
p0 = start; p0 = start;
maxX = flatCoordinates[end]; maxXX = flatCoordinates[end];
maxXY = flatCoordinates[end + 1];
for (i = end - stride, ii = 0; i >= ii; i -= stride) { for (i = end - stride, ii = 0; i >= ii; i -= stride) {
p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++); p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
segments.push(this.insertItem_(p0, p1, list)); segments.push(this.insertItem_(p0, p1, list));
extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x), extents.push([Math.min(p0.x, p1.x), Math.min(p0.y, p1.y), Math.max(p0.x, p1.x),
Math.max(p0.y, p1.y)]); Math.max(p0.y, p1.y)]);
maxX = flatCoordinates[i] > maxX ? flatCoordinates[i] : maxX; if (flatCoordinates[i] > maxXX) {
maxXX = flatCoordinates[i];
maxXY = flatCoordinates[i + 1];
}
p0 = p1; p0 = p1;
} }
segments.push(this.insertItem_(p1, start, list)); segments.push(this.insertItem_(p1, start, list));
@@ -164,7 +191,7 @@ if (ol.ENABLE_WEBGL) {
} }
rtree.load(extents, segments); rtree.load(extents, segments);
return maxX; return [maxXX, maxXY];
}; };
@@ -212,10 +239,10 @@ if (ol.ENABLE_WEBGL) {
* @param {ol.structs.LinkedList} list Linked list of the polygon. * @param {ol.structs.LinkedList} list Linked list of the polygon.
* @param {number} listMaxX Maximum X value of the polygon. * @param {number} listMaxX Maximum X value of the polygon.
* @param {ol.structs.RBush} rtree R-Tree of the polygon. * @param {ol.structs.RBush} rtree R-Tree of the polygon.
* @return {boolean} Bridging was successful.
*/ */
ol.render.webgl.PolygonReplay.prototype.bridgeHole_ = function(hole, holeMaxX, ol.render.webgl.PolygonReplay.prototype.bridgeHole_ = function(hole, holeMaxX,
list, listMaxX, rtree) { list, listMaxX, rtree) {
this.classifyPoints_(hole, rtree, true);
var seg = hole.firstItem(); var seg = hole.firstItem();
while (seg.p1.x !== holeMaxX) { while (seg.p1.x !== holeMaxX) {
seg = hole.nextItem(); seg = hole.nextItem();
@@ -232,19 +259,18 @@ if (ol.ENABLE_WEBGL) {
var intersectingSegments = this.getIntersections_({p0: p1, p1: p2}, rtree, true); var intersectingSegments = this.getIntersections_({p0: p1, p1: p2}, rtree, true);
for (i = 0, ii = intersectingSegments.length; i < ii; ++i) { for (i = 0, ii = intersectingSegments.length; i < ii; ++i) {
var currSeg = intersectingSegments[i]; var currSeg = intersectingSegments[i];
if (currSeg.p0.reflex === undefined) { var intersection = this.calculateIntersection_(p1, p2, currSeg.p0,
var intersection = this.calculateIntersection_(p1, p2, currSeg.p0, currSeg.p1, true);
currSeg.p1, true); var dist = Math.abs(p1.x - intersection[0]);
var dist = Math.abs(p1.x - intersection[0]); if (dist < minDist && ol.render.webgl.triangleIsCounterClockwise(p1.x, p1.y,
if (dist < minDist) { currSeg.p0.x, currSeg.p0.y, currSeg.p1.x, currSeg.p1.y) !== undefined) {
minDist = dist; minDist = dist;
p5 = {x: intersection[0], y: intersection[1], i: -1}; p5 = {x: intersection[0], y: intersection[1], i: -1};
seg = currSeg; seg = currSeg;
}
} }
} }
if (minDist === Infinity) { if (minDist === Infinity) {
return; return false;
} }
bestPoint = seg.p1; bestPoint = seg.p1;
@@ -264,7 +290,7 @@ if (ol.ENABLE_WEBGL) {
} }
seg = list.firstItem(); seg = list.firstItem();
while (seg.p1 !== bestPoint) { while (seg.p1.x !== bestPoint.x || seg.p1.y !== bestPoint.y) {
seg = list.nextItem(); seg = list.nextItem();
} }
@@ -278,6 +304,8 @@ if (ol.ENABLE_WEBGL) {
seg.p1 = p1Bridge; seg.p1 = p1Bridge;
hole.setFirstItem(); hole.setFirstItem();
list.concat(hole); list.concat(hole);
return true;
}; };
@@ -712,28 +740,33 @@ if (ol.ENABLE_WEBGL) {
* @inheritDoc * @inheritDoc
*/ */
ol.render.webgl.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) { ol.render.webgl.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
var polygons = multiPolygonGeometry.getPolygons(); var endss = multiPolygonGeometry.getEndss();
var stride = multiPolygonGeometry.getStride(); var stride = multiPolygonGeometry.getStride();
var currIndex = this.indices.length; var currIndex = this.indices.length;
var currLineIndex = this.lineStringReplay.getCurrentIndex(); var currLineIndex = this.lineStringReplay.getCurrentIndex();
var flatCoordinates = multiPolygonGeometry.getFlatCoordinates();
var i, ii, j, jj; var i, ii, j, jj;
for (i = 0, ii = polygons.length; i < ii; ++i) { var start = 0;
var linearRings = polygons[i].getLinearRings(); for (i = 0, ii = endss.length; i < ii; ++i) {
if (linearRings.length > 0) { var ends = endss[i];
var flatCoordinates = linearRings[0].getFlatCoordinates(); if (ends.length > 0) {
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length, var outerRing = ol.geom.flat.transform.translate(flatCoordinates, start, ends[0],
stride, -this.origin[0], -this.origin[1]); stride, -this.origin[0], -this.origin[1]);
var holes = []; if (outerRing.length) {
var holeFlatCoords; var holes = [];
for (j = 1, jj = linearRings.length; j < jj; ++j) { var holeFlatCoords;
holeFlatCoords = linearRings[j].getFlatCoordinates(); for (j = 1, jj = ends.length; j < jj; ++j) {
holeFlatCoords = ol.geom.flat.transform.translate(holeFlatCoords, 0, holeFlatCoords.length, if (ends[j] !== ends[j - 1]) {
stride, -this.origin[0], -this.origin[1]); holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[j - 1],
holes.push(holeFlatCoords); ends[j], stride, -this.origin[0], -this.origin[1]);
holes.push(holeFlatCoords);
}
}
this.lineStringReplay.drawPolygonCoordinates(outerRing, holes, stride);
this.drawCoordinates_(outerRing, holes, stride);
} }
this.lineStringReplay.drawPolygonCoordinates(flatCoordinates, holes, stride);
this.drawCoordinates_(flatCoordinates, holes, stride);
} }
start = ends[ends.length - 1];
} }
if (this.indices.length > currIndex) { if (this.indices.length > currIndex) {
this.startIndices.push(currIndex); this.startIndices.push(currIndex);
@@ -753,30 +786,34 @@ if (ol.ENABLE_WEBGL) {
* @inheritDoc * @inheritDoc
*/ */
ol.render.webgl.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) { ol.render.webgl.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
var linearRings = polygonGeometry.getLinearRings(); var ends = polygonGeometry.getEnds();
var stride = polygonGeometry.getStride(); var stride = polygonGeometry.getStride();
if (linearRings.length > 0) { if (ends.length > 0) {
this.startIndices.push(this.indices.length); var flatCoordinates = polygonGeometry.getFlatCoordinates().map(Number);
this.startIndicesFeature.push(feature); var outerRing = ol.geom.flat.transform.translate(flatCoordinates, 0, ends[0],
if (this.state_.changed) {
this.styleIndices_.push(this.indices.length);
this.state_.changed = false;
}
this.lineStringReplay.setPolygonStyle(feature);
var flatCoordinates = linearRings[0].getFlatCoordinates();
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length,
stride, -this.origin[0], -this.origin[1]); stride, -this.origin[0], -this.origin[1]);
var holes = []; if (outerRing.length) {
var i, ii, holeFlatCoords; var holes = [];
for (i = 1, ii = linearRings.length; i < ii; ++i) { var i, ii, holeFlatCoords;
holeFlatCoords = linearRings[i].getFlatCoordinates(); for (i = 1, ii = ends.length; i < ii; ++i) {
holeFlatCoords = ol.geom.flat.transform.translate(holeFlatCoords, 0, holeFlatCoords.length, if (ends[i] !== ends[i - 1]) {
stride, -this.origin[0], -this.origin[1]); holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1],
holes.push(holeFlatCoords); ends[i], stride, -this.origin[0], -this.origin[1]);
holes.push(holeFlatCoords);
}
}
this.startIndices.push(this.indices.length);
this.startIndicesFeature.push(feature);
if (this.state_.changed) {
this.styleIndices_.push(this.indices.length);
this.state_.changed = false;
}
this.lineStringReplay.setPolygonStyle(feature);
this.lineStringReplay.drawPolygonCoordinates(outerRing, holes, stride);
this.drawCoordinates_(outerRing, holes, stride);
} }
this.lineStringReplay.drawPolygonCoordinates(flatCoordinates, holes, stride);
this.drawCoordinates_(flatCoordinates, holes, stride);
} }
}; };
+11
View File
@@ -215,3 +215,14 @@ ol.structs.RBush.prototype.getExtent = function(opt_extent) {
var data = this.rbush_.data; var data = this.rbush_.data;
return ol.extent.createOrUpdate(data.minX, data.minY, data.maxX, data.maxY, opt_extent); 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];
}
};
+25
View File
@@ -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]);
});
});
}); });