Merge pull request #1368 from twpayne/vector-api-kml

[vector-api] ol.format.KML
This commit is contained in:
Tom Payne
2013-12-19 09:07:43 -08:00
23 changed files with 17978 additions and 70 deletions
File diff suppressed because one or more lines are too long
+9 -9
View File
@@ -104,13 +104,13 @@
</Style> </Style>
<Folder> <Folder>
<name>Paths</name> <name>Paths</name>
<visibility>0</visibility> <visibility>1</visibility>
<description>Examples of paths. Note that the tessellate tag is by default <description>Examples of paths. Note that the tessellate tag is by default
set to 0. If you want to create tessellated lines, they must be authored set to 0. If you want to create tessellated lines, they must be authored
(or edited) directly in KML.</description> (or edited) directly in KML.</description>
<Placemark> <Placemark>
<name>Tessellated</name> <name>Tessellated</name>
<visibility>0</visibility> <visibility>1</visibility>
<description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description> <description><![CDATA[If the <tessellate> tag has a value of 1, the line will contour to the underlying terrain]]></description>
<LookAt> <LookAt>
<longitude>-112.0822680013139</longitude> <longitude>-112.0822680013139</longitude>
@@ -128,7 +128,7 @@
</Placemark> </Placemark>
<Placemark> <Placemark>
<name>Untessellated</name> <name>Untessellated</name>
<visibility>0</visibility> <visibility>1</visibility>
<description><![CDATA[If the <tessellate> tag has a value of 0, the line follow a simple straight-line path from point to point]]></description> <description><![CDATA[If the <tessellate> tag has a value of 0, the line follow a simple straight-line path from point to point]]></description>
<LookAt> <LookAt>
<longitude>-112.0822680013139</longitude> <longitude>-112.0822680013139</longitude>
@@ -146,7 +146,7 @@
</Placemark> </Placemark>
<Placemark> <Placemark>
<name>Absolute</name> <name>Absolute</name>
<visibility>0</visibility> <visibility>1</visibility>
<description>Transparent purple line</description> <description>Transparent purple line</description>
<LookAt> <LookAt>
<longitude>-112.2719329043177</longitude> <longitude>-112.2719329043177</longitude>
@@ -175,7 +175,7 @@
</Placemark> </Placemark>
<Placemark> <Placemark>
<name>Absolute Extruded</name> <name>Absolute Extruded</name>
<visibility>0</visibility> <visibility>1</visibility>
<description>Transparent green wall with yellow outlines</description> <description>Transparent green wall with yellow outlines</description>
<LookAt> <LookAt>
<longitude>-112.2643334742529</longitude> <longitude>-112.2643334742529</longitude>
@@ -205,7 +205,7 @@
</Placemark> </Placemark>
<Placemark> <Placemark>
<name>Relative</name> <name>Relative</name>
<visibility>0</visibility> <visibility>1</visibility>
<description>Black line (10 pixels wide), height tracks terrain</description> <description>Black line (10 pixels wide), height tracks terrain</description>
<LookAt> <LookAt>
<longitude>-112.2580438551384</longitude> <longitude>-112.2580438551384</longitude>
@@ -234,7 +234,7 @@
</Placemark> </Placemark>
<Placemark> <Placemark>
<name>Relative Extruded</name> <name>Relative Extruded</name>
<visibility>0</visibility> <visibility>1</visibility>
<description>Opaque blue walls with red outline, height tracks terrain</description> <description>Opaque blue walls with red outline, height tracks terrain</description>
<LookAt> <LookAt>
<longitude>-112.2683594333433</longitude> <longitude>-112.2683594333433</longitude>
@@ -265,7 +265,7 @@
<Placemark> <Placemark>
<name>Blue Icon</name> <name>Blue Icon</name>
<description>Just another blue icon.</description> <description>Just another blue icon.</description>
<styleUrl>data/kml/styles.kml#blueIcons</styleUrl> <styleUrl>styles.kml#blueIcons</styleUrl>
<Point> <Point>
<coordinates>-112.292238941097,36.09520916122063,630</coordinates> <coordinates>-112.292238941097,36.09520916122063,630</coordinates>
</Point> </Point>
@@ -273,7 +273,7 @@
<Placemark> <Placemark>
<name>Sun Icon</name> <name>Sun Icon</name>
<description>Just another sun icon.</description> <description>Just another sun icon.</description>
<styleUrl>data/kml/styles.kml#sunIconMap</styleUrl> <styleUrl>styles.kml#sunIconMap</styleUrl>
<Point> <Point>
<coordinates>-112.292238941097,36.15520916122063,630</coordinates> <coordinates>-112.292238941097,36.15520916122063,630</coordinates>
</Point> </Point>
+56
View File
@@ -0,0 +1,56 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Drag-and-Drop example</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>
<div class="row-fluid">
<div class="span4">
<h4 id="title">Drag-and-Drop example</h4>
<p id="shortdesc">Example of using the drag-and-drop interaction. Drag and drop KML files on to the map.</p>
<div id="docs">
<p>See the <a href="drag-and-drop.js" target="_blank">drag-and-drop.js source</a> to see how this is done.</p>
</div>
<div id="tags">drag-and-drop, kml</div>
</div>
<div class="span4 offset4">
<div id="info" class="alert alert-success">
&nbsp;
</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="loader.js?id=drag-and-drop" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
</body>
</html>
+60
View File
@@ -0,0 +1,60 @@
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.format.KML');
goog.require('ol.interaction');
goog.require('ol.interaction.DragAndDrop');
goog.require('ol.layer.Tile');
goog.require('ol.source.BingMaps');
var map = new ol.Map({
interactions: ol.interaction.defaults().extend([
new ol.interaction.DragAndDrop({
formatConstructors: [
ol.format.KML
]
})
]),
layers: [
new ol.layer.Tile({
source: new ol.source.BingMaps({
imagerySet: 'Aerial',
key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'
})
})
],
renderer: ol.RendererHint.CANVAS,
target: 'map',
view: new ol.View2D({
center: [0, 0],
zoom: 2
})
});
var displayFeatureInfo = function(pixel) {
var features = [];
map.forEachFeatureAtPixel(pixel, function(feature, layer) {
features.push(feature);
});
if (features.length > 0) {
var info = [];
var i, ii;
for (i = 0, ii = features.length; i < ii; ++i) {
info.push(features[i].get('name'));
}
document.getElementById('info').innerHTML = info.join(', ') || '&nbsp';
} else {
document.getElementById('info').innerHTML = '&nbsp;';
}
};
$(map.getViewport()).on('mousemove', function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on('singleclick', function(evt) {
var pixel = evt.getPixel();
displayFeatureInfo(pixel);
});
+75
View File
@@ -0,0 +1,75 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Earthquakes in KML</title>
<style>
#map {
position: relative;
}
#info {
position: absolute;
height: 1px;
width: 1px;
z-index: 100;
}
.tooltip.in {
opacity: 1;
filter: alpha(opacity=100);
}
.tooltip.top .tooltip-arrow {
border-top-color: white;
}
.tooltip-inner {
border: 2px solid white;
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"><div id="info"></div></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">Earthquakes in KML</h4>
<p id="shortdesc">Demonstrates the use of a Shape symbolizer to render earthquake locations.</p>
<div id="docs">
<p>
This example parses a KML file and renders the features as a vector layer. The layer is given a <code>styleFunction</code> that renders earthquake locations with a size relative to their magnitude.
</p>
<p>See the <a href="kml-earthquakes.js" target="_blank">kml-earthquakes.js source</a> to see how this is done.</p>
</div>
<div id="tags">KML, vector, style</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="../resources/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="loader.js?id=kml-earthquakes" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
</body>
</html>
+96
View File
@@ -0,0 +1,96 @@
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.KML');
goog.require('ol.source.Stamen');
goog.require('ol.style.Circle');
goog.require('ol.style.Fill');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
var styleCache = {};
var styleFunction = function(feature, resolution) {
// 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a
// standards-violating <magnitude> tag in each Placemark. We extract it from
// the Placemark's name instead.
var name = feature.get('name');
var magnitude = parseFloat(name.substr(2));
var radius = 5 + 20 * (magnitude - 5);
var style = styleCache[radius];
if (!style) {
style = [new ol.style.Style({
image: new ol.style.Circle({
radius: radius,
fill: new ol.style.Fill({
color: 'rgba(255, 153, 0, 0.4)'
}),
stroke: new ol.style.Stroke({
color: 'rgba(255, 204, 0, 0.2)',
width: 1
})
})
})];
styleCache[radius] = style;
}
return style;
};
var vector = new ol.layer.Vector({
source: new ol.source.KML({
reprojectTo: 'EPSG:3857',
url: 'data/kml/2012_Earthquakes_Mag5.kml'
}),
styleFunction: styleFunction
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var map = new ol.Map({
layers: [raster, vector],
renderer: ol.RendererHint.CANVAS,
target: 'map',
view: new ol.View2D({
center: [0, 0],
zoom: 2
})
});
var info = $('#info');
info.tooltip({
animation: false,
trigger: 'manual'
});
var displayFeatureInfo = function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
info.css({
left: pixel[0] + 'px',
top: (pixel[1] - 15) + 'px'
});
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
return feature;
});
if (feature) {
info.tooltip('hide')
.attr('data-original-title', feature.get('name'))
.tooltip('fixTitle')
.tooltip('show');
} else {
info.tooltip('hide');
}
};
$(map.getViewport()).on('mousemove', function(evt) {
displayFeatureInfo(evt);
});
map.on('singleclick', function(evt) {
displayFeatureInfo(evt);
});
+63
View File
@@ -0,0 +1,63 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Timezones in KML</title>
<style>
#map {
position: relative;
}
#info {
position: absolute;
height: 1px;
width: 1px;
z-index: 100;
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"><div id="info"></div></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">Timezones in KML</h4>
<p id="shortdesc">Demonstrates rendering timezones from KML.</p>
<div id="docs">
<p>This example parses a KML file and renders the features as a vector layer. The layer is given a <code>ol.style.Style</code> that fills timezones yellow with an opacity calculated based on the current offset to local noon.</p>
<p>See the <a href="kml-timezones.js" target="_blank">kml-timezones.js source</a> to see how this is done.</p>
</div>
<div id="tags">KML, vector, style</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="../resources/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="loader.js?id=kml-timezones" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
</body>
</html>
+102
View File
@@ -0,0 +1,102 @@
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.KML');
goog.require('ol.source.Stamen');
goog.require('ol.style.Fill');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
/*
* Compute the style of the feature. Here we want the opacity of polygons to
* be based on the offset from local noon. For example, a timezone where it is
* currently noon would have an opacity of 0.75. And a timezone where it is
* currently midnight would have an opacity of 0. This doesn't account for
* daylight savings, so don't use it to plan your vacation.
*/
var styleFunction = function(feature, resolution) {
var offset = 0;
var name = feature.get('name'); // e.g. GMT -08:30
var match = name.match(/([\-+]\d{2}):(\d{2})$/);
if (match) {
var hours = parseInt(match[1], 10);
var minutes = parseInt(match[2], 10);
offset = 60 * hours + minutes;
}
var date = new Date();
var local = new Date(date.getTime() +
(date.getTimezoneOffset() + offset) * 60000);
// offset from local noon (in hours)
var delta = Math.abs(12 - local.getHours() + (local.getMinutes() / 60));
if (delta > 12) {
delta = 24 - delta;
}
var opacity = 0.75 * (1 - delta / 12);
return [new ol.style.Style({
fill: new ol.style.Fill({
color: [0xff, 0xff, 0x33, opacity]
}),
stroke: new ol.style.Stroke({
color: '#ffffff'
})
})];
};
var vector = new ol.layer.Vector({
source: new ol.source.KML({
url: 'data/kml/timezones.kml'
}),
styleFunction: styleFunction
});
var raster = new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'toner'
})
});
var map = new ol.Map({
layers: [raster, vector],
renderer: ol.RendererHint.CANVAS,
target: 'map',
view: new ol.View2D({
center: [0, 0],
zoom: 2
})
});
var info = $('#info');
info.tooltip({
animation: false,
trigger: 'manual'
});
var displayFeatureInfo = function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
info.css({
left: pixel[0] + 'px',
top: (pixel[1] - 15) + 'px'
});
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
return feature;
});
if (feature) {
info.tooltip('hide')
.attr('data-original-title', feature.get('name'))
.tooltip('fixTitle')
.tooltip('show');
} else {
info.tooltip('hide');
}
};
$(map.getViewport()).on('mousemove', function(evt) {
displayFeatureInfo(evt);
});
map.on('singleclick', function(evt) {
displayFeatureInfo(evt);
});
+56
View File
@@ -0,0 +1,56 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>KML example</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>
<div class="row-fluid">
<div class="span4">
<h4 id="title">KML example</h4>
<p id="shortdesc">Example of using the KML source.</p>
<div id="docs">
<p>See the <a href="kml.js" target="_blank">kml.js source</a> to see how this is done.</p>
</div>
<div id="tags">KML</div>
</div>
<div class="span4 offset4">
<div id="info" class="alert alert-success">
&nbsp;
</div>
</div>
</div>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="loader.js?id=kml" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
</body>
</html>
+58
View File
@@ -0,0 +1,58 @@
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.BingMaps');
goog.require('ol.source.KML');
var raster = new ol.layer.Tile({
source: new ol.source.BingMaps({
imagerySet: 'Aerial',
key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3'
})
});
var vector = new ol.layer.Vector({
source: new ol.source.KML({
reprojectTo: 'EPSG:3857',
url: 'data/kml/2012-02-10.kml'
})
});
var map = new ol.Map({
layers: [raster, vector],
renderer: ol.RendererHint.CANVAS,
target: 'map',
view: new ol.View2D({
center: [876970.8463461736, 5859807.853963373],
zoom: 10
})
});
var displayFeatureInfo = function(pixel) {
var features = [];
map.forEachFeatureAtPixel(pixel, function(feature, layer) {
features.push(feature);
});
if (features.length > 0) {
var info = [];
var i, ii;
for (i = 0, ii = features.length; i < ii; ++i) {
info.push(features[i].get('name'));
}
document.getElementById('info').innerHTML = info.join(', ') || '&nbsp';
} else {
document.getElementById('info').innerHTML = '&nbsp;';
}
};
$(map.getViewport()).on('mousemove', function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
displayFeatureInfo(pixel);
});
map.on('singleclick', function(evt) {
var pixel = evt.getPixel();
displayFeatureInfo(pixel);
});
+32
View File
@@ -260,6 +260,12 @@
* Possible values are `barometric`, `gps`, and `none`. Default is `none`. * Possible values are `barometric`, `gps`, and `none`. Default is `none`.
*/ */
/**
* @typedef {Object} olx.format.KMLOptions
* @property {boolean|undefined} extractAttributes Extract attributes.
* @property {boolean|undefined} extractStyles Extract styles.
*/
/** /**
* @typedef {Object} olx.interaction.DoubleClickZoomOptions * @typedef {Object} olx.interaction.DoubleClickZoomOptions
* @property {number|undefined} duration Animation duration in milliseconds. Default is `250`. * @property {number|undefined} duration Animation duration in milliseconds. Default is `250`.
@@ -268,6 +274,19 @@
* @todo stability experimental * @todo stability experimental
*/ */
/**
* @typedef {Object} olx.interaction.DragAndDropOptions
* @property {boolean|undefined} fitView Fit view. Default is `true`.
* @property {Array.<function(new: ol.format.Format)>|undefined}
* formatConstructors Format constructors.
* @property {ol.source.Vector|undefined} source Source. If this is defined
* then features will be added to this source.
* @property {ol.layer.Vector|undefined} layer Layer. If this is defined then
* features will be added to this layer's source. If neither `source` nor
* `layer` are defined then the dropped features will be added as a new
* layer.
*/
/** /**
* @typedef {Object} olx.interaction.DragPanOptions * @typedef {Object} olx.interaction.DragPanOptions
* @property {ol.Kinetic|undefined} kinetic Kinetic inertia to apply to the pan. * @property {ol.Kinetic|undefined} kinetic Kinetic inertia to apply to the pan.
@@ -530,6 +549,19 @@
* @property {Object|undefined} params Additional parameters. * @property {Object|undefined} params Additional parameters.
*/ */
/**
* @typedef {Object} olx.source.KMLOptions
* @property {Array.<ol.Attribution>|undefined} attributions Attributions.
* @property {Document|undefined} doc Document.
* @property {ol.Extent|undefined} extent Extent.
* @property {string|undefined} logo Logo.
* @property {Node|undefined| node Node.
* @property {ol.proj.ProjectionLike} projection Projection.
* @property {ol.proj.ProjectionLike} reprojectTo Re-project to.
* @property {string|undefined} text Text.
* @property {string|undefined} url URL.
*/
/** /**
* @typedef {Object} olx.source.MapQuestOptions * @typedef {Object} olx.source.MapQuestOptions
* @property {ol.TileLoadFunctionType|undefined} tileLoadFunction Optional * @property {ol.TileLoadFunctionType|undefined} tileLoadFunction Optional
+6
View File
@@ -23,6 +23,12 @@ ol.format.Format = function() {
}; };
/**
* @return {Array.<string>} Extensions.
*/
ol.format.Format.prototype.getExtensions = goog.abstractMethod;
/** /**
* @return {ol.format.FormatType} Format. * @return {ol.format.FormatType} Format.
*/ */
+15
View File
@@ -41,6 +41,13 @@ ol.format.GeoJSON = function(opt_options) {
goog.inherits(ol.format.GeoJSON, ol.format.JSON); goog.inherits(ol.format.GeoJSON, ol.format.JSON);
/**
* @const {Array.<string>}
* @private
*/
ol.format.GeoJSON.EXTENSIONS_ = ['.geojson'];
/** /**
* @param {GeoJSONObject} object Object. * @param {GeoJSONObject} object Object.
* @private * @private
@@ -278,6 +285,14 @@ ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
}; };
/**
* @inheritDoc
*/
ol.format.GeoJSON.prototype.getExtensions = function() {
return ol.format.GeoJSON.EXTENSIONS_;
};
/** /**
* @inheritDoc * @inheritDoc
*/ */
+1
View File
@@ -0,0 +1 @@
@exportSymbol ol.format.KML
File diff suppressed because it is too large Load Diff
+81 -61
View File
@@ -1,6 +1,8 @@
goog.provide('ol.format.XML'); goog.provide('ol.format.XML');
goog.require('goog.array');
goog.require('goog.asserts'); goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.xml'); goog.require('goog.dom.xml');
goog.require('ol.format.Format'); goog.require('ol.format.Format');
goog.require('ol.format.FormatType'); goog.require('ol.format.FormatType');
@@ -17,57 +19,6 @@ ol.format.XML = function() {
goog.inherits(ol.format.XML, ol.format.Format); goog.inherits(ol.format.XML, ol.format.Format);
/**
* @param {Document|Node|Object|string} source Source.
* @private
* @return {Document} Document.
*/
ol.format.XML.prototype.getDocument_ = function(source) {
if (source instanceof Document) {
return source;
} else if (goog.isString(source)) {
return goog.dom.xml.loadXml(source);
} else {
goog.asserts.fail();
return null;
}
};
/**
* @param {Document|Node|Object|string} source Source.
* @private
* @return {Document|Node} Document.
*/
ol.format.XML.prototype.getDocumentOrNode_ = function(source) {
if (source instanceof Document) {
return source;
} else if (source instanceof Node) {
return source;
} else if (goog.isString(source)) {
return goog.dom.xml.loadXml(source);
} else {
goog.asserts.fail();
return null;
}
};
/**
* @param {Document|Node|Object|string} source Source.
* @private
* @return {Node} Node.
*/
ol.format.XML.prototype.getNode_ = function(source) {
if (source instanceof Node) {
return source;
} else {
goog.asserts.fail();
return null;
}
};
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -80,7 +31,31 @@ ol.format.XML.prototype.getType = function() {
* @inheritDoc * @inheritDoc
*/ */
ol.format.XML.prototype.readFeature = function(source) { ol.format.XML.prototype.readFeature = function(source) {
return this.readFeatureFromNode(this.getNode_(source)); if (source instanceof Document) {
return this.readFeatureFromDocument(source);
} else if (source instanceof Node) {
return this.readFeatureFromNode(source);
} else if (goog.isString(source)) {
var doc = goog.dom.xml.loadXml(source);
return this.readFeatureFromDocument(doc);
} else {
goog.asserts.fail();
return null;
}
};
/**
* @param {Document} doc Document.
* @return {ol.Feature} Feature.
*/
ol.format.XML.prototype.readFeatureFromDocument = function(doc) {
var features = this.readFeaturesFromDocument(doc);
if (features.length > 0) {
return features[0];
} else {
return null;
}
}; };
@@ -95,11 +70,13 @@ ol.format.XML.prototype.readFeatureFromNode = goog.abstractMethod;
* @inheritDoc * @inheritDoc
*/ */
ol.format.XML.prototype.readFeatures = function(source) { ol.format.XML.prototype.readFeatures = function(source) {
var documentOrNode = this.getDocumentOrNode_(source); if (source instanceof Document) {
if (documentOrNode instanceof Document) { return this.readFeaturesFromDocument(source);
return this.readFeaturesFromDocument(documentOrNode); } else if (source instanceof Node) {
} else if (documentOrNode instanceof Node) { return this.readFeaturesFromNode(source);
return this.readFeaturesFromNode(documentOrNode); } else if (goog.isString(source)) {
var doc = goog.dom.xml.loadXml(source);
return this.readFeaturesFromDocument(doc);
} else { } else {
goog.asserts.fail(); goog.asserts.fail();
return null; return null;
@@ -113,8 +90,15 @@ ol.format.XML.prototype.readFeatures = function(source) {
* @return {Array.<ol.Feature>} Features. * @return {Array.<ol.Feature>} Features.
*/ */
ol.format.XML.prototype.readFeaturesFromDocument = function(doc) { ol.format.XML.prototype.readFeaturesFromDocument = function(doc) {
goog.asserts.assert(doc.childNodes.length == 1); /** @type {Array.<ol.Feature>} */
return this.readFeaturesFromNode(doc.firstChild); var features = [];
var n;
for (n = doc.firstChild; !goog.isNull(n); n = n.nextSibling) {
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
goog.array.extend(features, this.readFeaturesFromNode(n));
}
}
return features;
}; };
@@ -130,10 +114,28 @@ ol.format.XML.prototype.readFeaturesFromNode = goog.abstractMethod;
* @inheritDoc * @inheritDoc
*/ */
ol.format.XML.prototype.readGeometry = function(source) { ol.format.XML.prototype.readGeometry = function(source) {
return this.readGeometryFromNode(this.getNode_(source)); if (source instanceof Document) {
return this.readGeometryFromDocument(source);
} else if (source instanceof Node) {
return this.readGeometryFromNode(source);
} else if (goog.isString(source)) {
var doc = goog.dom.xml.loadXml(source);
return this.readGeometryFromDocument(doc);
} else {
goog.asserts.fail();
return null;
}
}; };
/**
* @param {Document} doc Document.
* @protected
* @return {ol.geom.Geometry} Geometry.
*/
ol.format.XML.prototype.readGeometryFromDocument = goog.abstractMethod;
/** /**
* @param {Node} node Node. * @param {Node} node Node.
* @protected * @protected
@@ -146,10 +148,28 @@ ol.format.XML.prototype.readGeometryFromNode = goog.abstractMethod;
* @inheritDoc * @inheritDoc
*/ */
ol.format.XML.prototype.readProjection = function(source) { ol.format.XML.prototype.readProjection = function(source) {
return this.readProjectionFromNode(this.getNode_(source)); if (source instanceof Document) {
return this.readProjectionFromDocument(source);
} else if (source instanceof Node) {
return this.readProjectionFromNode(source);
} else if (goog.isString(source)) {
var doc = goog.dom.xml.loadXml(source);
return this.readProjectionFromDocument(doc);
} else {
goog.asserts.fail();
return null;
}
}; };
/**
* @param {Document} doc Document.
* @protected
* @return {ol.proj.Projection} Projection.
*/
ol.format.XML.prototype.readProjectionFromDocument = goog.abstractMethod;
/** /**
* @param {Node} node Node. * @param {Node} node Node.
* @protected * @protected
@@ -0,0 +1 @@
@exportSymbol ol.interaction.DragAndDrop
@@ -0,0 +1,202 @@
// FIXME should handle all geo-referenced data, not just vector data
goog.provide('ol.interaction.DragAndDrop');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.FileDropHandler');
goog.require('goog.events.FileDropHandler.EventType');
goog.require('goog.fs.FileReader');
goog.require('goog.functions');
goog.require('ol.interaction.Interaction');
goog.require('ol.layer.Vector');
goog.require('ol.proj');
goog.require('ol.source.Vector');
/**
* @constructor
* @extends {ol.interaction.Interaction}
* @param {olx.interaction.DragAndDropOptions=} opt_options Options.
*/
ol.interaction.DragAndDrop = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {};
goog.base(this);
/**
* @private
* @type {boolean}
*/
this.fitView_ = goog.isDef(options.fitView) ? options.fitView : true;
/**
* @private
* @type {Array.<function(new: ol.format.Format)>}
*/
this.formatConstructors_ = goog.isDef(options.formatConstructors) ?
options.formatConstructors : [];
/**
* @private
* @type {ol.source.Vector}
*/
this.source_ = goog.isDef(options.source) ? options.source : null;
/**
* @private
* @type {ol.layer.Vector}
*/
this.layer_ = goog.isDef(options.layer) ? options.layer : null;
/**
* @private
* @type {goog.events.FileDropHandler}
*/
this.fileDropHandler_ = null;
/**
* @private
* @type {goog.events.Key|undefined}
*/
this.dropListenKey_ = undefined;
};
goog.inherits(ol.interaction.DragAndDrop, ol.interaction.Interaction);
/**
* @inheritDoc
*/
ol.interaction.DragAndDrop.prototype.disposeInternal = function() {
if (goog.isDef(this.dropListenKey_)) {
goog.events.unlistenByKey(this.dropListenKey_);
}
goog.base(this, 'disposeInternal');
};
/**
* @param {goog.events.BrowserEvent} event Event.
* @private
*/
ol.interaction.DragAndDrop.prototype.handleDrop_ = function(event) {
var files = event.getBrowserEvent().dataTransfer.files;
var i, ii;
for (i = 0, ii = files.length; i < ii; ++i) {
var reader = goog.fs.FileReader.readAsText(files[i]);
reader.addCallback(this.handleResult_, this);
}
};
/**
* @param {string} result Result.
* @private
*/
ol.interaction.DragAndDrop.prototype.handleResult_ = function(result) {
var map = this.getMap();
goog.asserts.assert(!goog.isNull(map));
var view = map.getView();
goog.asserts.assert(goog.isDef(view));
var view2D = view.getView2D();
var targetProjection;
if (!goog.isNull(this.source_)) {
targetProjection = this.source_.getProjection();
} else if (!goog.isNull(this.layer_)) {
targetProjection = this.layer_.getSource().getProjection();
} else {
targetProjection = view2D.getProjection();
}
var formatConstructors = this.formatConstructors_;
var features = [];
var i, ii;
for (i = 0, ii = formatConstructors.length; i < ii; ++i) {
var formatConstructor = formatConstructors[i];
var format = new formatConstructor();
var readFeatures = this.tryReadFeatures_(format, result);
if (!goog.isNull(readFeatures)) {
var featureProjection = format.readProjection(result);
var transform = ol.proj.getTransform(featureProjection, targetProjection);
var j, jj;
for (j = 0, jj = readFeatures.length; j < jj; ++j) {
var feature = readFeatures[j];
var geometry = feature.getGeometry();
if (!goog.isNull(geometry)) {
geometry.transform(transform);
}
features.push(feature);
}
}
}
if (features.length > 0) {
var source;
if (!goog.isNull(this.source_)) {
source = this.source_;
} else if (!goog.isNull(this.layer_)) {
source = this.layer_.getSource();
goog.asserts.assertInstanceof(source, ol.source.Vector);
} else {
source = new ol.source.Vector();
}
for (i = 0, ii = features.length; i < ii; ++i) {
source.addFeature(features[i]);
}
if (goog.isNull(this.layer_)) {
map.getLayers().push(new ol.layer.Vector({
source: source
}));
}
if (this.fitView_) {
view2D.fitExtent(source.getExtent(), map.getSize());
}
}
};
/**
* @inheritDoc
*/
ol.interaction.DragAndDrop.prototype.handleMapBrowserEvent =
goog.functions.TRUE;
/**
* @inheritDoc
*/
ol.interaction.DragAndDrop.prototype.setMap = function(map) {
if (goog.isDef(this.dropListenKey_)) {
goog.events.unlistenByKey(this.dropListenKey_);
this.dropListenKey_ = undefined;
}
if (!goog.isNull(this.fileDropHandler_)) {
goog.dispose(this.fileDropHandler_);
this.fileDropHandler_ = null;
}
goog.asserts.assert(!goog.isDef(this.dropListenKey_));
goog.base(this, 'setMap', map);
if (!goog.isNull(map)) {
this.fileDropHandler_ = new goog.events.FileDropHandler(map.getViewport());
this.dropListenKey_ = goog.events.listen(
this.fileDropHandler_, goog.events.FileDropHandler.EventType.DROP,
this.handleDrop_, false, this);
}
};
/**
* @param {ol.format.Format} format Format.
* @param {string} text Text.
* @private
* @return {Array.<ol.Feature>} Features.
*/
ol.interaction.DragAndDrop.prototype.tryReadFeatures_ = function(format, text) {
try {
return format.readFeatures(text);
} catch (e) {
return null;
}
};
+1
View File
@@ -0,0 +1 @@
@exportSymbol ol.source.KML
+31
View File
@@ -0,0 +1,31 @@
goog.provide('ol.source.KML');
goog.require('ol.format.KML');
goog.require('ol.source.VectorFile');
/**
* @constructor
* @extends {ol.source.VectorFile}
* @param {olx.source.KMLOptions=} opt_options Options.
*/
ol.source.KML = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {};
goog.base(this, {
attributions: options.attributions,
doc: options.doc,
extent: options.extent,
format: new ol.format.KML(),
logo: options.logo,
node: options.node,
projection: options.projection,
reprojectTo: options.reprojectTo,
text: options.text,
url: options.url
});
};
goog.inherits(ol.source.KML, ol.source.VectorFile);
+202
View File
@@ -0,0 +1,202 @@
goog.provide('ol.xml');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.dom.NodeType');
goog.require('goog.object');
/**
* @typedef {function(Node, Array.<*>)}
*/
ol.xml.Parser;
/**
* @param {Node} node Node.
* @param {boolean} normalizeWhitespace Normalize whitespace.
* @return {string} All text content.
*/
ol.xml.getAllTextContent = function(node, normalizeWhitespace) {
return ol.xml.getAllTextContent_(node, normalizeWhitespace, []).join('');
};
/**
* @param {Node} node Node.
* @param {boolean} normalizeWhitespace Normalize whitespace.
* @param {Array.<String|string>} accumulator Accumulator.
* @private
* @return {Array.<String|string>} Accumulator.
*/
ol.xml.getAllTextContent_ = function(node, normalizeWhitespace, accumulator) {
if (node.nodeType == goog.dom.NodeType.CDATA_SECTION ||
node.nodeType == goog.dom.NodeType.TEXT) {
if (normalizeWhitespace) {
// FIXME understand why goog.dom.getTextContent_ uses String here
accumulator.push(String(node.nodeValue).replace(/(\r\n|\r|\n)/g, ''));
} else {
accumulator.push(node.nodeValue);
}
} else {
var n;
for (n = node.firstChild; !goog.isNull(n); n = n.nextSibling) {
ol.xml.getAllTextContent_(n, normalizeWhitespace, accumulator);
}
}
return accumulator;
};
/**
* @param {function(this: T, Node, Array.<*>): (Array.<*>|undefined)}
* valueReader Value reader.
* @param {T=} opt_obj Scope.
* @return {ol.xml.Parser} Parser.
* @template T
*/
ol.xml.makeArrayExtender = function(valueReader, opt_obj) {
return (
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
*/
function(node, objectStack) {
var value = valueReader.call(opt_obj, node, objectStack);
if (goog.isDef(value)) {
goog.asserts.assert(goog.isArray(value));
var array = /** @type {Array.<*>} */
(objectStack[objectStack.length - 1]);
goog.asserts.assert(goog.isArray(array));
goog.array.extend(array, value);
}
});
};
/**
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {T=} opt_obj Scope.
* @return {ol.xml.Parser} Parser.
* @template T
*/
ol.xml.makeArrayPusher = function(valueReader, opt_obj) {
return (
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
*/
function(node, objectStack) {
var value = valueReader.call(opt_obj, node, objectStack);
if (goog.isDef(value)) {
var array = objectStack[objectStack.length - 1];
goog.asserts.assert(goog.isArray(array));
array.push(value);
}
});
};
/**
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {T=} opt_obj Scope.
* @return {ol.xml.Parser} Parser.
* @template T
*/
ol.xml.makeReplacer = function(valueReader, opt_obj) {
return (
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
*/
function(node, objectStack) {
var value = valueReader.call(opt_obj, node, objectStack);
if (goog.isDef(value)) {
objectStack[objectStack.length - 1] = value;
}
});
};
/**
* @param {function(this: T, Node, Array.<*>): *} valueReader Value reader.
* @param {string=} opt_property Property.
* @param {T=} opt_obj Scope.
* @return {ol.xml.Parser} Parser.
* @template T
*/
ol.xml.makeObjectPropertySetter = function(valueReader, opt_property, opt_obj) {
goog.asserts.assert(goog.isDef(valueReader));
return (
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
*/
function(node, objectStack) {
var value = valueReader.call(opt_obj, node, objectStack);
if (goog.isDef(value)) {
var object = /** @type {Object} */
(objectStack[objectStack.length - 1]);
var property = goog.isDef(opt_property) ?
opt_property : node.localName;
goog.asserts.assert(goog.isObject(object));
goog.object.set(object, property, value);
}
});
};
/**
* @param {Array.<string>} namespaceURIs Namespace URIs.
* @param {Object.<string, ol.xml.Parser>} parsers Parsers.
* @return {Object.<string, Object.<string, ol.xml.Parser>>} Parsers NS.
*/
ol.xml.makeParsersNS = function(namespaceURIs, parsers) {
/** @type {Object.<string, Object.<string, ol.xml.Parser>>} */
var parsersNS = {};
var i, ii;
for (i = 0, ii = namespaceURIs.length; i < ii; ++i) {
parsersNS[namespaceURIs[i]] = parsers;
}
return parsersNS;
};
/**
* @param {Object.<string, Object.<string, ol.xml.Parser>>} parsersNS
* Parsers by namespace.
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @param {*=} opt_obj Scope.
*/
ol.xml.parse = function(parsersNS, node, objectStack, opt_obj) {
var n;
for (n = node.firstChild; !goog.isNull(n); n = n.nextSibling) {
if (n.nodeType == goog.dom.NodeType.ELEMENT) {
var parsers = parsersNS[n.namespaceURI];
if (goog.isDef(parsers)) {
var parser = parsers[n.localName];
if (goog.isDef(parser)) {
parser.call(opt_obj, n, objectStack);
}
}
}
}
};
/**
* @param {T} object Object.
* @param {Object.<string, Object.<string, ol.xml.Parser>>} parsersNS
* Parsers by namespace.
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @param {*=} opt_obj Scope.
* @return {T|undefined} Object.
* @template T
*/
ol.xml.pushAndParse = function(object, parsersNS, node, objectStack, opt_obj) {
objectStack.push(object);
ol.xml.parse(parsersNS, node, objectStack, opt_obj);
return objectStack.pop();
};
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff