diff --git a/old/examples/draw-features.js b/old/examples/draw-features.js index 637035f756..1d48f6d9b4 100644 --- a/old/examples/draw-features.js +++ b/old/examples/draw-features.js @@ -18,7 +18,7 @@ var raster = new ol.layer.Tile({ }); var vector = new ol.layer.Vector({ - source: new ol.source.Vector({parser: null}), + source: new ol.source.Vector(), style: new ol.style.Style({ rules: [ new ol.style.Rule({ diff --git a/old/examples/style-rules.js b/old/examples/style-rules.js index c730704afc..c78bcb207f 100644 --- a/old/examples/style-rules.js +++ b/old/examples/style-rules.js @@ -1,11 +1,12 @@ +goog.require('ol.Feature'); goog.require('ol.Map'); goog.require('ol.RendererHint'); goog.require('ol.View2D'); goog.require('ol.control'); goog.require('ol.expr'); +goog.require('ol.geom.LineString'); +goog.require('ol.geom.Point'); goog.require('ol.layer.Vector'); -goog.require('ol.parser.GeoJSON'); -goog.require('ol.proj'); goog.require('ol.source.Vector'); goog.require('ol.style.Fill'); goog.require('ol.style.Rule'); @@ -62,108 +63,60 @@ var style = new ol.style.Style({rules: [ var vector = new ol.layer.Vector({ style: style, source: new ol.source.Vector({ - data: { - 'type': 'FeatureCollection', - 'features': [{ - 'type': 'Feature', - 'properties': { - 'color': '#BADA55', - 'where': 'inner' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[-10000000, -10000000], [10000000, 10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'color': '#BADA55', - 'where': 'inner' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[-10000000, 10000000], [10000000, -10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'color': '#013', - 'where': 'outer' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[-10000000, -10000000], [-10000000, 10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'color': '#013', - 'where': 'outer' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[-10000000, 10000000], [10000000, 10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'color': '#013', - 'where': 'outer' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[10000000, 10000000], [10000000, -10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'color': '#013', - 'where': 'outer' - }, - 'geometry': { - 'type': 'LineString', - 'coordinates': [[10000000, -10000000], [-10000000, -10000000]] - } - }, { - 'type': 'Feature', - 'properties': { - 'label': 'South' - }, - 'geometry': { - 'type': 'Point', - 'coordinates': [0, -6000000] - } - }, { - 'type': 'Feature', - 'properties': { - 'label': 'West' - }, - 'geometry': { - 'type': 'Point', - 'coordinates': [-6000000, 0] - } - }, { - 'type': 'Feature', - 'properties': { - 'label': 'North' - }, - 'geometry': { - 'type': 'Point', - 'coordinates': [0, 6000000] - } - }, { - 'type': 'Feature', - 'properties': { - 'label': 'East' - }, - 'geometry': { - 'type': 'Point', - 'coordinates': [6000000, 0] - } - }] - }, - parser: new ol.parser.GeoJSON(), - projection: ol.proj.get('EPSG:3857') + features: [ + new ol.Feature({ + color: '#BADA55', + where: 'inner', + geometry: new ol.geom.LineString( + [[-10000000, -10000000], [10000000, 10000000]]) + }), + new ol.Feature({ + color: '#BADA55', + where: 'inner', + geometry: new ol.geom.LineString( + [[-10000000, 10000000], [10000000, -10000000]]) + }), + new ol.Feature({ + color: '#013', + where: 'outer', + geometry: new ol.geom.LineString( + [[-10000000, -10000000], [-10000000, 10000000]]) + }), + new ol.Feature({ + color: '#013', + where: 'outer', + geometry: new ol.geom.LineString( + [[-10000000, 10000000], [10000000, 10000000]]) + }), + new ol.Feature({ + color: '#013', + where: 'outer', + geometry: new ol.geom.LineString( + [[10000000, 10000000], [10000000, -10000000]]) + }), + new ol.Feature({ + color: '#013', + where: 'outer', + geometry: new ol.geom.LineString( + [[10000000, -10000000], [-10000000, -10000000]]) + }), + new ol.Feature({ + label: 'South', + geometry: new ol.geom.Point([0, -6000000]) + }), + new ol.Feature({ + label: 'West', + geometry: new ol.geom.Point([-6000000, 0]) + }), + new ol.Feature({ + label: 'North', + geometry: new ol.geom.Point([0, 6000000]) + }), + new ol.Feature({ + label: 'East', + geometry: new ol.geom.Point([6000000, 0]) + }) + ] }) }); diff --git a/old/src/ol/interaction/drawinteraction.js b/old/src/ol/interaction/drawinteraction.js index 274fa87977..8a698818a1 100644 --- a/old/src/ol/interaction/drawinteraction.js +++ b/old/src/ol/interaction/drawinteraction.js @@ -4,6 +4,7 @@ goog.require('goog.asserts'); goog.require('ol.Coordinate'); goog.require('ol.Feature'); +goog.require('ol.FeatureRenderIntent'); goog.require('ol.Map'); goog.require('ol.MapBrowserEvent'); goog.require('ol.MapBrowserEvent.EventType'); @@ -16,7 +17,6 @@ goog.require('ol.geom.Point'); goog.require('ol.geom.Polygon'); goog.require('ol.interaction.Interaction'); goog.require('ol.layer.Vector'); -goog.require('ol.layer.VectorLayerRenderIntent'); goog.require('ol.source.Vector'); @@ -113,7 +113,7 @@ ol.interaction.Draw.prototype.setMap = function(map) { if (!goog.isNull(map)) { if (goog.isNull(this.sketchLayer_)) { var layer = new ol.layer.Vector({ - source: new ol.source.Vector({parser: null}), + source: new ol.source.Vector(), style: this.layer_.getStyle() }); layer.setTemporary(true); @@ -233,7 +233,7 @@ ol.interaction.Draw.prototype.startDrawing_ = function(event) { var start = event.getCoordinate(); this.finishCoordinate_ = start; var sketchFeature = new ol.Feature(); - sketchFeature.setRenderIntent(ol.layer.VectorLayerRenderIntent.SELECTED); + sketchFeature.setRenderIntent(ol.FeatureRenderIntent.SELECTED); var features = [sketchFeature]; var geometry; if (this.mode_ === ol.interaction.DrawMode.POINT) { @@ -242,7 +242,7 @@ ol.interaction.Draw.prototype.startDrawing_ = function(event) { var sketchPoint = new ol.Feature({ geom: new ol.geom.Point(start.slice()) }); - sketchPoint.setRenderIntent(ol.layer.VectorLayerRenderIntent.TEMPORARY); + sketchPoint.setRenderIntent(ol.FeatureRenderIntent.TEMPORARY); this.sketchPoint_ = sketchPoint; features.push(sketchPoint); @@ -256,7 +256,7 @@ ol.interaction.Draw.prototype.startDrawing_ = function(event) { sketchFeature.setGeometry(geometry); this.sketchFeature_ = sketchFeature; - this.sketchLayer_.addFeatures(features); + this.sketchLayer_.getVectorSource().addFeatures(features); }; @@ -325,7 +325,7 @@ ol.interaction.Draw.prototype.addToDrawing_ = function(event) { ol.interaction.Draw.prototype.finishDrawing_ = function(event) { var sketchFeature = this.abortDrawing_(); goog.asserts.assert(!goog.isNull(sketchFeature)); - sketchFeature.setRenderIntent(ol.layer.VectorLayerRenderIntent.DEFAULT); + sketchFeature.setRenderIntent(ol.FeatureRenderIntent.DEFAULT); var geometry = sketchFeature.getGeometry(); var coordinates = geometry.getCoordinates(); if (this.mode_ === ol.interaction.DrawMode.LINESTRING) { @@ -344,7 +344,7 @@ ol.interaction.Draw.prototype.finishDrawing_ = function(event) { } else if (this.type_ === ol.geom.GeometryType.MULTIPOLYGON) { sketchFeature.setGeometry(new ol.geom.MultiPolygon([coordinates])); } - this.layer_.addFeatures([sketchFeature]); + this.layer_.getVectorSource().addFeatures([sketchFeature]); }; @@ -363,7 +363,7 @@ ol.interaction.Draw.prototype.abortDrawing_ = function() { features.push(this.sketchPoint_); this.sketchPoint_ = null; } - this.sketchLayer_.removeFeatures(features); + this.sketchLayer_.getVectorSource().removeFeatures(features); } return sketchFeature; }; diff --git a/old/src/ol/interaction/modifyinteraction.js b/old/src/ol/interaction/modifyinteraction.js index e473be2f9c..692c0cd74d 100644 --- a/old/src/ol/interaction/modifyinteraction.js +++ b/old/src/ol/interaction/modifyinteraction.js @@ -6,6 +6,7 @@ goog.require('goog.events'); goog.require('goog.functions'); goog.require('ol.CollectionEventType'); goog.require('ol.Feature'); +goog.require('ol.FeatureRenderIntent'); goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.ViewHint'); goog.require('ol.coordinate'); @@ -18,9 +19,8 @@ goog.require('ol.geom.Polygon'); goog.require('ol.interaction.Drag'); goog.require('ol.layer.Layer'); goog.require('ol.layer.Vector'); -goog.require('ol.layer.VectorEventType'); -goog.require('ol.layer.VectorLayerRenderIntent'); goog.require('ol.source.Vector'); +goog.require('ol.source.VectorEventType'); goog.require('ol.structs.RBush'); @@ -59,6 +59,13 @@ ol.interaction.Modify = function(opt_options) { */ this.layerFilter_ = layerFilter; + /** + * Layer lookup. Keys source id to layer. + * @type {Object.} + * @private + */ + this.layerLookup_ = null; + /** * Temporary sketch layer. * @type {ol.layer.Vector} @@ -121,12 +128,13 @@ ol.interaction.Modify.prototype.setMap = function(map) { } if (!goog.isNull(map)) { + this.layerLookup_ = {}; if (goog.isNull(this.rBush_)) { this.rBush_ = new ol.structs.RBush(); } if (goog.isNull(this.sketchLayer_)) { var sketchLayer = new ol.layer.Vector({ - source: new ol.source.Vector({parser: null}) + source: new ol.source.Vector() }); this.sketchLayer_ = sketchLayer; sketchLayer.setTemporary(true); @@ -141,6 +149,7 @@ ol.interaction.Modify.prototype.setMap = function(map) { false, this); } else { // removing from a map, clean up + this.layerLookup_ = null; this.rBush_ = null; this.sketchLayer_ = null; } @@ -168,9 +177,11 @@ ol.interaction.Modify.prototype.handleLayerAdded_ = function(evt) { ol.interaction.Modify.prototype.addLayer_ = function(layer) { if (this.layerFilter_(layer) && layer instanceof ol.layer.Vector && !layer.getTemporary()) { - this.addIndex_(layer.getFeatures(ol.layer.Vector.selectedFeaturesFilter), + var source = layer.getVectorSource(); + this.layerLookup_[goog.getUid(source)] = layer; + this.addIndex_(source.getFeatures(ol.layer.Vector.selectedFeaturesFilter), layer); - goog.events.listen(layer, ol.layer.VectorEventType.INTENTCHANGE, + goog.events.listen(source, ol.source.VectorEventType.INTENTCHANGE, this.handleIntentChange_, false, this); } }; @@ -195,9 +206,11 @@ ol.interaction.Modify.prototype.handleLayerRemoved_ = function(evt) { ol.interaction.Modify.prototype.removeLayer_ = function(layer) { if (this.layerFilter_(layer) && layer instanceof ol.layer.Vector && !layer.getTemporary()) { + var source = layer.getVectorSource(); + delete this.layerLookup_[goog.getUid(source)]; this.removeIndex_( - layer.getFeatures(ol.layer.Vector.selectedFeaturesFilter)); - goog.events.unlisten(layer, ol.layer.VectorEventType.INTENTCHANGE, + source.getFeatures(ol.layer.Vector.selectedFeaturesFilter)); + goog.events.unlisten(source, ol.source.VectorEventType.INTENTCHANGE, this.handleIntentChange_, false, this); } }; @@ -248,17 +261,19 @@ ol.interaction.Modify.prototype.removeIndex_ = function(features) { /** * Listen for feature additions. - * @param {ol.layer.VectorEvent} evt Event object. + * @param {ol.source.VectorEvent} evt Event object. * @private */ ol.interaction.Modify.prototype.handleIntentChange_ = function(evt) { - var layer = evt.target; + var source = evt.target; + goog.asserts.assertInstanceof(source, ol.source.Vector); + var layer = this.layerLookup_[goog.getUid(source)]; goog.asserts.assertInstanceof(layer, ol.layer.Vector); var features = evt.features; for (var i = 0, ii = features.length; i < ii; ++i) { var feature = features[i]; var renderIntent = feature.getRenderIntent(); - if (renderIntent == ol.layer.VectorLayerRenderIntent.SELECTED) { + if (renderIntent == ol.FeatureRenderIntent.SELECTED) { this.addIndex_([feature], layer); } else { this.removeIndex_([feature]); @@ -322,7 +337,7 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ = if (goog.isNull(vertexFeature)) { vertexFeature = new ol.Feature({g: new ol.geom.Point(coordinates)}); this.vertexFeature_ = vertexFeature; - this.sketchLayer_.addFeatures([vertexFeature]); + this.sketchLayer_.getVectorSource().addFeatures([vertexFeature]); } else { var geometry = vertexFeature.getGeometry(); geometry.setCoordinates(coordinates); @@ -341,7 +356,7 @@ ol.interaction.Modify.prototype.handleDragStart = function(evt) { this.dragSegments_ = []; var vertexFeature = this.vertexFeature_; if (!goog.isNull(vertexFeature) && vertexFeature.getRenderIntent() != - ol.layer.VectorLayerRenderIntent.HIDDEN) { + ol.FeatureRenderIntent.HIDDEN) { var renderIntent = vertexFeature.getRenderIntent(); var insertVertices = []; var vertex = vertexFeature.getGeometry().getCoordinates(); @@ -360,7 +375,7 @@ ol.interaction.Modify.prototype.handleDragStart = function(evt) { original.setSymbolizers(feature.getSymbolizers()); feature.setOriginal(original); } - if (renderIntent == ol.layer.VectorLayerRenderIntent.TEMPORARY) { + if (renderIntent == ol.FeatureRenderIntent.TEMPORARY) { if (ol.coordinate.equals(segment[0], vertex)) { dragSegments.push([node, 0]); } else if (ol.coordinate.equals(segment[1], vertex)) { @@ -455,7 +470,7 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) { var vertexFeature = this.vertexFeature_; var rBush = this.rBush_; var nodes = rBush.getAllInExtent(box); - var renderIntent = ol.layer.VectorLayerRenderIntent.HIDDEN; + var renderIntent = ol.FeatureRenderIntent.HIDDEN; if (nodes.length > 0) { nodes.sort(sortByDistance); var node = nodes[0]; @@ -469,10 +484,10 @@ ol.interaction.Modify.prototype.handleMouseMove_ = function(evt) { var squaredDist1 = ol.coordinate.squaredDistance(vertexPixel, pixel1); var squaredDist2 = ol.coordinate.squaredDistance(vertexPixel, pixel2); var dist = Math.sqrt(Math.min(squaredDist1, squaredDist2)); - renderIntent = ol.layer.VectorLayerRenderIntent.FUTURE; + renderIntent = ol.FeatureRenderIntent.FUTURE; if (dist <= 10) { vertex = squaredDist1 > squaredDist2 ? segment[1] : segment[0]; - renderIntent = ol.layer.VectorLayerRenderIntent.TEMPORARY; + renderIntent = ol.FeatureRenderIntent.TEMPORARY; } vertexFeature = this.createOrUpdateVertexFeature_(node.style, vertex); this.modifiable_ = true; diff --git a/old/src/ol/interaction/selectinteraction.js b/old/src/ol/interaction/selectinteraction.js index 41ecf96085..6442cd9d5b 100644 --- a/old/src/ol/interaction/selectinteraction.js +++ b/old/src/ol/interaction/selectinteraction.js @@ -3,11 +3,11 @@ goog.provide('ol.interaction.Select'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('ol.Feature'); +goog.require('ol.FeatureRenderIntent'); goog.require('ol.events.ConditionType'); goog.require('ol.events.condition'); goog.require('ol.interaction.Interaction'); goog.require('ol.layer.Vector'); -goog.require('ol.layer.VectorLayerRenderIntent'); @@ -97,21 +97,21 @@ ol.interaction.Select.prototype.select = } var featuresToSelect = featuresByLayer[i]; - var selectedFeatures = layer.getFeatures( + var selectedFeatures = layer.getVectorSource().getFeatures( ol.layer.Vector.selectedFeaturesFilter); if (clear) { for (var j = selectedFeatures.length - 1; j >= 0; --j) { selectedFeatures[j].setRenderIntent( - ol.layer.VectorLayerRenderIntent.DEFAULT); + ol.FeatureRenderIntent.DEFAULT); } } for (var j = featuresToSelect.length - 1; j >= 0; --j) { var feature = featuresToSelect[j]; // TODO: Make toggle configurable feature.setRenderIntent(feature.getRenderIntent() == - ol.layer.VectorLayerRenderIntent.SELECTED ? - ol.layer.VectorLayerRenderIntent.DEFAULT : - ol.layer.VectorLayerRenderIntent.SELECTED); + ol.FeatureRenderIntent.SELECTED ? + ol.FeatureRenderIntent.DEFAULT : + ol.FeatureRenderIntent.SELECTED); } // TODO: Dispatch an event with selectedFeatures and unselectedFeatures } diff --git a/old/src/ol/layer/vectorlayerrenderintent.js b/old/src/ol/layer/vectorlayerrenderintent.js deleted file mode 100644 index 6b84c28700..0000000000 --- a/old/src/ol/layer/vectorlayerrenderintent.js +++ /dev/null @@ -1,13 +0,0 @@ -goog.provide('ol.layer.VectorLayerRenderIntent'); - - -/** - * @enum {string} - */ -ol.layer.VectorLayerRenderIntent = { - DEFAULT: 'default', - FUTURE: 'future', - HIDDEN: 'hidden', - SELECTED: 'selected', - TEMPORARY: 'temporary' -}; diff --git a/old/src/ol/parser/kmlparser.js b/old/src/ol/parser/kmlparser.js index 1fecd92d39..a815485d7f 100644 --- a/old/src/ol/parser/kmlparser.js +++ b/old/src/ol/parser/kmlparser.js @@ -75,7 +75,7 @@ ol.parser.KML = function(opt_options) { '*': function(node, obj) { if (this.extractAttributes === true) { var len = node.childNodes.length; - if ((len === 1 || len === 2) && (node.firstChild.nodeType === 3 || + if (len > 0 && (node.firstChild.nodeType === 3 || node.firstChild.nodeType === 4)) { var readers = this.readers[this.defaultNamespaceURI]; readers['_attribute'].apply(this, arguments); diff --git a/old/src/ol/renderer/canvas/canvasvectorrenderer.js b/old/src/ol/renderer/canvas/canvasvectorrenderer.js index 2305b0dad2..47635e516a 100644 --- a/old/src/ol/renderer/canvas/canvasvectorrenderer.js +++ b/old/src/ol/renderer/canvas/canvasvectorrenderer.js @@ -8,6 +8,7 @@ goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('goog.vec.Mat4'); goog.require('ol.Feature'); +goog.require('ol.FeatureRenderIntent'); goog.require('ol.geom.AbstractCollection'); goog.require('ol.geom.Geometry'); goog.require('ol.geom.GeometryType'); @@ -17,7 +18,6 @@ goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.MultiPolygon'); goog.require('ol.geom.Point'); goog.require('ol.geom.Polygon'); -goog.require('ol.layer.VectorLayerRenderIntent'); goog.require('ol.style.IconLiteral'); goog.require('ol.style.LineLiteral'); goog.require('ol.style.Literal'); @@ -158,7 +158,7 @@ ol.renderer.canvas.Vector.prototype.renderLineStringFeatures_ = context.beginPath(); for (i = 0, ii = features.length; i < ii; ++i) { feature = features[i]; - if (feature.getRenderIntent() == ol.layer.VectorLayerRenderIntent.HIDDEN) { + if (feature.getRenderIntent() == ol.FeatureRenderIntent.HIDDEN) { continue; } id = goog.getUid(feature); @@ -247,7 +247,7 @@ ol.renderer.canvas.Vector.prototype.renderPointFeatures_ = context.globalAlpha = alpha; for (i = 0, ii = features.length; i < ii; ++i) { feature = features[i]; - if (feature.getRenderIntent() == ol.layer.VectorLayerRenderIntent.HIDDEN) { + if (feature.getRenderIntent() == ol.FeatureRenderIntent.HIDDEN) { continue; } id = goog.getUid(feature); @@ -323,7 +323,7 @@ ol.renderer.canvas.Vector.prototype.renderText_ = for (var i = 0, ii = features.length; i < ii; ++i) { feature = features[i]; - if (feature.getRenderIntent() == ol.layer.VectorLayerRenderIntent.HIDDEN) { + if (feature.getRenderIntent() == ol.FeatureRenderIntent.HIDDEN) { continue; } vecs = ol.renderer.canvas.Vector.getLabelVectors( @@ -391,7 +391,7 @@ ol.renderer.canvas.Vector.prototype.renderPolygonFeatures_ = context.beginPath(); for (i = 0, ii = features.length; i < ii; ++i) { feature = features[i]; - if (feature.getRenderIntent() == ol.layer.VectorLayerRenderIntent.HIDDEN) { + if (feature.getRenderIntent() == ol.FeatureRenderIntent.HIDDEN) { continue; } geometry = feature.getGeometry(); diff --git a/old/src/ol/structs/rtree.js b/old/src/ol/structs/rtree.js deleted file mode 100644 index e74bacaa69..0000000000 --- a/old/src/ol/structs/rtree.js +++ /dev/null @@ -1,630 +0,0 @@ -// rtree.js - General-Purpose Non-Recursive Javascript R-Tree Library -// Version 0.6.2, December 5st 2009 -// -// Copyright (c) 2009 Jon-Carlos Rivera -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -// Jon-Carlos Rivera - imbcmdth@hotmail.com - - -goog.provide('ol.structs.RTree'); - -goog.require('goog.array'); -goog.require('ol.extent'); - - -/** - * @typedef {{extent: ol.Extent, - * leaf: (Object|undefined), - * nodes: (Array.|undefined), - * target: (Object|undefined)}} - */ -ol.structs.RTreeNode; - - - -/** - * @constructor - * @param {number=} opt_maxWidth Width before a node is split. Default is `6`. - */ -ol.structs.RTree = function(opt_maxWidth) { - - /** - * Maximum width of any node before a split. - * @private - * @type {number} - */ - this.maxWidth_ = goog.isDef(opt_maxWidth) ? opt_maxWidth : 6; - - /** - * Minimum width of any node before a merge. - * @private - * @type {number} - */ - this.minWidth_ = Math.floor(this.maxWidth_ / 2); - - /** - * Start with an empty root-tree. - * @private - * @type {ol.structs.RTreeNode} - */ - this.rootTree_ = /** @type {ol.structs.RTreeNode} */ - ({extent: ol.extent.createEmpty(), nodes: []}); - -}; - - -/** - * @param {ol.structs.RTreeNode} node Node. - * @private - */ -ol.structs.RTree.recalculateExtent_ = function(node) { - var n = node.nodes.length; - var extent = node.extent; - if (n === 0) { - ol.extent.empty(extent); - } else { - var firstNodeExtent = node.nodes[0].extent; - extent[0] = firstNodeExtent[0]; - extent[2] = firstNodeExtent[2]; - extent[1] = firstNodeExtent[1]; - extent[3] = firstNodeExtent[3]; - var i; - for (i = 1; i < n; ++i) { - ol.extent.extend(extent, node.nodes[i].extent); - } - } -}; - - -/** - * This is Jon-Carlos Rivera's special addition to the world of r-trees. - * Every other (simple) method he found produced poor trees. - * This skews insertions to prefering squarer and emptier nodes. - * - * @param {number} l L. - * @param {number} w W. - * @param {number} fill Fill. - * @private - * @return {number} Squarified ratio. - */ -ol.structs.RTree.squarifiedRatio_ = function(l, w, fill) { - // Area of new enlarged rectangle - var peri = (l + w) / 2; // Average size of a side of the new rectangle - var area = l * w; // Area of new rectangle - // return the ratio of the perimeter to the area - the closer to 1 we are, - // the more "square" a rectangle is. conversly, when approaching zero the - // more elongated a rectangle is - var geo = area / (peri * peri); - return area * fill / geo; -}; - - -/** - * Choose the best for rectangle to be inserted into. - * - * @param {ol.structs.RTreeNode} rect Rectangle. - * @param {ol.structs.RTreeNode} root Root to start search. - * @private - * @return {Array} Leaf node parent. - */ -ol.structs.RTree.prototype.chooseLeafSubtree_ = function(rect, root) { - var bestChoiceIndex = -1; - var bestChoiceStack = []; - var bestChoiceArea; - - bestChoiceStack.push(root); - var nodes = root.nodes; - - do { - if (bestChoiceIndex != -1) { - bestChoiceStack.push(nodes[bestChoiceIndex]); - nodes = nodes[bestChoiceIndex].nodes; - bestChoiceIndex = -1; - } - - for (var i = nodes.length - 1; i >= 0; --i) { - var lTree = nodes[i]; - if (goog.isDef(lTree.leaf)) { - // Bail out of everything and start inserting - bestChoiceIndex = -1; - break; - } - // Area of new enlarged rectangle - var oldLRatio = ol.structs.RTree.squarifiedRatio_( - lTree.extent[2] - lTree.extent[0], - lTree.extent[3] - lTree.extent[1], - lTree.nodes.length + 1); - - // Enlarge rectangle to fit new rectangle - var nw = (lTree.extent[2] > rect.extent[2] ? - lTree.extent[2] : rect.extent[2]) - - (lTree.extent[0] < rect.extent[0] ? - lTree.extent[0] : rect.extent[0]); - var nh = (lTree.extent[3] > rect.extent[3] ? - lTree.extent[3] : rect.extent[3]) - - (lTree.extent[1] < rect.extent[1] ? - lTree.extent[1] : rect.extent[1]); - - // Area of new enlarged rectangle - var lRatio = ol.structs.RTree.squarifiedRatio_( - nw, nh, lTree.nodes.length + 2); - - if (bestChoiceIndex < 0 || - Math.abs(lRatio - oldLRatio) < bestChoiceArea) { - bestChoiceArea = Math.abs(lRatio - oldLRatio); - bestChoiceIndex = i; - } - } - } while (bestChoiceIndex != -1); - - return bestChoiceStack; -}; - - -/** - * Non-recursive insert function. - * - * @param {ol.Extent} extent Extent. - * @param {Object} obj Object to insert. - */ -ol.structs.RTree.prototype.insert = function(extent, obj) { - var node = /** @type {ol.structs.RTreeNode} */ - ({extent: extent, leaf: obj}); - this.insertSubtree_(node, this.rootTree_); -}; - - -/** - * Non-recursive internal insert function. - * - * @param {ol.structs.RTreeNode} node Node to insert. - * @param {ol.structs.RTreeNode} root Root to begin insertion at. - * @private - */ -ol.structs.RTree.prototype.insertSubtree_ = function(node, root) { - var bc; // Best Current node - // Initial insertion is special because we resize the Tree and we don't - // care about any overflow (seriously, how can the first object overflow?) - if (root.nodes.length === 0) { - root.extent = ol.extent.clone(node.extent); - root.nodes.push(node); - return; - } - - // Find the best fitting leaf node - // chooseLeaf returns an array of all tree levels (including root) - // that were traversed while trying to find the leaf - var treeStack = this.chooseLeafSubtree_(node, root); - var workingObject = node; - - // Walk back up the tree resizing and inserting as needed - do { - //handle the case of an empty node (from a split) - if (bc && goog.isDef(bc.nodes) && bc.nodes.length === 0) { - var pbc = bc; // Past bc - bc = treeStack.pop(); - for (var t = 0, tt = bc.nodes.length; t < tt; ++t) { - if (bc.nodes[t] === pbc || bc.nodes[t].nodes.length === 0) { - bc.nodes.splice(t, 1); - break; - } - } - } else { - bc = treeStack.pop(); - } - - // If there is data attached to this workingObject - var isArray = goog.isArray(workingObject); - if (goog.isDef(workingObject.leaf) || - goog.isDef(workingObject.nodes) || isArray) { - // Do Insert - if (isArray) { - for (var ai = 0, aii = workingObject.length; ai < aii; ++ai) { - ol.extent.extend(bc.extent, workingObject[ai].extent); - } - bc.nodes = bc.nodes.concat(workingObject); - } else { - ol.extent.extend(bc.extent, workingObject.extent); - bc.nodes.push(workingObject); // Do Insert - } - - if (bc.nodes.length <= this.maxWidth_) { // Start Resizeing Up the Tree - workingObject = {extent: ol.extent.clone(bc.extent)}; - } else { // Otherwise Split this Node - // linearSplit_() returns an array containing two new nodes - // formed from the split of the previous node's overflow - var a = this.linearSplit_(bc.nodes); - workingObject = a;//[1]; - - if (treeStack.length < 1) { // If are splitting the root.. - bc.nodes.push(a[0]); - treeStack.push(bc); // Reconsider the root element - workingObject = a[1]; - } - } - } else { // Otherwise Do Resize - //Just keep applying the new bounding rectangle to the parents.. - ol.extent.extend(bc.extent, workingObject.extent); - workingObject = ({extent: ol.extent.clone(bc.extent)}); - } - } while (treeStack.length > 0); -}; - - -/** - * Split a set of nodes into two roughly equally-filled nodes. - * - * @param {Array.} nodes Array of nodes. - * @private - * @return {Array.} An array of two nodes. - */ -ol.structs.RTree.prototype.linearSplit_ = function(nodes) { - var n = this.pickLinear_(nodes); - while (nodes.length > 0) { - this.pickNext_(nodes, n[0], n[1]); - } - return n; -}; - - -/** - * Pick the "best" two starter nodes to use as seeds using the "linear" - * criteria. - * - * @param {Array.} nodes Array of source nodes. - * @private - * @return {Array.} An array of two nodes. - */ -ol.structs.RTree.prototype.pickLinear_ = function(nodes) { - var lowestHighX = nodes.length - 1; - var highestLowX = 0; - var lowestHighY = nodes.length - 1; - var highestLowY = 0; - var t1, t2; - - for (var i = nodes.length - 2; i >= 0; --i) { - var l = nodes[i]; - if (l.extent[0] > nodes[highestLowX].extent[0]) { - highestLowX = i; - } else if (l.extent[2] < nodes[lowestHighX].extent[1]) { - lowestHighX = i; - } - if (l.extent[1] > nodes[highestLowY].extent[1]) { - highestLowY = i; - } else if (l.extent[3] < nodes[lowestHighY].extent[3]) { - lowestHighY = i; - } - } - var dx = Math.abs(nodes[lowestHighX].extent[2] - - nodes[highestLowX].extent[0]); - var dy = Math.abs(nodes[lowestHighY].extent[3] - - nodes[highestLowY].extent[1]); - if (dx > dy) { - if (lowestHighX > highestLowX) { - t1 = nodes.splice(lowestHighX, 1)[0]; - t2 = nodes.splice(highestLowX, 1)[0]; - } else { - t2 = nodes.splice(highestLowX, 1)[0]; - t1 = nodes.splice(lowestHighX, 1)[0]; - } - } else { - if (lowestHighY > highestLowY) { - t1 = nodes.splice(lowestHighY, 1)[0]; - t2 = nodes.splice(highestLowY, 1)[0]; - } else { - t2 = nodes.splice(highestLowY, 1)[0]; - t1 = nodes.splice(lowestHighY, 1)[0]; - } - } - return [ - /** @type {ol.structs.RTreeNode} */ - ({extent: ol.extent.clone(t1.extent), nodes: [t1]}), - /** @type {ol.structs.RTreeNode} */ - ({extent: ol.extent.clone(t2.extent), nodes: [t2]}) - ]; -}; - - -/** - * Insert the best source rectangle into the best fitting parent node: a or b. - * - * @param {Array.} nodes Source node array. - * @param {ol.structs.RTreeNode} a Target node array a. - * @param {ol.structs.RTreeNode} b Target node array b. - * @private - */ -ol.structs.RTree.prototype.pickNext_ = function(nodes, a, b) { - // Area of new enlarged rectangle - var areaA = ol.structs.RTree.squarifiedRatio_(a.extent[2] - a.extent[0], - a.extent[3] - a.extent[1], a.nodes.length + 1); - var areaB = ol.structs.RTree.squarifiedRatio_(b.extent[2] - b.extent[0], - b.extent[3] - b.extent[1], b.nodes.length + 1); - var highAreaDelta; - var highAreaNode; - var lowestGrowthGroup; - - for (var i = nodes.length - 1; i >= 0; --i) { - var l = nodes[i]; - - var newAreaA = [ - a.extent[0] < l.extent[0] ? a.extent[0] : l.extent[0], - a.extent[2] > l.extent[2] ? a.extent[2] : l.extent[2], - a.extent[1] < l.extent[1] ? a.extent[1] : l.extent[1], - a.extent[3] > l.extent[3] ? a.extent[3] : l.extent[3] - ]; - var changeNewAreaA = Math.abs(ol.structs.RTree.squarifiedRatio_( - newAreaA[1] - newAreaA[0], - newAreaA[3] - newAreaA[2], a.nodes.length + 2) - areaA); - - var newAreaB = [ - b.extent[0] < l.extent[0] ? b.extent[0] : l.extent[0], - b.extent[2] > l.extent[2] ? b.extent[2] : l.extent[2], - b.extent[1] < l.extent[1] ? b.extent[1] : l.extent[1], - b.extent[3] > l.extent[3] ? b.extent[3] : l.extent[3] - ]; - var changeNewAreaB = Math.abs(ol.structs.RTree.squarifiedRatio_( - newAreaB[1] - newAreaB[0], newAreaB[3] - newAreaB[2], - b.nodes.length + 2) - areaB); - - var changeNewAreaDelta = Math.abs(changeNewAreaB - changeNewAreaA); - if (!highAreaNode || !highAreaDelta || - changeNewAreaDelta < highAreaDelta) { - highAreaNode = i; - highAreaDelta = changeNewAreaDelta; - lowestGrowthGroup = changeNewAreaB < changeNewAreaA ? b : a; - } - } - var tempNode = nodes.splice(highAreaNode, 1)[0]; - if (a.nodes.length + nodes.length + 1 <= this.minWidth_) { - a.nodes.push(tempNode); - ol.extent.extend(a.extent, tempNode.extent); - } else if (b.nodes.length + nodes.length + 1 <= this.minWidth_) { - b.nodes.push(tempNode); - ol.extent.extend(b.extent, tempNode.extent); - } - else { - lowestGrowthGroup.nodes.push(tempNode); - ol.extent.extend(lowestGrowthGroup.extent, tempNode.extent); - } -}; - - -/** - * Non-recursive function that deletes a specific region. - * - * @param {ol.Extent} extent Extent. - * @param {Object=} opt_obj Object. - * @return {Array} Result. - * @this {ol.structs.RTree} - */ -ol.structs.RTree.prototype.remove = function(extent, opt_obj) { - arguments[0] = /** @type {ol.structs.RTreeNode} */ ({extent: extent}); - switch (arguments.length) { - case 1: - arguments[1] = false; // opt_obj == false for conditionals - case 2: - arguments[2] = this.rootTree_; // Add root node to end of argument list - default: - arguments.length = 3; - } - if (arguments[1] === false) { // Do area-wide † - var numberDeleted = 0; - var result = []; - do { - numberDeleted = result.length; - result = result.concat(this.removeSubtree_.apply(this, arguments)); - } while (numberDeleted != result.length); - return result; - } else { // Delete a specific item - return this.removeSubtree_.apply(this, arguments); - } -}; - - -/** - * Find the best specific node(s) for object to be deleted from. - * - * @param {ol.structs.RTreeNode} rect Rectangle. - * @param {Object} obj Object. - * @param {ol.structs.RTreeNode} root Root to start search. - * @private - * @return {Array} Leaf node parent. - */ -ol.structs.RTree.prototype.removeSubtree_ = function(rect, obj, root) { - var hitStack = []; // Contains the elements that overlap - var countStack = []; // Contains the elements that overlap - var returnArray = []; - var currentDepth = 1; - - if (!rect || !ol.extent.intersects(rect.extent, root.extent)) { - return returnArray; - } - - /** @type {ol.structs.RTreeNode} */ - var workingObject = /** @type {ol.structs.RTreeNode} */ - ({extent: ol.extent.clone(rect.extent), target: obj}); - - countStack.push(root.nodes.length); - hitStack.push(root); - - do { - var tree = hitStack.pop(); - var i = countStack.pop() - 1; - - if (goog.isDef(workingObject.target)) { - // We are searching for a target - while (i >= 0) { - var lTree = tree.nodes[i]; - if (ol.extent.intersects(workingObject.extent, lTree.extent)) { - if ((workingObject.target && goog.isDef(lTree.leaf) && - lTree.leaf === workingObject.target) || - (!workingObject.target && (goog.isDef(lTree.leaf) || - ol.extent.containsExtent(workingObject.extent, lTree.extent)))) - { // A Match !! - // Yup we found a match... - // we can cancel search and start walking up the list - if (goog.isDef(lTree.nodes)) { - // If we are deleting a node not a leaf... - returnArray = this.searchSubtree_(lTree, true, [], lTree); - tree.nodes.splice(i, 1); - } else { - returnArray = tree.nodes.splice(i, 1); - } - // Resize MBR down... - ol.structs.RTree.recalculateExtent_(tree); - workingObject.target = undefined; - if (tree.nodes.length < this.minWidth_) { // Underflow - workingObject.nodes = /** @type {Array} */ - (this.searchSubtree_(tree, true, [], tree)); - } - break; - } else if (goog.isDef(lTree.nodes)) { - // Not a Leaf - currentDepth += 1; - countStack.push(i); - hitStack.push(tree); - tree = lTree; - i = lTree.nodes.length; - } - } - i -= 1; - } - } else if (goog.isDef(workingObject.nodes)) { - // We are unsplitting - tree.nodes.splice(i + 1, 1); // Remove unsplit node - // workingObject.nodes contains a list of elements removed from the - // tree so far - if (tree.nodes.length > 0) { - ol.structs.RTree.recalculateExtent_(tree); - } - for (var t = 0, tt = workingObject.nodes.length; t < tt; ++t) { - this.insertSubtree_(workingObject.nodes[t], tree); - } - workingObject.nodes.length = 0; - if (hitStack.length === 0 && tree.nodes.length <= 1) { - // Underflow..on root! - workingObject.nodes = /** @type {Array} */ - (this.searchSubtree_(tree, true, workingObject.nodes, tree)); - tree.nodes.length = 0; - hitStack.push(tree); - countStack.push(1); - } else if (hitStack.length > 0 && tree.nodes.length < this.minWidth_) { - // Underflow..AGAIN! - workingObject.nodes = /** @type {Array} */ - (this.searchSubtree_(tree, true, workingObject.nodes, tree)); - tree.nodes.length = 0; - } else { - workingObject.nodes = undefined; // Just start resizing - } - } else { // we are just resizing - ol.structs.RTree.recalculateExtent_(tree); - } - currentDepth -= 1; - } while (hitStack.length > 0); - - return returnArray; -}; - - -/** - * Non-recursive search function - * - * @param {ol.Extent} extent Extent. - * @return {Array} Result. - * @this {ol.structs.RTree} - */ -ol.structs.RTree.prototype.search = function(extent) { - var rect = /** @type {ol.structs.RTreeNode} */ ({extent: extent}); - return /** @type {Array} */ ( - this.searchSubtree_(rect, false, [], this.rootTree_)); -}; - - -/** - * Non-recursive search function - * - * @param {ol.Extent} extent Extent. - * @return {Object} Result. Keys are UIDs of the values. - * @this {ol.structs.RTree} - */ -ol.structs.RTree.prototype.searchReturningObject = function(extent) { - var rect = /** @type {ol.structs.RTreeNode} */ ({extent: extent}); - return /** @type {Object} */ ( - this.searchSubtree_(rect, false, [], this.rootTree_, true)); -}; - - -/** - * Non-recursive internal search function - * - * @param {ol.structs.RTreeNode} rect Rectangle. - * @param {boolean} returnNode Do we return nodes? - * @param {Array|Object} result Result. - * @param {ol.structs.RTreeNode} root Root. - * @param {boolean=} opt_resultAsObject If set, result will be an object keyed - * by UID. - * @private - * @return {Array|Object} Result. - */ -ol.structs.RTree.prototype.searchSubtree_ = function( - rect, returnNode, result, root, opt_resultAsObject) { - var resultObject = {}; - var hitStack = []; // Contains the elements that overlap - - if (!ol.extent.intersects(rect.extent, root.extent)) { - return result; - } - - hitStack.push(root.nodes); - - do { - var nodes = hitStack.pop(); - - for (var i = nodes.length - 1; i >= 0; --i) { - var lTree = nodes[i]; - if (ol.extent.intersects(rect.extent, lTree.extent)) { - if (goog.isDef(lTree.nodes)) { // Not a Leaf - hitStack.push(lTree.nodes); - } else if (goog.isDef(lTree.leaf)) { // A Leaf !! - if (!returnNode) { - // TODO keep track of type on all nodes so we don't have to - // walk all the way in to the leaf to know that we don't need it - var obj = lTree.leaf; - if (goog.isDef(opt_resultAsObject)) { - resultObject[goog.getUid(obj).toString()] = obj; - } else { - result.push(obj); - } - } else { - result.push(lTree); - } - } - } - } - } while (hitStack.length > 0); - - if (goog.isDef(opt_resultAsObject)) { - return resultObject; - } else { - return result; - } -}; diff --git a/old/test/spec/ol/interaction/drawinteraction.test.js b/old/test/spec/ol/interaction/drawinteraction.test.js index f4c27f6b42..9f9867a7b2 100644 --- a/old/test/spec/ol/interaction/drawinteraction.test.js +++ b/old/test/spec/ol/interaction/drawinteraction.test.js @@ -1,7 +1,7 @@ goog.provide('ol.test.interaction.Draw'); describe('ol.interaction.Draw', function() { - var target, map, vector; + var target, map, source, layer; var width = 360; var height = 180; @@ -15,11 +15,12 @@ describe('ol.interaction.Draw', function() { style.width = width + 'px'; style.height = height + 'px'; document.body.appendChild(target); - vector = new ol.layer.Vector({source: new ol.source.Vector({})}); + source = new ol.source.Vector(); + layer = new ol.layer.Vector({source: source}); map = new ol.Map({ target: target, renderer: ol.RendererHint.CANVAS, - layers: [vector], + layers: [layer], view: new ol.View2D({ projection: 'EPSG:4326', center: [0, 0], @@ -56,7 +57,7 @@ describe('ol.interaction.Draw', function() { it('creates a new interaction', function() { var draw = new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.POINT }); expect(draw).to.be.a(ol.interaction.Draw); @@ -69,7 +70,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.POINT })); }); @@ -79,7 +80,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mousedown', 10, 20); simulateEvent('mouseup', 10, 20); simulateEvent('click', 10, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.Point); @@ -92,7 +93,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mousemove', 15, 20); simulateEvent('mouseup', 15, 20); simulateEvent('click', 15, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(0); }); @@ -102,7 +103,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.MULTIPOINT })); }); @@ -112,7 +113,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mousedown', 30, 15); simulateEvent('mouseup', 30, 15); simulateEvent('click', 30, 15); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.MultiPoint); @@ -125,7 +126,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.LINESTRING })); }); @@ -148,7 +149,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mouseup', 30, 20); simulateEvent('click', 30, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.LineString); @@ -181,7 +182,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mouseup', 30, 20); simulateEvent('click', 30, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.LineString); @@ -194,7 +195,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.MULTILINESTRING })); }); @@ -217,7 +218,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mouseup', 30, 20); simulateEvent('click', 30, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.MultiLineString); @@ -230,7 +231,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.POLYGON })); }); @@ -260,7 +261,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mouseup', 10, 20); simulateEvent('click', 10, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.Polygon); @@ -277,7 +278,7 @@ describe('ol.interaction.Draw', function() { beforeEach(function() { map.addInteraction(new ol.interaction.Draw({ - layer: vector, + layer: layer, type: ol.geom.GeometryType.MULTIPOLYGON })); }); @@ -307,7 +308,7 @@ describe('ol.interaction.Draw', function() { simulateEvent('mouseup', 10, 20); simulateEvent('click', 10, 20); - var features = vector.getFeatures(); + var features = source.getFeatures(); expect(features).to.have.length(1); var geometry = features[0].getGeometry(); expect(geometry).to.be.a(ol.geom.MultiPolygon); diff --git a/old/test/spec/ol/interaction/selectinteraction.test.js b/old/test/spec/ol/interaction/selectinteraction.test.js index 5c412af9dd..473653d352 100644 --- a/old/test/spec/ol/interaction/selectinteraction.test.js +++ b/old/test/spec/ol/interaction/selectinteraction.test.js @@ -1,7 +1,7 @@ goog.provide('ol.test.interaction.Select'); describe('ol.interaction.Select', function() { - var map, target, select, vector, features; + var map, target, select, source, vector, features; beforeEach(function() { target = document.createElement('div'); @@ -11,24 +11,19 @@ describe('ol.interaction.Select', function() { map = new ol.Map({ target: target }); - features = ol.parser.GeoJSON.read(JSON.stringify({ - 'type': 'FeatureCollection', - 'features': [{ - 'type': 'Feature', - 'geometry': { - 'type': 'Point', - 'coordinates': [-1, 1] - } - }, { - 'type': 'Feature', - 'geometry': { - 'type': 'Point', - 'coordinates': [1, -1] - } - }] - })); - vector = new ol.layer.Vector({source: new ol.source.Vector({})}); - vector.addFeatures(features); + + features = [ + new ol.Feature({ + geometry: new ol.geom.Point([-1, 1]) + }), + new ol.Feature({ + geometry: new ol.geom.Point([1, -1]) + }) + ]; + + source = new ol.source.Vector({}); + source.addFeatures(features); + vector = new ol.layer.Vector({source: source}); select = new ol.interaction.Select({ layers: [vector] }); @@ -52,21 +47,21 @@ describe('ol.interaction.Select', function() { it('toggles selection of features', function() { select.select(map, [features], [vector]); - expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(2); + expect(source.getFeatures(selectedFeaturesFilter).length).to.be(2); select.select(map, [features], [vector]); - expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(0); + expect(source.getFeatures(selectedFeaturesFilter).length).to.be(0); }); it('can append features to an existing selection', function() { select.select(map, [[features[0]]], [vector], true); select.select(map, [[features[1]]], [vector]); - expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(2); + expect(source.getFeatures(selectedFeaturesFilter).length).to.be(2); }); it('can clear a selection before selecting new features', function() { select.select(map, [[features[0]]], [vector], true); select.select(map, [[features[1]]], [vector], true); - expect(vector.getFeatures(selectedFeaturesFilter).length).to.be(1); + expect(source.getFeatures(selectedFeaturesFilter).length).to.be(1); }); }); @@ -74,8 +69,9 @@ describe('ol.interaction.Select', function() { }); goog.require('goog.dispose'); +goog.require('ol.Feature'); goog.require('ol.Map'); +goog.require('ol.geom.Point'); goog.require('ol.interaction.Select'); goog.require('ol.layer.Vector'); -goog.require('ol.parser.GeoJSON'); goog.require('ol.source.Vector'); diff --git a/old/test/spec/ol/layer/vectorlayer.test.js b/old/test/spec/ol/layer/vectorlayer.test.js index ea6977736e..f98cf65184 100644 --- a/old/test/spec/ol/layer/vectorlayer.test.js +++ b/old/test/spec/ol/layer/vectorlayer.test.js @@ -2,177 +2,15 @@ goog.provide('ol.test.layer.Vector'); describe('ol.layer.Vector', function() { - describe('#addFeatures()', function() { + describe('constructor', function() { + + it('creates a new layer', function() { - it('allows adding features', function() { var layer = new ol.layer.Vector({ - source: new ol.source.Vector({}) + source: new ol.source.Vector() }); - layer.addFeatures([new ol.Feature(), new ol.Feature()]); - expect(goog.object.getCount(layer.featureCache_.getFeaturesObject())) - .to.eql(2); - }); - }); - - describe('ol.layer.FeatureCache#getFeaturesObject()', function() { - - var layer, features; - - beforeEach(function() { - features = [ - new ol.Feature({ - g: new ol.geom.Point([16.0, 48.0]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[17.0, 49.0], [17.1, 49.1]]) - }) - ]; - layer = new ol.layer.Vector({ - source: new ol.source.Vector({}) - }); - layer.addFeatures(features); - }); - - it('returns the features in an object', function() { - var featuresObject = layer.featureCache_.getFeaturesObject(); - expect(goog.object.getCount(featuresObject)).to.eql(features.length); - }); - - }); - - describe('#groupFeaturesBySymbolizerLiteral()', function() { - - var layer = new ol.layer.Vector({ - source: new ol.source.Vector({ - projection: ol.proj.get('EPSG:4326') - }), - style: new ol.style.Style({ - rules: [ - new ol.style.Rule({ - symbolizers: [ - new ol.style.Stroke({ - width: 2, - color: ol.expr.parse('colorProperty'), - opacity: 1 - }) - ] - }) - ] - }) - }); - var features; - - it('groups equal symbolizers', function() { - features = [ - new ol.Feature({ - g: new ol.geom.LineString([[-10, -10], [10, 10]]), - colorProperty: '#BADA55' - }), - new ol.Feature({ - g: new ol.geom.LineString([[-10, 10], [10, -10]]), - colorProperty: '#013' - }), - new ol.Feature({ - g: new ol.geom.LineString([[10, -10], [-10, -10]]), - colorProperty: '#013' - }) - ]; - - var groups = layer.groupFeaturesBySymbolizerLiteral(features, 1); - expect(groups.length).to.be(2); - expect(groups[0][0].length).to.be(1); - expect(groups[0][1].color).to.be('#BADA55'); - expect(groups[1][0].length).to.be(2); - expect(groups[1][1].color).to.be('#013'); - }); - - it('groups equal symbolizers also when defined on features', function() { - var symbolizer = new ol.style.Stroke({ - width: 3, - color: ol.expr.parse('colorProperty'), - opacity: 1 - }); - var anotherSymbolizer = new ol.style.Stroke({ - width: 3, - color: '#BADA55', - opacity: 1 - }); - var featureWithSymbolizers = new ol.Feature({ - g: new ol.geom.LineString([[-10, -10], [-10, 10]]), - colorProperty: '#BADA55' - }); - featureWithSymbolizers.setSymbolizers([symbolizer]); - var anotherFeatureWithSymbolizers = new ol.Feature({ - g: new ol.geom.LineString([[-10, 10], [-10, -10]]) - }); - anotherFeatureWithSymbolizers.setSymbolizers([anotherSymbolizer]); - features.push(featureWithSymbolizers, anotherFeatureWithSymbolizers); - - var groups = layer.groupFeaturesBySymbolizerLiteral(features, 1); - expect(groups).to.have.length(3); - expect(groups[2][0].length).to.be(2); - expect(groups[2][1].width).to.be(3); - - }); - - it('sorts groups by zIndex', function() { - var symbolizer = new ol.style.Stroke({ - width: 3, - color: '#BADA55', - opacity: 1, - zIndex: 1 - }); - var anotherSymbolizer = new ol.style.Stroke({ - width: 3, - color: '#BADA55', - opacity: 1 - }); - var featureWithSymbolizers = new ol.Feature({ - g: new ol.geom.LineString([[-10, -10], [-10, 10]]) - }); - featureWithSymbolizers.setSymbolizers([symbolizer]); - var anotherFeatureWithSymbolizers = new ol.Feature({ - g: new ol.geom.LineString([[-10, 10], [-10, -10]]) - }); - anotherFeatureWithSymbolizers.setSymbolizers([anotherSymbolizer]); - features = [featureWithSymbolizers, anotherFeatureWithSymbolizers]; - - var groups = layer.groupFeaturesBySymbolizerLiteral(features, 1); - expect(groups).to.have.length(2); - expect(groups[0][1].zIndex).to.be(0); - expect(groups[1][1].zIndex).to.be(1); - }); - - goog.dispose(layer); - - }); - - describe('ol.layer.VectorEvent', function() { - - var layer, features; - - beforeEach(function() { - features = [ - new ol.Feature({ - g: new ol.geom.Point([16.0, 48.0]) - }), - new ol.Feature({ - g: new ol.geom.LineString([[17.0, 49.0], [17.1, 49.1]]) - }) - ]; - layer = new ol.layer.Vector({ - source: new ol.source.Vector({}) - }); - layer.addFeatures(features); - }); - - it('dispatches events on feature change', function(done) { - layer.on('featurechange', function(evt) { - expect(evt.features[0]).to.be(features[0]); - expect(evt.extents[0]).to.eql(features[0].getGeometry().getBounds()); - done(); - }); - features[0].set('foo', 'bar'); + expect(layer).to.be.a(ol.layer.Vector); + expect(layer).to.be.a(ol.layer.Layer); }); @@ -180,15 +18,6 @@ describe('ol.layer.Vector', function() { }); -goog.require('goog.dispose'); -goog.require('goog.object'); -goog.require('ol.Feature'); -goog.require('ol.expr'); -goog.require('ol.geom.LineString'); -goog.require('ol.geom.Point'); -goog.require('ol.proj'); +goog.require('ol.layer.Layer'); goog.require('ol.layer.Vector'); goog.require('ol.source.Vector'); -goog.require('ol.style.Rule'); -goog.require('ol.style.Stroke'); -goog.require('ol.style.Style'); diff --git a/old/test/spec/ol/parser/kml.test.js b/old/test/spec/ol/parser/kml.test.js index 4fb7774edc..4a165f055b 100644 --- a/old/test/spec/ol/parser/kml.test.js +++ b/old/test/spec/ol/parser/kml.test.js @@ -163,6 +163,19 @@ describe('ol.parser.KML', function() { expect(obj.features[0].get('description')).to.eql('Full of text.'); expect(obj.features[0].get('name')).to.eql('Pezinok'); }); + it('Test CDATA attributes with newlines', function() { + var cdata = '' + + ' ' + + '\n' + + '' + + '\n' + + '#rel1.0' + + ' 17.266666, 48.283333' + + ''; + var obj = parser.read(cdata); + expect(obj.features[0].get('description')).to.eql('Full of text.'); + expect(obj.features[0].get('name')).to.eql('Pezinok'); + }); it('handles line style (read / write)', function() { var kml = ' 0) { - var min = [Math.random() * 10000, Math.random() * 10000]; - var max = [min[0] + Math.random() * 500, min[1] + Math.random() * 500]; - var bounds = [min[0], min[1], max[0], max[1]]; - rTree.insert(bounds, 'JUST A TEST OBJECT!_' + i); - i--; - } - expect(goog.object.getCount(rTree.search([0, 0, 10600, 10600]))) - .to.be(1000); - }); - it('can insert 1k more objects', function() { - var i = 1000; - while (i > 0) { - var min = [Math.random() * 10000, Math.random() * 10000]; - var max = [min[0] + Math.random() * 500, min[1] + Math.random() * 500]; - var bounds = [min[0], min[1], max[0], max[1]]; - rTree.insert(bounds, 'JUST A TEST OBJECT!_' + i); - i--; - } - expect(goog.object.getCount(rTree.search([0, 0, 10600, 10600]))) - .to.be(2000); - }); - }); - - describe('search', function() { - it('can perform 1k out-of-bounds searches', function() { - var i = 1000; - var len = 0; - while (i > 0) { - var min = [-(Math.random() * 10000 + 501), - -(Math.random() * 10000 + 501)]; - var max = [min[0] + Math.random() * 500, min[1] + Math.random() * 500]; - var bounds = [min[0], min[1], max[0], max[1]]; - len += rTree.search(bounds).length; - i--; - } - expect(len).to.be(0); - }); - it('can perform 1k in-bounds searches', function() { - var i = 1000; - var len = 0; - while (i > 0) { - var min = [Math.random() * 10000, Math.random() * 10000]; - var max = [min[0] + Math.random() * 500, min[1] + Math.random() * 500]; - var bounds = [min[0], min[1], max[0], max[1]]; - len += rTree.search(bounds).length; - i--; - } - expect(len).not.to.be(0); - }); - }); - - describe('deletion', function() { - var len = 0; - it('can delete half the RTree', function() { - var bounds = [5000, 0, 10500, 10500]; - len += rTree.remove(bounds).length; - expect(len).to.not.be(0); - }); - it('can delete the other half of the RTree', function() { - var bounds = [0, 0, 5000, 10500]; - len += rTree.remove(bounds).length; - expect(len).to.be(2000); - }); - }); - - describe('result plausibility and structure', function() { - - it('filters by rectangle', function() { - rTree.insert([0, 0, 1, 1], 1); - rTree.insert([1, 1, 4, 4], 2); - rTree.insert([2, 2, 3, 3], 3); - rTree.insert([-5, -5, -4, -4], 4); - rTree.insert([-4, -4, -1, -1], 5); - rTree.insert([-3, -3, -2, -2], 6); - - var result; - result = goog.object.getValues(rTree.search([2, 2, 3, 3])); - expect(result).to.contain(2); - expect(result).to.contain(3); - expect(result.length).to.be(2); - result = goog.object.getValues(rTree.search([-1, -1, 2, 2])); - expect(result).to.contain(1); - expect(result).to.contain(2); - expect(result).to.contain(3); - expect(result).to.contain(5); - expect(result.length).to.be(4); - expect(goog.object.getCount(rTree.search([5, 5, 6, 6]))).to.be(0); - }); - - it('can return objects instead of arrays', function() { - var obj = {foo: 'bar'}; - rTree.insert([5, 5, 5, 5], obj); - var result = rTree.searchReturningObject([4, 4, 6, 6]); - expect(result[goog.getUid(obj)]).to.equal(obj); - }); - - }); - -}); - -goog.require('goog.object'); -goog.require('ol.structs.RTree'); diff --git a/old/test/spec/ol/style/style.test.js b/old/test/spec/ol/style/style.test.js index d282a06dcd..a58e68275d 100644 --- a/old/test/spec/ol/style/style.test.js +++ b/old/test/spec/ol/style/style.test.js @@ -122,6 +122,102 @@ describe('ol.style.Style', function() { }); + describe('#groupFeaturesBySymbolizerLiteral()', function() { + + var style = new ol.style.Style({ + symbolizers: [ + new ol.style.Stroke({ + width: 2, + color: ol.expr.parse('colorProperty'), + opacity: 1 + }) + ] + }); + var features; + + it('groups equal symbolizers', function() { + features = [ + new ol.Feature({ + g: new ol.geom.LineString([[-10, -10], [10, 10]]), + colorProperty: '#BADA55' + }), + new ol.Feature({ + g: new ol.geom.LineString([[-10, 10], [10, -10]]), + colorProperty: '#013' + }), + new ol.Feature({ + g: new ol.geom.LineString([[10, -10], [-10, -10]]), + colorProperty: '#013' + }) + ]; + + var groups = style.groupFeaturesBySymbolizerLiteral(features, 1); + expect(groups.length).to.be(2); + expect(groups[0][0].length).to.be(1); + expect(groups[0][1].color).to.be('#BADA55'); + expect(groups[1][0].length).to.be(2); + expect(groups[1][1].color).to.be('#013'); + }); + + it('groups equal symbolizers also when defined on features', function() { + var symbolizer = new ol.style.Stroke({ + width: 3, + color: ol.expr.parse('colorProperty'), + opacity: 1 + }); + var anotherSymbolizer = new ol.style.Stroke({ + width: 3, + color: '#BADA55', + opacity: 1 + }); + var featureWithSymbolizers = new ol.Feature({ + g: new ol.geom.LineString([[-10, -10], [-10, 10]]), + colorProperty: '#BADA55' + }); + featureWithSymbolizers.setSymbolizers([symbolizer]); + var anotherFeatureWithSymbolizers = new ol.Feature({ + g: new ol.geom.LineString([[-10, 10], [-10, -10]]) + }); + anotherFeatureWithSymbolizers.setSymbolizers([anotherSymbolizer]); + features.push(featureWithSymbolizers, anotherFeatureWithSymbolizers); + + var groups = style.groupFeaturesBySymbolizerLiteral(features, 1); + expect(groups).to.have.length(3); + expect(groups[2][0].length).to.be(2); + expect(groups[2][1].width).to.be(3); + + }); + + it('sorts groups by zIndex', function() { + var symbolizer = new ol.style.Stroke({ + width: 3, + color: '#BADA55', + opacity: 1, + zIndex: 1 + }); + var anotherSymbolizer = new ol.style.Stroke({ + width: 3, + color: '#BADA55', + opacity: 1 + }); + var featureWithSymbolizers = new ol.Feature({ + g: new ol.geom.LineString([[-10, -10], [-10, 10]]) + }); + featureWithSymbolizers.setSymbolizers([symbolizer]); + var anotherFeatureWithSymbolizers = new ol.Feature({ + g: new ol.geom.LineString([[-10, 10], [-10, -10]]) + }); + anotherFeatureWithSymbolizers.setSymbolizers([anotherSymbolizer]); + features = [featureWithSymbolizers, anotherFeatureWithSymbolizers]; + + var groups = style.groupFeaturesBySymbolizerLiteral(features, 1); + expect(groups).to.have.length(2); + expect(groups[0][1].zIndex).to.be(0); + expect(groups[1][1].zIndex).to.be(1); + }); + + }); + describe('ol.style.getDefault()', function() { var style = ol.style.getDefault(); diff --git a/test/spec/ol/source/vectorsource/single-feature.json b/test/spec/ol/source/vectorsource/single-feature.json new file mode 100644 index 0000000000..5d7944efbe --- /dev/null +++ b/test/spec/ol/source/vectorsource/single-feature.json @@ -0,0 +1,16 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "point_1", + "geometry": { + "coordinates": [1, 2], + "type": "Point" + }, + "properties": { + "name": "point" + } + } + ] +} diff --git a/test/spec/ol/structs/rbush.js b/test/spec/ol/structs/rbush.test.js similarity index 100% rename from test/spec/ol/structs/rbush.js rename to test/spec/ol/structs/rbush.test.js