blob: 78a33d15a6f10cd6b8f098af5ded6ff7b9bee05a [file] [log] [blame]
Simon Hunt7ac7be92015-01-06 10:47:56 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Simon Hunt7ac7be92015-01-06 10:47:56 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- SVG -- Map Service
Simon Hunt7ac7be92015-01-06 10:47:56 -080019 */
Simon Huntf044d8a2015-01-07 17:53:04 -080020
21/*
Simon Huntf8173382015-01-13 14:12:09 -080022 The Map Service provides a simple API for loading geographical maps into
23 an SVG layer. For example, as a background to the Topology View.
Simon Huntf044d8a2015-01-07 17:53:04 -080024
Simon Huntac4c6f72015-02-03 19:50:53 -080025 e.g. var promise = MapService.loadMapInto(svgLayer, '*continental-us');
Simon Huntf044d8a2015-01-07 17:53:04 -080026
Simon Huntf8173382015-01-13 14:12:09 -080027 The Map Service makes use of the GeoDataService to load the required data
Simon Hunta7b6a6b2015-01-13 19:53:09 -080028 from the server and to create the appropriate geographical projection.
29
Simon Huntac4c6f72015-02-03 19:50:53 -080030 A promise is returned to the caller, which is resolved with the
31 map projection once created.
Simon Huntf8173382015-01-13 14:12:09 -080032*/
Simon Huntf044d8a2015-01-07 17:53:04 -080033
Simon Hunt7ac7be92015-01-06 10:47:56 -080034(function () {
35 'use strict';
36
Simon Huntf044d8a2015-01-07 17:53:04 -080037 // injected references
Simon Huntac4c6f72015-02-03 19:50:53 -080038 var $log, $q, fs, gds;
39
Simon Hunt2362b072015-06-11 20:08:22 -070040 // NOTE: This method assumes the datafile has exactly the map data
41 // that you want to load; for example id="*continental_us"
42 // mapping to ~/data/map/continental_us.topojson contains
43 // exactly the paths for the continental US.
44
Steven Burrows3a9a6442016-05-05 15:31:16 +010045 function loadMapInto(mapLayer, mapPath, id, opts) {
46 var promise = gds.fetchTopoData(mapPath),
Simon Huntac4c6f72015-02-03 19:50:53 -080047 deferredProjection = $q.defer();
48
49 if (!promise) {
Steven Burrows3a9a6442016-05-05 15:31:16 +010050 $log.warn('Failed to load map: ' + mapPath);
Simon Huntac4c6f72015-02-03 19:50:53 -080051 return false;
52 }
53
54 promise.then(function () {
Steven Burrows3a9a6442016-05-05 15:31:16 +010055
56 // NOTE: This finds the topo object within the topojson file
57 var topoObjects = promise.topodata.objects;
58
59 if (topoObjects.hasOwnProperty(id)) {
60 opts.objectTag = id;
61 }
62
Simon Huntac4c6f72015-02-03 19:50:53 -080063 var gen = gds.createPathGenerator(promise.topodata, opts);
64
65 deferredProjection.resolve(gen.settings.projection);
66
Simon Hunta34fcb52016-02-25 16:27:32 -080067 mapLayer.selectAll('path')
Simon Huntac4c6f72015-02-03 19:50:53 -080068 .data(gen.geodata.features)
69 .enter()
70 .append('path')
71 .attr('d', gen.pathgen);
Simon Huntfacad992016-02-25 09:58:33 -080072
Simon Hunta34fcb52016-02-25 16:27:32 -080073 reshade(opts.shading);
Simon Huntac4c6f72015-02-03 19:50:53 -080074 });
75 return deferredProjection.promise;
76 }
77
Simon Hunt2362b072015-06-11 20:08:22 -070078 // ---
79
80 // NOTE: This method uses the countries.topojson data file, and then
81 // filters the results based on the supplied options.
82 // Usage:
83 // promise = loadMapRegionInto(svgGroup, {
84 // countryFilter: function (country) {
85 // return country.properties.continent === 'South America';
86 // }
87 // });
88
Simon Hunta34fcb52016-02-25 16:27:32 -080089 function loadMapRegionInto(mapLayer, opts) {
Simon Hunt2362b072015-06-11 20:08:22 -070090 var promise = gds.fetchTopoData("*countries"),
91 deferredProjection = $q.defer();
92
93 if (!promise) {
94 $log.warn('Failed to load countries TopoJSON data');
95 return false;
96 }
97
98 promise.then(function () {
99 var width = 1000,
100 height = 1000,
101 proj = d3.geo.mercator().translate([width/2, height/2]),
102 pathGen = d3.geo.path().projection(proj),
103 data = promise.topodata,
104 features = topojson.feature(data, data.objects.countries).features,
Simon Hunta34fcb52016-02-25 16:27:32 -0800105 country = features.filter(opts.countryFilter),
Simon Hunt2362b072015-06-11 20:08:22 -0700106 countryFeature = {
107 type: 'FeatureCollection',
108 features: country
109 },
110 path = d3.geo.path().projection(proj);
111
Simon Hunta34fcb52016-02-25 16:27:32 -0800112 gds.rescaleProjection(proj, 0.95, 1000, path, countryFeature, opts.adjustScale);
Simon Hunt2362b072015-06-11 20:08:22 -0700113
114 deferredProjection.resolve(proj);
115
116 mapLayer.selectAll('path.country')
117 .data([countryFeature])
118 .enter()
119 .append('path').classed('country', true)
120 .attr('d', pathGen);
Simon Hunta34fcb52016-02-25 16:27:32 -0800121
122 reshade(opts.shading);
Simon Hunt2362b072015-06-11 20:08:22 -0700123 });
124 return deferredProjection.promise;
125 }
Simon Hunt7ac7be92015-01-06 10:47:56 -0800126
Simon Hunta34fcb52016-02-25 16:27:32 -0800127 function reshade(sh) {
128 var p = sh && sh.palette,
Thomas Vachuska26be4f32016-03-31 01:10:27 -0700129 paths, stroke, fill, bg,
130 svg = d3.select('#ov-topo').select('svg');
Simon Hunta34fcb52016-02-25 16:27:32 -0800131 if (sh) {
132 stroke = p.outline;
133 fill = sh.flip ? p.sea : p.land;
134 bg = sh.flip ? p.land : p.sea;
135
Simon Hunta34fcb52016-02-25 16:27:32 -0800136 paths = d3.select('#topo-map').selectAll('path');
Simon Hunta34fcb52016-02-25 16:27:32 -0800137 svg.style('background-color', bg);
138 paths.attr({
139 stroke: stroke,
140 fill: fill
141 });
Thomas Vachuska26be4f32016-03-31 01:10:27 -0700142 } else {
143 svg.style('background-color', null);
Simon Hunta34fcb52016-02-25 16:27:32 -0800144 }
145 }
146
Simon Hunt7ac7be92015-01-06 10:47:56 -0800147 angular.module('onosSvg')
Simon Huntac4c6f72015-02-03 19:50:53 -0800148 .factory('MapService', ['$log', '$q', 'FnService', 'GeoDataService',
149 function (_$log_, _$q_, _fs_, _gds_) {
Simon Hunt7ac7be92015-01-06 10:47:56 -0800150 $log = _$log_;
Simon Huntac4c6f72015-02-03 19:50:53 -0800151 $q = _$q_;
Simon Huntf044d8a2015-01-07 17:53:04 -0800152 fs = _fs_;
Simon Hunta7b6a6b2015-01-13 19:53:09 -0800153 gds = _gds_;
Simon Hunt404e54c2015-01-09 11:58:49 -0800154
Simon Hunt7ac7be92015-01-06 10:47:56 -0800155 return {
Simon Hunt2362b072015-06-11 20:08:22 -0700156 loadMapRegionInto: loadMapRegionInto,
Simon Hunta34fcb52016-02-25 16:27:32 -0800157 loadMapInto: loadMapInto,
158 reshade: reshade
Simon Hunt7ac7be92015-01-06 10:47:56 -0800159 };
160 }]);
161
162}());