Skip to content

Commit

Permalink
Merge pull request #41 from jansule/parse-scaleDenominator
Browse files Browse the repository at this point in the history
Parse scale denominator
  • Loading branch information
jansule authored Oct 29, 2018
2 parents bd1a7d2 + f9e6666 commit 8c2b18e
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 14 deletions.
25 changes: 25 additions & 0 deletions data/styles/scaleDenom_line.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Style } from 'geostyler-style';

const scaleDenomLine: Style = {
name: 'OL Style',
rules: [
{
name: 'OL Style Rule 0',
scaleDenominator: {
min: 0,
max: 500
},
symbolizers: [{
kind: 'Line',
color: '#000000',
width: 3,
dasharray: [1, 2, 3, 4],
cap: 'round',
join: 'miter',
dashOffset: 5
}]
}
]
};

export default scaleDenomLine;
37 changes: 37 additions & 0 deletions data/styles/scaleDenom_line_circle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Style } from 'geostyler-style';

const scaleDenomLineCircle: Style = {
name: 'OL Style',
rules: [
{
name: 'OL Style Rule 0',
scaleDenominator: {
min: 0,
max: 500
},
symbolizers: [{
kind: 'Line',
color: '#000000',
width: 3,
dasharray: [1, 2, 3, 4],
cap: 'round',
join: 'miter',
dashOffset: 5
}]
}, {
name: 'OL Style Rule 1',
scaleDenominator: {
min: 500,
max: 1000
},
symbolizers: [{
kind: 'Mark',
wellKnownName: 'Circle',
color: '#FF0000',
radius: 6
}]
}
]
};

export default scaleDenomLineCircle;
37 changes: 37 additions & 0 deletions data/styles/scaleDenom_line_circle_overlap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Style } from 'geostyler-style';

const scaleDenomLineCircleOverlap: Style = {
name: 'OL Style',
rules: [
{
name: 'OL Style Rule 0',
scaleDenominator: {
min: 0,
max: 800
},
symbolizers: [{
kind: 'Line',
color: '#000000',
width: 3,
dasharray: [1, 2, 3, 4],
cap: 'round',
join: 'miter',
dashOffset: 5
}]
}, {
name: 'OL Style Rule 1',
scaleDenominator: {
min: 500,
max: 1000
},
symbolizers: [{
kind: 'Mark',
wellKnownName: 'Circle',
color: '#FF0000',
radius: 6
}]
}
]
};

export default scaleDenomLineCircleOverlap;
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
declare module 'geostyler-openlayers-parser';
declare module '@terrestris/ol-util/dist/MapUtil/MapUtil';
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
},
"homepage": "https://github.com/terrestris/geostyler-openlayers-parser#readme",
"dependencies": {
"@terrestris/ol-util": "0.4.0",
"geostyler-style": "0.14.1",
"jest-preset-typescript": "1.2.0",
"lodash": "4.17.11",
Expand Down
90 changes: 89 additions & 1 deletion src/OlStyleParser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import line_simpleline from '../data/styles/line_simpleline';
import point_styledLabel_static from '../data/styles/point_styledLabel_static';
import multi_twoRulesSimplepoint from '../data/styles/multi_twoRulesSimplepoint';
import multi_simplefillSimpleline from '../data/styles/multi_simplefillSimpleline';
import scaleDenomLine from '../data/styles/scaleDenom_line';
import scaleDenomLineCircle from '../data/styles/scaleDenom_line_circle';
import scaleDenomLineCircleOverlap from '../data/styles/scaleDenom_line_circle_overlap';
import polygon_transparentpolygon from '../data/styles/polygon_transparentpolygon';
import point_styledlabel from '../data/styles/point_styledlabel';
import ol_point_simplepoint from '../data/olStyles/point_simplepoint';
Expand Down Expand Up @@ -58,10 +61,12 @@ import {
TextSymbolizer,
Style,
IconSymbolizer,
MarkSymbolizer
MarkSymbolizer,
Symbolizer
} from 'geostyler-style';

import OlStyleUtil from './Util/OlStyleUtil';
import MapUtil from '@terrestris/ol-util/dist/MapUtil/MapUtil';

it('OlStyleParser is defined', () => {
expect(OlStyleParser).toBeDefined();
Expand Down Expand Up @@ -947,6 +952,89 @@ describe('OlStyleParser implements StyleParser', () => {

});
});
it('returns style if scale is within scaleDenominators', () => {
expect.assertions(3);
return styleParser.writeStyle(scaleDenomLine)
.then((olStyle: OlParserStyleFct) => {
expect(olStyle).toBeDefined();

const withinScale: number = scaleDenomLine.rules[0].scaleDenominator.min;
const beyondScale: number = scaleDenomLine.rules[0].scaleDenominator.max;

const resolutionRuleOne = MapUtil.getResolutionForScale(withinScale, 'm');
const resolutionRuleTwo = MapUtil.getResolutionForScale(beyondScale, 'm');

const dummyFeat = new OlFeature();
const styleWithinScale = olStyle(dummyFeat, resolutionRuleOne);
const styleBeyondScale = olStyle(dummyFeat, resolutionRuleTwo);

expect(styleWithinScale).toHaveLength(1);
expect(styleBeyondScale).toHaveLength(0);
});
});
it('returns right style based on scaleDenominators', () => {
expect.assertions(11);
return styleParser.writeStyle(scaleDenomLineCircle)
.then((olStyle: OlParserStyleFct) => {
expect(olStyle).toBeDefined();

const scaleWithinFirst: number = scaleDenomLineCircle.rules[0].scaleDenominator.min;
const scaleWithinSecond: number = scaleDenomLineCircle.rules[1].scaleDenominator.min;
const scaleBeyond: number = scaleDenomLineCircle.rules[1].scaleDenominator.max;

const resolutionWithinFirst = MapUtil.getResolutionForScale(scaleWithinFirst, 'm');
const resolutionWithinSecond = MapUtil.getResolutionForScale(scaleWithinSecond, 'm');
const resolutionBeyond = MapUtil.getResolutionForScale(scaleBeyond, 'm');

const dummyFeat = new OlFeature();
const styleWithinFirst = olStyle(dummyFeat, resolutionWithinFirst);
const styleWithinSecond = olStyle(dummyFeat, resolutionWithinSecond);
const styleBeyond = olStyle(dummyFeat, resolutionBeyond);

expect(styleWithinFirst).toHaveLength(1);
expect(styleWithinSecond).toHaveLength(1);
expect(styleBeyond).toHaveLength(0);

const styleFirst: OlStyle = styleWithinFirst[0];
const expecFirst = scaleDenomLineCircle.rules[0].symbolizers[0] as LineSymbolizer;
const olStroke = styleFirst.getStroke();
expect(olStroke).toBeDefined();
expect(olStroke.getColor()).toEqual(expecFirst.color);
expect(olStroke.getWidth()).toBeCloseTo(expecFirst.width);
expect(olStroke.getLineDash()).toEqual(expecFirst.dasharray);

const styleSecond: OlStyle = styleWithinSecond[0];
const expecSecond = scaleDenomLineCircle.rules[1].symbolizers[0] as MarkSymbolizer;
const olCircle: OlStyleCircle = styleSecond.getImage() as OlStyleCircle;
expect(olCircle).toBeDefined();
expect(olCircle.getRadius()).toBeCloseTo(expecSecond.radius);
expect(olCircle.getFill().getColor()).toEqual(expecSecond.color);
});
});
it('returns styles of all rules that lie within scaleDenominator', () => {
expect.assertions(4);
return styleParser.writeStyle(scaleDenomLineCircleOverlap)
.then((olStyle: OlParserStyleFct) => {
expect(olStyle).toBeDefined();

const scaleOnlyFirst: number = scaleDenomLineCircleOverlap.rules[0].scaleDenominator.min;
const scaleOverlap: number = scaleDenomLineCircleOverlap.rules[1].scaleDenominator.min;
const scaleOnlySecond: number = scaleDenomLineCircleOverlap.rules[1].scaleDenominator.max - 1;

const resolutionOnlyFirst = MapUtil.getResolutionForScale(scaleOnlyFirst, 'm');
const resolutionOverlap = MapUtil.getResolutionForScale(scaleOverlap, 'm');
const resolutionOnlySecond = MapUtil.getResolutionForScale(scaleOnlySecond, 'm');

const dummyFeat = new OlFeature();
const styleOnlyFirst = olStyle(dummyFeat, resolutionOnlyFirst);
const styleOverlap = olStyle(dummyFeat, resolutionOverlap);
const styleOnlySecond = olStyle(dummyFeat, resolutionOnlySecond);

expect(styleOnlyFirst).toHaveLength(1);
expect(styleOverlap).toHaveLength(2);
expect(styleOnlySecond).toHaveLength(1);
});
});
// it('can write a OpenLayers style with a filter', () => {
// expect.assertions(2);
// return styleParser.writeStyle(point_simplepoint_filter)
Expand Down
41 changes: 28 additions & 13 deletions src/OlStyleParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import OlStyleIcon from 'ol/style/icon';
import OlStyleRegularshape from 'ol/style/regularshape';

import OlStyleUtil from './Util/OlStyleUtil';
import MapUtil from '@terrestris/ol-util/dist/MapUtil/MapUtil';
import { isNumber } from 'util';
const _get = require('lodash/get');

Expand Down Expand Up @@ -443,9 +444,9 @@ export class OlStyleParser implements StyleParser {
const rules = geoStylerStyle.rules;
const nrRules = rules.length;
if (nrRules === 1) {
const hasFilter = _get(geoStylerStyle, 'rules[0].filter') !== undefined ? true : false;
const hasMinScale = _get(geoStylerStyle, 'rules[0].scaleDenominator.min') !== undefined ? true : false;
const hasMaxScale = _get(geoStylerStyle, 'rules[0].scaleDenominator.max') !== undefined ? true : false;
const hasFilter = typeof _get(geoStylerStyle, 'rules[0].filter') !== 'undefined' ? true : false;
const hasMinScale = typeof _get(geoStylerStyle, 'rules[0].scaleDenominator.min') !== 'undefined' ? true : false;
const hasMaxScale = typeof _get(geoStylerStyle, 'rules[0].scaleDenominator.max') !== 'undefined' ? true : false;
const hasScaleDenominator = hasMinScale || hasMaxScale ? true : false;
const nrSymbolizers = geoStylerStyle.rules[0].symbolizers.length;
const hasTextSymbolizer = rules[0].symbolizers.some((symbolizer: Symbolizer) => {
Expand Down Expand Up @@ -504,24 +505,38 @@ export class OlStyleParser implements StyleParser {
const rules = geoStylerStyle.rules;
const olStyle: ol.StyleFunction = (feature: ol.Feature, resolution: number): OlStyle[] => {
// TODO
// handle scaleDenominators and Filters here
// Parse Filters here
const styles: OlStyle[] = [];
const scale = MapUtil.getScaleForResolution(resolution, 'm');
rules.forEach((rule: Rule) => {
rule.symbolizers.forEach((symb: Symbolizer) => {
const olSymbolizer: OlStyle|ol.StyleFunction = this.getOlSymbolizerFromSymbolizer(symb);
const minScale = _get(rule, 'scaleDenominator.min');
const maxScale = _get(rule, 'scaleDenominator.max');
let isWithinScale = true;
if (typeof minScale !== 'undefined' || typeof maxScale !== 'undefined') {
if (typeof minScale !== 'undefined' && scale < minScale) {
isWithinScale = false;
}
if (typeof maxScale !== 'undefined' && scale >= maxScale) {
isWithinScale = false;
}
}
if (isWithinScale) {
rule.symbolizers.forEach((symb: Symbolizer) => {
const olSymbolizer: OlStyle|ol.StyleFunction = this.getOlSymbolizerFromSymbolizer(symb);

// this.getOlTextSymbolizerFromTextSymbolizer returns
// either an OlStyle or an ol.StyleFunction. OpenLayers only accepts an array
// of OlStyles, not ol.StyleFunctions.
// So we have to check it and in case of an ol.StyleFunction call that function
// and add the returned style to const styles.
if (olSymbolizer instanceof OlStyle) {
styles.push(olSymbolizer);
} else {
const styleFromFct: OlStyle = olSymbolizer(feature, resolution) as OlStyle;
styles.push(styleFromFct);
}
});
if (olSymbolizer instanceof OlStyle) {
styles.push(olSymbolizer);
} else {
const styleFromFct: OlStyle = olSymbolizer(feature, resolution) as OlStyle;
styles.push(styleFromFct);
}
});
}
});
return styles;
};
Expand Down

0 comments on commit 8c2b18e

Please sign in to comment.