Thank you very much for your explanation. This makes a lot more sense now. So now I am trying to apply this functionality to an actual problem of mine seen below;
Note that originally this data was scattered around (0,0), so the range was from -1 to 1, but the insert function would not work, so I had to offset the data by 2 on both x and y. This is fine since I am just doing neighbour search anyways.
I have checked again and it seems like the code always produces a row and column too much of gridc, so I simply added “-1” as such;
gridc = [Set{Int}() for x=1:1:3-1, y=1:1:3-1];
And gridc return 2x2 now, which I expect, since I basically for the above example define squares from 1 to 2 and 2 to 3 in both axis, so 2x2. I also confirm it works by noting that each square has same number of particles, so that is great!
So now comes my final difficulty for now.
I want to use this neighbour search for an SPH (Smoothed Particle Hydrodynamics), which means that I would prefer to use much smaller squares, for example something like;
gridc = [Set{Int}() for x=1:0.05:3-1, y=1:0.05:3-1];
But doing this does not produce the correct results anymore, which I believe is due to “trunc” not working as expected, i.e. as you described before.
If I try to scale my data with the inverse, i.e. 1/0.05 = 20, then I start getting errors like;
BoundsError: attempt to access 21×21 Array{Set{Int64},2} at index [20, 38]
getindex at array.jl:729 [inlined]
#293 at NL.jl:16 [inlined]
foreach(::getfield(Main, Symbol("##293#294")){Array{Set{Int64},2}}, ::Array{NamedTuple{(:x, :y, :n),Tuple{Float64,Float64,Int64}},1}) at abstractarray.jl:1920
top-level scope at NL.jl:20
So I am a bit at a loss at what to do. Do you think it is possible to keep using your approach, since it is really neat?
The code I am using currently (without scaling by 20 on x and y) is here:
using Plots
using DelimitedFiles
#Define equal sized square grids
gridc = [Set{Int}() for x=1:0.05:3-1, y=1:0.05:3-1];
#Generate arbitrary 2D data
dataini = readdlm("CircleGridUniform.txt", '\t', Float64, '\n')
data = [(x=2+dataini[n,1], y=2+dataini[n,2], n=n) for n in 1:size(dataini)[1]];
#data = [(x=1+4*rand(), y=1+4*rand(), n=n) for n in 1:30];
# Define a function "insert", but I have a hard time understanding what it does
# Could you try explaining this step by step?
# I assume p is basically "data", and then we check for each square what "data"
# lies in it
insert(gridc) = p -> push!(gridc[trunc(Int, p.x), trunc(Int, p.y)], p.n);
# "foreach" syntax is a bit new for me, I get confused since we only have one
# variable "data"?
foreach(insert(gridc), data)
# We will continue onward using the GR backend
gr()
x = [x[1] for x in data]
y = [y[2] for y in data]
#series_annotations = text.(1:length(x), :bottom)
plot(x, y, seriestype = :scatter, title = "My Scatter Plot",aspect_ratio=:equal)
And the datafile is too big to copy and paste here, but using;
data = [(x=1+4*rand(), y=1+4*rand(), n=n) for n in 1:10000];
One can see the same problem I experience, with gridc being filled incorrectly due to the trunc I suppose.
Kind regards