aur-openlayers 19.6.4 → 19.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,8 @@ import Collection from 'ol/Collection';
9
9
  import DragPan from 'ol/interaction/DragPan';
10
10
  import Modify from 'ol/interaction/Modify';
11
11
  import * as Observable from 'ol/Observable';
12
+ import { unByKey } from 'ol/Observable';
13
+ import { LineString, MultiLineString, Point } from 'ol/geom';
12
14
 
13
15
  class LibService {
14
16
  constructor() { }
@@ -1585,7 +1587,7 @@ class StyleCache {
1585
1587
  }
1586
1588
  }
1587
1589
 
1588
- const resolveMaybeFn = (value, args) => {
1590
+ const resolveMaybeFn$1 = (value, args) => {
1589
1591
  if (typeof value === 'function') {
1590
1592
  return value(...args);
1591
1593
  }
@@ -1620,7 +1622,7 @@ const createStyleFunction = (options) => {
1620
1622
  resolution,
1621
1623
  zoom: map?.getView().getZoom(),
1622
1624
  };
1623
- let opts = resolveMaybeFn(style.base, [model, view]);
1625
+ let opts = resolveMaybeFn$1(style.base, [model, view]);
1624
1626
  if (style.states) {
1625
1627
  const featureStates = orderStates(getFeatureStates(feature), style.statePriority);
1626
1628
  featureStates.forEach((state) => {
@@ -1628,7 +1630,7 @@ const createStyleFunction = (options) => {
1628
1630
  if (!patchFactory) {
1629
1631
  return;
1630
1632
  }
1631
- const patch = resolveMaybeFn(patchFactory, [model, view]);
1633
+ const patch = resolveMaybeFn$1(patchFactory, [model, view]);
1632
1634
  opts = applyPatch(opts, patch);
1633
1635
  });
1634
1636
  }
@@ -2292,6 +2294,140 @@ class PopupHost {
2292
2294
  }
2293
2295
  }
2294
2296
 
2297
+ const resolveMaybeFn = (value, args) => typeof value === 'function' ? value(...args) : value;
2298
+ /**
2299
+ * Extracts flat coordinate arrays from a feature's geometry.
2300
+ * Supports LineString and MultiLineString; returns empty array for others.
2301
+ */
2302
+ function extractLineCoords(geometry) {
2303
+ if (geometry instanceof LineString) {
2304
+ return [geometry.getCoordinates()];
2305
+ }
2306
+ if (geometry instanceof MultiLineString) {
2307
+ return geometry.getCoordinates();
2308
+ }
2309
+ return [];
2310
+ }
2311
+ /**
2312
+ * Generate arrow points along a polyline at a given interval (meters in EPSG:3857).
2313
+ */
2314
+ function generateArrowPoints(coords, intervalMeters, offsetRatio) {
2315
+ if (coords.length < 2 || intervalMeters <= 0)
2316
+ return [];
2317
+ const arrows = [];
2318
+ let accumulated = intervalMeters * offsetRatio;
2319
+ for (let i = 0; i < coords.length - 1; i++) {
2320
+ const ax = coords[i][0], ay = coords[i][1];
2321
+ const bx = coords[i + 1][0], by = coords[i + 1][1];
2322
+ const segLen = Math.hypot(bx - ax, by - ay);
2323
+ const rotation = Math.atan2(bx - ax, by - ay);
2324
+ while (accumulated <= segLen) {
2325
+ const t = accumulated / segLen;
2326
+ arrows.push({
2327
+ coordinate: [ax + t * (bx - ax), ay + t * (by - ay)],
2328
+ rotation,
2329
+ });
2330
+ accumulated += intervalMeters;
2331
+ }
2332
+ accumulated -= segLen;
2333
+ }
2334
+ return arrows;
2335
+ }
2336
+ class ArrowDecorationManager {
2337
+ source = new VectorSource();
2338
+ layer;
2339
+ config;
2340
+ map;
2341
+ parentLayer;
2342
+ parentApi;
2343
+ moveEndKey;
2344
+ unsubCollection;
2345
+ unsubChanges;
2346
+ rafId = null;
2347
+ constructor(options) {
2348
+ this.config = options.config;
2349
+ this.map = options.map;
2350
+ this.parentLayer = options.parentLayer;
2351
+ this.parentApi = options.parentApi;
2352
+ const parentZ = this.parentLayer.getZIndex() ?? 0;
2353
+ this.layer = new VectorLayer({
2354
+ source: this.source,
2355
+ zIndex: parentZ + 1,
2356
+ });
2357
+ this.layer.set('id', `__decoration_arrows`);
2358
+ this.map.addLayer(this.layer);
2359
+ this.syncVisibility();
2360
+ this.syncOpacity();
2361
+ this.moveEndKey = this.map.on('moveend', () => this.scheduleUpdate());
2362
+ this.unsubCollection = this.parentApi.onModelsCollectionChanged(() => this.scheduleUpdate());
2363
+ this.unsubChanges = this.parentApi.onModelsChanged?.(() => this.scheduleUpdate());
2364
+ }
2365
+ scheduleUpdate() {
2366
+ if (this.rafId !== null)
2367
+ return;
2368
+ this.rafId = requestAnimationFrame(() => {
2369
+ this.rafId = null;
2370
+ this.rebuild();
2371
+ });
2372
+ }
2373
+ rebuild() {
2374
+ this.syncVisibility();
2375
+ this.syncOpacity();
2376
+ if (!this.parentLayer.getVisible()) {
2377
+ this.source.clear();
2378
+ return;
2379
+ }
2380
+ const view = this.map.getView();
2381
+ const resolution = view.getResolution() ?? 1;
2382
+ const styleView = { resolution, zoom: view.getZoom() };
2383
+ const interval = resolveMaybeFn(this.config.interval, [styleView]);
2384
+ const offsetRatio = this.config.offsetRatio ?? 0.5;
2385
+ const parentSource = this.parentLayer.getSource();
2386
+ if (!parentSource) {
2387
+ this.source.clear();
2388
+ return;
2389
+ }
2390
+ const allArrows = [];
2391
+ parentSource.getFeatures().forEach((feature) => {
2392
+ const geom = feature.getGeometry();
2393
+ if (!geom)
2394
+ return;
2395
+ const lines = extractLineCoords(geom);
2396
+ for (const coords of lines) {
2397
+ const arrows = generateArrowPoints(coords, interval, offsetRatio);
2398
+ allArrows.push(...arrows);
2399
+ }
2400
+ });
2401
+ const features = allArrows.map((arrow, i) => {
2402
+ const f = new Feature({ geometry: new Point(arrow.coordinate) });
2403
+ f.setId(`__arrow_${i}`);
2404
+ const styleResult = this.config.style({ rotation: arrow.rotation, view: styleView });
2405
+ f.setStyle(Array.isArray(styleResult) ? styleResult : [styleResult]);
2406
+ return f;
2407
+ });
2408
+ this.source.clear();
2409
+ if (features.length > 0) {
2410
+ this.source.addFeatures(features);
2411
+ }
2412
+ }
2413
+ syncVisibility() {
2414
+ this.layer.setVisible(this.parentLayer.getVisible());
2415
+ }
2416
+ syncOpacity() {
2417
+ this.layer.setOpacity(this.parentLayer.getOpacity());
2418
+ }
2419
+ dispose() {
2420
+ if (this.rafId !== null) {
2421
+ cancelAnimationFrame(this.rafId);
2422
+ this.rafId = null;
2423
+ }
2424
+ unByKey(this.moveEndKey);
2425
+ this.unsubCollection();
2426
+ this.unsubChanges?.();
2427
+ this.map.removeLayer(this.layer);
2428
+ }
2429
+ }
2430
+
2295
2431
  class LayerManager {
2296
2432
  map;
2297
2433
  layers = {};
@@ -2300,6 +2436,7 @@ class LayerManager {
2300
2436
  scheduler;
2301
2437
  popupHost;
2302
2438
  ctx;
2439
+ decorationManagers = [];
2303
2440
  constructor(map, schema) {
2304
2441
  this.map = map;
2305
2442
  const popupHost = schema.options?.popupHost ? new PopupHost(schema.options.popupHost) : undefined;
@@ -2347,6 +2484,15 @@ class LayerManager {
2347
2484
  this.layers[descriptor.id] = layer;
2348
2485
  this.apis[descriptor.id] = api;
2349
2486
  this.map.addLayer(layer);
2487
+ if (descriptor.feature.decorations?.arrows) {
2488
+ const decorationManager = new ArrowDecorationManager({
2489
+ map: this.map,
2490
+ parentLayer: layer,
2491
+ parentApi: api,
2492
+ config: descriptor.feature.decorations.arrows,
2493
+ });
2494
+ this.decorationManagers.push(decorationManager);
2495
+ }
2350
2496
  });
2351
2497
  this.interactions = new InteractionManager({
2352
2498
  ctx,
@@ -2378,6 +2524,7 @@ class LayerManager {
2378
2524
  this.interactions.dispose();
2379
2525
  this.popupHost?.dispose();
2380
2526
  this.scheduler.dispose();
2527
+ this.decorationManagers.forEach((dm) => dm.dispose());
2381
2528
  Object.values(this.layers).forEach((layer) => this.map.removeLayer(layer));
2382
2529
  }
2383
2530
  }