Skip to content

Commit

Permalink
Add support for dashed lines using PolylineDash
Browse files Browse the repository at this point in the history
- add tests;
- add allowSyntheticDefaultImports to allow loading node assert and test modules.
  • Loading branch information
fredj authored and gberaudo committed Feb 28, 2024
1 parent 3ee7619 commit e2471d2
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 8 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
- name: CI
run: npm ci
- name: Lint
run: npm run lint
- name: Prepare
run: npm run prepare
- name: Test
run: npm test
- name: Build examples
run: npm run build-examples
9 changes: 8 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
# Changelog

## v 2.19.3

* Changes
* Support dashed lines by converting the pattern


## v 2.19.2

* Port to OpenLayers 9
* Changes
* Add OpenLayers 9 support

## v 2.19.1

Expand Down
75 changes: 75 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "2.19.2",
"description": "OpenLayers Cesium integration and plugin library",
"scripts": {
"test": "node --enable-source-maps --import @swc-node/register/esm-register --test src/olcs/*.test.ts",
"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/",
"prepare": "tsc --pretty && node buildtools/fix_paths_recast.js; npm run doc",
"typecheck": "tsc --pretty --noEmit",
Expand Down Expand Up @@ -77,6 +78,7 @@
"devDependencies": {
"@babel/parser": "7.23.9",
"@mapbox/geojsonhint": "3.3.0",
"@swc-node/register": "^1.8.0",
"@typescript-eslint/eslint-plugin": "7.0.2",
"@typescript-eslint/parser": "7.0.2",
"cesium": "1.114.0",
Expand Down
51 changes: 45 additions & 6 deletions src/olcs/FeatureConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -976,12 +976,11 @@ export default class FeatureConverter {
const olColor = outline ? stroke.getColor() : fill.getColor();
const color = convertColorToCesium(olColor);

if (outline && stroke.getLineDash()) {
return Cesium.Material.fromType('Stripe', {
horizontal: false,
repeat: 500, // TODO how to calculate this?
evenColor: color,
oddColor: new Cesium.Color(0, 0, 0, 0) // transparent
const lineDash = stroke.getLineDash();
if (outline && lineDash) {
return Cesium.Material.fromType('PolylineDash', {
dashPattern: dashPattern(lineDash),
color
});
} else {
return Cesium.Material.fromType('Color', {
Expand Down Expand Up @@ -1230,3 +1229,43 @@ export default class FeatureConverter {
return primitives;
}
}

/**
* Transform a canvas line dash pattern to a Cesium dash pattern
* See https://cesium.com/learn/cesiumjs/ref-doc/PolylineDashMaterialProperty.html#dashPattern
* @param lineDash
*/
export function dashPattern(lineDash: number[]): number {
if (lineDash.length < 2) {
lineDash = [1, 1];
}
const segments = lineDash.length % 2 === 0 ? lineDash : [...lineDash, ...lineDash];
const total = segments.reduce((a, b) => a + b, 0);
const div = total / 16;
// create a 16 bit binary string
let binaryString = segments.map((segment, index) => {
// we alternate between 1 and 0
const digit = index % 2 === 0 ? '1' : '0';
// We scale the segment length to fit 16 slots.
let count = Math.round(segment / div);
if (index === 0 && count === 0) {
// We need to start with a 1
count = 1;
}
return digit.repeat(count);
}).join('');

// We rounded so it might be that the string is too short or too long.
// We try to fix it by padding or truncating the string.
if (binaryString.length < 16) {
binaryString = binaryString.padEnd(16, '0');
} else if (binaryString.length > 16) {
binaryString = binaryString.substring(0, 16);
}
if (binaryString[15] === '1') {
// We need to really finish with a 0
binaryString = binaryString.substring(0, 15) + '0';
}
console.assert(binaryString.length === 16);
return parseInt(binaryString, 2);
}
38 changes: 38 additions & 0 deletions src/olcs/dashPatternConversion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import test from 'node:test';
import assert from 'node:assert';

import {dashPattern} from './FeatureConverter';

function olPatternAsBinary(pattern: number[]): string {
const pattern16 = dashPattern(pattern);
return pattern16.toString(2);
}

test('pattern-100-100', (t) => {
// Whatever the scaling, the result should be the same.
// Only propoprtion matters.
assert.strictEqual(olPatternAsBinary([100, 100]), '1111111100000000');
assert.strictEqual(olPatternAsBinary([1, 1]), '1111111100000000');
assert.strictEqual(olPatternAsBinary([999999, 999999]), '1111111100000000');
});

test('pattern-100-100-100-100', (t) => {
// We should see 4 dashes of equal length.
assert.strictEqual(olPatternAsBinary([100, 100, 100, 100]), '1111000011110000');
});

test('pattern-too-long', (t) => {
// When the pattern is too long, here we have 200 segments
// we should still ensure that the pattern is well formed (I guess):
// - starts with a 1:
// - ends with a 0.
assert.strictEqual(olPatternAsBinary(Array.from({length: 200}, _ => 1)), '1000000000000000');
});


test('pattern-uneven', (t) => {
// When the pattern is uneven, it is duplicated
assert.strictEqual(olPatternAsBinary([6, 1, 2, 6, 1, 2]), '1111101100000100');
assert.strictEqual(olPatternAsBinary([6, 1, 2]), '1111101100000100');
assert.strictEqual(olPatternAsBinary([12, 2, 4]), '1111101100000100');
});
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"noImplicitAny": true,
"declarationMap": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"paths": {
"ol/*": ["node_modules/ol/*"]
},
Expand Down

0 comments on commit e2471d2

Please sign in to comment.