///|
pub(all) enum Direction {
Warp
Weft
} derive(Eq, Debug, ToJson, FromJson)
///|
/// Thread and start are zero-based drawdown coordinates.
pub(all) struct FloatRun {
direction : Direction
thread : Int
start : Int
length : Int
} derive(Eq, Debug, ToJson, FromJson)
///|
fn linear_runs(
bits : Array[Bool],
direction : Direction,
thread : Int,
min_length : Int,
) -> Array[FloatRun] {
let out = []
let mut start = 0
while start < bits.length() {
if !bits[start] {
start = start + 1
continue
}
let mut end = start + 1
while end < bits.length() && bits[end] {
end = end + 1
}
if end - start >= min_length {
out.push({ direction, thread, start, length: end - start, })
}
start = end
}
out
}
///|
/// Front-face warp runs vertically, weft runs horizontally. Back swaps visibility.
pub fn Draft::floats(
self : Draft,
min_length : Int,
back? : Bool = false,
) -> Result[Array[FloatRun], String] {
if min_length < 1 {
return Err("weave.float-limit")
}
let cells = self.drawdown()
let out = []
for x = 0; x < self.width(); x = x + 1 {
let bits = cells.map(fn(row) { row[x] != back })
for run in linear_runs(bits, Warp, x, min_length) {
out.push(run)
}
}
for y = 0; y < self.height(); y = y + 1 {
let bits = cells[y].map(fn(b) { b == back })
for run in linear_runs(bits, Weft, y, min_length) {
out.push(run)
}
}
Ok(out)
}