Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add voronoi grid #30

Closed
virgile-baudrot opened this issue Feb 18, 2021 · 13 comments
Closed

Add voronoi grid #30

virgile-baudrot opened this issue Feb 18, 2021 · 13 comments
Assignees
Labels
enhancement New feature or request

Comments

@virgile-baudrot
Copy link
Contributor

The following lines provide a simple way to make grid landscape using voronoi tesselation. It's working but need to be reframe to fit package requirement.

Computing the voronoi is done using VoronoiCells.jl and then the rasterization is by using ArchGDAL.jl.

Digging into both dependencies, I should be able to make things clearer.

using VoronoiCells
using GeometryBasics
using ArchGDAL
using Distributions
using Plots

const VC=VoronoiCells
const GB=GeometryBasics
const AG=ArchGDAL
const DB=Distributions

I created 3 functions. The 2 first create the set of polygones

function voronoitess(min_x, max_x, min_y, max_y, nCell::Int)
    rect = VC.Rectangle(GB.Point2(min_x, min_y), GB.Point2(max_x, max_y))
    points = [GB.Point2(rand(DB.Uniform(min_x, max_x)), rand(DB.Uniform(min_y, max_y))) for _ in 1:nCell]
    return (tess=VC.voronoicells(points, rect),rect,points)
end

vortess = voronoitess(0, 1, 0, 1, 100)

function polygonset(tess)
    tc = tess.tess.Cells
    poly = [ArchGDAL.createpolygon([(tc[i][j][1], tc[i][j][2]) for j in vcat(1:length(tc[i]),1)])
    for i in 1:length(tc)]
    return (poly, tess.rect, tess.points)
end

polyset = polygonset(vortess)
plot(polyset[1])

image

And the last is making a rasterization providing some features:

# Create a grid over the map
function rasterize(polygonset, nrow, ncol,feature)
    w = rect.UpperRight[1] - rect.LowerLeft[1]
    h = rect.UpperRight[2] - rect.LowerLeft[2]
    gridcell_x=w/ncol
    gridcell_y=h/nrow
    gridX=(rect.LowerLeft[1]:gridcell_x:(rect.UpperRight[1]-gridcell_x)) .+ (gridcell_x/2)
    gridY=(rect.LowerLeft[2]:gridcell_y:(rect.UpperRight[2]-gridcell_y)) .+ (gridcell_y/2)

    gridX_seq=repeat(gridX,inner=nrow)
    gridY_seq=repeat(gridY,outer=ncol)

    gridCell = fill(0,nrow,ncol)
    for j in 1:length(gridCell)
        for i in 1:length(polygonset[1])
            if AG.contains(polygonset[1][i],
                AG.createpoint((gridX_seq[j], gridY_seq[j]))
            ) 
            gridCell[j] = feature[i]
            end        
        end
    end
    return gridCell
end

feature = rand(0:3,length(polyset[1]))
nrow, ncol = 200, 10

gridCell = rasterize(polyset, nrow, ncol, feature)
Plots.heatmap(gridCell)

image

@virgile-baudrot virgile-baudrot added the enhancement New feature or request label Feb 18, 2021
@mkborregaard
Copy link
Member

So is this a suggestion to add the functionality or to put this in the docs?
I wouldn't be keen to add an ArchGDAL dep to this repo. VoroniCells might be OK (it adds Colors, GeometryBasics, VoronoDelaunay, GeometricalPredicates and RecipesBase).

@virgile-baudrot
Copy link
Contributor Author

Well I don't know what you can do with that 😄 . Just that voronoi tesselation would be nice to have so I propose to work on it if it's something you think is relevant.
Basically, Voronoi is only made from GeometryBasics and VoronoDelaunay, so I just need to remove dependency with ArchGDAL, finding a better algorithm to rasterize.

@rafaqz
Copy link
Member

rafaqz commented Feb 18, 2021

@virgile-baudrot you see my dependency concerns are widespread in the Julia world ;)

But this would be great, but without ArchGDAL.

@mkborregaard
Copy link
Member

Just for clarity - isn't rasterized voronoi just nearest-neighbor from a grid to the set of points? We have nearestneighbors.jl as a dep already.

@mkborregaard
Copy link
Member

mkborregaard commented Feb 18, 2021

E.g.

using NearestNeighbors
pts = rand(1.:1000, 2, 30)
tr = KDTree(pts)
mat = [knn(tr, [i, j], 1)[1][1] for i in 1:1000, j in 1:1000]

The heatmap:
Screenshot 2021-02-19 at 00 55 02

@tpoisot
Copy link
Contributor

tpoisot commented Feb 19, 2021

I think it's a good improvement if we don't need ArchGDAL - I think @mkborregaard suggestion makes sense!

@tpoisot
Copy link
Contributor

tpoisot commented Feb 19, 2021

Wait, so is it NearestNeighborElement? I've added an option to set various values of k, but for k=1, this is a Voronoi tessellation?

@mkborregaard
Copy link
Member

I was wondering if it wasn't just that yes. But couldn't tell from the code last night - I was heading home late on the train and was beer coding 😅

@mkborregaard
Copy link
Member

But voronoi is just a vector format nearest neighbor yes

@virgile-baudrot
Copy link
Contributor Author

Oh great. I didn't know that. So fantastic if it's already there!

@tpoisot
Copy link
Contributor

tpoisot commented Feb 19, 2021

Let's be explicit and add a VoronoiGrid type or something, as a thin wrapper on NearestNeighborElement? @virgile-baudrot do you want to do this? Happy to give feedback.

@virgile-baudrot
Copy link
Contributor Author

ok, I'll try to implement it and PR

virgile-baudrot added a commit to virgile-baudrot/NeutralLandscapes.jl that referenced this issue Mar 2, 2021
@virgile-baudrot virgile-baudrot mentioned this issue Mar 2, 2021
11 tasks
mkborregaard added a commit that referenced this issue Mar 2, 2021
@tpoisot
Copy link
Contributor

tpoisot commented Mar 3, 2021

This was closed by #46

@tpoisot tpoisot closed this as completed Mar 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants