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

View File

@@ -324,16 +324,19 @@ if (ol.ENABLE_WEBGL) {
*/
ol.render.webgl.LineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {
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;
for (i = 0, ii = lineStringGeometries.length; i < ii; ++i) {
var flatCoordinates = lineStringGeometries[i].getFlatCoordinates();
var stride = lineStringGeometries[i].getStride();
if (this.isValid_(flatCoordinates, 0, flatCoordinates.length, stride)) {
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length,
stride, -this.origin[0], -this.origin[1]);
this.drawCoordinates_(
flatCoordinates, 0, flatCoordinates.length, stride);
if (ends.length > 1) {
for (i = 1, ii = ends.length; i < ii; ++i) {
if (this.isValid_(flatCoordinates, ends[i - 1], ends[i], stride)) {
var lineString = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1], ends[i],
stride, -this.origin[0], -this.origin[1]);
this.drawCoordinates_(
lineString, 0, lineString.length, stride);
}
}
}
if (this.indices.length > indexCount) {

View File

@@ -88,20 +88,39 @@ 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;
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) {
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);
};
@@ -114,13 +133,13 @@ if (ol.ENABLE_WEBGL) {
* @param {ol.structs.LinkedList} list Linked list.
* @param {ol.structs.RBush} rtree R-Tree of the polygon.
* @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(
flatCoordinates, stride, list, rtree, clockwise) {
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(flatCoordinates,
0, flatCoordinates.length, stride);
var i, ii, maxX;
var i, ii, maxXX, maxXY;
var n = this.vertices.length / 2;
/** @type {ol.WebglPolygonVertex} */
var start;
@@ -133,13 +152,17 @@ if (ol.ENABLE_WEBGL) {
if (clockwise === isClockwise) {
start = this.createPoint_(flatCoordinates[0], flatCoordinates[1], n++);
p0 = start;
maxX = flatCoordinates[0];
maxXX = flatCoordinates[0];
maxXY = flatCoordinates[1];
for (i = stride, ii = flatCoordinates.length; i < ii; i += stride) {
p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
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),
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;
}
segments.push(this.insertItem_(p1, start, list));
@@ -149,13 +172,17 @@ if (ol.ENABLE_WEBGL) {
var end = flatCoordinates.length - stride;
start = this.createPoint_(flatCoordinates[end], flatCoordinates[end + 1], n++);
p0 = start;
maxX = flatCoordinates[end];
maxXX = flatCoordinates[end];
maxXY = flatCoordinates[end + 1];
for (i = end - stride, ii = 0; i >= ii; i -= stride) {
p1 = this.createPoint_(flatCoordinates[i], flatCoordinates[i + 1], n++);
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),
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;
}
segments.push(this.insertItem_(p1, start, list));
@@ -164,7 +191,7 @@ if (ol.ENABLE_WEBGL) {
}
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 {number} listMaxX Maximum X value 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,
list, listMaxX, rtree) {
this.classifyPoints_(hole, rtree, true);
var seg = hole.firstItem();
while (seg.p1.x !== holeMaxX) {
seg = hole.nextItem();
@@ -232,19 +259,18 @@ if (ol.ENABLE_WEBGL) {
var intersectingSegments = this.getIntersections_({p0: p1, p1: p2}, rtree, true);
for (i = 0, ii = intersectingSegments.length; i < ii; ++i) {
var currSeg = intersectingSegments[i];
if (currSeg.p0.reflex === undefined) {
var intersection = this.calculateIntersection_(p1, p2, currSeg.p0,
currSeg.p1, true);
var dist = Math.abs(p1.x - intersection[0]);
if (dist < minDist) {
minDist = dist;
p5 = {x: intersection[0], y: intersection[1], i: -1};
seg = currSeg;
}
var intersection = this.calculateIntersection_(p1, p2, currSeg.p0,
currSeg.p1, true);
var dist = Math.abs(p1.x - intersection[0]);
if (dist < minDist && ol.render.webgl.triangleIsCounterClockwise(p1.x, p1.y,
currSeg.p0.x, currSeg.p0.y, currSeg.p1.x, currSeg.p1.y) !== undefined) {
minDist = dist;
p5 = {x: intersection[0], y: intersection[1], i: -1};
seg = currSeg;
}
}
if (minDist === Infinity) {
return;
return false;
}
bestPoint = seg.p1;
@@ -264,7 +290,7 @@ if (ol.ENABLE_WEBGL) {
}
seg = list.firstItem();
while (seg.p1 !== bestPoint) {
while (seg.p1.x !== bestPoint.x || seg.p1.y !== bestPoint.y) {
seg = list.nextItem();
}
@@ -278,6 +304,8 @@ if (ol.ENABLE_WEBGL) {
seg.p1 = p1Bridge;
hole.setFirstItem();
list.concat(hole);
return true;
};
@@ -712,28 +740,33 @@ if (ol.ENABLE_WEBGL) {
* @inheritDoc
*/
ol.render.webgl.PolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {
var polygons = multiPolygonGeometry.getPolygons();
var endss = multiPolygonGeometry.getEndss();
var stride = multiPolygonGeometry.getStride();
var currIndex = this.indices.length;
var currLineIndex = this.lineStringReplay.getCurrentIndex();
var flatCoordinates = multiPolygonGeometry.getFlatCoordinates();
var i, ii, j, jj;
for (i = 0, ii = polygons.length; i < ii; ++i) {
var linearRings = polygons[i].getLinearRings();
if (linearRings.length > 0) {
var flatCoordinates = linearRings[0].getFlatCoordinates();
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length,
var start = 0;
for (i = 0, ii = endss.length; i < ii; ++i) {
var ends = endss[i];
if (ends.length > 0) {
var outerRing = ol.geom.flat.transform.translate(flatCoordinates, start, ends[0],
stride, -this.origin[0], -this.origin[1]);
var holes = [];
var holeFlatCoords;
for (j = 1, jj = linearRings.length; j < jj; ++j) {
holeFlatCoords = linearRings[j].getFlatCoordinates();
holeFlatCoords = ol.geom.flat.transform.translate(holeFlatCoords, 0, holeFlatCoords.length,
stride, -this.origin[0], -this.origin[1]);
holes.push(holeFlatCoords);
if (outerRing.length) {
var holes = [];
var holeFlatCoords;
for (j = 1, jj = ends.length; j < jj; ++j) {
if (ends[j] !== ends[j - 1]) {
holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[j - 1],
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) {
this.startIndices.push(currIndex);
@@ -753,30 +786,34 @@ if (ol.ENABLE_WEBGL) {
* @inheritDoc
*/
ol.render.webgl.PolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
var linearRings = polygonGeometry.getLinearRings();
var ends = polygonGeometry.getEnds();
var stride = polygonGeometry.getStride();
if (linearRings.length > 0) {
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);
var flatCoordinates = linearRings[0].getFlatCoordinates();
flatCoordinates = ol.geom.flat.transform.translate(flatCoordinates, 0, flatCoordinates.length,
if (ends.length > 0) {
var flatCoordinates = polygonGeometry.getFlatCoordinates().map(Number);
var outerRing = ol.geom.flat.transform.translate(flatCoordinates, 0, ends[0],
stride, -this.origin[0], -this.origin[1]);
var holes = [];
var i, ii, holeFlatCoords;
for (i = 1, ii = linearRings.length; i < ii; ++i) {
holeFlatCoords = linearRings[i].getFlatCoordinates();
holeFlatCoords = ol.geom.flat.transform.translate(holeFlatCoords, 0, holeFlatCoords.length,
stride, -this.origin[0], -this.origin[1]);
holes.push(holeFlatCoords);
if (outerRing.length) {
var holes = [];
var i, ii, holeFlatCoords;
for (i = 1, ii = ends.length; i < ii; ++i) {
if (ends[i] !== ends[i - 1]) {
holeFlatCoords = ol.geom.flat.transform.translate(flatCoordinates, ends[i - 1],
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);
}
};

View File

@@ -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];
}
};

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]);
});
});
});