GUI -- Further work on MapService and GeoDataService. Still WIP.
Change-Id: I92e826cc15cc1a07238cc4b4eac20583260a3c84
Showing
4 changed files
with
152 additions
and
136 deletions
| ... | @@ -21,18 +21,36 @@ | ... | @@ -21,18 +21,36 @@ |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | /* | 23 | /* |
| 24 | - The GeoData Service caches GeoJSON map data, and provides supporting | 24 | + The GeoData Service facilitates the fetching and caching of TopoJSON data |
| 25 | - projections for mapping into SVG layers. | 25 | + from the server, as well as providing a way of creating a path generator |
| 26 | + for that data, to be used to render the map in an SVG layer. | ||
| 26 | 27 | ||
| 27 | - A GeoMap object can be fetched by ID. IDs that start with an asterisk | 28 | + A TopoData object can be fetched by ID. IDs that start with an asterisk |
| 28 | identify maps bundled with the GUI. IDs that do not start with an | 29 | identify maps bundled with the GUI. IDs that do not start with an |
| 29 | - asterisk are assumed to be URLs to externally provided data (exact | 30 | + asterisk are assumed to be URLs to externally provided data. |
| 30 | - format to be decided). | ||
| 31 | 31 | ||
| 32 | - e.g. var geomap = GeoDataService.fetchGeoMap('*continental-us'); | 32 | + var topodata = GeoDataService.fetchTopoData('*continental-us'); |
| 33 | 33 | ||
| 34 | - Note that, since the GeoMap instance is cached / shared, it should | 34 | + The path generator can then be created for that data-set: |
| 35 | - contain no state. | 35 | + |
| 36 | + var gen = GeoDataService.createPathGenerator(topodata, opts); | ||
| 37 | + | ||
| 38 | + opts is an optional argument that allows the override of default settings: | ||
| 39 | + { | ||
| 40 | + objectTag: 'states', | ||
| 41 | + projection: d3.geo.mercator(), | ||
| 42 | + logicalSize: 1000, | ||
| 43 | + mapFillScale: .95 | ||
| 44 | + }; | ||
| 45 | + | ||
| 46 | + The returned object (gen) comprises transformed data (TopoJSON -> GeoJSON), | ||
| 47 | + the D3 path generator function, and the settings used ... | ||
| 48 | + | ||
| 49 | + { | ||
| 50 | + geodata: { ... }, | ||
| 51 | + pathgen: function (...) { ... }, | ||
| 52 | + settings: { ... } | ||
| 53 | + } | ||
| 36 | */ | 54 | */ |
| 37 | 55 | ||
| 38 | (function () { | 56 | (function () { |
| ... | @@ -66,9 +84,9 @@ | ... | @@ -66,9 +84,9 @@ |
| 66 | 84 | ||
| 67 | // returns a promise decorated with: | 85 | // returns a promise decorated with: |
| 68 | // .meta -- id, url, and whether the data was cached | 86 | // .meta -- id, url, and whether the data was cached |
| 69 | - // .mapdata -- geojson data (on response from server) | 87 | + // .topodata -- TopoJSON data (on response from server) |
| 70 | 88 | ||
| 71 | - function fetchGeoMap(id) { | 89 | + function fetchTopoData(id) { |
| 72 | if (!fs.isS(id)) { | 90 | if (!fs.isS(id)) { |
| 73 | return null; | 91 | return null; |
| 74 | } | 92 | } |
| ... | @@ -88,10 +106,10 @@ | ... | @@ -88,10 +106,10 @@ |
| 88 | 106 | ||
| 89 | promise.then(function (response) { | 107 | promise.then(function (response) { |
| 90 | // success | 108 | // success |
| 91 | - promise.mapdata = response.data; | 109 | + promise.topodata = response.data; |
| 92 | }, function (response) { | 110 | }, function (response) { |
| 93 | // error | 111 | // error |
| 94 | - $log.warn('Failed to retrieve map data: ' + url, | 112 | + $log.warn('Failed to retrieve map TopoJSON data: ' + url, |
| 95 | response.status, response.data); | 113 | response.status, response.data); |
| 96 | }); | 114 | }); |
| 97 | 115 | ||
| ... | @@ -104,15 +122,32 @@ | ... | @@ -104,15 +122,32 @@ |
| 104 | return promise; | 122 | return promise; |
| 105 | } | 123 | } |
| 106 | 124 | ||
| 107 | - // TODO: clean up implementation of projection... | 125 | + var defaultGenSettings = { |
| 108 | - function setProjForView(path, topoData) { | 126 | + objectTag: 'states', |
| 109 | - var dim = 1000; | 127 | + projection: d3.geo.mercator(), |
| 128 | + logicalSize: 1000, | ||
| 129 | + mapFillScale: .95 | ||
| 130 | + }; | ||
| 131 | + | ||
| 132 | + // converts given TopoJSON-format data into corresponding GeoJSON | ||
| 133 | + // data, and creates a path generator for that data. | ||
| 134 | + function createPathGenerator(topoData, opts) { | ||
| 135 | + var settings = $.extend({}, defaultGenSettings, opts), | ||
| 136 | + topoObject = topoData.objects[settings.objectTag], | ||
| 137 | + geoData = topojson.feature(topoData, topoObject), | ||
| 138 | + proj = settings.projection, | ||
| 139 | + dim = settings.logicalSize, | ||
| 140 | + mfs = settings.mapFillScale, | ||
| 141 | + path = d3.geo.path().projection(proj); | ||
| 142 | + | ||
| 143 | + // adjust projection scale and translation to fill the view | ||
| 144 | + // with the map | ||
| 110 | 145 | ||
| 111 | // start with unit scale, no translation.. | 146 | // start with unit scale, no translation.. |
| 112 | - geoMapProj.scale(1).translate([0, 0]); | 147 | + proj.scale(1).translate([0, 0]); |
| 113 | 148 | ||
| 114 | // figure out dimensions of map data.. | 149 | // figure out dimensions of map data.. |
| 115 | - var b = path.bounds(topoData), | 150 | + var b = path.bounds(geoData), |
| 116 | x1 = b[0][0], | 151 | x1 = b[0][0], |
| 117 | y1 = b[0][1], | 152 | y1 = b[0][1], |
| 118 | x2 = b[1][0], | 153 | x2 = b[1][0], |
| ... | @@ -123,17 +158,24 @@ | ... | @@ -123,17 +158,24 @@ |
| 123 | y = (y1 + y2) / 2; | 158 | y = (y1 + y2) / 2; |
| 124 | 159 | ||
| 125 | // size map to 95% of minimum dimension to fill space.. | 160 | // size map to 95% of minimum dimension to fill space.. |
| 126 | - var s = .95 / Math.min(dx / dim, dy / dim); | 161 | + var s = mfs / Math.min(dx / dim, dy / dim), |
| 127 | - var t = [dim / 2 - s * x, dim / 2 - s * y]; | 162 | + t = [dim / 2 - s * x, dim / 2 - s * y]; |
| 128 | 163 | ||
| 129 | // set new scale, translation on the projection.. | 164 | // set new scale, translation on the projection.. |
| 130 | - geoMapProj.scale(s).translate(t); | 165 | + proj.scale(s).translate(t); |
| 166 | + | ||
| 167 | + // return the results | ||
| 168 | + return { | ||
| 169 | + geodata: geoData, | ||
| 170 | + pathgen: path, | ||
| 171 | + settings: settings | ||
| 172 | + }; | ||
| 131 | } | 173 | } |
| 132 | 174 | ||
| 133 | - | ||
| 134 | return { | 175 | return { |
| 135 | clearCache: clearCache, | 176 | clearCache: clearCache, |
| 136 | - fetchGeoMap: fetchGeoMap | 177 | + fetchTopoData: fetchTopoData, |
| 178 | + createPathGenerator: createPathGenerator | ||
| 137 | }; | 179 | }; |
| 138 | }]); | 180 | }]); |
| 139 | }()); | 181 | }()); |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -27,126 +27,40 @@ | ... | @@ -27,126 +27,40 @@ |
| 27 | e.g. var ok = MapService.loadMapInto(svgLayer, '*continental-us'); | 27 | e.g. var ok = MapService.loadMapInto(svgLayer, '*continental-us'); |
| 28 | 28 | ||
| 29 | The Map Service makes use of the GeoDataService to load the required data | 29 | The Map Service makes use of the GeoDataService to load the required data |
| 30 | - from the server. | 30 | + from the server and to create the appropriate geographical projection. |
| 31 | + | ||
| 31 | */ | 32 | */ |
| 32 | 33 | ||
| 33 | (function () { | 34 | (function () { |
| 34 | 'use strict'; | 35 | 'use strict'; |
| 35 | 36 | ||
| 36 | // injected references | 37 | // injected references |
| 37 | - var $log, $http, fs; | 38 | + var $log, fs, gds; |
| 38 | - | ||
| 39 | - // internal state | ||
| 40 | - var mapCache = d3.map(), | ||
| 41 | - bundledUrlPrefix = '../data/map/'; | ||
| 42 | - | ||
| 43 | - function getUrl(id) { | ||
| 44 | - if (id[0] === '*') { | ||
| 45 | - return bundledUrlPrefix + id.slice(1) + '.json'; | ||
| 46 | - } | ||
| 47 | - return id + '.json'; | ||
| 48 | - } | ||
| 49 | 39 | ||
| 50 | angular.module('onosSvg') | 40 | angular.module('onosSvg') |
| 51 | - .factory('MapService', ['$log', '$http', 'FnService', | 41 | + .factory('MapService', ['$log', 'FnService', 'GeoDataService', |
| 52 | - function (_$log_, _$http_, _fs_) { | 42 | + function (_$log_, _fs_, _gds_) { |
| 53 | $log = _$log_; | 43 | $log = _$log_; |
| 54 | - $http = _$http_; | ||
| 55 | fs = _fs_; | 44 | fs = _fs_; |
| 56 | - | 45 | + gds = _gds_; |
| 57 | - | ||
| 58 | - function fetchGeoMap(id) { | ||
| 59 | - if (!fs.isS(id)) { | ||
| 60 | - return null; | ||
| 61 | - } | ||
| 62 | - var url = getUrl(id), | ||
| 63 | - promise = mapCache.get(id); | ||
| 64 | - | ||
| 65 | - if (!promise) { | ||
| 66 | - // need to fetch the data, build the object, | ||
| 67 | - // cache it, and return it. | ||
| 68 | - promise = $http.get(url); | ||
| 69 | - | ||
| 70 | - promise.meta = { | ||
| 71 | - id: id, | ||
| 72 | - url: url, | ||
| 73 | - wasCached: false | ||
| 74 | - }; | ||
| 75 | - | ||
| 76 | - promise.then(function (response) { | ||
| 77 | - // success | ||
| 78 | - promise.mapdata = response.data; | ||
| 79 | - }, function (response) { | ||
| 80 | - // error | ||
| 81 | - $log.warn('Failed to retrieve map data: ' + url, | ||
| 82 | - response.status, response.data); | ||
| 83 | - }); | ||
| 84 | - | ||
| 85 | - mapCache.set(id, promise); | ||
| 86 | - | ||
| 87 | - } else { | ||
| 88 | - promise.meta.wasCached = true; | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - return promise; | ||
| 92 | - } | ||
| 93 | - | ||
| 94 | - var geoMapProj; | ||
| 95 | - | ||
| 96 | - function setProjForView(path, topoData) { | ||
| 97 | - var dim = 1000; | ||
| 98 | - | ||
| 99 | - // start with unit scale, no translation.. | ||
| 100 | - geoMapProj.scale(1).translate([0, 0]); | ||
| 101 | - | ||
| 102 | - // figure out dimensions of map data.. | ||
| 103 | - var b = path.bounds(topoData), | ||
| 104 | - x1 = b[0][0], | ||
| 105 | - y1 = b[0][1], | ||
| 106 | - x2 = b[1][0], | ||
| 107 | - y2 = b[1][1], | ||
| 108 | - dx = x2 - x1, | ||
| 109 | - dy = y2 - y1, | ||
| 110 | - x = (x1 + x2) / 2, | ||
| 111 | - y = (y1 + y2) / 2; | ||
| 112 | - | ||
| 113 | - // size map to 95% of minimum dimension to fill space.. | ||
| 114 | - var s = .95 / Math.min(dx / dim, dy / dim); | ||
| 115 | - var t = [dim / 2 - s * x, dim / 2 - s * y]; | ||
| 116 | - | ||
| 117 | - // set new scale, translation on the projection.. | ||
| 118 | - geoMapProj.scale(s).translate(t); | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | 46 | ||
| 122 | function loadMapInto(mapLayer, id) { | 47 | function loadMapInto(mapLayer, id) { |
| 123 | - var mapObject = fetchGeoMap(id); | 48 | + var promise = gds.fetchTopoData(id); |
| 124 | - if (!mapObject) { | 49 | + if (!promise) { |
| 125 | $log.warn('Failed to load map: ' + id); | 50 | $log.warn('Failed to load map: ' + id); |
| 126 | - return null; | 51 | + return false; |
| 127 | } | 52 | } |
| 128 | 53 | ||
| 129 | - var mapdata = mapObject.mapdata, | 54 | + promise.then(function () { |
| 130 | - topoData, path; | 55 | + var gen = gds.createPathGenerator(promise.topodata); |
| 131 | - | ||
| 132 | - mapObject.then(function () { | ||
| 133 | - // extracts the topojson data into geocoordinate-based geometry | ||
| 134 | - topoData = topojson.feature(mapdata, mapdata.objects.states); | ||
| 135 | - | ||
| 136 | - // see: http://bl.ocks.org/mbostock/4707858 | ||
| 137 | - geoMapProj = d3.geo.mercator(); | ||
| 138 | - path = d3.geo.path().projection(geoMapProj); | ||
| 139 | - | ||
| 140 | - setProjForView(path, topoData); | ||
| 141 | 56 | ||
| 142 | mapLayer.selectAll('path') | 57 | mapLayer.selectAll('path') |
| 143 | - .data(topoData.features) | 58 | + .data(gen.geodata.features) |
| 144 | .enter() | 59 | .enter() |
| 145 | .append('path') | 60 | .append('path') |
| 146 | - .attr('d', path); | 61 | + .attr('d', gen.pathgen); |
| 147 | }); | 62 | }); |
| 148 | - // TODO: review whether we should just return true (not the map object) | 63 | + return true; |
| 149 | - return mapObject; | ||
| 150 | } | 64 | } |
| 151 | 65 | ||
| 152 | return { | 66 | return { | ... | ... |
| ... | @@ -32,7 +32,7 @@ | ... | @@ -32,7 +32,7 @@ |
| 32 | var $log, ks, zs, gs, ms; | 32 | var $log, ks, zs, gs, ms; |
| 33 | 33 | ||
| 34 | // DOM elements | 34 | // DOM elements |
| 35 | - var svg, defs; | 35 | + var svg, defs, zoomLayer, map; |
| 36 | 36 | ||
| 37 | // Internal state | 37 | // Internal state |
| 38 | var zoomer; | 38 | var zoomer; |
| ... | @@ -91,7 +91,7 @@ | ... | @@ -91,7 +91,7 @@ |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | function setUpZoom() { | 93 | function setUpZoom() { |
| 94 | - var zoomLayer = svg.append('g').attr('id', 'topo-zoomlayer'); | 94 | + zoomLayer = svg.append('g').attr('id', 'topo-zoomlayer'); |
| 95 | zoomer = zs.createZoomer({ | 95 | zoomer = zs.createZoomer({ |
| 96 | svg: svg, | 96 | svg: svg, |
| 97 | zoomLayer: zoomLayer, | 97 | zoomLayer: zoomLayer, |
| ... | @@ -101,6 +101,13 @@ | ... | @@ -101,6 +101,13 @@ |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | + // --- Background Map ------------------------------------------------ | ||
| 105 | + | ||
| 106 | + function setUpMap() { | ||
| 107 | + map = zoomLayer.append('g').attr('id', '#topo-map'); | ||
| 108 | + ms.loadMapInto(map, '*continental_us'); | ||
| 109 | + } | ||
| 110 | + | ||
| 104 | // --- Controller Definition ----------------------------------------- | 111 | // --- Controller Definition ----------------------------------------- |
| 105 | 112 | ||
| 106 | angular.module('ovTopo', moduleDependencies) | 113 | angular.module('ovTopo', moduleDependencies) |
| ... | @@ -124,6 +131,7 @@ | ... | @@ -124,6 +131,7 @@ |
| 124 | setUpKeys(); | 131 | setUpKeys(); |
| 125 | setUpDefs(); | 132 | setUpDefs(); |
| 126 | setUpZoom(); | 133 | setUpZoom(); |
| 134 | + setUpMap(); | ||
| 127 | 135 | ||
| 128 | $log.log('OvTopoCtrl has been created'); | 136 | $log.log('OvTopoCtrl has been created'); |
| 129 | }]); | 137 | }]); | ... | ... |
| ... | @@ -39,18 +39,18 @@ describe('factory: fw/svg/geodata.js', function() { | ... | @@ -39,18 +39,18 @@ describe('factory: fw/svg/geodata.js', function() { |
| 39 | 39 | ||
| 40 | it('should define api functions', function () { | 40 | it('should define api functions', function () { |
| 41 | expect(fs.areFunctions(gds, [ | 41 | expect(fs.areFunctions(gds, [ |
| 42 | - 'clearCache', 'fetchGeoMap' | 42 | + 'clearCache', 'fetchTopoData', 'createPathGenerator' |
| 43 | ])).toBeTruthy(); | 43 | ])).toBeTruthy(); |
| 44 | }); | 44 | }); |
| 45 | 45 | ||
| 46 | it('should return null when no parameters given', function () { | 46 | it('should return null when no parameters given', function () { |
| 47 | - promise = gds.fetchGeoMap(); | 47 | + promise = gds.fetchTopoData(); |
| 48 | expect(promise).toBeNull(); | 48 | expect(promise).toBeNull(); |
| 49 | }); | 49 | }); |
| 50 | 50 | ||
| 51 | it('should augment the id of a bundled map', function () { | 51 | it('should augment the id of a bundled map', function () { |
| 52 | var id = '*foo'; | 52 | var id = '*foo'; |
| 53 | - promise = gds.fetchGeoMap(id); | 53 | + promise = gds.fetchTopoData(id); |
| 54 | expect(promise.meta).toBeDefined(); | 54 | expect(promise.meta).toBeDefined(); |
| 55 | expect(promise.meta.id).toBe(id); | 55 | expect(promise.meta.id).toBe(id); |
| 56 | expect(promise.meta.url).toBe('../data/map/foo.json'); | 56 | expect(promise.meta.url).toBe('../data/map/foo.json'); |
| ... | @@ -58,7 +58,7 @@ describe('factory: fw/svg/geodata.js', function() { | ... | @@ -58,7 +58,7 @@ describe('factory: fw/svg/geodata.js', function() { |
| 58 | 58 | ||
| 59 | it('should treat an external id as the url itself', function () { | 59 | it('should treat an external id as the url itself', function () { |
| 60 | var id = 'some/path/to/foo'; | 60 | var id = 'some/path/to/foo'; |
| 61 | - promise = gds.fetchGeoMap(id); | 61 | + promise = gds.fetchTopoData(id); |
| 62 | expect(promise.meta).toBeDefined(); | 62 | expect(promise.meta).toBeDefined(); |
| 63 | expect(promise.meta.id).toBe(id); | 63 | expect(promise.meta.id).toBe(id); |
| 64 | expect(promise.meta.url).toBe(id + '.json'); | 64 | expect(promise.meta.url).toBe(id + '.json'); |
| ... | @@ -66,14 +66,14 @@ describe('factory: fw/svg/geodata.js', function() { | ... | @@ -66,14 +66,14 @@ describe('factory: fw/svg/geodata.js', function() { |
| 66 | 66 | ||
| 67 | it('should cache the returned objects', function () { | 67 | it('should cache the returned objects', function () { |
| 68 | var id = 'foo'; | 68 | var id = 'foo'; |
| 69 | - promise = gds.fetchGeoMap(id); | 69 | + promise = gds.fetchTopoData(id); |
| 70 | expect(promise).toBeDefined(); | 70 | expect(promise).toBeDefined(); |
| 71 | expect(promise.meta.wasCached).toBeFalsy(); | 71 | expect(promise.meta.wasCached).toBeFalsy(); |
| 72 | expect(promise.tagged).toBeUndefined(); | 72 | expect(promise.tagged).toBeUndefined(); |
| 73 | 73 | ||
| 74 | promise.tagged = 'I woz here'; | 74 | promise.tagged = 'I woz here'; |
| 75 | 75 | ||
| 76 | - promise = gds.fetchGeoMap(id); | 76 | + promise = gds.fetchTopoData(id); |
| 77 | expect(promise).toBeDefined(); | 77 | expect(promise).toBeDefined(); |
| 78 | expect(promise.meta.wasCached).toBeTruthy(); | 78 | expect(promise.meta.wasCached).toBeTruthy(); |
| 79 | expect(promise.tagged).toEqual('I woz here'); | 79 | expect(promise.tagged).toEqual('I woz here'); |
| ... | @@ -81,14 +81,14 @@ describe('factory: fw/svg/geodata.js', function() { | ... | @@ -81,14 +81,14 @@ describe('factory: fw/svg/geodata.js', function() { |
| 81 | 81 | ||
| 82 | it('should clear the cache when asked', function () { | 82 | it('should clear the cache when asked', function () { |
| 83 | var id = 'foo'; | 83 | var id = 'foo'; |
| 84 | - promise = gds.fetchGeoMap(id); | 84 | + promise = gds.fetchTopoData(id); |
| 85 | expect(promise.meta.wasCached).toBeFalsy(); | 85 | expect(promise.meta.wasCached).toBeFalsy(); |
| 86 | 86 | ||
| 87 | - promise = gds.fetchGeoMap(id); | 87 | + promise = gds.fetchTopoData(id); |
| 88 | expect(promise.meta.wasCached).toBeTruthy(); | 88 | expect(promise.meta.wasCached).toBeTruthy(); |
| 89 | 89 | ||
| 90 | gds.clearCache(); | 90 | gds.clearCache(); |
| 91 | - promise = gds.fetchGeoMap(id); | 91 | + promise = gds.fetchTopoData(id); |
| 92 | expect(promise.meta.wasCached).toBeFalsy(); | 92 | expect(promise.meta.wasCached).toBeFalsy(); |
| 93 | }); | 93 | }); |
| 94 | 94 | ||
| ... | @@ -98,12 +98,64 @@ describe('factory: fw/svg/geodata.js', function() { | ... | @@ -98,12 +98,64 @@ describe('factory: fw/svg/geodata.js', function() { |
| 98 | $httpBackend.expectGET('foo.json').respond(404, 'Not found'); | 98 | $httpBackend.expectGET('foo.json').respond(404, 'Not found'); |
| 99 | spyOn($log, 'warn'); | 99 | spyOn($log, 'warn'); |
| 100 | 100 | ||
| 101 | - promise = gds.fetchGeoMap(id); | 101 | + promise = gds.fetchTopoData(id); |
| 102 | $httpBackend.flush(); | 102 | $httpBackend.flush(); |
| 103 | - expect(promise.mapdata).toBeUndefined(); | 103 | + expect(promise.topodata).toBeUndefined(); |
| 104 | expect($log.warn) | 104 | expect($log.warn) |
| 105 | - .toHaveBeenCalledWith('Failed to retrieve map data: foo.json', | 105 | + .toHaveBeenCalledWith('Failed to retrieve map TopoJSON data: foo.json', |
| 106 | 404, 'Not found'); | 106 | 404, 'Not found'); |
| 107 | }); | 107 | }); |
| 108 | 108 | ||
| 109 | + // --- path generator tests | ||
| 110 | + | ||
| 111 | + function simpleTopology(object) { | ||
| 112 | + return { | ||
| 113 | + type: "Topology", | ||
| 114 | + transform: {scale: [1, 1], translate: [0, 0]}, | ||
| 115 | + objects: {states: object}, | ||
| 116 | + arcs: [ | ||
| 117 | + [[0, 0], [1, 0], [0, 1], [-1, 0], [0, -1]], | ||
| 118 | + [[0, 0], [1, 0], [0, 1]], | ||
| 119 | + [[1, 1], [-1, 0], [0, -1]], | ||
| 120 | + [[1, 1]], | ||
| 121 | + [[0, 0]] | ||
| 122 | + ] | ||
| 123 | + }; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + function simpleLineStringTopo() { | ||
| 127 | + return simpleTopology({type: "LineString", arcs: [1, 2]}); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + it('should use default settings if none are supplied', function () { | ||
| 131 | + var gen = gds.createPathGenerator(simpleLineStringTopo()); | ||
| 132 | + expect(gen.settings.objectTag).toBe('states'); | ||
| 133 | + expect(gen.settings.logicalSize).toBe(1000); | ||
| 134 | + expect(gen.settings.mapFillScale).toBe(.95); | ||
| 135 | + // best we can do for now is test that projection is a function ... | ||
| 136 | + expect(fs.isF(gen.settings.projection)).toBeTruthy(); | ||
| 137 | + }); | ||
| 138 | + | ||
| 139 | + it('should allow us to override default settings', function () { | ||
| 140 | + var gen = gds.createPathGenerator(simpleLineStringTopo(), { | ||
| 141 | + mapFillScale: .80 | ||
| 142 | + }); | ||
| 143 | + expect(gen.settings.objectTag).toBe('states'); | ||
| 144 | + expect(gen.settings.logicalSize).toBe(1000); | ||
| 145 | + expect(gen.settings.mapFillScale).toBe(.80); | ||
| 146 | + }); | ||
| 147 | + | ||
| 148 | + it('should create transformed geodata, and a path generator', function () { | ||
| 149 | + var gen = gds.createPathGenerator(simpleLineStringTopo()); | ||
| 150 | + expect(fs.isO(gen.settings)).toBeTruthy(); | ||
| 151 | + expect(fs.isO(gen.geodata)).toBeTruthy(); | ||
| 152 | + expect(fs.isF(gen.pathgen)).toBeTruthy(); | ||
| 153 | + }); | ||
| 154 | + // NOTE: we probably should have more unit tests that assert stuff about | ||
| 155 | + // the transformed data (geo data) -- though perhaps we can rely on | ||
| 156 | + // the unit testing of TopoJSON? See... | ||
| 157 | + // https://github.com/mbostock/topojson/blob/master/test/feature-test.js | ||
| 158 | + // and, what about the path generator?, and the computed bounds? | ||
| 159 | + // In summary, more work should be done here.. | ||
| 160 | + | ||
| 109 | }); | 161 | }); | ... | ... |
-
Please register or login to post a comment