Skip to content

Commit e2471d2

Browse files
fredjgberaudo
authored andcommittedFeb 28, 2024·
Add support for dashed lines using PolylineDash
- add tests; - add allowSyntheticDefaultImports to allow loading node assert and test modules.
1 parent 3ee7619 commit e2471d2

7 files changed

+172
-8
lines changed
 

‎.github/workflows/test.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ jobs:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-node@v4
1414
with:
15-
node-version: 18
15+
node-version: 20
1616
- name: CI
1717
run: npm ci
1818
- name: Lint
1919
run: npm run lint
2020
- name: Prepare
2121
run: npm run prepare
22+
- name: Test
23+
run: npm test
2224
- name: Build examples
2325
run: npm run build-examples

‎CHANGES.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
# Changelog
22

3+
## v 2.19.3
4+
5+
* Changes
6+
* Support dashed lines by converting the pattern
7+
8+
39
## v 2.19.2
410

5-
* Port to OpenLayers 9
11+
* Changes
12+
* Add OpenLayers 9 support
613

714
## v 2.19.1
815

‎package-lock.json

+75
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "2.19.2",
44
"description": "OpenLayers Cesium integration and plugin library",
55
"scripts": {
6+
"test": "node --enable-source-maps --import @swc-node/register/esm-register --test src/olcs/*.test.ts",
67
"build-examples": "rm -rf dist; parcel build; mkdir -p dist/examples/node_modules/ol; mkdir -p dist/examples/node_modules/cesium/Build/; cp examples/inject_ol_cesium.js dist/examples/; cp node_modules/ol/ol.css dist/examples/node_modules/ol/; cp -R node_modules/cesium/Build/CesiumUnminified node_modules/cesium/Build/Cesium dist/examples/node_modules/cesium/Build/; cp -R examples/data dist/examples/",
78
"prepare": "tsc --pretty && node buildtools/fix_paths_recast.js; npm run doc",
89
"typecheck": "tsc --pretty --noEmit",
@@ -77,6 +78,7 @@
7778
"devDependencies": {
7879
"@babel/parser": "7.23.9",
7980
"@mapbox/geojsonhint": "3.3.0",
81+
"@swc-node/register": "^1.8.0",
8082
"@typescript-eslint/eslint-plugin": "7.0.2",
8183
"@typescript-eslint/parser": "7.0.2",
8284
"cesium": "1.114.0",

‎src/olcs/FeatureConverter.ts

+45-6
Original file line numberDiff line numberDiff line change
@@ -976,12 +976,11 @@ export default class FeatureConverter {
976976
const olColor = outline ? stroke.getColor() : fill.getColor();
977977
const color = convertColorToCesium(olColor);
978978

979-
if (outline && stroke.getLineDash()) {
980-
return Cesium.Material.fromType('Stripe', {
981-
horizontal: false,
982-
repeat: 500, // TODO how to calculate this?
983-
evenColor: color,
984-
oddColor: new Cesium.Color(0, 0, 0, 0) // transparent
979+
const lineDash = stroke.getLineDash();
980+
if (outline && lineDash) {
981+
return Cesium.Material.fromType('PolylineDash', {
982+
dashPattern: dashPattern(lineDash),
983+
color
985984
});
986985
} else {
987986
return Cesium.Material.fromType('Color', {
@@ -1230,3 +1229,43 @@ export default class FeatureConverter {
12301229
return primitives;
12311230
}
12321231
}
1232+
1233+
/**
1234+
* Transform a canvas line dash pattern to a Cesium dash pattern
1235+
* See https://cesium.com/learn/cesiumjs/ref-doc/PolylineDashMaterialProperty.html#dashPattern
1236+
* @param lineDash
1237+
*/
1238+
export function dashPattern(lineDash: number[]): number {
1239+
if (lineDash.length < 2) {
1240+
lineDash = [1, 1];
1241+
}
1242+
const segments = lineDash.length % 2 === 0 ? lineDash : [...lineDash, ...lineDash];
1243+
const total = segments.reduce((a, b) => a + b, 0);
1244+
const div = total / 16;
1245+
// create a 16 bit binary string
1246+
let binaryString = segments.map((segment, index) => {
1247+
// we alternate between 1 and 0
1248+
const digit = index % 2 === 0 ? '1' : '0';
1249+
// We scale the segment length to fit 16 slots.
1250+
let count = Math.round(segment / div);
1251+
if (index === 0 && count === 0) {
1252+
// We need to start with a 1
1253+
count = 1;
1254+
}
1255+
return digit.repeat(count);
1256+
}).join('');
1257+
1258+
// We rounded so it might be that the string is too short or too long.
1259+
// We try to fix it by padding or truncating the string.
1260+
if (binaryString.length < 16) {
1261+
binaryString = binaryString.padEnd(16, '0');
1262+
} else if (binaryString.length > 16) {
1263+
binaryString = binaryString.substring(0, 16);
1264+
}
1265+
if (binaryString[15] === '1') {
1266+
// We need to really finish with a 0
1267+
binaryString = binaryString.substring(0, 15) + '0';
1268+
}
1269+
console.assert(binaryString.length === 16);
1270+
return parseInt(binaryString, 2);
1271+
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import test from 'node:test';
2+
import assert from 'node:assert';
3+
4+
import {dashPattern} from './FeatureConverter';
5+
6+
function olPatternAsBinary(pattern: number[]): string {
7+
const pattern16 = dashPattern(pattern);
8+
return pattern16.toString(2);
9+
}
10+
11+
test('pattern-100-100', (t) => {
12+
// Whatever the scaling, the result should be the same.
13+
// Only propoprtion matters.
14+
assert.strictEqual(olPatternAsBinary([100, 100]), '1111111100000000');
15+
assert.strictEqual(olPatternAsBinary([1, 1]), '1111111100000000');
16+
assert.strictEqual(olPatternAsBinary([999999, 999999]), '1111111100000000');
17+
});
18+
19+
test('pattern-100-100-100-100', (t) => {
20+
// We should see 4 dashes of equal length.
21+
assert.strictEqual(olPatternAsBinary([100, 100, 100, 100]), '1111000011110000');
22+
});
23+
24+
test('pattern-too-long', (t) => {
25+
// When the pattern is too long, here we have 200 segments
26+
// we should still ensure that the pattern is well formed (I guess):
27+
// - starts with a 1:
28+
// - ends with a 0.
29+
assert.strictEqual(olPatternAsBinary(Array.from({length: 200}, _ => 1)), '1000000000000000');
30+
});
31+
32+
33+
test('pattern-uneven', (t) => {
34+
// When the pattern is uneven, it is duplicated
35+
assert.strictEqual(olPatternAsBinary([6, 1, 2, 6, 1, 2]), '1111101100000100');
36+
assert.strictEqual(olPatternAsBinary([6, 1, 2]), '1111101100000100');
37+
assert.strictEqual(olPatternAsBinary([12, 2, 4]), '1111101100000100');
38+
});

‎tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"noImplicitAny": true,
1414
"declarationMap": true,
1515
"forceConsistentCasingInFileNames": true,
16+
"allowSyntheticDefaultImports": true,
1617
"paths": {
1718
"ol/*": ["node_modules/ol/*"]
1819
},

0 commit comments

Comments
 (0)
Please sign in to comment.