OpenLayers OpenLayers

Changeset 7930

Show
Ignore:
Timestamp:
09/02/08 13:17:52 (3 months ago)
Author:
ahocevar
Message:

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

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/openlayers/lib/OpenLayers/Layer/Vector.js

    r7862 r7930  
    107107     */ 
    108108    selectedFeatures: null, 
     109     
     110    /** 
     111     * Property: unrenderedFeatures 
     112     * {Object} hash of features, keyed by feature.id, that the renderer 
     113     *     failed to draw 
     114     */ 
     115    unrenderedFeatures: null, 
    109116 
    110117    /** 
     
    214221        this.features = []; 
    215222        this.selectedFeatures = []; 
     223        this.unrenderedFeatures = {}; 
    216224         
    217225        // Allow for custom layer behavior 
     
    248256        this.features = null; 
    249257        this.selectedFeatures = null; 
     258        this.unrenderedFeatures = null; 
    250259        if (this.renderer) { 
    251260            this.renderer.destroy(); 
     
    360369    moveTo: function(bounds, zoomChanged, dragging) { 
    361370        OpenLayers.Layer.prototype.moveTo.apply(this, arguments); 
     371         
     372        var coordSysUnchanged = true; 
    362373 
    363374        if (!dragging) { 
     
    367378            this.div.style.top = -parseInt(this.map.layerContainerDiv.style.top) + "px"; 
    368379            var extent = this.map.getExtent(); 
    369             this.renderer.setExtent(extent); 
     380            coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged); 
    370381             
    371382            this.renderer.root.style.visibility = "visible"; 
     
    377388                this.div.scrollLeft = this.div.scrollLeft; 
    378389            } 
     390             
     391            if(!zoomChanged && coordSysUnchanged) { 
     392                var unrenderedFeatures = {}; 
     393                for(var i in this.unrenderedFeatures) { 
     394                    var feature = this.unrenderedFeatures[i]; 
     395                    if(!this.drawFeature(feature)) { 
     396                        unrenderedFeatures[i] = feature; 
     397                    } 
     398                } 
     399                this.unrenderedFeatures = unrenderedFeatures; 
     400            } 
    379401        } 
    380402         
    381         if (!this.drawn || zoomChanged) { 
     403        if (!this.drawn || zoomChanged || !coordSysUnchanged) { 
     404            this.unrenderedFeatures = {}; 
    382405            this.drawn = true; 
     406            var feature; 
    383407            for(var i=0, len=this.features.length; i<len; i++) { 
    384408                if (i != (this.features.length - 1)) { 
     
    387411                    this.renderer.locked = false; 
    388412                }     
    389                 this.drawFeature(this.features[i]); 
     413                feature = this.features[i]; 
     414                if (!this.drawFeature(feature)) { 
     415                    this.unrenderedFeatures[feature.id] = feature; 
     416                }; 
    390417            } 
    391418        }     
     
    439466 
    440467            if (this.drawn) { 
    441                 this.drawFeature(feature); 
     468                if(!this.drawFeature(feature)) { 
     469                    this.unrenderedFeatures[feature.id] = feature; 
     470                } 
    442471            } 
    443472             
     
    489518     
    490519            var feature = features[i]; 
     520            delete this.unrenderedFeatures[feature.id]; 
    491521 
    492522            if (notify) { 
     
    554584     * feature - {<OpenLayers.Feature.Vector>}  
    555585     * style - {Object} Symbolizer hash or {String} renderIntent 
     586     *  
     587     * Returns: 
     588     * {Boolean} true if the renderer was able to draw the feature, false 
     589     *     otherwise 
    556590     */ 
    557591    drawFeature: function(feature, style) { 
     
    565599        } 
    566600         
    567         this.renderer.drawFeature(feature, style); 
     601        return this.renderer.drawFeature(feature, style); 
    568602    }, 
    569603     
  • trunk/openlayers/lib/OpenLayers/Renderer.js

    r7862 r7930  
    104104     * cache (this.resolution) -- this way it will be re-computed when  
    105105     * next it is needed. 
    106      * 
    107      * Parameters: 
    108      * extent - {<OpenLayers.Bounds>}  
    109      */ 
    110     setExtent: function(extent) { 
     106     * We nullify the resolution cache (this.resolution) if resolutionChanged 
     107     * is set to true - this way it will be re-computed on the next 
     108     * getResolution() request. 
     109     * 
     110     * Parameters: 
     111     * extent - {<OpenLayers.Bounds>} 
     112     * resolutionChanged - {Boolean} 
     113     */ 
     114    setExtent: function(extent, resolutionChanged) { 
    111115        this.extent = extent.clone(); 
    112         this.resolution = null; 
     116        if (resolutionChanged) { 
     117            this.resolution = null; 
     118        } 
    113119    }, 
    114120     
     
    149155     * Parameters: 
    150156     * feature - {<OpenLayers.Feature.Vector>}  
    151      * style - {<Object>}  
     157     * style - {<Object>} 
     158     *  
     159     * Returns: 
     160     * {Boolean} true if the feature has been drawn completely, false if not, 
     161     *     undefined if the feature had no geometry 
    152162     */ 
    153163    drawFeature: function(feature, style) { 
     
    156166        } 
    157167        if (feature.geometry) { 
    158             this.drawGeometry(feature.geometry, style, feature.id); 
     168            if (!feature.geometry.getBounds().intersectsBounds(this.extent)) { 
     169                style = {display: "none"}; 
     170            } 
     171            return this.drawGeometry(feature.geometry, style, feature.id); 
    159172        } 
    160173    }, 
  • trunk/openlayers/lib/OpenLayers/Renderer/Elements.js

    r7919 r7930  
    451451     * style - {Object} 
    452452     * featureId - {String} 
     453     *  
     454     * Returns: 
     455     * {Boolean} true if the geometry has been drawn completely; null if 
     456     *     incomplete; false otherwise 
    453457     */ 
    454458    drawGeometry: function(geometry, style, featureId) { 
    455459        var className = geometry.CLASS_NAME; 
     460        var rendered = true; 
    456461        if ((className == "OpenLayers.Geometry.Collection") || 
    457462            (className == "OpenLayers.Geometry.MultiPoint") || 
     
    459464            (className == "OpenLayers.Geometry.MultiPolygon")) { 
    460465            for (var i = 0, len=geometry.components.length; i<len; i++) { 
    461                 this.drawGeometry(geometry.components[i], style, featureId); 
     466                rendered = rendered && this.drawGeometry( 
     467                    geometry.components[i], style, featureId); 
    462468            } 
    463             return
     469            return rendered
    464470        }; 
    465471 
     472        rendered = false; 
    466473        if (style.display != "none") { 
    467474            if (style.backgroundGraphic) { 
    468                 this.redrawBackgroundNode(geometry.id, geometry, style, featureId); 
     475                this.redrawBackgroundNode(geometry.id, geometry, style, 
     476                    featureId); 
    469477            } 
    470             this.redrawNode(geometry.id, geometry, style, featureId); 
    471         } else { 
    472             var node = OpenLayers.Util.getElement(geometry.id); 
     478            rendered = this.redrawNode(geometry.id, geometry, style, 
     479                featureId); 
     480        } 
     481        if (rendered == false) { 
     482            var node = document.getElementById(geometry.id); 
    473483            if (node) { 
    474484                if (node._style.backgroundGraphic) { 
     
    479489            } 
    480490        } 
     491        return rendered; 
    481492    }, 
    482493     
     
    489500     * style - {Object} 
    490501     * featureId - {String} 
     502     *  
     503     * Returns: 
     504     * {Boolean} true if the complete geometry could be drawn, null if parts of 
     505     *     the geometry could not be drawn, false otherwise 
    491506     */ 
    492507    redrawNode: function(id, geometry, style, featureId) { 
     
    509524        newNode._geometryClass = geometry.CLASS_NAME; 
    510525        newNode._style = style; 
    511         newNode = this.drawGeometryNode(newNode, geometry, style); 
     526 
     527        var drawResult = this.drawGeometryNode(newNode, geometry, style); 
     528        if(drawResult === false) { 
     529            return false; 
     530        } 
     531          
     532        newNode = drawResult.node; 
    512533         
    513534        // Insert the node into the indexer so it can show us where to 
     
    523544        } 
    524545         
    525         this.postDraw(newNode);  
     546        this.postDraw(newNode); 
     547         
     548        return drawResult.complete; 
    526549    }, 
    527550     
     
    541564     * style - {Object} 
    542565     * featureId - {String} 
     566     *  
     567     * Returns: 
     568     * {Boolean} true if the complete geometry could be drawn, null if parts of 
     569     *     the geometry could not be drawn, false otherwise 
    543570     */ 
    544571    redrawBackgroundNode: function(id, geometry, style, featureId) { 
     
    557584        backgroundStyle.backgroundGraphicZIndex = null; 
    558585         
    559         this.redrawNode( 
     586        return this.redrawNode( 
    560587            id + this.BACKGROUND_ID_SUFFIX,  
    561588            geometry,  
     
    575602     * geometry - {<OpenLayers.Geometry>} 
    576603     * style - {Object} 
     604     *  
     605     * Returns: 
     606     * {Object} a hash with properties "node" (the drawn node) and "complete" 
     607     *     (null if parts of the geometry could not be drawn, false if nothing 
     608     *     could be drawn) 
    577609     */ 
    578610    drawGeometryNode: function(node, geometry, style) { 
     
    584616            'isStroked': !!style.strokeWidth 
    585617        }; 
     618        var drawn; 
    586619        switch (geometry.CLASS_NAME) { 
    587620            case "OpenLayers.Geometry.Point": 
    588                 this.drawPoint(node, geometry); 
     621                drawn = this.drawPoint(node, geometry); 
    589622                break; 
    590623            case "OpenLayers.Geometry.LineString": 
    591624                options.isFilled = false; 
    592                 this.drawLineString(node, geometry); 
     625                drawn = this.drawLineString(node, geometry); 
    593626                break; 
    594627            case "OpenLayers.Geometry.LinearRing": 
    595                 this.drawLinearRing(node, geometry); 
     628                drawn = this.drawLinearRing(node, geometry); 
    596629                break; 
    597630            case "OpenLayers.Geometry.Polygon": 
    598                 this.drawPolygon(node, geometry); 
     631                drawn = this.drawPolygon(node, geometry); 
    599632                break; 
    600633            case "OpenLayers.Geometry.Surface": 
    601                 this.drawSurface(node, geometry); 
     634                drawn = this.drawSurface(node, geometry); 
    602635                break; 
    603636            case "OpenLayers.Geometry.Rectangle": 
    604                 this.drawRectangle(node, geometry); 
     637                drawn = this.drawRectangle(node, geometry); 
    605638                break; 
    606639            default: 
     
    613646        //set style 
    614647        //TBD simplify this 
    615         return this.setStyle(node, style, options, geometry); 
     648        if (drawn != false) { 
     649            return { 
     650                node: this.setStyle(node, style, options, geometry), 
     651                complete: drawn 
     652            }; 
     653        } else { 
     654            return false; 
     655        } 
    616656    }, 
    617657     
     
    635675     * node - {DOMElement} 
    636676     * geometry - {<OpenLayers.Geometry>} 
     677     *  
     678     * Returns: 
     679     * {DOMElement} or false if the renderer could not draw the point 
    637680     */  
    638681    drawPoint: function(node, geometry) {}, 
     
    647690     * node - {DOMElement} 
    648691     * geometry - {<OpenLayers.Geometry>} 
     692     *  
     693     * Returns: 
     694     * {DOMElement} or null if the renderer could not draw all components of 
     695     *     the linestring, or false if nothing could be drawn 
    649696     */  
    650697    drawLineString: function(node, geometry) {}, 
     
    659706     * node - {DOMElement} 
    660707     * geometry - {<OpenLayers.Geometry>} 
     708     *  
     709     * Returns: 
     710     * {DOMElement} or null if the renderer could not draw all components 
     711     *     of the linear ring, or false if nothing could be drawn 
    661712     */  
    662713    drawLinearRing: function(node, geometry) {}, 
     
    671722     * node - {DOMElement} 
    672723     * geometry - {<OpenLayers.Geometry>} 
     724     *  
     725     * Returns: 
     726     * {DOMElement} or null if the renderer could not draw all components 
     727     *     of the polygon, or false if nothing could be drawn 
    673728     */  
    674729    drawPolygon: function(node, geometry) {}, 
     
    683738     * node - {DOMElement} 
    684739     * geometry - {<OpenLayers.Geometry>} 
     740     *  
     741     * Returns: 
     742     * {DOMElement} or false if the renderer could not draw the rectangle 
    685743     */  
    686744    drawRectangle: function(node, geometry) {}, 
     
    695753     * node - {DOMElement} 
    696754     * geometry - {<OpenLayers.Geometry>} 
     755     *  
     756     * Returns: 
     757     * {DOMElement} or false if the renderer could not draw the circle 
    697758     */  
    698759    drawCircle: function(node, geometry) {}, 
     
    707768     * node - {DOMElement} 
    708769     * geometry - {<OpenLayers.Geometry>} 
     770     *  
     771     * Returns: 
     772     * {DOMElement} or false if the renderer could not draw the surface 
    709773     */  
    710774    drawSurface: function(node, geometry) {}, 
  • trunk/openlayers/lib/OpenLayers/Renderer/SVG.js

    r7673 r7930  
    3232     *           about 15000 in an SVG document lock the browser up. This  
    3333     *           works around it. 
    34       */ 
     34     */ 
    3535    MAX_PIXEL: 15000, 
    3636 
    37     /**  
    38      * Property: localResolution 
    39      * {Float} 
    40      */ 
    41     localResolution: null, 
     37    /** 
     38     * Property: translationParameters 
     39     * {Object} Hash with "x" and "y" properties 
     40     */ 
     41    translationParameters: null, 
    4242     
    4343    /** 
     
    5959        OpenLayers.Renderer.Elements.prototype.initialize.apply(this,  
    6060                                                                arguments); 
     61        this.translationParameters = {x: 0, y: 0}; 
    6162    }, 
    6263 
     
    8788     * 
    8889     * Parameters: 
    89      * x - {Integer} 
    90      * y - {Integer} 
     90     * x      - {Integer} 
     91     * y      - {Integer} 
     92     * xyOnly - {Boolean} whether or not to just check for x and y, which means 
     93     *     to not take the current translation parameters into account if true. 
    9194     *  
    9295     * Returns: 
     
    9497     *           valid range. 
    9598     */  
    96     inValidRange: function(x, y) { 
    97         return (x >= -this.MAX_PIXEL && x <= this.MAX_PIXEL && 
    98                 y >= -this.MAX_PIXEL && y <= this.MAX_PIXEL); 
     99    inValidRange: function(x, y, xyOnly) { 
     100        var left = x + (xyOnly ? 0 : this.translationParameters.x); 
     101        var top = y + (xyOnly ? 0 : this.translationParameters.y); 
     102        return (left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL && 
     103                top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL); 
    99104    }, 
    100105 
     
    104109     * Parameters: 
    105110     * extent - {<OpenLayers.Bounds>} 
    106      */ 
    107     setExtent: function(extent) { 
     111     * resolutionChanged - {Boolean} 
     112     *  
     113     * Returns: 
     114     * {Boolean} true to notify the layer that the new extent does not exceed 
     115     *     the coordinate range, and the features will not need to be redrawn. 
     116     *     False otherwise. 
     117     */ 
     118    setExtent: function(extent, resolutionChanged) { 
    108119        OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,  
    109120                                                               arguments); 
    110121         
    111122        var resolution = this.getResolution(); 
     123        var left = -extent.left / resolution; 
     124        var top = extent.top / resolution; 
    112125 
    113126        // If the resolution has changed, start over changing the corner, because 
    114127        // the features will redraw. 
    115         if (!this.localResolution || resolution != this.localResolution) { 
    116             this.left = -extent.left / resolution; 
    117             this.top = extent.top / resolution; 
    118         } 
    119          
    120         var left = 0; 
    121         var top = 0; 
    122  
    123         // If the resolution has not changed, we already have features, and we need 
    124         // to adjust the viewbox to fit them. 
    125         if (this.localResolution && resolution == this.localResolution) { 
    126             left = (this.left) - (-extent.left / resolution); 
    127             top  = (this.top) - (extent.top / resolution); 
    128         }     
    129          
    130         // Store resolution for use later. 
    131         this.localResolution = resolution; 
    132          
    133         // Set the viewbox -- the left/top will be pixels-dragged-since-res change, 
    134         // the width/height will be pixels. 
    135         var extentString = left + " " + top + " " +  
    136                              this.size.w + " " + this.size.h; 
    137         //var extentString = extent.left / resolution + " " + -extent.top / resolution + " " +  
    138         this.rendererRoot.setAttributeNS(null, "viewBox", extentString); 
     128        if (resolutionChanged) { 
     129            this.left = left; 
     130            this.top = top; 
     131            // Set the viewbox 
     132            var extentString = "0 0 " + this.size.w + " " + this.size.h; 
     133 
     134            this.rendererRoot.setAttributeNS(null, "viewBox", extentString); 
     135            this.translate(0, 0); 
     136            return true; 
     137        } else { 
     138            var inRange = this.translate(left - this.left, top - this.top); 
     139            if (!inRange) { 
     140                // recenter the coordinate system 
     141                this.setExtent(extent, true); 
     142            } 
     143            return inRange; 
     144        } 
     145    }, 
     146     
     147    /** 
     148     * Method: translate 
     149     * Transforms the SVG coordinate system 
     150     *  
     151     * Parameters: 
     152     * x - {Float} 
     153     * y - {Float} 
     154     *  
     155     * Returns: 
     156     * {Boolean} true if the translation parameters ar in the valid coordinates 
     157     *     range, false otherwise. 
     158     */ 
     159    translate: function(x, y) { 
     160        if (!this.inValidRange(x, y, true)) { 
     161            return false; 
     162        } else { 
     163            var transformString = ""; 
     164            if (x || y) { 
     165                transformString = "translate(" + x + "," + y + ")"; 
     166            } 
     167            this.root.setAttributeNS(null, "transform", transformString); 
     168            this.translationParameters = {x: x, y: y}; 
     169            return true; 
     170        } 
    139171    }, 
    140172 
     
    414446     * node - {DOMElement} 
    415447     * geometry - {<OpenLayers.Geometry>} 
     448     *  
     449     * Returns: 
     450     * {DOMElement} or false if the renderer could not draw the point 
    416451     */  
    417452    drawPoint: function(node, geometry) { 
    418         this.drawCircle(node, geometry, 1); 
     453        return this.drawCircle(node, geometry, 1); 
    419454    }, 
    420455 
     
    427462     * geometry - {<OpenLayers.Geometry>} 
    428463     * radius - {Float} 
     464     *  
     465     * Returns: 
     466     * {DOMElement} or false if the renderer could not draw the circle 
    429467     */ 
    430468    drawCircle: function(node, geometry, radius) { 
     
    437475            node.setAttributeNS(null, "cy", y); 
    438476            node.setAttributeNS(null, "r", radius); 
    439         } else { 
    440             node.setAttributeNS(null, "cx", ""); 
    441             node.setAttributeNS(null, "cy", ""); 
    442             node.setAttributeNS(null, "r", 0); 
     477            return node; 
     478        } else { 
     479            return false; 
    443480        }     
    444481             
     
    452489     * node - {DOMElement} 
    453490     * geometry - {<OpenLayers.Geometry>} 
     491     *  
     492     * Returns: 
     493     * {DOMElement} or null if the renderer could not draw all components of 
     494     *     the linestring, or false if nothing could be drawn 
    454495     */  
    455496    drawLineString: function(node, geometry) { 
    456         node.setAttributeNS(null, "points",  
    457                             this.getComponentsString(geometry.components));   
    458     }, 
    459      
    460     /**v 
     497        var componentsResult = this.getComponentsString(geometry.components); 
     498        if (componentsResult.path) { 
     499            node.setAttributeNS(null, "points", componentsResult.path); 
     500            return (componentsResult.complete ? node : null);   
     501        } else { 
     502            return false; 
     503        } 
     504    }, 
     505     
     506    /** 
    461507     * Method: drawLinearRing 
    462508     * This method is only called by the renderer itself. 
     
    465511     * node - {DOMElement} 
    466512     * geometry - {<OpenLayers.Geometry>} 
     513     *  
     514     * Returns: 
     515     * {DOMElement} or null if the renderer could not draw all components 
     516     *     of the linear ring, or false if nothing could be drawn 
    467517     */  
    468518    drawLinearRing: function(node, geometry) { 
    469         node.setAttributeNS(null, "points",  
    470                             this.getComponentsString(geometry.components)); 
     519        var componentsResult = this.getComponentsString(geometry.components); 
     520        if (componentsResult.path) { 
     521            node.setAttributeNS(null, "points", componentsResult.path); 
     522            return (componentsResult.complete ? node : null);   
     523        } else { 
     524            return false; 
     525        } 
    471526    }, 
    472527     
     
    478533     * node - {DOMElement} 
    479534     * geometry - {<OpenLayers.Geometry>} 
     535     *  
     536     * Returns: 
     537     * {DOMElement} or null if the renderer could not draw all components 
     538     *     of the polygon, or false if nothing could be drawn 
    480539     */  
    481540    drawPolygon: function(node, geometry) { 
    482541        var d = ""; 
    483542        var draw = true; 
     543        var complete = true; 
     544        var linearRingResult, path; 
    484545        for (var j=0, len=geometry.components.length; j<len; j++) { 
    485             var linearRing = geometry.components[j]; 
    486546            d += " M"; 
    487             for (var i=0, ilen=linearRing.components.length; i<ilen; i++) { 
    488                 var component = this.getShortString(linearRing.components[i]); 
    489                 if (component) { 
    490                     d += " " + component; 
    491                 } else { 
    492                     draw = false; 
    493                 }     
     547            linearRingResult = this.getComponentsString( 
     548                geometry.components[j].components, " "); 
     549            path = linearRingResult.path; 
     550            if (path) { 
     551                d += " " + path; 
     552                complete = linearRingResult.complete && complete; 
     553            } else { 
     554                draw = false; 
    494555            } 
    495556        } 
     
    498559            node.setAttributeNS(null, "d", d); 
    499560            node.setAttributeNS(null, "fill-rule", "evenodd"); 
    500         } else { 
    501             node.setAttributeNS(null, "d", ""); 
     561            return complete ? node : null; 
     562        } else { 
     563            return false; 
    502564        }     
    503565    }, 
     
    510572     * node - {DOMElement} 
    511573     * geometry - {<OpenLayers.Geometry>} 
     574     *  
     575     * Returns: 
     576     * {DOMElement} or false if the renderer could not draw the rectangle 
    512577     */  
    513578    drawRectangle: function(node, geometry) { 
     
    521586            node.setAttributeNS(null, "width", geometry.width / resolution); 
    522587            node.setAttributeNS(null, "height", geometry.height / resolution); 
    523         } else { 
    524             node.setAttributeNS(null, "x", ""); 
    525             node.setAttributeNS(null, "y", ""); 
    526             node.setAttributeNS(null, "width", 0); 
    527             node.setAttributeNS(null, "height", 0); 
     588            return node; 
     589        } else { 
     590            return false; 
    528591        } 
    529592    }, 
     
    536599     * node - {DOMElement} 
    537600     * geometry - {<OpenLayers.Geometry>} 
     601     *  
     602     * Returns: 
     603     * {DOMElement} or false if the renderer could not draw the surface 
    538604     */  
    539605    drawSurface: function(node, geometry) { 
     
    560626        if (draw) { 
    561627            node.setAttributeNS(null, "d", d); 
    562         } else { 
    563             node.setAttributeNS(null, "d", ""); 
     628            return node; 
     629        } else { 
     630            return false; 
    564631        }     
    565632    }, 
     
    570637     * Parameters: 
    571638     * components - {Array(<OpenLayers.Geometry.Point>)} Array of points 
    572      */ 
    573     getComponentsString: function(components) { 
     639     * separator - {String} character between coordinate pairs. Defaults to "," 
     640     *  
     641     * Returns: 
     642     * {Object} hash with properties "path" (the string created from the 
     643     *     components and "complete" (false if the renderer was unable to 
     644     *     draw all components) 
     645     */ 
     646    getComponentsString: function(components, separator) { 
     647        var renderCmp = []; 
     648        var complete = true; 
     649        var len = components.length; 
    574650        var strings = []; 
    575         for(var i=0, len=components.length; i<len; i++) { 
    576             var component = this.getShortString(components[i]); 
    577             if (component) { 
    578                 strings.push(component); 
     651        var str, component, j; 
     652        for(var i=0; i<len; i++) { 
     653            component = components[i]; 
     654            renderCmp.push(component); 
     655            str = this.getShortString(component); 
     656            if (str) { 
     657                strings.push(str); 
     658            } else { 
     659                // The current component is outside the valid range. Let's 
     660                // see if the previous or next component is inside the range. 
     661                // If so, add the coordinate of the intersection with the 
     662                // valid range bounds. 
     663                if (i > 0) { 
     664                    if (this.getShortString(components[i + 1])) { 
     665                        strings.push(this.clipLine(components[i], 
     666                            components[i-1])); 
     667                    } 
     668                } 
     669                if (i < len - 1) { 
     670                    if (this.getShortString(components[i + 1])) { 
     671                        strings.push(this.clipLine(components[i], 
     672                            components[i+1])); 
     673                    } 
     674                } 
     675                complete = false; 
    579676            } 
    580677        } 
    581         return strings.join(","); 
    582     }, 
    583  
    584      
     678 
     679        return { 
     680            path: strings.join(separator || ","), 
     681            complete: complete 
     682        }; 
     683    }, 
     684     
     685    /** 
     686     * Method: clipLine 
     687     * Given two points (one inside the valid range, and one outside), 
     688     * clips the line betweeen the two points so that the new points are both 
     689     * inside the valid range. 
     690     *  
     691     * Parameters: 
     692     * badComponent - {<OpenLayers.Geometry.Point>)} original geometry of the 
     693     *     invalid point 
     694     * goodComponent - {<OpenLayers.Geometry.Point>)} original geometry of the 
     695     *     valid point 
     696     * Returns 
     697     * {String} the SVG coordinate pair of the clipped point (like 
     698     *     getShortString), or an empty string if both passed componets are at 
     699     *     the same point. 
     700     */ 
     701    clipLine: function(badComponent, goodComponent) { 
     702        if (goodComponent.equals(badComponent)) { 
     703            return ""; 
     704        } 
     705        var resolution = this.getResolution(); 
     706        var maxX = this.MAX_PIXEL - this.translationParameters.x; 
     707        var maxY = this.MAX_PIXEL - this.translationParameters.y; 
     708        var x1 = goodComponent.x / resolution + this.left; 
     709        var y1 = this.top - goodComponent.y / resolution; 
     710        var x2 = badComponent.x / resolution + this.left; 
     711        var y2 = this.top - badComponent.y / resolution; 
     712        var k; 
     713        if (x2 < -maxX || x2 > maxX) { 
     714            k = (y2 - y1) / (x2 - x1); 
     715            x2 = x2 < 0 ? -maxX : maxX; 
     716            y2 = y1 + (x2 - x1) * k; 
     717        } 
     718        if (y2 < -maxY || y2 > maxY) { 
     719            k = (x2 - x1) / (y2 - y1); 
     720            y2 = y2 < 0 ? -maxY : maxY; 
     721            x2 = x1 + (y2 - y1) * k; 
     722        } 
     723        return x2 + "," + y2; 
     724    }, 
     725 
    585726    /**  
    586727     * Method: getShortString 
     
    590731     *  
    591732     * Returns: 
    592      * {String} 
     733     * {String} or false if point is outside the valid range 
    593734     */ 
    594735    getShortString: function(point) { 
  • trunk/openlayers/lib/OpenLayers/Renderer/VML.js

    r7673 r7930  
    8080     * Parameters: 
    8181     * extent - {<OpenLayers.Bounds>} 
    82      */ 
    83     setExtent: function(extent) { 
     82     * resolutionChanged - {Boolean} 
     83     *  
     84     * Returns: 
     85     * {Boolean} true to notify the layer that the new extent does not exceed 
     86     *     the coordinate range, and the features will not need to be redrawn. 
     87     */ 
     88    setExtent: function(extent, resolutionChanged) { 
    8489        OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,  
    8590                                                               arguments); 
     
    96101        // matches the display Y axis of the map 
    97102        this.root.style.flip = "y"; 
     103         
     104        return true; 
    98105    }, 
    99106 
     
    570577    }, 
    571578     
    572     /** 
    573      * Method: drawFeature 
    574      * Overrides the superclass's drawFeature method to take care of features 
    575      * that are outside the viewport. 
    576      * 
    577      * Parameters: 
    578      * feature - {<OpenLayers.Feature.Vector>}  
    579      * style - {<Object>}  
    580      */ 
    581     drawFeature: function(feature, style) { 
    582         if (!feature.geometry.getBounds().intersectsBounds(this.extent)) { 
    583             style = {display: "none"}; 
    584         } 
    585         OpenLayers.Renderer.Elements.prototype.drawFeature.apply(this, 
    586             [feature, style]); 
    587     }, 
    588  
    589579    /************************************** 
    590580     *                                    * 
     
    600590     * node - {DOMElement} 
    601591     * geometry - {<OpenLayers.Geometry>} 
     592     *  
     593     * Returns: 
     594     * {DOMElement} or false if the point could not be drawn 
    602595     */ 
    603596    drawPoint: function(node, geometry) { 
    604         this.drawCircle(node, geometry, 1); 
     597        return this.drawCircle(node, geometry, 1); 
    605598    }, 
    606599 
     
    614607     * geometry - {<OpenLayers.Geometry>} 
    615608     * radius - {float} 
     609     *  
     610     * Returns: 
     611     * {DOMElement} or false if the circle could not ne drawn 
    616612     */ 
    617613    drawCircle: function(node, geometry, radius) { 
     
    626622            node.style.width = diameter + "px"; 
    627623            node.style.height = diameter + "px"; 
    628         } 
     624            return node; 
     625        } 
     626        return false; 
    629627    }, 
    630628 
     
    637635     * node - {DOMElement} 
    638636     * geometry - {<OpenLayers.Geometry>} 
     637     *  
     638     * Returns: 
     639     * {DOMElement} 
    639640     */ 
    640641    drawLineString: function(node, geometry) { 
    641         this.drawLine(node, geometry, false); 
     642        return this.drawLine(node, geometry, false); 
    642643    }, 
    643644 
     
    649650     * node - {DOMElement} 
    650651     * geometry - {<OpenLayers.Geometry>} 
     652     *  
     653     * Returns: 
     654     * {DOMElement} 
    651655     */ 
    652656    drawLinearRing: function(node, geometry) { 
    653         this.drawLine(node, geometry, true); 
     657        return this.drawLine(node, geometry, true); 
    654658    }, 
    655659 
     
    662666     * geometry - {<OpenLayers.Geometry>} 
    663667     * closeLine - {Boolean} Close the line? (make it a ring?) 
     668     *  
     669     * Returns: 
     670     * {DOMElement} 
    664671     */ 
    665672    drawLine: function(node, geometry, closeLine) { 
     
    680687        var end = (closeLine) ? " x e" : " e"; 
    681688        node.path = "m" + parts.join("") + end; 
     689        return node; 
    682690    }, 
    683691 
     
    689697     * node - {DOMElement} 
    690698     * geometry - {<OpenLayers.Geometry>} 
     699     *  
     700     * Returns: 
     701     * {DOMElement} 
    691702     */ 
    692703    drawPolygon: function(node, geometry) { 
     
    714725        path.push("e"); 
    715726        node.path = path.join(""); 
     727        return node; 
    716728    }, 
    717729 
     
    723735     * node - {DOMElement} 
    724736     * geometry - {<OpenLayers.Geometry>} 
     737     *  
     738     * Returns: 
     739     * {DOMElement} 
    725740     */ 
    726741    drawRectangle: function(node, geometry) { 
     
    731746        node.style.width = geometry.width/resolution + "px"; 
    732747        node.style.height = geometry.height/resolution + "px"; 
     748         
     749        return node; 
    733750    }, 
    734751 
     
    739756     * node - {DOMElement} 
    740757     * geometry - {<OpenLayers.Geometry>} 
     758     *  
     759     * Returns: 
     760     * {DOMElement} 
    741761     */ 
    742762    drawSurface: function(node, geometry) { 
    …</