├── .eslintrc
├── .gitignore
├── README.md
├── SLD_to_JSON.js
├── exampleData
├── FKB_ElvBekk.xml
└── Skyggefiler.json
├── exampleMultipleLayers
├── FKB_ElvBekk 2.xml
├── FKB_ElvBekk 3.xml
├── FKB_ElvBekk 4.xml
└── FKB_ElvBekk.xml
├── images
├── diagram.png
├── forsekningskurver.png
├── mapbox-forsenkningskurve.png
└── sld-forsenkningskurve.png
├── license.txt
├── package.json
└── reorder
├── create_correct_layerorder.js
└── layers_ordering.txt
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | "sourceType": "module"
4 | },
5 | "env": {
6 | "browser": true,
7 | "es6": true,
8 | "node": true
9 | },
10 | "rules": {
11 | "eqeqeq": 2,
12 | "no-multi-spaces": 2,
13 | "no-mixed-spaces-and-tabs": 2,
14 | "no-trailing-spaces": 2,
15 | "space-infix-ops": 2,
16 | "space-before-blocks":2,
17 | "keyword-spacing": ["error", {"before": true, "after": true}],
18 | "quotes": [2, "single"],
19 | "comma-dangle": [2, "never"],
20 | "strict": [2, "global"],
21 | "comma-spacing": [2, {"before": false, "after": true}],
22 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}],
23 | "comma-style": [2, "last"],
24 | "curly": 2,
25 | "object-curly-spacing": [2, "never"],
26 | "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }],
27 | "max-len": [1, 100, 4],
28 | "semi": [2, "always"],
29 | "no-undef": 2,
30 | "radix": 2,
31 | "brace-style": 2
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SLDexit - A script for converting from SLD to Mapbox GL
2 |
3 | `SLD_to_JSON.js` is a script for converting FKB[1]-data in SLD[2]-format to JSON-files according to the Mapbox GL style specification[3].
4 | The SLD-format is an XML-schema for describing the appearance of map layers, while the Mapbox GL specification is a JSON schema.
5 |
6 | This script is not a complete SLD to Mapbox GL converter (yet?), but it supports the styles in use by Norkart that needed to be converted. Therefore there might be attributes in the SLD standard that is not supported, simply because it wasn't in any if the styles we needed to convert.
7 |
8 | Although the script is tailored to fit our specific needs, the code should be able to handle most SLD files, and if you find cases where this isn't the case, feel free to submit a pull request.
9 |
10 | ## Contents
11 | 1. [The Mapbox GL specification](#The Mapbox GL specification)
12 | 2. [The SLD-files and the conversion](#The SLD-files and the conversion)
13 | 3. [Layout of the code](#Layout of the code)
14 | 4. [Result and manual changes](#Result and manual changes)
15 | 5. [Unsolved problems](#Unsolved problems)
16 | 6. [Running the script](#Running the script)
17 | 7. [Useful links](#Useful links)
18 |
19 |
20 | ## The Mapbox GL specification
21 | Example of valid Mapbox GL format:
22 |
23 | ```json
24 | {
25 | "id": "fill-FKB_ArealressursFlate_bebyggelse",
26 | "layout": {},
27 | "source": "norkart",
28 | "source-layer": "FKB_ArealressursFlate_bebyggelse",
29 | "minzoom": 13,
30 | "maxzoom": 22,
31 | "type": "fill",
32 | "paint": {
33 | "fill-color": "#d7dcdf"
34 | }
35 | },
36 | {
37 | "id": "line-FKB_ArealressursFlate_bebyggelse",
38 | "layout": {},
39 | "source": "norkart",
40 | "source-layer": "FKB_ArealressursFlate_bebyggelse",
41 | "minzoom": 16,
42 | "maxzoom": 22,
43 | "type": "line",
44 | "paint": {
45 | "line-color": "#d7dcdf",
46 | "line-width": 0.1
47 | }
48 | }
49 | ```
50 |
51 | - ```id``` is *unique*
52 | - ```type``` describes if it is a polygon (fill), line, text(symbol) or point(symbol)
53 | - ```source-layer``` refers to the vector tile layer-id
54 | - ```minzoom``` and ```maxzoom``` defines what zoom level the style is visible
55 | - ```paint``` and ```layout``` are objects with different attributes that describes how the layer is drawn (ie: how it will look)
56 |
57 |
58 | ## The SLD-files and the conversion
59 |
60 |
61 | To get the paint and layout attributes I used the part of the XML-schema that was within the 'rules' tag, and their valid inner tags:
62 | - **LineSymbolizer**, **TextSymbolizer**,**PolygonSymbolizer** and **PointSymbolizer**.
63 |
64 | I used xml2js.Parser() to read the XML. The disadvantage of this was that I could not directly look up the tag name, but had to iterate through the structure until the correct tag was found. This made the code less readable, as I had to learn how the layout for all the different versions of the SLD could be, to know where the tags could be found.
65 |
66 | #### Mapping from attribute name in SLD to Mapbox GL:
67 | The Xml-files has, as mentioned above, relevant info in a symbolizer-tag, that defines the "type"-attribute in Mapbox GL.
68 |
69 | The translation from symbolizer to type is:
70 |
71 | SLD symbolizer | Mapbox type
72 | ---|---
73 | LineSymbolizer|line
74 | PolygonSymbolizer|fill
75 | TextSymbolizer|symbol
76 | PointSymbolizer|symbol
77 |
78 | Each of these has an inner tag that defines attributes that contains the "cssParameter"-tags. A lot of these could be converted directly from the css parameter name ("CssParameter name= "…" "):
79 |
80 | SLD attribute | Mapbox attribute
81 | ---|---
82 | stroke|line-color
83 | stroke-width|line-width
84 | stroke-dasharray|line-dasharray
85 | stroke-linejoin|line-join
86 | opacity|line-opacity
87 | font-size|text-size
88 | font-family|text-font
89 |
90 | Other translations was dependent on the parent tag.
91 |
92 | SLD attribute | Mapbox attribute
93 | ---|---
94 | PolygonSymbolizer-Fill-fill | fill-color
95 | PolygonSymbolizer-Fill-fill-opacity| fill-opacity
96 | PolygonSymbolizer-Fill-opacity|fill-opacity
97 | Label|text-field
98 | TextSymbolizer-Halo-Fill-fill|text-halo-color
99 | TextSymbolizer-Fill-fill|text-color
100 |
101 | Some of the attributes I did not find a translation for:
102 | - Font-style (could be added through text-font by adding bold after name of the font)
103 | - Font-weight
104 |
105 |
106 | #### Attribute values:
107 | An important part of the script was to extract the attribute values. I wrote a general method for this: `getCssParameters(symbTag, validAttrTag, type, outerTag)`. This method returns an array with attribute names and attribute values.
108 |
109 | The method is written based on the structure I could find in most of the SLD files I had. These files had the attribute information in a css-parameter-tagg, within a symbolizer-tag with an inner tag that defined the type, example `` or ``.
110 |
111 | ```xml
112 |
113 |
114 |
115 | #
116 | bbg
117 | 87bef1
118 |
119 |
120 | 0.1
121 |
122 |
123 | ```
124 |
125 | Fill, stroke and opacity had the same layout as you can see above, where the attribute value is in the other `` tag.
126 |
127 | Other then this, the rest of the attributes had their values directly in the css-parameter-tag, as with you can se with for example stroke-width.
128 |
129 | Even though most of the files had layout like this, it did not apply for all attributes, or all cases of each attribute.
130 | An example is the code underneath, that shows an example where the layout is very different.
131 |
132 | ```xml
133 |
134 |
137 |
138 |
139 | 1.5
140 |
141 | ```
142 |
143 | To handle these exceptions, I created the method `getObjFromDiffAttr()`. Here I wrote completely separate methods for the exceptions.
144 |
145 |
146 | ## Layout of the code
147 |
148 | 
149 |
150 |
151 |
152 | ## Order of the layers
153 |
154 | In Mapbox GL the layers are drawn in the order they are defined in the JSON file. This order has to be defined manually after the creation of the JSON file. Therefor a script was created to reorder the layers. The file `layers_ordering.txt`, contains a list with the id-names for the layers, where the names are written in the order they should be drawn. By running the code `create_correct_layerorder.js` the layers in the input file are sorted in the same order as they are defined in `layers_ordering.txt`.
155 |
156 | One thing that was important, but not obvious (at least to me), was that the lines to the polygons always had to be drawn before the polygon itself. The reason is that the polygons overlap the lines, and parts of the lines are therefore hidden behind the polygon. This made it seem like the rendering of the lines were bad because they were hidden behind the polygon, which has poor rendering on the sides.
157 |
158 |
159 | ## Result and manual changes
160 |
161 | The goal of the script was to get a map which was equivalent to the map located on 1881.no now. For the most parts it worked well, and translation worked well. Still, some parts of the SLD was not translated or did not worked optimally and therefore required manual changes after the conversion.
162 |
163 |
164 | #### "Stops" attribute
165 |
166 | An important attribute in Mapbox GL, which was added to a lot of the layers and attributes manually afterwards, were 'stops'. Mapbox defines "Stops" as:
167 |
168 | *The value for any layout or paint property may be specified as a function, allowing you to parameterize the value according to the current zoom level. Functions are written as an array of stops, where each stop is an array with two elements: a zoom level and a corresponding value. Stops must be in ascending zoom order.*
169 |
170 | *Some properties support interpolated functions. The result of an interpolated function is an interpolated value between the last stop whose zoom level is less than or equal to the current zoom level, and the next stop. By default, linear interpolation is used, but you can use a different exponential base for the interpolation curve via the base property. If the current zoom is less than the first stop or greater than the last stop, the result is the value from the first or last stop respectively.*
171 |
172 | *For properties that do not support interpolated functions, the result is the value of the last stop whose zoom value is less than or equal to the current zoom level.*
173 |
174 | ```json
175 | {
176 | "line-width": {
177 | "base": 1.5,
178 | "stops": [[5, 1], [7, 2], [11, 3]]
179 | }
180 | }
181 | ```
182 |
183 | *base: Optional number. Default is 1.
184 | The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With values close to 1 the result increases linearly.*
185 |
186 | *stops: Required array.
187 | An array of zoom level and value pairs. The value can be a number or a color value for color properties.*
188 |
189 | #### Extra layers
190 | Something that was missing in the SLD files, and that I could not find anywhere, was border lines on some of the buildings. Therefore I had to manually create some layers afterwards, and the id of these were:
191 | - line-FKB_Bygning_1
192 | - line-FKB_Bygning_2
193 | - line-FKB_Bygning_3
194 | - line-FKB_AnnenBygning_1
195 | - line-FKB_AnnenBygning_2
196 | - line-FKB_AnnenBygning_3
197 |
198 | In addition to the shadow files that were translated directly, I also made some extra shadow layers by drawing an additional building-polygon with offset and opacity value. The good thing about drawing shadow in this way is that you can choose the direction of the shadow and you can resize depending on zoom level by using the [ "stop" -attribute] (# stop).
199 |
200 |
201 | ## Unsolved problems
202 |
203 | I was not able to find how to draw Depression curves in the correct way.
204 | The image to the left shows how it should have been drawn, and is drawn in SLD, while the image to the right shows how it is drawn in Mapbox GL. It could be possible to solve this by using "line-image" in Mapbox GL.
205 |
206 | 
207 |
208 | Even when symbols are placed in the end of the JSON file, and should be drawn on top of everything else, some of the symbols are still hidden behind other elements. As far as I can tell, this is solved by adding `icon-allow-overlap:true` to the layers in question. An improvement to the script could be to add this automatically to all symbol layers, but this could maybe have an unwanted effect to some symbols.
209 |
210 | Icons are not added to all layers of type **symbol**, and not images that should fill polygons,`fill-image`, since I was not sure what icons should be used. Mapbox do have sprite sheets available, but they do not cover everything.
211 |
212 |
213 |
214 |
215 | ## Running the script
216 | 1. Run `npm install` to install dependencies.
217 |
218 | 2. You can choose to either convert one file, or to convert all files in a given folder. This is dependent on if you are commented out `parseAllFiles()`, or `parse_sld_to_rules_tag()`. You also need to fill in some specific fields, and the instruction for this is added in the script.
219 |
220 | 3. Run the script with node.
221 |
222 | 4. When the script is finished, two files are created; `Result.JSON` and `errorFiles.txt`. `Result.JSON` is the result of the conversion, and the `errorFiles.txt` is a file with names of files that could not be converted, if any.
223 |
224 |
225 | ## Useful links
226 | Mapbox GL style specification:
227 | https://www.mapbox.com/mapbox-gl-style-spec/
228 |
229 | Mapbox GL validator: https://github.com/mapbox/mapbox-gl-style-spec/blob/mb-pages/README.md#validation
230 |
231 | SLD specification: http://docs.geoserver.org/latest/en/user/styling/sld-cookbook/index.html#sld-cookbook
232 |
233 | # Contributors
234 |
235 | - Written by: Mathilde Ørstavik, summer intern, Norkart 2015.
236 | - Input from various employees at Norkart
237 |
238 | [1]: http://www.opengeospatial.org/standards/sld
239 | [2]: http://www.kartverket.no/kart/kartdata/vektorkart/fkb/
240 | [3]: https://www.mapbox.com/mapbox-gl-style-spec/
241 |
--------------------------------------------------------------------------------
/SLD_to_JSON.js:
--------------------------------------------------------------------------------
1 | var us = require('underscore');
2 | var util = require('util');
3 | var path = require('path');
4 | var parseString = require('xml2js').parseString;
5 | var fs = require('fs');
6 | var xml2js = require('xml2js');
7 | var parser = new xml2js.Parser();
8 | var nrToParse = 1; //nr to check if last file is converted - if so the end of json file is written!
9 | var nrParsed = 0; //Nr of parsed files so far
10 |
11 |
12 | //-----------------------TODO-------------------------------------
13 | //ADD YOUR SPECIFIC INFO HERE BEFORE RUNNING THE CODE:
14 | var styleSpecName = 'MapboxGLStyle2';//choose the name you want
15 | var sourceName = ''; //name of source for the tiles you want the style specification to apply for
16 | var sourceUrl = ''; //URL to the tileJSON resource
17 | var type = 'vector';//vector, raster, GeoJSON ++
18 |
19 |
20 | //----------------------- Run script ------------------------//
21 |
22 | //You can run the script either from one file or a directory of files.
23 | //Comment out the one you don't want
24 |
25 | //add path for directory where all files you want to convert are placed
26 | var DIRECTORY_PATH = 'exampleMultipleLayers';
27 |
28 | parseAllFiles(DIRECTORY_PATH); //parse all files in given directory
29 |
30 | var SPECIFIC_FILE_PATH = 'exampleData/FKB_ElvBekk.xml'; //path of specific file
31 | //parse_sld_to_rules_tag(SPECIFIC_FILE_PATH); //Parse only one file
32 |
33 |
34 | //-------------------------------------------------------------//
35 |
36 | var RESULT_PATH = ''; //Add path you want result files written to
37 |
38 | var VALID_SYMBOLIZERS = [
39 | 'LineSymbolizer',
40 | 'TextSymbolizer',
41 | 'PolygonSymbolizer',
42 | 'PointSymbolizer'
43 | ];
44 |
45 | var VALID_ATTR_TAGS = [
46 | 'Stroke',
47 | 'Fill',
48 | 'Label',
49 | 'Font',
50 | 'Halo',
51 | 'Mark',
52 | 'Size',
53 | 'Geometry',
54 | 'Graphic'
55 | ];
56 | //attribute-tags that must be handeled different than the rest
57 | var DIFF_ATTR_TAG = ['Label', 'Halo', 'Mark', 'Geometry', 'Graphic'];
58 |
59 | //mapping from sld symbolizer til mapbox GL type-attribute
60 | var CONV_TYPE = {
61 | 'LineSymbolizer': 'line',
62 | 'PolygonSymbolizer': 'fill',
63 | 'TextSymbolizer': 'symbol',
64 | 'PointSymbolizer': 'symbol'
65 | };
66 |
67 | //attributes that must be handeled different than the rest,
68 | //and has relevant info placed differently (inner tag)
69 | var DIFF_ATTR = ['stroke', 'opacity', 'fill', 'fill-opacity', 'font-size', 'stroke-width'];
70 |
71 | //attrbiutes that belongs to the paint-object in Mapbox gl
72 | var PAINT_ATTR = [
73 | 'line-color', 'line-width', 'line-dasharray', 'line-opacity',
74 | 'text-color', 'text-halo-color', 'text-halo-width', 'text-halo-blur', 'text-size',
75 | 'fill-color', 'fill-opacity', 'fill-image',
76 | 'icon-color', 'icon-opacity', 'icon-size'
77 | ];
78 |
79 | //attributes that belongs to the layout-object in Mapbox gl
80 | var LAYOUT_ATTR = [
81 | 'text-field', 'text-font', 'text-max-size', 'text-max-witdth',
82 | 'line-join', 'symbol-placement', 'icon-image'
83 | ];
84 |
85 | //mapping from sld to mapbox
86 | var CONVERT_ATTR_NAME = {
87 | 'stroke': 'line-color',
88 | 'stroke-width': 'line-width',
89 | 'stroke-dasharray': 'line-dasharray',
90 | 'stroke-linejoin': 'line-join',
91 | 'opacity': 'line-opacity',
92 | 'PolygonSymbolizer-Fill-fill': 'fill-color',
93 | 'PolygonSymbolizer-Fill-fill-opacity': 'fill-opacity',
94 | 'PolygonSymbolizer-Fill-opacity': 'fill-opacity',
95 | 'font-size': 'text-size',
96 | 'font-family': 'text-font',
97 | 'Label': 'text-field',
98 | 'TextSymbolizer-Halo-Fill-fill': 'text-halo-color',
99 | 'TextSymbolizer-Fill-fill': 'text-color'
100 | };
101 |
102 | var PUNKT = 'circle-12'; //?
103 | //get the icon-image
104 | var CONV_ICON_IMG = {
105 | 'FKB_Gravplass.xml': 'religious-christian-12',
106 | 'FKB_BautaStatue.xml': 'monument-12',
107 | 'FKB_Bensinpumpe.xml': 'fuel-24',
108 | 'FKB_Broenn.xml': '',
109 | 'FKB_Kum.xml': 'circle-stroked-24'
110 | //, 'FKB_MastTele':,'FKB_Mast_Telesmast'
111 | };
112 |
113 | var FILES_WRITTEN = [];
114 |
115 |
116 | //translate zoom-scale to zoom-level
117 | function scale_to_zoom(scale) {
118 | if (scale > 500000000) {
119 | return 0;
120 | }
121 | if (scale > 250000000) {
122 | return 1;
123 | }
124 | if (scale > 150000000) {
125 | return 2;
126 | }
127 | if (scale > 70000000) {
128 | return 3;
129 | }
130 | if (scale > 35000000) {
131 | return 4;
132 | }
133 | if (scale > 15000000) {
134 | return 5;
135 | }
136 | if (scale > 10000000) {
137 | return 6;
138 | }
139 | if (scale > 4000000) {
140 | return 7;
141 | }
142 | if (scale > 2000000) {
143 | return 8;
144 | }
145 | if (scale > 1000000) {
146 | return 9;
147 | }
148 | if (scale > 500000) {
149 | return 10;
150 | }
151 | if (scale > 250000) {
152 | return 11;
153 | }
154 | if (scale > 150000) {
155 | return 12;
156 | }
157 | if (scale > 70000) {
158 | return 13;
159 | }
160 | if (scale > 35000) {
161 | return 14;
162 | }
163 | if (scale > 15000) {
164 | return 15;
165 | }
166 | if (scale > 8000) {
167 | return 16;
168 | }
169 | if (scale > 4000) {
170 | return 17;
171 | }
172 | if (scale > 2000) {
173 | return 18;
174 | }
175 | if (scale > 1000) {
176 | return 19;
177 | }
178 | return 20;
179 | }
180 |
181 | function parseAllFiles(path) {
182 | fs.readdir(path, function (error, list) {
183 | if (error) {
184 | console.log('error');
185 | return error;
186 | }
187 | var filelist = [];
188 | for (var variable of list) {
189 | filelist.push(variable);
190 | }
191 | var i;
192 | nrToParse = filelist.length;
193 | for (var i = 0; i < filelist.length; i++) {
194 | parse_sld_to_rules_tag(path + '/' + filelist[i]);
195 | }
196 | });
197 |
198 | setTimeout(function () {
199 | //not sure what time will be sufficent in large datasets
200 | }, 5000);
201 | }
202 |
203 | //parses the xml and finds symbolizer-element and type
204 | function parse_sld_to_rules_tag(file) {
205 | fs.readFile(file, function (err, data) {
206 | if (err) {
207 | console.log(err);
208 | }
209 | parseFile(data, file);
210 | });
211 | nrParsed++;
212 | if (nrParsed === nrToParse) {
213 | //TODO: Find a way to remove the timeout? Problem is that there is no way to
214 | //know how many layers will be written to the result json
215 | //and you can therefor not do a check if the last is written or not.
216 | //You cannot send a callback since it should only be written the last time.
217 | setTimeout(function () {
218 | writeEndOfJSON();
219 | }, 500);
220 | }
221 | }
222 |
223 | function writeStartOfJSON() {
224 | var top = '{ "version": 7, "name": "' + styleSpecName + '", "sources": { "' + sourceName + '": { "type": "vector", "url": "' + sourceUrl + '" } }, "glyphs": "mapbox://fontstack/{fontstack}/{range}.pbf", "sprite": "https://www.mapbox.com/mapbox-gl-styles/sprites/sprite", "layers": [ { "id": "background", "type": "background", "paint": { "background-color": "rgb(237, 234, 235)" } }';
225 | // var top = '{ "version": 7, "name": "MapboxGLStyle2", "sources": { "norkart": { "type": "vector", "url": "mapbox://andersob.3ukdquxr" } }, "glyphs": "mapbox://fontstack/{fontstack}/{range}.pbf", "sprite": "https://www.mapbox.com/mapbox-gl-styles/sprites/sprite", "layers": [ { "id": "background", "type": "background", "paint": { "background-color": "rgb(237, 234, 235)" } }';
226 | fs.writeFile(RESULT_PATH + '\\Result.JSON', top + '\n');
227 | fs.writeFile(RESULT_PATH + '\\errorFiles.txt', 'Files that could not be converted:' + '\n');
228 | }
229 |
230 | function writeEndOfJSON() {
231 | console.log('writing end of json');
232 | var end = ']}';
233 | fs.appendFile(RESULT_PATH + '\\Result.JSON', end);
234 | }
235 |
236 | var parseFile = function (data, file) {
237 | writeStartOfJSON();
238 | parser.parseString(data, function (err, result) {
239 | var FeatureTypeStyle = result.StyledLayerDescriptor.NamedLayer[0].UserStyle[0].FeatureTypeStyle;
240 | var rulesArr = [];
241 | var k;
242 | var rules = [];
243 | for (k = 0; k < FeatureTypeStyle.length; k++) { //some files had more than one FeatureTypeStyle
244 | var rulesVer = (FeatureTypeStyle[k].Rule);
245 | var rule;
246 | for (rule = 0; rule < rulesVer.length; rule++) {
247 | //pushes all rules-tag in different FeatureTypeStyle-tags to one array
248 | rules.push(rulesVer[rule]);
249 | }
250 | }
251 | var j;
252 | var maxzoom;
253 | var minzoom;
254 | for (j = 0; j < rules.length; j++) {
255 | rule = rules[j];
256 | name = rule.Name[0];
257 | maxzoom = scale_to_zoom(rule.MaxScaleDenominator[0]);
258 | minzoom = scale_to_zoom(rule.MinScaleDenominator[0]);
259 | //Checks if the tag is valid, and if it is: saves the object and type-name
260 | var i;
261 | var ruleArray = Object.keys(rule);
262 | for (i = 0; i < ruleArray.length; i++) {
263 | if ((VALID_SYMBOLIZERS.indexOf(ruleArray[i])) > -1) {
264 | //Sends object, symbolizer and filename
265 | writeJSON(rule[ruleArray[i]], ruleArray[i], name, minzoom, maxzoom, file);
266 | }
267 | }
268 | }
269 | });
270 | };
271 |
272 |
273 | //called for each symbolizer
274 | //this runs the rest of the methods through make_JSON and so on, and writes the objects to file
275 | function writeJSON(symbTag, type, name, minzoom, maxzoom, file) {
276 | var errorFiles = [];
277 | var convType = convertType(type);
278 | try {
279 | var cssObj = getSymbolizersObj(symbTag, type, file);
280 | //if css-obj contains both fill and stroke, you have to split them into two layers
281 | if (cssObj['fill-color'] !== undefined && cssObj['line-color'] !== undefined) {
282 | var attPos = (Object.keys(cssObj)).indexOf('line-color');
283 | var i;
284 | var obj = {};
285 | var size = ((Object.keys(cssObj)).length);
286 | for (i = attPos; i < (size); i++) {
287 | //since i delete for each loop, it will always be this position
288 | var key = Object.keys(cssObj)[attPos];
289 | obj[key] = cssObj[key];
290 | delete cssObj[key];
291 | }
292 | var styleObj1 = make_JSON(name, convType, cssObj, minzoom, maxzoom);
293 | var styleObj2 = make_JSON(name, 'line', obj, minzoom, maxzoom);
294 | var print1 = JSON.stringify(styleObj1, null, 4);
295 | var print2 = JSON.stringify(styleObj2, null, 4);
296 | console.log('Writing converted');
297 | fs.appendFile(RESULT_PATH + '\\Result.JSON', ',\n' + print1);
298 | fs.appendFile(RESULT_PATH + '\\Result.JSON', ',\n' + print2);
299 | } else {
300 | var styleObj = make_JSON(name, convType, cssObj, minzoom, maxzoom);
301 | print = JSON.stringify(styleObj, null, 4);
302 | fs.appendFile(RESULT_PATH + '\\Result.JSON', ',\n' + print);
303 | }
304 | } catch (err) {
305 | //writes a file with all the sld-files with errors
306 | fs.appendFile(RESULT_PATH + '\\errorFiles.txt', file + '-' + name + '\n');
307 | }
308 | }
309 |
310 | //this makes the layout of each mapbox-layout-object
311 | //name=file name, css is an object [cssName: cssValue]pairs, cssName is ie stroke, stroke-width
312 | function make_JSON(name, type, cssObj, minzoom, maxzoom) {
313 | var attr = getPaintAndLayoutAttr(cssObj);
314 | var paint = attr[0];
315 | var layout = attr[1];
316 |
317 | //Removing default-values, they are redundant
318 | if (Object.keys(paint).indexOf('fill-opacity') > -1) {
319 | if (paint['fill-opacity'] === 1) {
320 | delete paint['fill-opacity'];
321 | }
322 | }
323 |
324 | var styleObj = {
325 | 'id': type + '-' + name,
326 | 'type': type,
327 | 'source': 'norkart',
328 | 'source-layer': name,
329 | 'minzoom': maxzoom,
330 | 'maxzoom': minzoom,
331 | 'layout': layout,
332 | 'paint': paint
333 | };
334 | if (!Object.keys(layout).length > 0) { //if no layout attributes
335 | delete styleObj['layout'];
336 | }
337 | return styleObj;
338 | }
339 |
340 |
341 | function getSymbolizersObj(symbTag, type, file) {
342 | //have to check all taggs in symbolizer
343 | var i;
344 | var cssObj = {};
345 | for (i = 0; i < Object.keys(symbTag[0]).length; i++) { //for all tags under <-Symbolizer>
346 | var tagName = Object.keys(symbTag[0])[i];
347 | if (VALID_ATTR_TAGS.indexOf(tagName) > -1) { //if tag exists in valid-array, eks Stroke
348 |
349 | //if values are not in the regular place
350 | if (DIFF_ATTR_TAG.indexOf(tagName) > -1 ||
351 | ((tagName === 'Fill') && symbTag[0].Fill[0].GraphicFill !== undefined)) {
352 | var obj = getObjFromDiffAttr(tagName, type, symbTag, file);
353 | for (var key in obj) {
354 | cssObj[key] = obj[key];
355 | }
356 | } else {//if common cssParameterTags
357 | //array with key-value pairs to add to cssObj
358 | var cssArray = getCssParameters(symbTag, tagName, type);
359 | var k;
360 | for (k = 0; k < cssArray.length; k++) {
361 | cssObj[cssArray[k][0]] = cssArray[k][1];
362 | }
363 | }
364 | } else if (tagName !== undefined) {
365 | //console.log(tagName+" is not a valid attribute tag");
366 | }
367 | }
368 | return cssObj;
369 | }
370 |
371 | function getCssParameters(symbTag, validAttrTag, type, outerTag) {
372 | var cssArr = [];
373 | if (outerTag === undefined) {
374 | var allCssArray = symbTag[0][validAttrTag][0]['CssParameter'];
375 | } else {
376 | var allCssArray = symbTag[0][outerTag][0][validAttrTag][0]['CssParameter'];
377 | }
378 |
379 | var nrOfCssTags = Object.keys(allCssArray).length;
380 | var j;
381 | for (j = 0; j < nrOfCssTags; j++) { //for all cssParameters
382 | var cssTag = allCssArray[j];
383 | var conv = convert_css_parameter(cssTag, validAttrTag, type, outerTag);
384 | cssArr.push(conv); //array with arrays of cssName and cssValue
385 | }
386 | return cssArr;
387 | }
388 |
389 | //gets called if attribute-values are not placed as the rest and therefor needs
390 | //a different method the get the css-value
391 | function getObjFromDiffAttr(tagName, type, symbTag, file) {
392 | var obj = {};
393 | if (tagName === 'Label') {
394 | obj = getLabelObj(tagName, type, symbTag, obj);
395 | } else if (tagName === 'Fill') { //some fill-attributes are defined differently than the rest
396 | obj['fill-image'] = 'SPRITE-NAME';
397 | } else if (tagName === 'Halo') {
398 | obj = getHaloObj(tagName, type, symbTag, obj);
399 | } else if (tagName === 'Geometry') {
400 | obj = getGeometryObj(symbTag, obj);
401 | } else if (tagName === 'Graphic') {
402 | obj = getGraphicObj(file, symbTag, type, obj);
403 | }
404 | return obj;
405 | }
406 |
407 | function getLabelObj(tagName, type, symbTag, obj) {
408 | var convertedTagName = convertCssName(tagName, tagName, type);
409 | obj[convertedTagName] = '{' + symbTag[0].Label[0]['ogc:PropertyName'][0] + '}';
410 | return obj;
411 | }
412 |
413 | function getHaloObj(tagName, type, symbTag, obj) {
414 | var j;
415 | for (j = 0; j < Object.keys(symbTag[0].Halo[0]).length; j++) {
416 | var innerTagName = (Object.keys(symbTag[0].Halo[0]))[j];
417 |
418 | if (innerTagName === 'Radius') {
419 | var value = symbTag[0].Halo[0]['Radius'][0]['ogc:Literal'][0];
420 | obj['text-halo-width'] = parseInt(value, 10);
421 | } else if (innerTagName === 'Fill') {
422 | //array with key-value pair to add in obj
423 | var cssArray = getCssParameters(symbTag, innerTagName, type, 'Halo');
424 | var k;
425 | for (k = 0; k < cssArray.length; k++) {
426 | obj[cssArray[k][0]] = cssArray[k][1];
427 | }
428 | } else {
429 | console.log('translation of: ' + innerTagName + ' is not added');
430 | }
431 | }
432 | return obj;
433 | }
434 |
435 | function getGeometryObj(symbTag, obj) {
436 | if (symbTag[0].Geometry[0]['ogc:Function'][0].$.name === 'vertices') {
437 | obj['icon-image'] = PUNKT;
438 | } else {
439 | console.log('Cannot convert attribute value: ' + symbTag[0].Geometry[0]['ogc:Function'][0].$.name + ', for tag Geometry');
440 | }
441 | return obj;
442 | }
443 | function getGraphicObj(file, symbTag, type, obj) {
444 | var fillColor;
445 | try {
446 | fillColor = symbTag[0].Graphic[0].Mark[0].Fill[0].CssParameter[0]['ogc:Function'][0]['ogc:Literal'][1];
447 | var color = '#' + fillColor;
448 | var regInteger = /^\d+$/;
449 | if (!regInteger.test(fillColor)) {
450 | //console.log('Different graphic tag: '+fillColor+ ' from file: '+ file);
451 | } else {
452 | obj['icon-color'] = color;
453 | }
454 | } catch (err) {
455 | console.log('Could not set fill color for graphic tag in file: ' + file);
456 | }
457 | //Sets size
458 | try {
459 | var size = symbTag[0].Graphic[0].Size[0];
460 | obj['icon-size'] = parseInt(size, 10);
461 | } catch (err) {
462 | console.log('Size does not exist in this graphic-tag');
463 | }
464 | var img = getIconImage(file);
465 | if (img !== undefined) {
466 | obj['icon-image'] = img;
467 | } else {
468 | obj['icon-image'] = 'circle-12';
469 | }
470 | return obj;
471 | }
472 |
473 | function getIconImage(file) {
474 | try {
475 | var img = CONV_ICON_IMG[file];
476 | } catch (err) {
477 | console.log('Unknown icon');
478 | img = undefined;
479 | }
480 | return img;
481 | }
482 |
483 | //returns an array with css parameter name and value, correctly converted
484 | //validAttrTag=name of outer tag, example stroke, fill, label
485 | function convert_css_parameter(cssTag, ValidAttrTag, type, outerTag) {
486 | var cssName = cssTag['$'].name;
487 | var cssValue;
488 | var regLetters = /^[a-zA-Z]+$/;
489 | var regInt = /^\d+$/;
490 | var regDouble = /^[0-9]+([\,\.][0-9]+)?$/g;
491 | var regNumbers = /^\d+$/;
492 |
493 | try {
494 | var cssColorValue = cssTag['_'].split('#')[1];
495 | //testing if the value is a color:
496 | if ((DIFF_ATTR.indexOf(cssName)) > -1
497 | && !(regInt.test(cssTag['_']))
498 | && !(regDouble.test(cssTag['_']))
499 | && !regLetters.test(cssColorValue)
500 | && !regNumbers.test(cssColorValue) ) {//Check if different type of attribute
501 | cssValue = (cssTag['ogc:Function'][0]['ogc:Literal'][1]);
502 | } else {
503 | cssValue = cssTag['_'];
504 | }
505 | } catch (err) {
506 | if ((DIFF_ATTR.indexOf(cssName)) > -1
507 | && !(regInt.test(cssTag['_']))
508 | && !(regDouble.test(cssTag['_']))) {//Check if different type of attribute
509 | cssValue = (cssTag['ogc:Function'][0]['ogc:Literal'][1]);
510 | } else {
511 | cssValue = cssTag['_'];
512 | }
513 | }
514 | var convertedCssName = convertCssName(cssName, ValidAttrTag, type, outerTag);
515 | var convertedCssValue = convertCssValue(cssValue, cssName);
516 | return [convertedCssName, convertedCssValue];
517 | }
518 |
519 | //Makes sure the attribute values are returned in the correct type and defined
520 | //correctly (ie colors with a # in front)
521 | function convertCssValue(cssValue, cssName) {
522 |
523 | //linejoin describes rendering with values; mitre/round/bevel
524 | if ((cssName === 'stroke' || cssName === 'stroke-linejoin' || cssName === 'stroke-linecap')) {
525 | //some colors are defined with #, others not.
526 | //Split removes the # if it exists, so i always end up with the color value without the #
527 | //linecap is a line-border with values; butt/round/square
528 | return '#' + cssValue.split('#')[cssValue.split('#').length - 1];
529 | }
530 |
531 | if (cssName === 'stroke-width'
532 | || cssName === 'stroke-opacity'
533 | || cssName === 'stroke--dashoffset') {
534 | return parseFloat(cssValue);
535 | }
536 | if (cssName === 'stroke-dasharray') {
537 | return cssValue.split(' ').map(Number);
538 | }
539 |
540 | if (cssName === 'fill') {
541 | //some colors are defined with #, others not. Split removes the # if it exists,
542 | //so i always end up with the color value without the #
543 | return '#' + cssValue.split('#')[cssValue.split('#').length - 1];
544 | }
545 |
546 | if (cssName === 'opacity' || cssName === 'fill-opacity') {
547 | return parseFloat(cssValue);
548 | }
549 |
550 | if (cssName === 'font-size') {
551 | return parseFloat(cssValue);
552 | }
553 |
554 | return cssValue;
555 |
556 | }
557 |
558 | function convertCssName(cssName, validAttrTag, type, outerTag) {
559 | var newName;
560 | if (cssName === 'fill'
561 | || cssName === 'fill-opacity'
562 | || cssName === 'opacity'
563 | && validAttrTag === 'Fill') {
564 | if (outerTag === undefined) {
565 | newName = CONVERT_ATTR_NAME[type + '-' + validAttrTag + '-' + cssName];
566 |
567 | } else {
568 | var newName = CONVERT_ATTR_NAME[type + '-' + outerTag + '-' + validAttrTag + '-' + cssName];
569 | if (newName === undefined) {
570 | console.log(
571 | 'could not convert the attribute name: ' + type + '-' +
572 | outerTag + '-' + validAttrTag + '-' + cssName
573 | );
574 | }
575 | }
576 | return newName;
577 | } else {
578 | var newName = CONVERT_ATTR_NAME[cssName];
579 | //List to print those I know cannot be translated
580 | var ACCEPTED = ['font-weight', 'font-style'];
581 | //skip printing the ones I know are not translated
582 | if (newName === undefined && ACCEPTED.indexOf(newName) > -1) {
583 | console.log('could not convert the attribute name: ' + cssName);
584 | }
585 | return newName;
586 | }
587 | }
588 |
589 | function convertType(type) {
590 | try {
591 | return CONV_TYPE[type];
592 | } catch (err) {
593 | console.log('could not convert the type: ' + type);
594 | }
595 | }
596 |
597 | //Makes paint object og layout object
598 | function getPaintAndLayoutAttr(cssObj) {
599 | var paint = {};
600 | var layout = {};
601 | var i;
602 | for (i = 0; i < Object.keys(cssObj).length; i++) {// for all in cssObj
603 | var key = Object.keys(cssObj)[i];//becomes line-color
604 | var value = cssObj[key];
605 | if (PAINT_ATTR.indexOf(key) > -1) {
606 | paint[key] = value;
607 | } else if (LAYOUT_ATTR.indexOf(key) > -1) {
608 | layout[key] = value;
609 | } else {
610 | console.log('The css-key: ' + key + ', is not a valid paint or layout attribute');
611 | }
612 | }
613 | return [paint, layout];
614 | }
615 |
--------------------------------------------------------------------------------
/exampleData/FKB_ElvBekk.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | FKB_ElvBekk
10 |
11 | FKB_ElvBekk
12 |
13 |
14 |
15 |
16 | FKB_ElvBekk_midtlinje
17 |
18 |
19 |
20 | geometritype
21 | 3
22 |
23 |
24 |
25 |
26 | medium
27 | U
28 |
29 |
30 |
31 | medium
32 |
33 |
34 |
35 |
36 | 1
37 | 8501
38 |
39 |
40 |
41 | #
42 | aebm
43 | 87BEF1
44 |
45 |
46 | 0.1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | FKB_ElvBekk_flate
56 |
57 |
58 |
59 | geometritype
60 | 10
61 |
62 |
63 |
64 |
65 | medium
66 | U
67 |
68 |
69 |
70 | medium
71 |
72 |
73 |
74 |
75 | 1
76 | 8501
77 |
78 |
79 |
80 | #
81 | aff
82 | B2D8FA
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/exampleData/Skyggefiler.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "fill-FKB_Bygning_1-Skygge",
3 | "type": "fill",
4 | "source": "norkart",
5 | "source-layer": "FKB_Bygning_1",
6 | "paint": {
7 | "fill-color": "#8c9398",
8 | "fill-opacity": 0.8,
9 | "fill-translate": [2, 2]
10 | }
11 | },
12 | {
13 | "id": "fill-FKB_Bygning_2-Skygge",
14 | "type": "fill",
15 | "source": "norkart",
16 | "source-layer": "FKB_Bygning_2",
17 | "paint": {
18 | "fill-color": "#8c9398",
19 | "fill-opacity": 0.8,
20 | "fill-translate": [2, 2]
21 | }
22 | },
23 | {
24 | "id": "fill-FKB_Bygning_3-Skygge",
25 | "type": "fill",
26 | "source": "norkart",
27 | "source-layer": "FKB_Bygning_3",
28 | "paint": {
29 | "fill-color": "#8c9398",
30 | "fill-opacity": 0.8,
31 | "fill-translate": [2, 2]
32 | }
33 | },
34 |
--------------------------------------------------------------------------------
/exampleMultipleLayers/FKB_ElvBekk 2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | FKB_ElvBekk
10 |
11 | FKB_ElvBekk
12 |
13 |
14 |
15 |
16 | FKB_ElvBekk_midtlinje
17 |
18 |
19 |
20 | geometritype
21 | 3
22 |
23 |
24 |
25 |
26 | medium
27 | U
28 |
29 |
30 |
31 | medium
32 |
33 |
34 |
35 |
36 | 1
37 | 8501
38 |
39 |
40 |
41 | #
42 | aebm
43 | 87BEF1
44 |
45 |
46 | 0.1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | FKB_ElvBekk_flate
56 |
57 |
58 |
59 | geometritype
60 | 10
61 |
62 |
63 |
64 |
65 | medium
66 | U
67 |
68 |
69 |
70 | medium
71 |
72 |
73 |
74 |
75 | 1
76 | 8501
77 |
78 |
79 |
80 | #
81 | aff
82 | B2D8FA
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/exampleMultipleLayers/FKB_ElvBekk 3.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | FKB_ElvBekk
10 |
11 | FKB_ElvBekk
12 |
13 |
14 |
15 |
16 | FKB_ElvBekk_midtlinje
17 |
18 |
19 |
20 | geometritype
21 | 3
22 |
23 |
24 |
25 |
26 | medium
27 | U
28 |
29 |
30 |
31 | medium
32 |
33 |
34 |
35 |
36 | 1
37 | 8501
38 |
39 |
40 |
41 | #
42 | aebm
43 | 87BEF1
44 |
45 |
46 | 0.1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | FKB_ElvBekk_flate
56 |
57 |
58 |
59 | geometritype
60 | 10
61 |
62 |
63 |
64 |
65 | medium
66 | U
67 |
68 |
69 |
70 | medium
71 |
72 |
73 |
74 |
75 | 1
76 | 8501
77 |
78 |
79 |
80 | #
81 | aff
82 | B2D8FA
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/exampleMultipleLayers/FKB_ElvBekk 4.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | FKB_ElvBekk
10 |
11 | FKB_ElvBekk
12 |
13 |
14 |
15 |
16 | FKB_ElvBekk_midtlinje
17 |
18 |
19 |
20 | geometritype
21 | 3
22 |
23 |
24 |
25 |
26 | medium
27 | U
28 |
29 |
30 |
31 | medium
32 |
33 |
34 |
35 |
36 | 1
37 | 8501
38 |
39 |
40 |
41 | #
42 | aebm
43 | 87BEF1
44 |
45 |
46 | 0.1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | FKB_ElvBekk_flate
56 |
57 |
58 |
59 | geometritype
60 | 10
61 |
62 |
63 |
64 |
65 | medium
66 | U
67 |
68 |
69 |
70 | medium
71 |
72 |
73 |
74 |
75 | 1
76 | 8501
77 |
78 |
79 |
80 | #
81 | aff
82 | B2D8FA
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/exampleMultipleLayers/FKB_ElvBekk.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | FKB_ElvBekk
10 |
11 | FKB_ElvBekk
12 |
13 |
14 |
15 |
16 | FKB_ElvBekk_midtlinje
17 |
18 |
19 |
20 | geometritype
21 | 3
22 |
23 |
24 |
25 |
26 | medium
27 | U
28 |
29 |
30 |
31 | medium
32 |
33 |
34 |
35 |
36 | 1
37 | 8501
38 |
39 |
40 |
41 | #
42 | aebm
43 | 87BEF1
44 |
45 |
46 | 0.1
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | FKB_ElvBekk_flate
56 |
57 |
58 |
59 | geometritype
60 | 10
61 |
62 |
63 |
64 |
65 | medium
66 | U
67 |
68 |
69 |
70 | medium
71 |
72 |
73 |
74 |
75 | 1
76 | 8501
77 |
78 |
79 |
80 | #
81 | aff
82 | B2D8FA
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/images/diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Norkart/SLDexit/76ddb0c04af934cd6c239160867eda0f35a9fb85/images/diagram.png
--------------------------------------------------------------------------------
/images/forsekningskurver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Norkart/SLDexit/76ddb0c04af934cd6c239160867eda0f35a9fb85/images/forsekningskurver.png
--------------------------------------------------------------------------------
/images/mapbox-forsenkningskurve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Norkart/SLDexit/76ddb0c04af934cd6c239160867eda0f35a9fb85/images/mapbox-forsenkningskurve.png
--------------------------------------------------------------------------------
/images/sld-forsenkningskurve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Norkart/SLDexit/76ddb0c04af934cd6c239160867eda0f35a9fb85/images/sld-forsenkningskurve.png
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2016, Norkart AS
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are
6 | permitted provided that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright notice, this list of
9 | conditions and the following disclaimer.
10 |
11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 | of conditions and the following disclaimer in the documentation and/or other materials
13 | provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sld_to_mapboxgl",
3 | "version": "1.0.0",
4 | "description": "Script to convert from SLD (Styled Layer Descriptor) to Mapbox Style Specification",
5 | "main": "SLD_to_JSON.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/Norkart/SLD_to_MapboxGL.git"
12 | },
13 | "author": "Mathilde Ørstavik",
14 | "license": "BSD-2-Clause",
15 | "bugs": {
16 | "url": "https://github.com/Norkart/SLD_to_MapboxGL/issues"
17 | },
18 | "homepage": "https://github.com/Norkart/SLD_to_MapboxGL#readme",
19 | "dependencies": {
20 | "underscore": "^1.8.3",
21 | "xml2js": "^0.4.17"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/reorder/create_correct_layerorder.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var _us = require('underscore');
3 |
4 | var json_file_name = "json-test.json"; //original json file
5 | var ordering_file_name = "layers_ordering.txt"; // file containing
6 | var output_filename = "json_style_ordered.json"; // name of the output file
7 |
8 | function main() {
9 | var json_original_style = JSON.parse(fs.readFileSync(json_file_name, 'utf8'));
10 | var ordering_file = fs.readFileSync(ordering_file_name, 'utf8');
11 |
12 | if (ordering_file.indexOf('\r\n') !== -1) {
13 | ordering_list = ordering_file.split('\r\n');
14 | }
15 | else {
16 | ordering_list = ordering_file.split('\n');
17 | }
18 |
19 | if (ordering_list[ordering_list.length-1] === "") { // last line is usualy empty
20 | ordering_list.splice(ordering_list.length - 1, ordering_list.length)
21 | }
22 |
23 | var json_ordered_style = {
24 | "version": json_original_style.version,
25 | "name": json_original_style.name,
26 | "sources": json_original_style.sources,
27 | "glyphs": json_original_style.glyphs,
28 | "sprite": json_original_style.sprite,
29 | "layers":[]
30 | };
31 | // console.log(JSON.stringify(json_ordered_style,null,2));
32 |
33 | for (var i = 0; i < ordering_list.length; i++) {
34 | json_ordered_style.layers.push(get_layer_by_id(json_original_style, ordering_list[i]));
35 | }
36 | // add min max zoom for testing once..
37 |
38 | fs.writeFileSync(output_filename, JSON.stringify(json_ordered_style, null, 2)); // resets file
39 |
40 | console.log("Is in same order as " + ordering_file_name + ": " +check_order(ordering_list, output_filename));
41 | }
42 |
43 |
44 | function check_order(order,created_file) {
45 | var json_created = JSON.parse(fs.readFileSync(created_file, 'utf8'));
46 |
47 | for (var i = 0; i < order.length; i++) {
48 | if (order[i] !== json_created.layers[i].id) {
49 | return false;
50 | }
51 | }
52 | return true;
53 | }
54 |
55 | function get_layer_by_id(json, layerid) {
56 | var i;
57 | for(i=0; i < json.layers.length; i++){
58 | // console.log(json.layers[i].id + "(" + json.layers[i].id.length + ")");
59 | // console.log(layerid + "(" + layerid.length + ")");
60 |
61 | if (json.layers[i].id === layerid){
62 | return json.layers[i];
63 | }
64 | }
65 | throw {name:"cantFindLayer", message:("can't find the wanted layerid: " + layerid)};
66 | }
67 |
68 | main();
69 |
--------------------------------------------------------------------------------
/reorder/layers_ordering.txt:
--------------------------------------------------------------------------------
1 | background
2 | fill-FKB_ArealressursFlate_bebyggelse
3 | line-FKB_ArealressursFlate_bebyggelse
4 | fill-FKB_ArealressursFlate_fulldyrka
5 | line-FKB_ArealressursFlate_fulldyrka
6 | fill-FKB_ArealressursFlate_overflatedyrka
7 | line-FKB_ArealressursFlate_overflatedyrka
8 | fill-FKB_ArealressursFlate_innmarksbeite
9 | line-FKB_ArealressursFlate_innmarksbeite
10 | fill-FKB_ArealressursFlate_skog
11 | line-FKB_ArealressursFlate_skog
12 | fill-FKB_ArealressursFlate_aapen_fastmark
13 | line-FKB_ArealressursFlate_aapen_fastmark
14 | fill-FKB_ArealressursFlate_myr
15 | fill-FKB_Havflate
16 | line-FKB_Havflate
17 | fill-FKB_Flytebrygge
18 | line-FKB_FlytebryggeKant
19 | line-FKB_ElvBekk_midtlinje
20 | fill-FKB_ElvBekk_flate
21 | line-FKB_ElvBekkKant
22 | line-FKB_ElveforbygningsKant
23 | fill-FKB_Dam
24 | line-FKB_DamKant
25 | fill-FKB_Innsjoe
26 | line-FKB_InnsjoekantRegulert
27 | line-FKB_Innsjoekant
28 | fill-FKB_SnoeIsbre
29 | line-FKB_SnoeIsbreKant
30 | line-FKB_Jernbane-close
31 | line-FKB_Jernbane
32 | line-FKB_T-Bane
33 | line-FKB_Trikk
34 | line-FKB_Jernbane_Tunnel
35 | line-FKB_T-Bane_Tunnel
36 | line-WAM_Teig
37 | fill-FKB_Alpinbakke
38 | fill-FKB_Campingplass
39 | fill-FKB_Fundament_2
40 | fill-FKB_Fundament_1
41 | fill-FKB_Fyllplass
42 | fill-FKB_Golfbane
43 | fill-FKB_Gravplass
44 | fill-FKB_Grustak
45 | fill-FKB_Gruve
46 | fill-FKB_Industriomraade
47 | fill-FKB_KanalGroeft_flate
48 | fill-FKB_Leirtak
49 | fill-FKB_Lekeplass
50 | fill-FKB_Park
51 | fill-FKB_Parkeringsomraade
52 | fill-FKB_PblTiltak_1
53 | fill-FKB_PblTiltak_2
54 | fill-FKB_PblTiltak_2-2
55 | fill-FKB_PblTiltak_3
56 | fill-FKB_PblTiltak_3-2
57 | fill-FKB_Pipe_2
58 | fill-FKB_Pipe_1
59 | fill-FKB_Rasteplass
60 | fill-FKB_Silo_1
61 | fill-FKB_Silo_2
62 | fill-FKB_Skytebane
63 | fill-FKB_SportIdrettPlass
64 | fill-FKB_Stein-1
65 | fill-FKB_Stein-2
66 | fill-FKB_Steinbrudd
67 | fill-FKB_Steintipp
68 | fill-FKB_Svoemmebasseng
69 | fill-FKB_Tank_1
70 | fill-FKB_Tank_2
71 | fill-FKB_Toemmervelte
72 | fill-FKB_Torvtak
73 | fill-FKB_Trafikkoey
74 | line-FKB_Aak_1
75 | line-FKB_Aak_2
76 | line-FKB_Alle_1
77 | line-FKB_Alle_2
78 | line-FKB_AnnetGjerde
79 | line-FKB_AnnetGjerde_2
80 | line-FKB_BautaStatueGrense
81 | line-FKB_Fasadeliv_1
82 | line-FKB_Fasadeliv_2
83 | line-FKB_Fasadeliv_3
84 | line-FKB_FiktivBygningsavgrensning
85 | line-FKB_Floetningsrenne
86 | line-FKB_FlomloepKant
87 | line-FKB_FundamentKant_1
88 | line-FKB_FundamentKant_2
89 | line-FKB_Grunnmur_1
90 | line-FKB_Grunnmur_2
91 | line-FKB_Grunnmur_3
92 | line-FKB_Hekk_1
93 | line-FKB_Hoppbakke
94 | line-FKB_Idrettsanlegg
95 | line-FKB_Jernbaneplattformkant_1
96 | line-FKB_Jernbaneplattformkant_2
97 | line-FKB_KaiBryggeKant
98 | line-FKB_KanalGroeft_midtlinje_1
99 | line-FKB_KanalGroeft_midtlinje_2
100 | line-FKB_KanalGroeftKant
101 | line-FKB_Kontaktledningsaak_1
102 | line-FKB_Kontaktledningsaak_2
103 | line-FKB_Kulvert_1
104 | line-FKB_Kulvert_2
105 | line-FKB_Kystkontur
106 | line-FKB_KystkonturTekniskAnlegg
107 | line-FKB_Laavebru
108 | line-FKB_LuftledningHSP_1
109 | line-FKB_LuftledningHSP_2
110 | line-FKB_LuftledningHSP_3
111 | line-FKB_LuftledningHSP_4
112 | line-FKB_Lysloeype
113 | line-FKB_Masteomriss_Telemast
114 | line-FKB_MastTeleGrense
115 | line-FKB_MoloKant
116 | line-FKB_MurFrittstaaende_1
117 | line-FKB_MurFrittstaaende_2
118 | line-FKB_MurLodrett_1
119 | line-FKB_MurLodrett_2
120 | line-FKB_MurLodrettTverr_1
121 | line-FKB_MurLodrettTverr_2
122 | line-FKB_NettstasjonGr
123 | line-FKB_Nettverkstasjonomriss_EL_Nettstasjon
124 | line-FKB_Nettverkstasjonomriss_EL_Vindturbin
125 | line-FKB_OperativArealavgrensning
126 | line-FKB_Oppdrettskar
127 | line-FKB_OppdrettsmerderKant
128 | line-FKB_ParkeringsomraadeAvgrensning
129 | line-FKB_PblTiltakGrense_1
130 | line-FKB_PblTiltakGrense_2
131 | line-FKB_PblTiltakGrense_3
132 | line-FKB_PipeKant_1
133 | line-FKB_PipeKant_2
134 | line-FKB_Plattformgrense
135 | line-FKB_Portrom_1
136 | line-FKB_Portrom_2
137 | line-FKB_Rullebanegrense
138 | line-FKB_Roergate
139 | line-FKB_Sandkasse_1
140 | line-FKB_Sandkasse_2
141 | line-FKB_SiloKant_1
142 | line-FKB_SiloKant_2
143 | line-FKB_Skiltportal_1
144 | line-FKB_Skiltportal_2
145 | line-FKB_Skitrekk
146 | line-FKB_Skjerm_stoey
147 | line-FKB_Skjerm_snoe
148 | line-FKB_Skjerm_ras
149 | line-FKB_Skjerm_vind
150 | line-FKB_Skjerm_le
151 | line-FKB_Skjerm_lede
152 | line-FKB_Skjerm_flom
153 | line-FKB_SkraaForstoetningsmurAvgrensning_1
154 | line-FKB_SkraaForstoetningsmurAvgrensning_2
155 | line-FKB_Skytebaneinnretning
156 | line-FKB_Skytefelt
157 | line-FKB_Slipp
158 | line-FKB_Steingjerde_1
159 | line-FKB_Steingjerde_2
160 | line-FKB_SteinOmriss_1
161 | line-FKB_SteinOmriss_2
162 | line-FKB_Sti
163 | line-FKB_Stikkrenne_1
164 | line-FKB_Stikkrenne_2
165 | line-FKB_Stolheis
166 | line-FKB_SvoemmebassengKant
167 | line-FKB_Sykkelfelt_1
168 | line-FKB_Sykkelfelt_2
169 | line-FKB_Taksebanegrense
170 | line-FKB_TankKant_1
171 | line-FKB_TankKant_2
172 | line-FKB_Taubane
173 | line-FKB_Trase_LuftledningHSP_1
174 | line-FKB_Trase_LuftledningHSP_2
175 | line-FKB_Trase_LuftledningHSP_3
176 | line-FKB_Trase_LuftledningHSP_4
177 | line-FKB_Tunnellportal
178 | line-FKB_VindkraftverkGr
179 | symbol-FKB_BautaStatue_1
180 | symbol-FKB_BautaStatue_2
181 | symbol-FKB_Bensinpumpe_1
182 | symbol-FKB_Bensinpumpe_2
183 | symbol-FKB_EL_Belysningspunkt_IMast_1
184 | symbol-FKB_EL_Belysningspunkt_IMast_2
185 | symbol-FKB_EL_Belysningspunkt_IMast_3
186 | symbol-FKB_EL_Nettstasjon-minikiosk
187 | symbol-FKB_EL_Vindturbin_1
188 | symbol-FKB_EL_Vindturbin_2
189 | symbol-FKB_Flaggstang_1
190 | symbol-FKB_Flaggstang_2
191 | symbol-FKB_Floetningsrenne
192 | symbol-FKB_Fordelingsskap_1
193 | symbol-FKB_Fordelingsskap_2
194 | symbol-FKB_Fortoeyningskar_1
195 | symbol-FKB_Fortoeyningskar_2
196 | symbol-FKB_Gravplass
197 | symbol-FKB_Gondolbane
198 | symbol-FKB_Hydrant_1
199 | symbol-FKB_Hydrant_2
200 | symbol-FKB_InnmaaltTre_1
201 | symbol-FKB_InnmaaltTre_2
202 | symbol-FKB_Kum_1
203 | symbol-FKB_Kum_2
204 | symbol-FKB_MastTele_1
205 | symbol-FKB_MastTele_2
206 | symbol-FKB_MastVeilys_2
207 | symbol-FKB_MastVeilys_1
208 | symbol-FKB_MastVeilys_3
209 | symbol-FKB_Mast_EL_2
210 | symbol-FKB_Mast_EL_1
211 | symbol-FKB_Mast_EL_3
212 | symbol-FKB_Mast_Signalmast_1
213 | symbol-FKB_Mast_Signalmast_2
214 | symbol-FKB_Mast_Telemast_1
215 | symbol-FKB_Mast_Telemast_2
216 | symbol-FKB_NettstasjonKiosk
217 | symbol-FKB_Portstolpe_1
218 | symbol-FKB_Portstolpe_2
219 | symbol-FKB_Signalmast_1
220 | symbol-FKB_Signalmast_2
221 | symbol-FKB_Skap_1
222 | symbol-FKB_Skap_2
223 | symbol-FKB_Skiltportal_1
224 | symbol-FKB_Skiltportal_2
225 | symbol-FKB_Skitrekk
226 | symbol-FKB_Skjaer_1
227 | symbol-FKB_Skjaer_2
228 | symbol-FKB_Sluk_1
229 | symbol-FKB_Sluk_2
230 | symbol-FKB_Stolheis
231 | symbol-FKB_StolpeEnkel_1
232 | symbol-FKB_StolpeEnkel_2
233 | symbol-FKB_StolpeEnkel_3
234 | symbol-FKB_Taubane
235 | symbol-FKB_Terrengpunkt
236 | symbol-FKB_Toppunkt
237 | symbol-FKB_Trafikksignalpunkt_1
238 | symbol-FKB_Trafikksignalpunkt_2
239 | symbol-FKB_Vindkraftverk_1
240 | symbol-FKB_Vindkraftverk_2
241 | symbol-FKB_Broenn_1
242 | symbol-FKB_Broenn_2
243 | line-FKB_Hoeydekurve_1
244 | line-FKB_Hoeydekurve_2
245 | line-FKB_Forsenkningskurve_1
246 | line-FKB_Forsenkningskurve_2
247 | fill-FKB_FrittstaaendeTrapp_1
248 | fill-FKB_FrittstaaendeTrapp_2
249 | fill-FKB_GangSykkelveg
250 | fill-FKB_Europaveg
251 | fill-FKB_Riksveg
252 | fill-FKB_Fylkesveg
253 | fill-FKB_Andreveger
254 | fill-FKB_Traktorveg
255 | fill-FKB_GangSykkelveg_Bro
256 | fill-FKB_Traktorveg_Bro
257 | fill-FKB_Parkeringsomraade_bro
258 | fill-FKB_Riksveg_bro
259 | fill-FKB_Fylkesveg_bro
260 | fill-FKB_Andreveger_bro
261 | fill-FKB_Trafikkoey_bro
262 | line-FKB_GangfeltAvgrensning_1
263 | line-FKB_GangfeltAvgrensning_2
264 | line-FKB_GangSykkelvegkant
265 | line-FKB_Gangvegkant
266 | line-FKB_Gondolbane
267 | line-FKB_Trafikkoeykant
268 | line-FKB_FrittstaaendeTrappKant_1
269 | line-FKB_FrittstaaendeTrappKant_2
270 | line-FKB_Europaveg
271 | line-FKB_Riksveg
272 | line-FKB_Fylkesveg
273 | line-FKB_Andreveger
274 | line-FKB_VeggFrittstaaende_1
275 | line-FKB_VeggFrittstaaende_2
276 | line-FKB_VegkantAnnetVegareal_1
277 | line-FKB_VegkantAnnetVegareal_2
278 | line-FKB_VegkantAvkjoersel
279 | line-FKB_Veglenke_Lysloeype
280 | line-FKB_Veglenke_Sti
281 | line-FKB_Veglenke_Traktorveg
282 | line-FKB_Vegrekkverk_1
283 | line-FKB_Vegrekkverk_2
284 | line-FKB_Vegsperring
285 | line-FKB_Traktorveg
286 | line-FKB_TraktorvegKant
287 | line-FKB_Fortauskant
288 | line-FKB_FortauskantYtre
289 | line-FKB_AnnetVegarealAvgrensning
290 | line-FKB_Vegdekkekant
291 | fill-FKB_GangSykkelveg_Bro
292 | fill-FKB_Traktorveg_Bro
293 | fill-FKB_Parkeringsomraade_bro
294 | fill-FKB_Riksveg_bro
295 | fill-FKB_Andreveger_bro
296 | line-FKB_FortauskantYtre_Bro
297 | line-FKB_Fortauskant_Bro
298 | line-FKB_GangfeltAvgrensning_Bro_1
299 | line-FKB_GangSykkelvegkant_Bro
300 | line-FKB_Gangvegkant_Bro
301 | line-FKB_Lysloeype_Bro
302 | line-FKB_ParkeringsomraadeAvgrensning_Bro
303 | line-FKB_Jernbane_Bro
304 | line-FKB_T-Bane_Bro
305 | line-FKB_Trikk_Bro
306 | line-FKB_Sykkelfelt_Bro_1
307 | line-FKB_Sykkelfelt_Bro_2
308 | line-FKB_TraktorvegKant_Bro
309 | fill-FKB_Trafikkoey_bro
310 | line-FKB_Traktorveg_Bro
311 | fill-FKB_Fylkesveg_bro
312 | fill-FKB_Europaveg_bro
313 | line-FKB_BroennGrense_1
314 | line-FKB_BroennGrense_2
315 | line-FKB_Veglenke_Lysloeype_Bro
316 | line-FKB_Veglenke_Sti_Bro
317 | line-FKB_Veglenke_Traktorveg_Bro
318 | line-FKB_Vegrekkverk_Bro_1
319 | line-FKB_Vegrekkverk_Bro_2
320 | line-FKB_GangfeltAvgrensning_bro_2
321 | line-FKB_Sti_bro
322 | line-FKB_Trafikkoeykant_bro
323 | line-FKB_Vegdekkekant_bro
324 | line-FKB_VegkantAnnetVegareal_bro_2
325 | line-FKB_VegkantAnnetVegareal_bro_1
326 | line-FKB_VegkantAvkjoersel_bro
327 | line-FKB_Europaveg_bro
328 | line-FKB_Riksveg_bro
329 | line-FKB_Fylkesveg_bro
330 | line-FKB_Andreveger_bro
331 | line-FKB_Bruavgrensning
332 | line-FKB_AnnetVegarealAvgrensning_Bro
333 | fill-FKB_Bygning_1-Skygge
334 | fill-FKB_Bygning_2-Skygge
335 | fill-FKB_Bygning_3-Skygge
336 | fill-FKBBSK_Skygge_Bygg-1
337 | fill-FKBBSK_Skygge_Bygg-2
338 | fill-FKB_Tribune
339 | fill-FKB_Bygning_1
340 | fill-FKB_Bygning_2
341 | fill-FKB_Bygning_3
342 | fill-FKB_Taarn-flate
343 | fill-FKB_AnnenBygning_1
344 | fill-FKB_AnnenBygning_2
345 | fill-FKB_AnnenBygning_3
346 | fill-FKB_Takoverbygg_1
347 | fill-FKB_Takoverbygg_2
348 | fill-FKB_Takoverbygg_3
349 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_1
350 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_1-2
351 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_2
352 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_2-2
353 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_3
354 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_3-2
355 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_4
356 | fill-FKBBSK_Takflate_omriss-Lysvinkel_3d_4-2
357 | line-FKB_AnnenBygning_1
358 | line-FKB_AnnenBygning_2
359 | line-FKB_AnnenBygning_3
360 | line-FKB_TrappBygg_1
361 | line-FKB_TrappBygg_2
362 | line-FKB_Bygning_1
363 | line-FKB_Bygning_2
364 | line-FKB_Bygning_3
365 | line-FKB_Bygning_3
366 | line-FKB_TribuneKant
367 | line-FKB_Veranda_1
368 | line-FKB_Veranda_2
369 | line-FKB_BygningBru_1
370 | line-FKB_BygningBru_2
371 | line-FKB_Bygningsdelelinje
372 | line-FKB_Taksprang_1
373 | line-FKB_Taksprang_2
374 | line-FKB_TaarnKant
375 | line-FKB_Takplataa_1
376 | line-FKB_Takplataa_2
377 | line-FKB_TakplataaTopp_1
378 | line-FKB_TakplataaTopp_2
379 | line-FKB_Takkant_1
380 | line-FKB_Takkant_2
381 | line-FKB_Takkant_3
382 | line-FKBBSK_Takflate_flate_1
383 | line-FKBBSK_Takflate_flate_2
384 | line-FKB_TakoverbyggKant_1
385 | line-FKB_TakoverbyggKant_2
386 | line-FKB_TakoverbyggKant_3
387 | line-FKB_Bygningslinje_1
388 | line-FKB_Bygningslinje_2
389 | line-FKB_Moenelinje_1
390 | line-FKB_Moenelinje_2
391 | symbol-FKB_Forsenkningspunkt
392 | symbol-FKB_Taarn-punkt
393 | symbol-Europaveg
394 | symbol-Riksveg
395 | symbol-Fylkesveg
396 | symbol-Andre_veger
397 | symbol-Europavegnummer
398 | symbol-Riksvegnummer
399 | symbol-Riksveg_Fylkesvegummer_901
400 | symbol-FLYPL_Flyplass
401 | symbol-WAM_Adresse_1
402 | symbol-WAM_Adresse_2
403 | symbol-WAM_Adresse_3
404 | symbol-WAM_Adresse_4
405 | symbol-WAM_Adresse_5
406 | symbol-WAM_GIDText_1
407 | symbol-WAM_GIDText_2
408 | symbol-WAM_GIDText_3
409 | symbol-WAM_GIDText_4
410 | symbol-FKB_PresAnnenTekst_Punkt
411 | symbol-FKB_PresAnnenTekst_Linje
412 | symbol-FKB_PresHoydetallVann
413 | symbol-FKB_PresHoydetallPunkt_7501
414 | symbol-FKB_PresHoydetallPunkt_3601
415 | symbol-FKB_PresHoydetallPunkt_1801
416 | symbol-FKB_PresStedsnavn_Terrengdetalj
417 | symbol-FKB_PresStedsnavn_Kyst_StorSkrift
418 | symbol-FKB_PresStedsnavn_Terrengform_StorSkrift
419 | symbol-FKB_PresStedsnavn_Terrengform_LitenSkrift
420 | symbol-FKB_PresStedsnavn_Terrengform_Hoyre
421 | symbol-FKB_PresStedsnavn_Kyst_LitenSkrift
422 | symbol-FKB_PresStedsnavn_Vann_StorSkrift
423 | symbol-FKB_PresStedsnavn_Vann_LitenSkrift
424 | symbol-FKB_PresStedsnavn_Vann-LandObj_Hoyre
425 | symbol-FKB_PresStedsnavn_Grustak
426 | symbol-FKB_PresStedsnavn_Myrer
427 | symbol-FKB_PresStedsnavn_Bebyggelse_StorSkrift
428 | symbol-FKB_PresStedsnavn_Bebyggelse_MiddelsSkrift
429 | symbol-FKB_PresStedsnavn_Bebyggelse_LitenSkrift
430 | symbol-FKB_PresStedsnavn_Garder
431 | symbol-FKB_PresStedsnavn_HusHytteSeter
432 | symbol-FKB_PresStedsnavn_BergverkIndustri
433 | symbol-FKB_PresStedsnavn_Samferdsel
434 | symbol-FKB_PresStedsnavn_AndreAdmOmr
435 | symbol-FKB_PresStedsnavn_Andre
436 |
--------------------------------------------------------------------------------