geostyler-openlayers-parser
Version:
GeoStyler Style Parser implementation for OpenLayers styles
205 lines (204 loc) • 7.02 kB
JavaScript
import T from "ol/geom/LineString.js";
class g {
/**
* Check if the given style contains a graphic stroke in any of its rules.
* @param style The style to check.
* @returns True if the style contains a graphic stroke, false otherwise.
*/
static containsGraphicStroke(t) {
return t.rules.some(
(n) => n.symbolizers?.some(
(s) => s.kind === "Line" && s.graphicStroke
)
);
}
/**
* Get the rotation in degrees for a line segment defined by its start and
* end coordinates.
* @param start The start coordinate of the line segment.
* @param end The end coordinate of the line segment.
* @returns The rotation in degrees.
*/
static getSegmentRotation(t, n) {
const s = n[0] - t[0], e = n[1] - t[1], i = Math.atan2(e, s), o = 180 / Math.PI;
return -i * o;
}
/**
* Get the rotations in degrees for each segment of a LineString geometry.
* @param geom The LineString geometry
* @returns An array of rotations in degrees for each segment
*/
static getSegmentRotations(t) {
const n = [];
return t.forEachSegment((s, e) => {
const i = g.getSegmentRotation(s, e);
n.push(i);
}), n;
}
/**
* Get the total size of a dash pattern in map units.
* @param dashArray The dash array in pixels.
* @param resolution The map resolution.
* @returns The total size of the dash pattern in map units.
*/
static getPatternSize(t, n) {
const s = t.reduce((i, o) => i + o, 0);
return n * s;
}
/**
* Get the normalized fractions along the line where each segment ends.
* @param geom The LineString geometry
* @returns An array of normalized fractions
*/
static getSegmentFractions(t) {
const n = [], s = t.getLength();
let e = 0;
return t.forEachSegment((i, o) => {
const u = new T([i, o]).getLength() / s;
e += u, n.push(e);
}), n;
}
/**
* Get the dash array as fractions of the total line length.
* @param dashArray The dash array in pixels.
* @param resolution The map resolution.
* @param lineLength The total length of the line in map units.
* @returns An array of fractions representing the dash lengths relative
* to the line length.
*/
static getDashAsFractions(t, n, s) {
const e = (i) => i * n / s;
return t.map((i) => e(i));
}
/**
* Get the fractions along the line where ticks should be placed, considering
* the symbol size, resolution, and optional dash pattern.
* @param geom The LineString geometry
* @param symbolSize The size of the symbol in pixels
* @param resolution The map resolution
* @param dashArray Optional dash array
* @param dashOffset Optional dash offset
* @returns An array of fractions along the line where ticks should be placed
*/
static getTickFractions(t, n, s, e, i) {
if (n <= 0)
return [];
const o = t.getLength(), r = n * s / o, c = (i ? i * s : 0) / o;
return e && e.length > 0 ? g.getTickFractionsWithDash(
e,
s,
o,
r,
c
) : g.getTickFractionsWithoutDash(
r
);
}
/**
* Helper method to add a tick at the given fraction if it's within valid bounds.
* @param ticks Array to add the tick to
* @param currentFraction The fraction to potentially add
* @returns True if the tick was added and we should continue, false if we've exceeded bounds
*/
static tryAddTick(t, n, s, e) {
return e > 1 ? !1 : (s >= 0 && t.push(n), !0);
}
/**
* Get tick fractions for a line without a dash pattern.
* @param symbolSizeFraction The symbol size as a fraction of the line length
* @param offsetFraction The offset as a fraction of the line length
* @returns An array of fractions along the line where ticks should be placed
*/
static getTickFractionsWithoutDash(t) {
const n = [], s = t / 2;
let e = s;
for (; ; ) {
const i = e + t, o = e - s, r = e + s, c = g.tryAddTick(n, e, o, r);
if (e = i, !c)
break;
}
return n;
}
/**
* Get tick fractions for a line with a dash pattern.
* @param dashArray The dash array in pixels
* @param resolution The map resolution
* @param lineLength The total length of the line in map units
* @param symbolSizeFraction The symbol size as a fraction of the line length
* @param offsetFraction The offset as a fraction of the line length
* @returns An array of fractions along the line where ticks should be placed
*/
static getTickFractionsWithDash(t, n, s, e, i) {
const o = t.length % 2 === 0 ? t : [...t, ...t], r = g.getDashAsFractions(o, n, s), c = e / 2, u = [];
let a = i + c, l = 0;
for (; a <= 1; ) {
const S = l % 2 === 1, m = r[l];
if (S)
a += m;
else {
const h = m / e, f = Math.floor(h);
for (let p = 0; p < f; p++) {
const F = a - c, L = a + c, R = a + e, k = g.tryAddTick(u, a, F, L);
if (a = R, !k)
return u;
}
const d = h % 1 * e;
a += d;
}
l = (l + 1) % r.length;
}
return u;
}
/**
* Process a single LineString geometry to generate graphic stroke styles.
*
* @param geom The LineString geometry to process
* @param symbolSize The size of the symbol in pixels
* @param resolution The map resolution
* @param dashArray Optional dash array for dashed patterns
* @param evaluatedDashOffset Evaluated dash offset value
* @param evaluatedSymbolRotation Evaluated symbol rotation in degrees
* @param graphicStroke The graphic stroke point symbolizer
* @param symbolizerGenerator Function to generate OL styles from a modified graphic stroke
* @param PointConstructor Constructor for creating OL Point geometries
* @returns Array of OL styles for the graphic stroke
*/
static processLineStringGraphicStroke(t, n, s, e, i, o, r, c, u) {
const a = g.getTickFractions(
t,
n,
s,
e,
i
), l = g.getSegmentFractions(t), m = g.getSegmentRotations(t).map((h) => {
const f = h + o, d = structuredClone(r);
return d.rotate = f, c(d);
});
return a.map((h) => {
const f = t.getCoordinateAt(h), d = new u(f), p = l.findIndex(
(L) => h <= L
), F = m[p].clone();
return F.setGeometry(d), F;
});
}
static getLineStringsFromGeometry(t, n) {
if (!t)
throw new Error(
"GraphicStroke can only be applied to features with geometries"
);
if (t instanceof n.LineString)
return [t];
if (t instanceof n.MultiLineString)
return t.getLineStrings();
if (t instanceof n.Polygon)
return t.getLinearRings().map((e) => new n.LineString(e.getCoordinates()));
if (t instanceof n.MultiPolygon)
return t.getPolygons().flatMap((e) => e.getLinearRings().map((o) => new n.LineString(o.getCoordinates())));
throw new Error(
"GraphicStroke can only be applied to (Multi-)LineString or (Multi-)Polygon geometries"
);
}
}
export {
g as default
};