@angular-helpers/openlayers 22.0.1 → 22.1.0
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.
|
@@ -341,17 +341,29 @@ class OlGeometryService {
|
|
|
341
341
|
if (segments < 8) {
|
|
342
342
|
throw new RangeError('segments must be >= 8');
|
|
343
343
|
}
|
|
344
|
-
const
|
|
345
|
-
const
|
|
344
|
+
const rRadius = 6371008.8; // Standard Earth radius used by OpenLayers
|
|
345
|
+
const alpha = semiMajor / rRadius;
|
|
346
|
+
const beta = semiMinor / rRadius;
|
|
347
|
+
// Failsafe for strategic-scale inputs exceeding spherical boundaries (quarter of Earth)
|
|
348
|
+
if (alpha >= Math.PI / 2 || beta >= Math.PI / 2) {
|
|
349
|
+
throw new RangeError('semiMajor and semiMinor must be less than quarter of Earth circumference');
|
|
350
|
+
}
|
|
351
|
+
const tanAlpha = Math.tan(alpha);
|
|
352
|
+
const tanBeta = Math.tan(beta);
|
|
353
|
+
const tanAlphaSq = tanAlpha * tanAlpha;
|
|
354
|
+
const tanBetaSq = tanBeta * tanBeta;
|
|
346
355
|
const ring = [];
|
|
347
356
|
for (let i = 0; i < segments; i++) {
|
|
348
357
|
const theta = (i / segments) * Math.PI * 2;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
|
|
358
|
+
const cosT = Math.cos(theta);
|
|
359
|
+
// Spherical ellipse polar equation:
|
|
360
|
+
// tan^2(rho) = tan^2(beta) / (1 - cos^2(theta) * (1 - tan^2(beta) / tan^2(alpha)))
|
|
361
|
+
const denom = 1 - cosT * cosT * (1 - tanBetaSq / tanAlphaSq);
|
|
362
|
+
const tanSqRho = tanBetaSq / denom;
|
|
363
|
+
const rho = Math.atan(Math.sqrt(tanSqRho));
|
|
364
|
+
const distance = rho * rRadius;
|
|
365
|
+
const bearing = Math.PI / 2 - (rotation + theta);
|
|
366
|
+
ring.push(offset(center, distance, bearing));
|
|
355
367
|
}
|
|
356
368
|
ring.push(ring[0]); // close the ring
|
|
357
369
|
return {
|
|
@@ -382,9 +394,8 @@ class OlGeometryService {
|
|
|
382
394
|
const span = endAngle - startAngle;
|
|
383
395
|
for (let i = 0; i <= segments; i++) {
|
|
384
396
|
const theta = startAngle + (i / segments) * span;
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
ring.push(this.offsetMetersToLonLat(center, dx, dy));
|
|
397
|
+
const bearing = Math.PI / 2 - theta;
|
|
398
|
+
ring.push(offset(center, radius, bearing));
|
|
388
399
|
}
|
|
389
400
|
ring.push(center); // close back to apex
|
|
390
401
|
return {
|
|
@@ -413,13 +424,9 @@ class OlGeometryService {
|
|
|
413
424
|
const inner = [];
|
|
414
425
|
for (let i = 0; i < segments; i++) {
|
|
415
426
|
const theta = (i / segments) * Math.PI * 2;
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
outer.push(this.offsetMetersToLonLat(center, cosT * outerRadius, sinT * outerRadius));
|
|
420
|
-
// Inner ring: CW — sample the SAME thetas but we'll reverse the
|
|
421
|
-
// accumulator below so the ring is traversed in the opposite sense.
|
|
422
|
-
inner.push(this.offsetMetersToLonLat(center, cosT * innerRadius, sinT * innerRadius));
|
|
427
|
+
const bearing = Math.PI / 2 - theta;
|
|
428
|
+
outer.push(offset(center, outerRadius, bearing));
|
|
429
|
+
inner.push(offset(center, innerRadius, bearing));
|
|
423
430
|
}
|
|
424
431
|
inner.reverse();
|
|
425
432
|
outer.push(outer[0]);
|
|
@@ -1279,6 +1279,9 @@ class OlWebGLTileLayerComponent {
|
|
|
1279
1279
|
/** Preload low-res tiles up to this many zoom levels */
|
|
1280
1280
|
preload = input(0, /* @ts-ignore */
|
|
1281
1281
|
...(ngDevMode ? [{ debugName: "preload" }] : /* istanbul ignore next */ []));
|
|
1282
|
+
/** Style variables for dynamic expressions (e.g. `['var', 'brightness']`) */
|
|
1283
|
+
variables = input(/* @ts-ignore */
|
|
1284
|
+
...(ngDevMode ? [undefined, { debugName: "variables" }] : /* istanbul ignore next */ []));
|
|
1282
1285
|
layer = null;
|
|
1283
1286
|
constructor() {
|
|
1284
1287
|
afterNextRender(() => {
|
|
@@ -1299,6 +1302,7 @@ class OlWebGLTileLayerComponent {
|
|
|
1299
1302
|
opacity: this.opacity(),
|
|
1300
1303
|
zIndex: this.zIndex(),
|
|
1301
1304
|
style: this.tileStyle() || {},
|
|
1305
|
+
...(this.variables() ? { variables: this.variables() } : {}),
|
|
1302
1306
|
});
|
|
1303
1307
|
break;
|
|
1304
1308
|
case 'xyz':
|
|
@@ -1313,6 +1317,7 @@ class OlWebGLTileLayerComponent {
|
|
|
1313
1317
|
zIndex: this.zIndex(),
|
|
1314
1318
|
preload: this.preload(),
|
|
1315
1319
|
...(this.tileStyle() ? { style: this.tileStyle() } : {}),
|
|
1320
|
+
...(this.variables() ? { variables: this.variables() } : {}),
|
|
1316
1321
|
});
|
|
1317
1322
|
break;
|
|
1318
1323
|
case 'osm':
|
|
@@ -1327,6 +1332,7 @@ class OlWebGLTileLayerComponent {
|
|
|
1327
1332
|
zIndex: this.zIndex(),
|
|
1328
1333
|
preload: this.preload(),
|
|
1329
1334
|
...(this.tileStyle() ? { style: this.tileStyle() } : {}),
|
|
1335
|
+
...(this.variables() ? { variables: this.variables() } : {}),
|
|
1330
1336
|
});
|
|
1331
1337
|
break;
|
|
1332
1338
|
}
|
|
@@ -1355,6 +1361,12 @@ class OlWebGLTileLayerComponent {
|
|
|
1355
1361
|
}
|
|
1356
1362
|
}
|
|
1357
1363
|
});
|
|
1364
|
+
effect(() => {
|
|
1365
|
+
const vars = this.variables();
|
|
1366
|
+
if (vars && this.layer) {
|
|
1367
|
+
this.layer.updateStyleVariables(vars);
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1358
1370
|
// WebGL tile layers also need manual dispose
|
|
1359
1371
|
this.destroyRef.onDestroy(() => {
|
|
1360
1372
|
const map = this.mapService.getMap();
|
|
@@ -1364,8 +1376,17 @@ class OlWebGLTileLayerComponent {
|
|
|
1364
1376
|
}
|
|
1365
1377
|
});
|
|
1366
1378
|
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Imperatively update style variables without triggering Angular change detection.
|
|
1381
|
+
* Ideal for 60FPS animations where you don't want to use the declarative [variables] input.
|
|
1382
|
+
*/
|
|
1383
|
+
updateVariables(vars) {
|
|
1384
|
+
if (this.layer) {
|
|
1385
|
+
this.layer.updateStyleVariables(vars);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1367
1388
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: OlWebGLTileLayerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1368
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.0", type: OlWebGLTileLayerComponent, isStandalone: true, selector: "ol-webgl-tile-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, attributions: { classPropertyName: "attributions", publicName: "attributions", isSignal: true, isRequired: false, transformFunction: null }, tileStyle: { classPropertyName: "tileStyle", publicName: "tileStyle", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, preload: { classPropertyName: "preload", publicName: "preload", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true });
|
|
1389
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.0", type: OlWebGLTileLayerComponent, isStandalone: true, selector: "ol-webgl-tile-layer", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: true, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null }, attributions: { classPropertyName: "attributions", publicName: "attributions", isSignal: true, isRequired: false, transformFunction: null }, tileStyle: { classPropertyName: "tileStyle", publicName: "tileStyle", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, opacity: { classPropertyName: "opacity", publicName: "opacity", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, preload: { classPropertyName: "preload", publicName: "preload", isSignal: true, isRequired: false, transformFunction: null }, variables: { classPropertyName: "variables", publicName: "variables", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true });
|
|
1369
1390
|
}
|
|
1370
1391
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: OlWebGLTileLayerComponent, decorators: [{
|
|
1371
1392
|
type: Component,
|
|
@@ -1373,7 +1394,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
|
|
|
1373
1394
|
selector: 'ol-webgl-tile-layer',
|
|
1374
1395
|
template: '',
|
|
1375
1396
|
}]
|
|
1376
|
-
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], tileStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "tileStyle", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], preload: [{ type: i0.Input, args: [{ isSignal: true, alias: "preload", required: false }] }] } });
|
|
1397
|
+
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: true }] }], url: [{ type: i0.Input, args: [{ isSignal: true, alias: "url", required: false }] }], attributions: [{ type: i0.Input, args: [{ isSignal: true, alias: "attributions", required: false }] }], tileStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "tileStyle", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], opacity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opacity", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], preload: [{ type: i0.Input, args: [{ isSignal: true, alias: "preload", required: false }] }], variables: [{ type: i0.Input, args: [{ isSignal: true, alias: "variables", required: false }] }] } });
|
|
1377
1398
|
|
|
1378
1399
|
// Provider functions
|
|
1379
1400
|
function withLayers() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-helpers/openlayers",
|
|
3
|
-
"version": "22.0
|
|
3
|
+
"version": "22.1.0",
|
|
4
4
|
"description": "Modern Angular wrapper for OpenLayers with modular architecture, standalone components, and hybrid template/programmatic API",
|
|
5
5
|
"homepage": "https://gaspar1992.github.io/angular-helpers/docs/openlayers",
|
|
6
6
|
"repository": {
|
|
@@ -241,10 +241,17 @@ declare class OlWebGLTileLayerComponent {
|
|
|
241
241
|
visible: _angular_core.InputSignal<boolean>;
|
|
242
242
|
/** Preload low-res tiles up to this many zoom levels */
|
|
243
243
|
preload: _angular_core.InputSignal<number>;
|
|
244
|
+
/** Style variables for dynamic expressions (e.g. `['var', 'brightness']`) */
|
|
245
|
+
variables: _angular_core.InputSignal<Record<string, string | number | boolean | number[]> | undefined>;
|
|
244
246
|
private layer;
|
|
245
247
|
constructor();
|
|
248
|
+
/**
|
|
249
|
+
* Imperatively update style variables without triggering Angular change detection.
|
|
250
|
+
* Ideal for 60FPS animations where you don't want to use the declarative [variables] input.
|
|
251
|
+
*/
|
|
252
|
+
updateVariables(vars: Record<string, string | number | boolean | number[]>): void;
|
|
246
253
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<OlWebGLTileLayerComponent, never>;
|
|
247
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<OlWebGLTileLayerComponent, "ol-webgl-tile-layer", never, { "id": { "alias": "id"; "required": true; "isSignal": true; }; "source": { "alias": "source"; "required": true; "isSignal": true; }; "url": { "alias": "url"; "required": false; "isSignal": true; }; "attributions": { "alias": "attributions"; "required": false; "isSignal": true; }; "tileStyle": { "alias": "tileStyle"; "required": false; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "opacity": { "alias": "opacity"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "preload": { "alias": "preload"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
254
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<OlWebGLTileLayerComponent, "ol-webgl-tile-layer", never, { "id": { "alias": "id"; "required": true; "isSignal": true; }; "source": { "alias": "source"; "required": true; "isSignal": true; }; "url": { "alias": "url"; "required": false; "isSignal": true; }; "attributions": { "alias": "attributions"; "required": false; "isSignal": true; }; "tileStyle": { "alias": "tileStyle"; "required": false; "isSignal": true; }; "zIndex": { "alias": "zIndex"; "required": false; "isSignal": true; }; "opacity": { "alias": "opacity"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "preload": { "alias": "preload"; "required": false; "isSignal": true; }; "variables": { "alias": "variables"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
248
255
|
}
|
|
249
256
|
|
|
250
257
|
interface LayerInfo {
|