benjann / geoplot

Stata module to draw maps
MIT License
33 stars 3 forks source link

Request for Buffers #11

Open fahad-mirza opened 1 year ago

fahad-mirza commented 1 year ago

Hi Ben. Thank you so much for doing this and also a big fan of your work. Hope to learn coding from you as well some day.

I just want request if a feature of making Buffers can be included in this awesome package you are developing?

Another followup request to possible consider marking observations that fall within the buffer with a variable as well?

Will be nice to have this feature.

benjann commented 1 year ago

I think you can use layertype symbol to create buffers. Here's an example. First load some data:

local url http://fmwww.bc.edu/repec/bocode/i/
local url shp/it/
geoframe create regions `url'Italy-RegionsData.dta, id(id) coord(xcoord ycoord) ///
         shpfile(`url'Italy-RegionsCoordinates.dta)
geoframe create capitals `url'Italy-Capitals.dta, coord(xcoord ycoord)

No I use symbol to draw a buffer with radius 100'000 km around Rome:

geoplot (area regions) ///
    (symbol capitals if city=="Roma", size(100000) color(Green%50))
image

Use symboli to create buffers around arbitrary coordinates. The following command would create the same graph above, as these are the coordinates of Rome.

geoplot (area regions) ///
    (symboli 4644022.5 788894.1, size(100000) color(Green%50))

For the second question, geoframe spjoin may be useful. However you would first have to create a frame that contains the coordinates of the buffer. I'll try to come up with an example.

benjann commented 1 year ago

In principle, here is how this could be done:

// get data
local url http://fmwww.bc.edu/repec/bocode/i/
local url shp/it/
geoframe create regions  `url'Italy-RegionsData.dta, id(id) coord(xcoord ycoord) ///
                 shpfile(`url'Italy-RegionsCoordinates.dta)
geoframe create capitals `url'Italy-Capitals.dta, coord(xcoord ycoord)
// create buffer
geoplot (symbol capitals if city=="Roma", size(100000)), ///
    nodraw frame(buffer)
geoframe create, id(LAYER) coordinates(X Y)
// spatial join
frame change capitals
geoframe spjoin buffer NearRome, noset
replace NearRome = 0 if NearRome>=.
// final graph
geoplot (area regions) (symbol capitals if city=="Roma", size(100000)) ///
    (point capitals NearRome, discrete label(1 = "Nope" 2 = "Yes, near Rome" ))

Graph

However, two remarks:

fahad-mirza commented 1 year ago

This is great! Thank you for doing this and looking forward to this update in geoplot!

fahad-mirza commented 1 year ago

Will this also be possible if we were to create a buffer around a line or polygon? For example lakes and roads?

benjann commented 1 year ago

Hm, yes, I guess. Not sure though what it would mean in case of a polygon, just add a margin of fixed width around the polygon? This may be a bit tricky, one would have to determine the outer bound of the margin in case of nonconvex shapes or if a buffer is to be constructed around multiple polygons. Or add a convex hull with some padding?

benjann commented 1 year ago

In the newest update there is now a command called geoframe symbol that can be used to generate symbol shapes directly, without taking the detour through geoplot, nodraw. Example:

// get data
local url http://fmwww.bc.edu/repec/bocode/i/
geoframe create regions  `url'Italy-RegionsData.dta, id(id) coord(xcoord ycoord) ///
    shpfile(Italy-RegionsCoordinates.dta)
geoframe create capitals `url'Italy-Capitals.dta, coord(xcoord ycoord)
// create buffer
geoframe symbol Rome_buffer if city=="Roma", size(100000)
// spatial join
geoframe spjoin Rome_buffer NearRome, noset
replace NearRome = NearRome<.
// final graph
geoplot (area regions) (area Rome_buffer) ///
    (point capitals i.NearRome, label(0 = "Nope" 1 = "Yes, near Rome" ))
Graph

Creating buffers for lines and polygons seems very complicated and I did not yet find any hint on an easy to implement algorithm. So I cannot make any promises.

fahad-mirza commented 1 year ago

This is really nice! I am not well versed in gis but maybe these documents might help with finding a n easy solution

https://www.tandfonline.com/doi/pdf/10.1080/10095020.2012.747643

https://en.m.wikipedia.org/wiki/Minkowski_addition

https://algorist.com/problems/Minkowski_Sum.html

benjann commented 1 year ago

Thanks. Well, easy it doesn't seem... :)