New vector rendering for better performance and less renderer specific limitations. r=elemoine (closes #1675, closes #1656, closes #1631, closes #1431, closes #1709)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@7930 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
ahocevar
2008-09-02 17:17:52 +00:00
parent ede7bef13c
commit c12cb25aee
12 changed files with 676 additions and 155 deletions

View File

@@ -107,6 +107,13 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
*/
selectedFeatures: null,
/**
* Property: unrenderedFeatures
* {Object} hash of features, keyed by feature.id, that the renderer
* failed to draw
*/
unrenderedFeatures: null,
/**
* APIProperty: reportError
* {Boolean} report friendly error message when loading of renderer
@@ -213,6 +220,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
this.features = [];
this.selectedFeatures = [];
this.unrenderedFeatures = {};
// Allow for custom layer behavior
if(this.strategies){
@@ -247,6 +255,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
this.destroyFeatures();
this.features = null;
this.selectedFeatures = null;
this.unrenderedFeatures = null;
if (this.renderer) {
this.renderer.destroy();
}
@@ -360,13 +369,15 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
moveTo: function(bounds, zoomChanged, dragging) {
OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
var coordSysUnchanged = true;
if (!dragging) {
this.renderer.root.style.visibility = "hidden";
this.div.style.left = -parseInt(this.map.layerContainerDiv.style.left) + "px";
this.div.style.top = -parseInt(this.map.layerContainerDiv.style.top) + "px";
var extent = this.map.getExtent();
this.renderer.setExtent(extent);
coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged);
this.renderer.root.style.visibility = "visible";
@@ -376,17 +387,33 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
if (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) {
this.div.scrollLeft = this.div.scrollLeft;
}
if(!zoomChanged && coordSysUnchanged) {
var unrenderedFeatures = {};
for(var i in this.unrenderedFeatures) {
var feature = this.unrenderedFeatures[i];
if(!this.drawFeature(feature)) {
unrenderedFeatures[i] = feature;
}
}
this.unrenderedFeatures = unrenderedFeatures;
}
}
if (!this.drawn || zoomChanged) {
if (!this.drawn || zoomChanged || !coordSysUnchanged) {
this.unrenderedFeatures = {};
this.drawn = true;
var feature;
for(var i=0, len=this.features.length; i<len; i++) {
if (i != (this.features.length - 1)) {
this.renderer.locked = true;
} else {
this.renderer.locked = false;
}
this.drawFeature(this.features[i]);
feature = this.features[i];
if (!this.drawFeature(feature)) {
this.unrenderedFeatures[feature.id] = feature;
};
}
}
},
@@ -438,7 +465,9 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
}
if (this.drawn) {
this.drawFeature(feature);
if(!this.drawFeature(feature)) {
this.unrenderedFeatures[feature.id] = feature;
}
}
if (notify) {
@@ -488,6 +517,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
}
var feature = features[i];
delete this.unrenderedFeatures[feature.id];
if (notify) {
this.events.triggerEvent("beforefeatureremoved", {
@@ -553,6 +583,10 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* style - {Object} Symbolizer hash or {String} renderIntent
*
* Returns:
* {Boolean} true if the renderer was able to draw the feature, false
* otherwise
*/
drawFeature: function(feature, style) {
if (typeof style != "object") {
@@ -564,7 +598,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
}
}
this.renderer.drawFeature(feature, style);
return this.renderer.drawFeature(feature, style);
},
/**

View File

@@ -103,13 +103,19 @@ OpenLayers.Renderer = OpenLayers.Class({
* Resolution has probably changed, so we nullify the resolution
* cache (this.resolution) -- this way it will be re-computed when
* next it is needed.
* We nullify the resolution cache (this.resolution) if resolutionChanged
* is set to true - this way it will be re-computed on the next
* getResolution() request.
*
* Parameters:
* extent - {<OpenLayers.Bounds>}
* resolutionChanged - {Boolean}
*/
setExtent: function(extent) {
setExtent: function(extent, resolutionChanged) {
this.extent = extent.clone();
if (resolutionChanged) {
this.resolution = null;
}
},
/**
@@ -149,13 +155,20 @@ OpenLayers.Renderer = OpenLayers.Class({
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* style - {<Object>}
*
* Returns:
* {Boolean} true if the feature has been drawn completely, false if not,
* undefined if the feature had no geometry
*/
drawFeature: function(feature, style) {
if(style == null) {
style = feature.style;
}
if (feature.geometry) {
this.drawGeometry(feature.geometry, style, feature.id);
if (!feature.geometry.getBounds().intersectsBounds(this.extent)) {
style = {display: "none"};
}
return this.drawGeometry(feature.geometry, style, feature.id);
}
},

View File

@@ -450,26 +450,36 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
* featureId - {String}
*
* Returns:
* {Boolean} true if the geometry has been drawn completely; null if
* incomplete; false otherwise
*/
drawGeometry: function(geometry, style, featureId) {
var className = geometry.CLASS_NAME;
var rendered = true;
if ((className == "OpenLayers.Geometry.Collection") ||
(className == "OpenLayers.Geometry.MultiPoint") ||
(className == "OpenLayers.Geometry.MultiLineString") ||
(className == "OpenLayers.Geometry.MultiPolygon")) {
for (var i = 0, len=geometry.components.length; i<len; i++) {
this.drawGeometry(geometry.components[i], style, featureId);
rendered = rendered && this.drawGeometry(
geometry.components[i], style, featureId);
}
return;
return rendered;
};
rendered = false;
if (style.display != "none") {
if (style.backgroundGraphic) {
this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
this.redrawBackgroundNode(geometry.id, geometry, style,
featureId);
}
this.redrawNode(geometry.id, geometry, style, featureId);
} else {
var node = OpenLayers.Util.getElement(geometry.id);
rendered = this.redrawNode(geometry.id, geometry, style,
featureId);
}
if (rendered == false) {
var node = document.getElementById(geometry.id);
if (node) {
if (node._style.backgroundGraphic) {
node.parentNode.removeChild(document.getElementById(
@@ -478,6 +488,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
node.parentNode.removeChild(node);
}
}
return rendered;
},
/**
@@ -488,6 +499,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
* featureId - {String}
*
* Returns:
* {Boolean} true if the complete geometry could be drawn, null if parts of
* the geometry could not be drawn, false otherwise
*/
redrawNode: function(id, geometry, style, featureId) {
// Get the node if it's already on the map.
@@ -508,7 +523,13 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
newNode._geometry = geometry;
newNode._geometryClass = geometry.CLASS_NAME;
newNode._style = style;
newNode = this.drawGeometryNode(newNode, geometry, style);
var drawResult = this.drawGeometryNode(newNode, geometry, style);
if(drawResult === false) {
return false;
}
newNode = drawResult.node;
// Insert the node into the indexer so it can show us where to
// place it. Note that this operation is O(log(n)). If there's a
@@ -523,6 +544,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
}
this.postDraw(newNode);
return drawResult.complete;
},
/**
@@ -540,6 +563,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
* featureId - {String}
*
* Returns:
* {Boolean} true if the complete geometry could be drawn, null if parts of
* the geometry could not be drawn, false otherwise
*/
redrawBackgroundNode: function(id, geometry, style, featureId) {
var backgroundStyle = OpenLayers.Util.extend({}, style);
@@ -556,7 +583,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
backgroundStyle.backgroundYOffset = null;
backgroundStyle.backgroundGraphicZIndex = null;
this.redrawNode(
return this.redrawNode(
id + this.BACKGROUND_ID_SUFFIX,
geometry,
backgroundStyle,
@@ -574,6 +601,11 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
*
* Returns:
* {Object} a hash with properties "node" (the drawn node) and "complete"
* (null if parts of the geometry could not be drawn, false if nothing
* could be drawn)
*/
drawGeometryNode: function(node, geometry, style) {
style = style || node._style;
@@ -583,25 +615,26 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
'isFilled': true,
'isStroked': !!style.strokeWidth
};
var drawn;
switch (geometry.CLASS_NAME) {
case "OpenLayers.Geometry.Point":
this.drawPoint(node, geometry);
drawn = this.drawPoint(node, geometry);
break;
case "OpenLayers.Geometry.LineString":
options.isFilled = false;
this.drawLineString(node, geometry);
drawn = this.drawLineString(node, geometry);
break;
case "OpenLayers.Geometry.LinearRing":
this.drawLinearRing(node, geometry);
drawn = this.drawLinearRing(node, geometry);
break;
case "OpenLayers.Geometry.Polygon":
this.drawPolygon(node, geometry);
drawn = this.drawPolygon(node, geometry);
break;
case "OpenLayers.Geometry.Surface":
this.drawSurface(node, geometry);
drawn = this.drawSurface(node, geometry);
break;
case "OpenLayers.Geometry.Rectangle":
this.drawRectangle(node, geometry);
drawn = this.drawRectangle(node, geometry);
break;
default:
break;
@@ -612,7 +645,14 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
//set style
//TBD simplify this
return this.setStyle(node, style, options, geometry);
if (drawn != false) {
return {
node: this.setStyle(node, style, options, geometry),
complete: drawn
};
} else {
return false;
}
},
/**
@@ -634,6 +674,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the point
*/
drawPoint: function(node, geometry) {},
@@ -646,6 +689,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components of
* the linestring, or false if nothing could be drawn
*/
drawLineString: function(node, geometry) {},
@@ -658,6 +705,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components
* of the linear ring, or false if nothing could be drawn
*/
drawLinearRing: function(node, geometry) {},
@@ -670,6 +721,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components
* of the polygon, or false if nothing could be drawn
*/
drawPolygon: function(node, geometry) {},
@@ -682,6 +737,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the rectangle
*/
drawRectangle: function(node, geometry) {},
@@ -694,6 +752,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the circle
*/
drawCircle: function(node, geometry) {},
@@ -706,6 +767,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the surface
*/
drawSurface: function(node, geometry) {},

View File

@@ -35,10 +35,10 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
MAX_PIXEL: 15000,
/**
* Property: localResolution
* {Float}
* Property: translationParameters
* {Object} Hash with "x" and "y" properties
*/
localResolution: null,
translationParameters: null,
/**
* Property: symbolSize
@@ -58,6 +58,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
}
OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
arguments);
this.translationParameters = {x: 0, y: 0};
},
/**
@@ -88,14 +89,18 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* x - {Integer}
* y - {Integer}
* xyOnly - {Boolean} whether or not to just check for x and y, which means
* to not take the current translation parameters into account if true.
*
* Returns:
* {Boolean} Whether or not the 'x' and 'y' coordinates are in the
* valid range.
*/
inValidRange: function(x, y) {
return (x >= -this.MAX_PIXEL && x <= this.MAX_PIXEL &&
y >= -this.MAX_PIXEL && y <= this.MAX_PIXEL);
inValidRange: function(x, y, xyOnly) {
var left = x + (xyOnly ? 0 : this.translationParameters.x);
var top = y + (xyOnly ? 0 : this.translationParameters.y);
return (left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL &&
top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL);
},
/**
@@ -103,39 +108,66 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
*
* Parameters:
* extent - {<OpenLayers.Bounds>}
* resolutionChanged - {Boolean}
*
* Returns:
* {Boolean} true to notify the layer that the new extent does not exceed
* the coordinate range, and the features will not need to be redrawn.
* False otherwise.
*/
setExtent: function(extent) {
setExtent: function(extent, resolutionChanged) {
OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,
arguments);
var resolution = this.getResolution();
var left = -extent.left / resolution;
var top = extent.top / resolution;
// If the resolution has changed, start over changing the corner, because
// the features will redraw.
if (!this.localResolution || resolution != this.localResolution) {
this.left = -extent.left / resolution;
this.top = extent.top / resolution;
}
if (resolutionChanged) {
this.left = left;
this.top = top;
// Set the viewbox
var extentString = "0 0 " + this.size.w + " " + this.size.h;
var left = 0;
var top = 0;
// If the resolution has not changed, we already have features, and we need
// to adjust the viewbox to fit them.
if (this.localResolution && resolution == this.localResolution) {
left = (this.left) - (-extent.left / resolution);
top = (this.top) - (extent.top / resolution);
}
// Store resolution for use later.
this.localResolution = resolution;
// Set the viewbox -- the left/top will be pixels-dragged-since-res change,
// the width/height will be pixels.
var extentString = left + " " + top + " " +
this.size.w + " " + this.size.h;
//var extentString = extent.left / resolution + " " + -extent.top / resolution + " " +
this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
this.translate(0, 0);
return true;
} else {
var inRange = this.translate(left - this.left, top - this.top);
if (!inRange) {
// recenter the coordinate system
this.setExtent(extent, true);
}
return inRange;
}
},
/**
* Method: translate
* Transforms the SVG coordinate system
*
* Parameters:
* x - {Float}
* y - {Float}
*
* Returns:
* {Boolean} true if the translation parameters ar in the valid coordinates
* range, false otherwise.
*/
translate: function(x, y) {
if (!this.inValidRange(x, y, true)) {
return false;
} else {
var transformString = "";
if (x || y) {
transformString = "translate(" + x + "," + y + ")";
}
this.root.setAttributeNS(null, "transform", transformString);
this.translationParameters = {x: x, y: y};
return true;
}
},
/**
@@ -413,9 +445,12 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the point
*/
drawPoint: function(node, geometry) {
this.drawCircle(node, geometry, 1);
return this.drawCircle(node, geometry, 1);
},
/**
@@ -426,6 +461,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
* radius - {Float}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the circle
*/
drawCircle: function(node, geometry, radius) {
var resolution = this.getResolution();
@@ -436,10 +474,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
node.setAttributeNS(null, "cx", x);
node.setAttributeNS(null, "cy", y);
node.setAttributeNS(null, "r", radius);
return node;
} else {
node.setAttributeNS(null, "cx", "");
node.setAttributeNS(null, "cy", "");
node.setAttributeNS(null, "r", 0);
return false;
}
},
@@ -451,23 +488,41 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components of
* the linestring, or false if nothing could be drawn
*/
drawLineString: function(node, geometry) {
node.setAttributeNS(null, "points",
this.getComponentsString(geometry.components));
var componentsResult = this.getComponentsString(geometry.components);
if (componentsResult.path) {
node.setAttributeNS(null, "points", componentsResult.path);
return (componentsResult.complete ? node : null);
} else {
return false;
}
},
/**v
/**
* Method: drawLinearRing
* This method is only called by the renderer itself.
*
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components
* of the linear ring, or false if nothing could be drawn
*/
drawLinearRing: function(node, geometry) {
node.setAttributeNS(null, "points",
this.getComponentsString(geometry.components));
var componentsResult = this.getComponentsString(geometry.components);
if (componentsResult.path) {
node.setAttributeNS(null, "points", componentsResult.path);
return (componentsResult.complete ? node : null);
} else {
return false;
}
},
/**
@@ -477,28 +532,35 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or null if the renderer could not draw all components
* of the polygon, or false if nothing could be drawn
*/
drawPolygon: function(node, geometry) {
var d = "";
var draw = true;
var complete = true;
var linearRingResult, path;
for (var j=0, len=geometry.components.length; j<len; j++) {
var linearRing = geometry.components[j];
d += " M";
for (var i=0, ilen=linearRing.components.length; i<ilen; i++) {
var component = this.getShortString(linearRing.components[i]);
if (component) {
d += " " + component;
linearRingResult = this.getComponentsString(
geometry.components[j].components, " ");
path = linearRingResult.path;
if (path) {
d += " " + path;
complete = linearRingResult.complete && complete;
} else {
draw = false;
}
}
}
d += " z";
if (draw) {
node.setAttributeNS(null, "d", d);
node.setAttributeNS(null, "fill-rule", "evenodd");
return complete ? node : null;
} else {
node.setAttributeNS(null, "d", "");
return false;
}
},
@@ -509,6 +571,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the rectangle
*/
drawRectangle: function(node, geometry) {
var resolution = this.getResolution();
@@ -520,11 +585,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
node.setAttributeNS(null, "y", y);
node.setAttributeNS(null, "width", geometry.width / resolution);
node.setAttributeNS(null, "height", geometry.height / resolution);
return node;
} else {
node.setAttributeNS(null, "x", "");
node.setAttributeNS(null, "y", "");
node.setAttributeNS(null, "width", 0);
node.setAttributeNS(null, "height", 0);
return false;
}
},
@@ -535,6 +598,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the renderer could not draw the surface
*/
drawSurface: function(node, geometry) {
@@ -559,8 +625,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
d += " Z";
if (draw) {
node.setAttributeNS(null, "d", d);
return node;
} else {
node.setAttributeNS(null, "d", "");
return false;
}
},
@@ -569,18 +636,92 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
*
* Parameters:
* components - {Array(<OpenLayers.Geometry.Point>)} Array of points
* separator - {String} character between coordinate pairs. Defaults to ","
*
* Returns:
* {Object} hash with properties "path" (the string created from the
* components and "complete" (false if the renderer was unable to
* draw all components)
*/
getComponentsString: function(components) {
getComponentsString: function(components, separator) {
var renderCmp = [];
var complete = true;
var len = components.length;
var strings = [];
for(var i=0, len=components.length; i<len; i++) {
var component = this.getShortString(components[i]);
if (component) {
strings.push(component);
var str, component, j;
for(var i=0; i<len; i++) {
component = components[i];
renderCmp.push(component);
str = this.getShortString(component);
if (str) {
strings.push(str);
} else {
// The current component is outside the valid range. Let's
// see if the previous or next component is inside the range.
// If so, add the coordinate of the intersection with the
// valid range bounds.
if (i > 0) {
if (this.getShortString(components[i + 1])) {
strings.push(this.clipLine(components[i],
components[i-1]));
}
}
return strings.join(",");
if (i < len - 1) {
if (this.getShortString(components[i + 1])) {
strings.push(this.clipLine(components[i],
components[i+1]));
}
}
complete = false;
}
}
return {
path: strings.join(separator || ","),
complete: complete
};
},
/**
* Method: clipLine
* Given two points (one inside the valid range, and one outside),
* clips the line betweeen the two points so that the new points are both
* inside the valid range.
*
* Parameters:
* badComponent - {<OpenLayers.Geometry.Point>)} original geometry of the
* invalid point
* goodComponent - {<OpenLayers.Geometry.Point>)} original geometry of the
* valid point
* Returns
* {String} the SVG coordinate pair of the clipped point (like
* getShortString), or an empty string if both passed componets are at
* the same point.
*/
clipLine: function(badComponent, goodComponent) {
if (goodComponent.equals(badComponent)) {
return "";
}
var resolution = this.getResolution();
var maxX = this.MAX_PIXEL - this.translationParameters.x;
var maxY = this.MAX_PIXEL - this.translationParameters.y;
var x1 = goodComponent.x / resolution + this.left;
var y1 = this.top - goodComponent.y / resolution;
var x2 = badComponent.x / resolution + this.left;
var y2 = this.top - badComponent.y / resolution;
var k;
if (x2 < -maxX || x2 > maxX) {
k = (y2 - y1) / (x2 - x1);
x2 = x2 < 0 ? -maxX : maxX;
y2 = y1 + (x2 - x1) * k;
}
if (y2 < -maxY || y2 > maxY) {
k = (x2 - x1) / (y2 - y1);
y2 = y2 < 0 ? -maxY : maxY;
x2 = x1 + (y2 - y1) * k;
}
return x2 + "," + y2;
},
/**
* Method: getShortString
@@ -589,7 +730,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* point - {<OpenLayers.Geometry.Point>}
*
* Returns:
* {String}
* {String} or false if point is outside the valid range
*/
getShortString: function(point) {
var resolution = this.getResolution();

View File

@@ -79,8 +79,13 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
*
* Parameters:
* extent - {<OpenLayers.Bounds>}
* resolutionChanged - {Boolean}
*
* Returns:
* {Boolean} true to notify the layer that the new extent does not exceed
* the coordinate range, and the features will not need to be redrawn.
*/
setExtent: function(extent) {
setExtent: function(extent, resolutionChanged) {
OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,
arguments);
var resolution = this.getResolution();
@@ -95,6 +100,8 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
// flip the VML display Y axis upside down so it
// matches the display Y axis of the map
this.root.style.flip = "y";
return true;
},
@@ -569,23 +576,6 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
return this.nodeFactory(this.container.id + "_root", "olv:group");
},
/**
* Method: drawFeature
* Overrides the superclass's drawFeature method to take care of features
* that are outside the viewport.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* style - {<Object>}
*/
drawFeature: function(feature, style) {
if (!feature.geometry.getBounds().intersectsBounds(this.extent)) {
style = {display: "none"};
}
OpenLayers.Renderer.Elements.prototype.drawFeature.apply(this,
[feature, style]);
},
/**************************************
* *
* GEOMETRY DRAWING FUNCTIONS *
@@ -599,9 +589,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement} or false if the point could not be drawn
*/
drawPoint: function(node, geometry) {
this.drawCircle(node, geometry, 1);
return this.drawCircle(node, geometry, 1);
},
/**
@@ -613,6 +606,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
* radius - {float}
*
* Returns:
* {DOMElement} or false if the circle could not ne drawn
*/
drawCircle: function(node, geometry, radius) {
if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {
@@ -625,7 +621,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
node.style.width = diameter + "px";
node.style.height = diameter + "px";
return node;
}
return false;
},
@@ -636,9 +634,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement}
*/
drawLineString: function(node, geometry) {
this.drawLine(node, geometry, false);
return this.drawLine(node, geometry, false);
},
/**
@@ -648,9 +649,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement}
*/
drawLinearRing: function(node, geometry) {
this.drawLine(node, geometry, true);
return this.drawLine(node, geometry, true);
},
/**
@@ -661,6 +665,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
* closeLine - {Boolean} Close the line? (make it a ring?)
*
* Returns:
* {DOMElement}
*/
drawLine: function(node, geometry, closeLine) {
@@ -679,6 +686,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
}
var end = (closeLine) ? " x e" : " e";
node.path = "m" + parts.join("") + end;
return node;
},
/**
@@ -688,6 +696,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement}
*/
drawPolygon: function(node, geometry) {
this.setNodeDimension(node, geometry);
@@ -713,6 +724,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
}
path.push("e");
node.path = path.join("");
return node;
},
/**
@@ -722,6 +734,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement}
*/
drawRectangle: function(node, geometry) {
var resolution = this.getResolution();
@@ -730,6 +745,8 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
node.style.top = geometry.y/resolution + "px";
node.style.width = geometry.width/resolution + "px";
node.style.height = geometry.height/resolution + "px";
return node;
},
/**
@@ -738,6 +755,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
* Parameters:
* node - {DOMElement}
* geometry - {<OpenLayers.Geometry>}
*
* Returns:
* {DOMElement}
*/
drawSurface: function(node, geometry) {
@@ -761,6 +781,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
path.push(" x e");
node.path = path.join("");
return node;
},
/**

View File

@@ -126,23 +126,28 @@
}
function test_Layer_Vector_drawFeature(t) {
t.plan(4);
var layer = new OpenLayers.Layer.Vector("Test Layer");
var map = new OpenLayers.Map('map');
t.plan(6);
var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
var map = new OpenLayers.Map('map', {
maxExtent: new OpenLayers.Bounds(-100, -100, 100, 100)
});
map.addLayer(layer);
var geometry = new OpenLayers.Geometry.Point(10, 10);
var feature = new OpenLayers.Feature.Vector(geometry);
var f, s;
// Layer renderer needs a destroy, and draw, for functional tests.
// Bogus layer renderer needs some methods
// for functional tests.
layer.renderer = {
drawFeature: function(feature, style) {
f = feature;
s = style;
},
root: document.createElement("div"),
destroy: function() { },
eraseFeatures: function() {}
eraseFeatures: function() {},
setExtent: function() {}
};
@@ -168,6 +173,17 @@
t.eq(customStyle.foo, s.foo,
"given a custom style, renders with that");
// the real renderer's drawFeature method is tested in Renderer.html
layer.renderer.drawFeature = function(feature) {
return(feature.geometry.getBounds().intersectsBounds(map.getExtent()));
}
layer.addFeatures([feature]);
map.setCenter(new OpenLayers.Bounds(0, 0, 0, 0), 6);
t.ok(layer.unrenderedFeatures[feature.id], "Did not render feature outside the viewport.");
map.panTo(new OpenLayers.LonLat(10, 10));
t.ok(!layer.unrenderedFeatures[feature.id], "Rendered feature inside the viewport.");
layer.features = [];
}
function test_Layer_Vector_eraseFeatures(t) {

View File

@@ -26,7 +26,7 @@
var r = new OpenLayers.Renderer();
var extent = new OpenLayers.Bounds(1,2,3,4);
r.resolution = 1;
r.setExtent(extent);
r.setExtent(extent, true);
t.ok(r.extent.equals(extent), "extent is correctly set");
t.eq(r.resolution, null, "resolution nullified");
}

View File

@@ -134,7 +134,6 @@
var r = create_renderer();
var element = document.createElement("div");
document.body.appendChild(element);
r.root = element;
r.nodeFactory = function(id, type) {
@@ -142,14 +141,15 @@
return element;
};
var g_Node = null;
var b_Node = null;
r.drawGeometryNode = function(node, geometry, style) {
g_Node = node;
return node;
return {node: node, complete: true};
};
r.redrawBackgroundNode = function(id, geometry, style, featureId) {
var el = r.nodeFactory();
el.id = "foo_background";
r.root.appendChild(el);
b_Node = r.nodeFactory();
b_Node.id = "foo_background";
r.root.appendChild(b_Node);
};
r.getNodeType = function(geometry, style) {
@@ -163,20 +163,25 @@
var featureId = 'dude';
r.drawGeometry(geometry, style, featureId);
t.ok(g_Node.parentNode == r.root, "node is correctly appended to root");
t.eq(r.root.childNodes.length, 2, "redrawBackgroundNode appended background node");
t.ok(b_Node.parentNode == r.root, "redrawBackgroundNode appended background node");
t.eq(g_Node._featureId, 'dude', "_featureId is correct");
t.eq(g_Node._style.backgroundGraphic, "foo", "_style is correct");
t.eq(g_Node._geometryClass, 'bar', "_geometryClass is correct");
var _getElement = OpenLayers.Util.getElement;
OpenLayers.Util.getElement = function(id) {
return g_Node;
var returnNode = function(id) {
return id == "foo_background" ? b_Node : g_Node;
}
var _getElement = document.getElementById;
document.getElementById = returnNode;
OpenLayers.Util.getElement = returnNode;
style = {'display':'none'};
r.drawGeometry(geometry, style, featureId);
t.ok(g_Node.parentNode != r.root, "node is correctly removed");
t.ok(!document.getElementById("foo_background"), "background node correctly removed")
t.ok(b_Node.parentNode != r.root, "background node correctly removed")
document.getElementById = _getElement;
tearDown();
}
@@ -216,7 +221,7 @@
properDraw = true;
return {};
};
geometry = {CLASS_NAME: 'OpenLayers.Geometry.LineString'};
geometry = {id: "foo", CLASS_NAME: 'OpenLayers.Geometry.LineString'};
style = true;
r.drawGeometry(geometry, style);
t.ok(properDraw, "drawGeometry called drawLineString when passed a line string");

View File

@@ -79,7 +79,7 @@
// test extent changes
var extent = new OpenLayers.Bounds(4,3,2,1);
r.setExtent(extent);
t.eq(r.rendererRoot.getAttributeNS(null, "viewBox"), "6 6 4 4", "rendererRoot viewBox is correct after a new setExtent");
t.eq(r.root.getAttributeNS(null, "transform").replace(/ /g, ""), "translate(-6,-6)", "rendererRoot viewBox is correct after a new setExtent");
OpenLayers.Renderer.Elements.prototype.setExtent =
OpenLayers.Renderer.Elements.prototype._setExtent;
@@ -128,7 +128,7 @@
return;
}
t.plan(6);
t.plan(5);
var r = new OpenLayers.Renderer.SVG(document.body);
r.resolution = 0.5;
@@ -151,14 +151,22 @@
// #1274: out of bound node fails when first added
var geometry = {
x: 10000000,
y: 200000000
y: 200000000,
CLASS_NAME: "OpenLayers.Geometry.Point",
id: "foo"
}
node.id = geometry.id;
r.root.appendChild(node);
var drawCircleCalled = false;
r.drawCircle = function() {
drawCircleCalled = true;
return OpenLayers.Renderer.SVG.prototype.drawCircle.apply(r, arguments);
}
r.drawCircle(node, geometry, "blah_4000");
t.eq(node.getAttributeNS(null, 'cx'), '', "cx is correct");
t.eq(node.getAttributeNS(null, 'cy'), '', "cy is correct");
t.eq(node.getAttributeNS(null, 'r'), '0', "r is correct");
r.drawGeometry(geometry, {pointRadius: 3}, "blah_4000");
t.eq(drawCircleCalled, true, "drawCircle called on drawGeometry for a point geometry.")
t.ok(node.parentNode != r.root, "circle will not be drawn when coordinates are outside the valid range");
}
function test_SVG_drawlinestring(t) {
@@ -181,7 +189,7 @@
r.getComponentsString = function(c) {
g_GetString = true;
g_Components = c;
return "bar";
return {path: "bar", complete: true};
}
r.drawLineString(node, geometry);
@@ -210,7 +218,7 @@
r.getComponentsString = function(c) {
g_GetString = true;
g_Components = c;
return "bar";
return {path: "bar", complete: true};
}
r.drawLinearRing(node, geometry);
@@ -255,8 +263,7 @@
r.getShortString = function(c) {
return false;
}
r.drawPolygon(node, geometry);
t.eq(node.getAttributeNS(null, "d"), "", "d attribute is empty if one linearRing cannot be drawn");
t.eq(r.drawPolygon(node, geometry), false, "drawPolygon returns false if one linearRing cannot be drawn");
}
function test_SVG_drawrectangle(t) {
@@ -319,8 +326,8 @@
r.getShortString = function(c) {
return false;
}
r.drawSurface(node, geometry);
t.eq(node.getAttributeNS(null, "d"), "", "d attribute is empty if one linearRing cannot be drawn");
t.eq(r.drawSurface(node, geometry), false, "drawSurface returns false if one linearRing cannot be drawn");
}
function test_SVG_getcomponentsstring(t) {
@@ -340,7 +347,7 @@
return p;
};
var string = OpenLayers.Renderer.SVG.prototype.getComponentsString(components);
var string = OpenLayers.Renderer.SVG.prototype.getComponentsString(components).path;
t.eq(string, "foo,bar", "returned string is correct");
OpenLayers.Renderer.SVG.prototype.getShortString =
@@ -424,6 +431,35 @@
t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "longdashdot"}, 1), "8,4,1,4", "dashdot dasharray created correctly");
}
function test_svg_clipline(t) {
if (!OpenLayers.Renderer.SVG.prototype.supported()) {
t.plan(0);
return;
}
t.plan(1);
var r = new OpenLayers.Renderer.SVG(document.body);
r.setSize(new OpenLayers.Size(0, 0));
r.map = {
getResolution: function() {
return 0.5;
}
}
r.setExtent(new OpenLayers.Bounds(0, 0, 0, 0));
var geometry = new OpenLayers.Geometry.LineString([
new OpenLayers.Geometry.Point(0, -5000),
new OpenLayers.Geometry.Point(10000, 0),
new OpenLayers.Geometry.Point(0, 5000)
]);
var node = document.createElement('div');
r.drawLineString(node, geometry);
t.eq(node.getAttribute("points"), "0,10000,15000,2500,15000,-2500,0,-10000", "Geometry correctly clipped at inValidRange bounds");
}
</script>
</head>
<body>

View File

@@ -0,0 +1,123 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SVG inValidRange Test Case</title><link
href="../../theme/default/style.css"
rel="stylesheet" type="text/css">
<style>
#map {
width: 512px;
height: 512px;
border: 1px solid #4B3624;
background: White;
}
.olControlAttribution { bottom: 0px!important }
</style>
<script src="../../lib/OpenLayers.js"
type="text/javascript"></script>
<script type="text/javascript">var map;
// avoid pink tiles
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";
var vectorLayer;
var markerLayer, boxes, newPoint;
function init(){
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
units: "m",
numZoomLevels: 19,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
20037508, 20037508.34)
};
map = new OpenLayers.Map('map', options);
map.addControl(new OpenLayers.Control.MousePosition());
vectorLayer = new OpenLayers.Layer.Vector("Trails", {isBaseLayer: true});
markerLayer = new OpenLayers.Layer.Markers("WayPoints");
map.addLayers([vectorLayer,markerLayer]);
var style_trail = OpenLayers.Util.extend({},
OpenLayers.Feature.Vector.style['default']);
style_trail.strokeColor = "green";
style_trail.strokeWidth = 5;
var pointList = [];
newPoint = new OpenLayers.Geometry.Point(-13653735.8487833,5726045.3578081);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653731.3960036,5726056.5070679);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653730.8394062,5726044.7207079);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653743.1958697,5726043.9243328);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653754.1051798,5726046.9505586);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653760.4503907,5726056.5070679);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653767.4635187,5726065.5857612);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653830.136392,5726052.2066375);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-13653846.5003571,5726042.3315828);
pointList.push(newPoint);
var lineFeature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LineString(pointList));
lineFeature.fid = 52730;
vectorLayer.addFeatures(lineFeature);
pointList = [];
newPoint = new OpenLayers.Geometry.Point(-12250153.3626406,4852001.6114048);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-12194315.5060664,4800503.5113048);
pointList.push(newPoint);
newPoint = new OpenLayers.Geometry.Point(-12180445.0975155,4873109.008858);
pointList.push(newPoint);
lineFeature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LineString(pointList),null,style_trail);
lineFeature.fid = 52751;
vectorLayer.addFeatures([lineFeature]);
var size = new OpenLayers.Size(15, 15);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon('../../img/marker.png', size, offset);
markerLayer.addMarker(new OpenLayers.Marker(
new OpenLayers.LonLat((newPoint.x + 400), (newPoint.y - 400)), icon));
map.setCenter(new OpenLayers.LonLat(newPoint.x, newPoint.y), 13)
}
function zoomToScale(zoom) {
if (zoom == 8) map.zoomToScale(3385.5001275);
else if(zoom == 7) map.zoomToScale(6771.000255);
else if (zoom == 6) map.zoomToScale(13542);
else if (zoom == 5) map.zoomToScale(27084.001020);
else if (zoom == 4) map.zoomToScale(54168.001020);
else if (zoom == 3) map.zoomToScale(108337);
else if (zoom == 2) map.zoomToScale(3466752.1306573446);
else if (zoom == 1) map.zoomToScale(13867008.522629378);
else if (zoom == 0) map.zoomToScale(55468034.09051751);
}
</script>
</head>
<body onLoad="init()">
<h1 id="title">SVG inValidRange Clipping Test Case</h1>
<p>Behavior before fixing #1631: Push Zoom 5. You see lines. Push
Zoom 6. No lines.</p>
<div id="map">
</div>
<button onClick="zoomToScale(5);">Zoom 5</button>
<button onClick="zoomToScale(6);">Zoom 6</button>
<button onClick="zoomToScale(7);">Zoom 7</button>
<button onClick="zoomToScale(8);">Zoom 8</button>
</body>
</html>

View File

@@ -0,0 +1,58 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
<style type="text/css">
#map {
width: 512px;
height: 512px;
border: 1px solid gray;
}
</style>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var map, point;
function init(){
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
maxResolution: 20, //0.07464553542137146,
maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
20037508, 20037508.34)
};
map = new OpenLayers.Map('map', options);
var vector = new OpenLayers.Layer.Vector(
"Vectors",
{isBaseLayer: true}
);
map.addLayer(vector);
var x = -20000;//4.33791754;
var y = 20000;
point = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(x, y)
);
map.addLayer(vector);
vector.addFeatures([point]);
map.setCenter(new OpenLayers.LonLat(0, 0), 5);
}
function pan(){
map.panTo(point.geometry.getBounds().getCenterLonLat());
}
</script>
</head>
<body onload="init()">
<h3 id="title">SVG inValidRange Redraw Test Case</h3>
<p>Before fixing #1631, after klicking Go! no point would have appeared. The Go! button
pans the map over a long distance. Before dragging, the point would have been
outside the valid range, and the pan operation would not have triggered the SVG
coordinate system to be recreated. The new vector rendering takes care of all this. </p>
<div id="map"></div>
<input type="button" value="Go!" onclick="pan();"></input>
</body>
</html>

View File

@@ -73,7 +73,7 @@
}
function vectorTestNew() {
vectorLayer.renderer.drawFeature = drawFeature;
vectorLayer.renderer.drawFeature = OpenLayers.Renderer[vectorLayer.renderer.CLASS_NAME.split(".")[2]].prototype.drawFeature;
console.time("addFeatures");
vectorLayer.addFeatures(features);
@@ -89,17 +89,25 @@
map.addControl(new OpenLayers.Control.MousePosition());
map.setCenter(new OpenLayers.LonLat(-22.5, -22.5), 3);
drawFeature = vectorLayer.renderer.drawFeature;
vectorLayer.events.register("featuresadded", this, nextRun);
features = new Array(100);
features = new Array(200);
var x, y
for (var i = 0; i < 100; i++) {
for (var i = 0; i < 200; i++) {
x = -Math.random()*45;
y = -Math.random()*45;
features[i] = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.LinearRing([
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
-Math.random()*5+x, -Math.random()*5+y),
new OpenLayers.Geometry.Point(
@@ -119,14 +127,16 @@
</script>
</head>
<body onload="init()">
<h1 id="title">Vector Features Performance Test</h1>
<h1 id="title">New Rendering - Vector Features Performance Test</h1>
<div id="map"></div>
<p>
This test examines if checking for a feature being inside the visible
extent before rendering it has an impact on performance. Make sure that
the Firebug console is visible when running this test to see the results.
extent before rendering it has an impact on performance. Open the Firebug
console after running this test (hit F12) to see the results.
<br/>
After the performance test, you can drag around the map to see how the new
vector rendering feels where features get rendered only when they are visible
inside the map extent.
</p>
</body>
</html>