Stipples using voronoi plot

Hi, I’m new to Julia and I’m trying to create a stippling based on voronoi diagrams. I’m using DelaunayTriangulation package. I’m confused on how to iterate for each point in the time series and generate a voronoi and extract its centroid positions and display the plot.

Does anyone have any insights, that would help me get the centroid points of each box defined at the graph.

Welcome to Julia Discourse! :wave:

It would help, if you could provide what you tried so far and the first steps in code as a small example, see also

1 Like

Hi, Thank you for responding.

Here’s a snippet off my code:

using GLMakie

using DelaunayTriangulation

using GeometryBasics

using JSON

using StableRNGs

using Plots

data = JsonReader.read_json_data("data.json")

mean_data = data["mean"]

std_data = data["std"]

series_index = 1

axis, fig = PlotConfig.configure_plot("Uncertain time series", "years", "value")

mean_data_float32 = Float32.(mean_data[series_index])

std_data_float32 = Float32.(std_data[series_index])

time_range_float32 = Float32.(1:length(mean_data[series_index]))

mean_color = GLMakie.RGB(rand(), rand(), rand())

lines!(axis, time_range_float32, mean_data_float32, color = GLMakie.RGBA(mean_color, 0.8), label = "Mean")

# band!(axis, time_range_float32, mean_data_float32 .- std_data_float32, mean_data_float32 .+ std_data_float32, color = GLMakie.RGBA(mean_color, 0.6), label = "Error")

function boundary_points(x, y_lower, y_upper)

xs = Float32[]

ys = Float32[]

push!(xs, x - 0.5)

push!(ys, y_lower)

push!(xs, x + 0.5)

push!(ys, y_lower)

push!(xs, x + 0.5)

push!(ys, y_upper)

push!(xs, x - 0.5)

push!(ys, y_upper)

return xs, ys


rng = StableRNG(2)

all_xs = Float32[]

all_ys = Float32[]

for j in 1:20

x = time_range_float32[j]

y_mean = mean_data_float32[j]

y_lower = y_mean - std_data_float32[j]

y_upper = y_mean + std_data_float32[j]

num_points = max(3, Int(ceil(std_data_float32[j])))

xs, ys = boundary_points(x, y_lower, y_upper)

points = [(xs[k], ys[k]) for k in eachindex(xs, ys)]

tri = triangulate(points; rng)

refine!(tri; max_area = 1e-3, min_angle = 29.871, rng)

vorn = voronoi(tri)

smooth_vorn = centroidal_smooth(vorn; maxiters = 2500)

voronoiplot!(axis, smooth_vorn, show_generators = true, markersize = 4)



Here i’m getting the boundaries of the error and constructing a voronoi. But i need them only to get the dots placement, Also it takes a lot of time to compute as well. Can you please suggest better ways to do.

Your code might be easier to read if you out them into a code block as follows.

# Your code here.
  1. Could you explain why you are loading both Plots.jl and GLMakie.jl? I think you only need GLMakie.jl.
  2. It might help to put mode of your code into a function, especially the for loop and loop comprehension.
  3. If provide the type to the first argument of ceil, it will directly return that type without a need for casting.
num_points = max(3, ceil(Int, std_data_float32[j]))
1 Like

Sorry that was something i was debugging on, yes you’re right I need just one of them. I have formatted the code as well. I want to get the positions of the centroids of the voronoi and plot them in a scatter plot

Is this what you want?

using DelaunayTriangulation 
using CairoMakie
using StableRNGs
rng = StableRNG(123) 
points = tuple.(rand(rng, 50), rand(rng, 50))
tri = triangulate(points; rng)
vorn = voronoi(tri; rng)
svorn = centroidal_smooth(vorn; rng)
centroids = zeros(2, num_polygons(svorn))
for (j, i) in enumerate(each_polygon_index(svorn))
    centroids[:, j] .= DelaunayTriangulation.get_centroid(svorn, i)


Regarding speed… it should be pretty fast, but maybe I’ve been a bit inefficient in some areas. With Float32 it’s possible you’re hitting some type instabilities since most of the testing is for Float64 (I’ve tried to test for Float32 where possible, but if I had to guess it’d be why).

HI, Yes I want to get the centroid positions. But I need to get the centroids for each positions in the error band area (the loop i have in the code for j in 1: 20, how can i store all the values and plot it?

You should be able to apply a similar idea as in the code I’ve given. DelaunayTriangulation.get_centroid(smooth_vorn, i) gives you the centroid for the ith polygon. You don’t need to use voronoiplot! to get these centroids.

So I imagine with your code just stop at smooth_vorn, use the loop I’ve shown you for computing the centroids of each polygon, and store it into some array like I’ve done. You can then plot via scatter as shown.

I will try this out. Thank you very much!! This really helps

Is this basically what the boundary_points function and the array comprehension are supposed to do?

julia> function boundary_points(x, y_lower, y_upper)
           xs = Float32[x-0.5, x+0.5, x+0.5, x-0.5]
           ys = Float32[y_lower, y_lower, y_upper, y_upper]
           return collect(zip(xs, ys))
boundary_points (generic function with 1 method)

julia> boundary_points(2, 1, 3)
4-element Vector{Tuple{Float32, Float32}}:
 (1.5, 1.0)
 (2.5, 1.0)
 (2.5, 3.0)
 (1.5, 3.0)

It seems to me that then that points is just four points around a rectangle. Is it for those four points which you then triangulate?

Yes these points are to create a boundary for the triangulation and inside that voronoi should be constructed