Draws multiple evenly-spaced and non-overlapping curves in a flow field.
even_spaced_curves.Rd
Draws multiple evenly-spaced and non-overlapping curves in a flow field, using the Jobard and Lefer (1997) algorithm.
Usage
even_spaced_curves(
x_start,
y_start,
n_curves,
n_steps,
min_steps_allowed,
step_length,
d_sep,
flow_field
)
Arguments
- x_start
the x coordinate of the starting point from which the function will start to draw your curve.
- y_start
the y coordinate of the starting point from which the function will start to draw your curve.
- n_curves
the number of curves you want to draw.
- n_steps
the number of steps used to draw each curve.
- min_steps_allowed
the minimum number of steps allowed in each curve (see Details for more info).
- step_length
the length/distance taken in each step.
- d_sep
the "separation distance", i.e., the amount of distance that each curve must be from neighbouring curves.
- flow_field
a 2D matrix with double values, each double value represents an angle value.
Value
This function returns a tibble
object with 6 columns:
curve_id
: the ID of the curve.x
: the x coordinates of each point that represents the curve.y
: the y coordinates of each point that represents the curve.direction_id
: which direction that the algorithm was following when drawing the current point (0 means from left to right, 1 means from right to left).step_id
: the ID (or the number) of the current step.steps_taken
: the number of steps taken to draw the current curve.
Details
You can use this function to draw multiple curves in a flow field. Each curve will be non-overlapping and evenly-space between it's neighbors.
In essence, this function takes a single starting point (x_start
and y_start
) in the flow field,
and it starts to draw a initial curve in the flow field. After that, the function starts a loop process,
to draw n_curves - 1
curves from this initial curve. In other words, all the curves that are drawn
into the flow field are derived from this initial curve.
Is
worth noting that each starting point
represents the "middle point" of the curve, because the function draws a curve
in both directions. That is why we have the direction_id
column in the
output of this function. It indicates what direction the function was
following when drawing the current section (or "step") of the current
curve.
In each step of the way, the function will check if the current curve that is being drawn is too close to it's neighbors, by calculating it's distance to the existing curves around it. If the current curve is getting too close to a neighbor curve, then, the function will stop drawing the current curve, and will start to draw the next curve in the queue.
If the function starts to draw a new curve, but the starting point of this new curve is already too close to other existing curves, then, the function completely drops this curve (i.e. it "gives up" on drawing this curve), and jumps to the next curve in the queue.
Also, if the function draws a new curve, but this curve have less than
min_allowed_steps
steps, then, this curve is also completely dropped.
This avoids getting a high number of curves that are too short.
In other words, it is not guaranteed that this function will draw exactly n_curves
curves
into the field, because, it might not have enough space for n_curves
curves, considering your current settings.
So, the function
will attempt to draw as many curves as possible. As long as they are not overlapping
each other, and they are not too close to other neighbouring curves, the function will
continue to draw curves into the field.
For more details about how the algorithm works, check: https://pedro-faria.netlify.app/posts/2024/2024-02-19-flow-even/en/
References
Jobard, Bruno, and Wilfrid Lefer. 1997. “Creating Evenly-Spaced Streamlines of Arbitrary Density.” In Visualization in Scientific Computing ’97, edited by Wilfrid Lefer and Michel Grave, 43–55. Vienna: Springer Vienna.
Examples
library(ambient)
set.seed(50)
flow_field <- noise_perlin(c(240, 240))
# The coordinates x = 45 and y = 24 are used as the starting point:
curves <- even_spaced_curves(
45, 24,
100,
30,
5,
0.01*240,
0.5,
flow_field
)