///|
priv struct StreamplotSource {
view : @render.StreamplotHitView
cursor : @ref.Ref[Int32]
}
///|
priv struct StreamplotIntent {
artist : Artist
source : StreamplotSource
}
///|
fn Axes::push_streamplot_owned(
self : Axes,
artist : Artist,
view : @render.StreamplotHitView,
) -> Unit {
self.push_artist(artist)
let source : StreamplotSource = { view, cursor: @ref.Ref(0), }
let records = self.state.val.artist_hits
records[records.length() - 1].streamplot = Some(source)
records[records.length() - 1].series = view.series()
self.state.val.streamplot_intents[self.state.val.artists.length() - 1] = {
artist,
source,
}
}
///|
fn Axes::push_streamplot_arrow(
self : Axes,
artist : Artist,
series : String,
) -> Unit {
let points = match artist {
Line(points, _) | Polygon(points, _) => points
_ => []
}
self.push_streamplot_owned(
artist,
@render.streamplot_static_hit(points, series),
)
}
///|
fn streamplot_sample_datum(
xs : Array[Double],
ys : Array[Double],
us : Array[Array[Double]],
vs : Array[Array[Double]],
point : @core.Point,
edge : Int32,
seed_index : Int32,
color_value : Double?,
) -> @render.StreamplotDatum? {
if !point.is_finite() {
return None
}
guard stream_sample(xs, ys, us, vs, point.x(), point.y()) is Some((u, v)) else {
return None
}
if !stream_finite(u) || !stream_finite(v) {
return None
}
Some(
@render.streamplot_datum(
edge,
point,
@drawing.streamplot_info(seed_index, u, v, color_value~),
),
)
}
///|
fn AxesData::remove_streamplot_slot(self : AxesData, removed : Int32) -> Unit {
if self.streamplot_intents.is_empty() {
return
}
let next = Map([])
for slot, intent in self.streamplot_intents {
if slot != removed {
next[if slot > removed { slot - 1 } else { slot }] = intent
}
}
self.streamplot_intents.clear()
for slot, intent in next {
self.streamplot_intents[slot] = intent
}
}