-
Notifications
You must be signed in to change notification settings - Fork 25
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
code to allow/fix coastlines with shifted reference longitude #128
Conversation
Could I get a review on this PR? @asinghvi17 maybe based on #118 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice PR! I'm no expert on GeoMakie / Makie at all, but thought I'd leave some suggestions since the PR addresses some issues I had some time back.
src/utils.jl
Outdated
|
||
function split(tmp::LineString,lon0=-160.0) | ||
lon0<0.0 ? lon1=lon0+180 : lon1=lon0-180 | ||
np=length(tmp) | ||
tmp2=fill(0,np) | ||
for p in 1:np | ||
tmp1=tmp[p] | ||
tmp2[p]=maximum( [(tmp1[1][1]<=lon1)+2*(tmp1[2][1]>=lon1) , (tmp1[2][1]<=lon1)+2*(tmp1[1][1]>=lon1)] ) | ||
end | ||
if sum(tmp2.==3)==0 | ||
[tmp] | ||
else | ||
jj=[0;findall(tmp2.==3)...;np+1] | ||
[LineString(tmp[jj[ii]+1:jj[ii+1]-1]) for ii in 1:length(jj)-1] | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be improved syntactically (if I understand your code correctly), by:
function split(tmp::LineString,lon0=-160.0) | |
lon0<0.0 ? lon1=lon0+180 : lon1=lon0-180 | |
np=length(tmp) | |
tmp2=fill(0,np) | |
for p in 1:np | |
tmp1=tmp[p] | |
tmp2[p]=maximum( [(tmp1[1][1]<=lon1)+2*(tmp1[2][1]>=lon1) , (tmp1[2][1]<=lon1)+2*(tmp1[1][1]>=lon1)] ) | |
end | |
if sum(tmp2.==3)==0 | |
[tmp] | |
else | |
jj=[0;findall(tmp2.==3)...;np+1] | |
[LineString(tmp[jj[ii]+1:jj[ii+1]-1]) for ii in 1:length(jj)-1] | |
end | |
end | |
getlon(p::GeometryBasics.Point) = p[1] | |
function split(tmp::LineString,lon0=-160.0) | |
lon1 = lon0 + (lon0 < 0 ? 180 : -180) | |
linenodes = GeometryBasics.coordinates(tmp) # get coordinates of line nodes | |
# Find nodes that are on either side of lon0 | |
cond = getlon.(linenodes) .>= lon1 | |
# Find interval starts and ends | |
end_cond = diff(cond) # nonzero values denote ends of intervals | |
end_inds = findall(!=(0), end_cond) | |
start_inds = [firstindex(linenodes); end_inds .+ 1] # starts of intervals | |
end_inds = [end_inds; lastindex(linenodes)] # ends of intervals | |
# do the splitting | |
split_coords = view.(Ref(linenodes), UnitRange.(start_inds, end_inds)) # For each start-end pair, get those coords | |
# reconstruct lines from points | |
split_lines = GeometryBasics.LineString.(split_coords) | |
end |
My expectation is that concatenating all the split nodes should be the same as the original nodes, which this suggestion satisfies, i.e.
vcat(split_coords...) == linenodes
In your code however, it seems that if the input is
julia> tmp = GeoMakie.coastlines()[1] # longitudes of ≈ - 161 ± 2
julia> lon0 = 20 # i.e. I want to split the coastline along -160
julia> split_lines = split(tmp, lon0)
julia> vcat(coordinates.(split_lines))
16-element Vector{GeometryBasics.Point{2, Float32}}:
[-163.71289, -78.595665]
[-163.1058, -78.223335]
[-163.1058, -78.223335]
[-161.24512, -78.38018]
[-161.24512, -78.38018]
[-160.2462, -78.69365]
[-159.4824, -79.04634]
[-159.20819, -79.49701]
[-161.1276, -79.63421]
[-162.43985, -79.28146]
[-162.43985, -79.28146]
[-163.0274, -78.92877]
[-163.0274, -78.92877]
[-163.0666, -78.869965]
[-163.0666, -78.869965]
[-163.71289, -78.595665]
then there are many duplicate coordinates in the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much for the suggested improvements. I tested your revised code back in Nov and it worked well from what I remember. Wanted to take another look to confirm I understood your code but then I got side tracked -- apologies for that.
Issue now though is that my basic test case no longer works (ax = GeoMakie.GeoAxis(f[1,1]; dest = "+proj=longlat +datum=WGS84 +lon_0=-160",lonlims=GeoMakie.automatic)
). I assume it's because of code merged ahead of this one but I am not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have now merged master into branch and updated example code, so I could try suggested change again. Might wait to hear from @asinghvi17 though
Will review this in a couple days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops - looks like I didn't post my review when I last looked at this. I'll look at it again in the next couple days.
Couple questions:
- Why is this in a Module?
- does this only work on LineStrings for now, or is there a more generic way?
Simon and I just spoke last night and we're trying to get this kind of splitting directly in the transform, so that we can override the behaviour for individual transforms as well (e.g., some of the weird transforms which aren't "convex").
Co-authored-by: Anshul Singhvi <[email protected]>
Co-authored-by: Haakon Ludvig Langeland Ervik <[email protected]>
Co-authored-by: Haakon Ludvig Langeland Ervik <[email protected]>
Co-authored-by: Haakon Ludvig Langeland Ervik <[email protected]>
Could we merge this (freshly updated) PR and punt further improvements to later revisions (when new issue arises)? The current implementation is not that intrusive (see module), PR provides test & docstrings, and having this feature inside GeoMakie would make the package more potentially useful for ocean viz. If a general solution were eventually found and implemented (for now this PR only treats the lon_0 & LineStrings case) then that's great, but this might take a few more years, who knows ... Currently I am just carrying what I need in an extension to MeshArrays ( https://github.com/JuliaClimate/MeshArrays.jl/blob/master/ext/MeshArraysMakieExt.jl ), because I couldn't get this merged here in timely manner. That's less than ideal, so I am giving GeoMakie one more try now. |
Sure, we can merge for now but I will refactor a bit to make it easier to merge #207. That PR also adds a dependency on GeometryOps.jl that should make it a lot easier to extend this for arbitrary geometry. |
This should definitely be changed to an internal function at some point, though
Great! Thank you very much @asinghvi17 & @haakon-e |
It looks like this doesn't do exactly what I had expected at first: julia> ls = LineString(Point2f[(-179, 0), (179, 0)])
LineString{2, Float32}(Point{2, Float32}[[-179.0, 0.0], [179.0, 0.0]])
julia> split(ls, 0)
MultiLineString{2, Float32}(LineString{2, Float32}[LineString{2, Float32}(Point{2, Float32}[[-179.0, 0.0], [179.0, 0.0]])])
julia> split(ls, 180)
MultiLineString{2, Float32}(LineString{2, Float32}[LineString{2, Float32}(Point{2, Float32}[[-179.0, 0.0]]), LineString{2, Float32}(Point{2, Float32}[[179.0, 0.0]])]) so will refactor it using a different approach. (Did we miss a |
@asinghvi17 It's a long time since I've thought about this PR, could you explain in a bit more detail what kind of output you would expect from each case above? |
This adresses
#118 (comment)
#126
#7
The new
split
method let's us go fromto
The new feature can be tested with: