Skip to content

Commit c49bd40

Browse files
committed
feat: station order reversal
1 parent 1d384ad commit c49bd40

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

docs/schemas.typ

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
sections: z.array(section),
8181
segments: z.array(segment),
8282
stations: z.array(station),
83+
ordered-stations: z.array(z.string()),
8384
station-indexer: z.mapping(z.integer(), key-name: "station-id"),
8485
optional: z.boolean(),
8586
features: z.mapping(z.array(z.string())),

src/elem/line.typ

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
/// - d (auto, str): Cardinal/diagonal direction from previous pin.
1414
///
1515
/// - end (bool): Marks end of a section, allowing disconnected branches.
16+
/// - reverse (auto, bool): Whether the order of subsequent stations should be reversed.
17+
/// - reverse-before (bool): Whether to reverse the order of all previous stations.
1618
///
1719
/// - cfg (str, none): Enabling conditions for subsequent segments.
1820
/// - cfg-not (str, none): Disabling conditions for subsequent segments.
@@ -32,6 +34,7 @@
3234
d: auto,
3335
end: false,
3436
reverse: auto,
37+
reverse-before: false,
3538
cfg: auto,
3639
cfg-not: auto,
3740
layer: auto,
@@ -42,7 +45,8 @@
4245
(
4346
raw-pos: (x: x, y: y, dx: dx, dy: dy, d: d),
4447
end: end,
45-
reverse: reverse,
48+
reversed: reverse,
49+
reverse-before: reverse-before,
4650
cfg: cfg,
4751
cfg-not: cfg-not,
4852
layer: layer,
@@ -56,6 +60,9 @@
5660
///
5761
/// - target (auto, str): The target station id where the loop ends.
5862
///
63+
/// - reverse (auto, bool): Whether the order of subsequent stations should be reversed.
64+
/// - reverse-before (bool): Whether to reverse the order of all previous stations.
65+
///
5966
/// - cfg (str, none): Enabling conditions for subsequent segments.
6067
/// - cfg-not (str, none): Disabling conditions for subsequent segments.
6168
///
@@ -66,6 +73,8 @@
6673
/// - ..metadata (arguments): Additional attributes of subsequent segments as named arguments.
6774
#let loop(
6875
target: auto,
76+
reverse: auto,
77+
reverse-before: false,
6978
cfg: auto,
7079
cfg-not: auto,
7180
layer: auto,
@@ -76,6 +85,8 @@
7685
(
7786
loop-target: target,
7887
end: true,
88+
reversed: reverse,
89+
reverse-before: reverse-before,
7990
cfg: cfg,
8091
cfg-not: cfg-not,
8192
layer: layer,
@@ -100,6 +111,7 @@
100111

101112
let last-pin = points.at(0) // resolved point
102113
let cur-attrs = (
114+
reversed: if last-pin.reversed == auto { false } else { last-pin.reversed },
103115
cfg: if last-pin.cfg == auto { none } else { last-pin.cfg },
104116
cfg-not: if last-pin.cfg-not == auto { none } else { last-pin.cfg-not },
105117
layer: if last-pin.layer == auto { 0 } else { last-pin.layer },
@@ -111,13 +123,15 @@
111123
let section-points = ()
112124
let segments = ()
113125
let stations = ()
126+
let ordered-stations = ()
114127

115128
let (sx, sy) = (last-pin.raw-pos.x, last-pin.raw-pos.y)
116129
let start-pos = (sx, sy)
117130
section-points.push(start-pos)
118131
let start-station-index = 0
132+
let reverse-first = if cur-attrs.reversed { 0 } else { -1 }
119133

120-
let seg-first = 1 // index of control point
134+
let seg-first = 1 // Current range of stations in `points`: [`seg-first`, `seg-last`)
121135
while seg-first < points.len() {
122136
let seg-last = seg-first
123137
while "id" in points.at(seg-last) {
@@ -171,6 +185,7 @@
171185
sta.line = line-id
172186
sta.pos = if x == auto or y == auto { auto } else { (x, y) } // mark pos auto, handle it later
173187
stations.push(sta)
188+
ordered-stations.push(sta.id)
174189
}
175190
if "loop-target" in cur-pin {
176191
let i = start-station-index
@@ -189,6 +204,7 @@
189204

190205
// update current pin and cfg
191206
let prev-attrs = cur-attrs
207+
if cur-pin.reversed != auto { cur-attrs.reversed = cur-pin.reversed }
192208
if cur-pin.cfg != auto { cur-attrs.cfg = cur-pin.cfg }
193209
if cur-pin.cfg-not != auto { cur-attrs.cfg-not = cur-pin.cfg-not }
194210
if cur-pin.layer != auto { cur-attrs.cfg-not = cur-pin.layer }
@@ -210,13 +226,30 @@
210226
if last-pin.end or cur-attrs != prev-attrs {
211227
sections.push((points: section-points, ..prev-attrs))
212228
section-points = (seg.end,)
229+
// handle reversal
230+
if not cur-attrs.reversed {
231+
if prev-attrs.reversed {
232+
ordered-stations = ordered-stations.slice(0, reverse-first) + ordered-stations.slice(reverse-first).rev()
233+
}
234+
reverse-first = ordered-stations.len()
235+
}
236+
// reverse all stations before
237+
if last-pin.reverse-before {
238+
ordered-stations = ordered-stations.rev()
239+
}
213240
}
214241

215242
last-pin = cur-pin
216243
sx = tx
217244
sy = ty
218245
seg-first = seg-last + 1
219246
}
247+
if cur-attrs.reversed {
248+
ordered-stations = ordered-stations.slice(0, reverse-first) + ordered-stations.slice(reverse-first).rev()
249+
}
250+
if last-pin.reverse-before {
251+
ordered-stations = ordered-stations.rev()
252+
}
220253
if section-points.len() > 0 {
221254
sections.push((points: section-points, ..cur-attrs))
222255
}
@@ -231,7 +264,7 @@
231264
}
232265
}
233266

234-
return (stations: stations, sections: sections, segments: segments)
267+
return (stations: stations, sections: sections, segments: segments, ordered-stations: ordered-stations)
235268
}
236269

237270
/// Constructor of metro line.
@@ -257,7 +290,7 @@
257290
stroke: auto,
258291
..points,
259292
) = {
260-
let (stations, sections, segments) = _extract-stations(points.pos(), id)
293+
let (stations, sections, segments, ordered-stations) = _extract-stations(points.pos(), id)
261294
let station-indexer = stations.enumerate().map(((i, sta)) => (sta.id, i)).to-dict()
262295
let data = (
263296
id: id,
@@ -266,6 +299,7 @@
266299
sections: sections,
267300
segments: segments,
268301
stations: stations,
302+
ordered-stations: ordered-stations,
269303
station-indexer: station-indexer,
270304
optional: optional,
271305
features: features,

0 commit comments

Comments
 (0)