JuliaGeometry / Contour.jl

Calculating contour curves for 2D scalar fields in Julia

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Contour line from specific point

anneaux opened this issue · comments

Hi!
Is it possible to access the contour line from (for?!) a specific point?
I mean, one could calculate the level of that point and then obtain the contour lines for that level. However, then one may get multiple lines (with the same level) and still needs to sort out which line actually intersects with the initially given point (and that might fail due to numerical inaccuracies...).
Thanks in advance!

Apologies for the late reply. I don't think we have exactly what you need here in the internal APIs. You can look at these functions to get an idea of how ambiguities are handled and so forth:

Contour.jl/src/Contour.jl

Lines 202 to 237 in 9e18fe6

@inline function _get_case(z, h)
case = z[1] > h ? 0x01 : 0x00
z[2] > h && (case |= 0x02)
z[3] > h && (case |= 0x04)
z[4] > h && (case |= 0x08)
case
end
function get_level_cells(z, h::Number)
cells = Dict{Tuple{Int,Int},UInt8}()
x_ax, y_ax = axes(z)
@inbounds for xi in first(x_ax):last(x_ax)-1
for yi in first(y_ax):last(y_ax)-1
elts = (z[xi, yi], z[xi + 1, yi], z[xi + 1, yi + 1], z[xi, yi + 1])
case = _get_case(elts, h)
# Contour does not go through these cells
if iszero(case) || case == 0x0f
continue
end
# Process ambiguous cells (case 5 and 10) using
# a bilinear interpolation of the cell-center value.
if case == 0x05
cells[(xi, yi)] = 0.25*sum(elts) >= h ? NWSE : NESW
elseif case == 0x0a
cells[(xi, yi)] = 0.25*sum(elts) >= h ? NESW : NWSE
else
cells[(xi, yi)] = edge_LUT[case]
end
end
end
return cells
end

Assuming what you mean by points is "indices" ?

Yeah, by points I mean indices.

Sorry for the super late response 🙈 😅

I realised that for getting the contour of a specific index one could just modify the trace_contour() function https://github.com/JuliaGeometry/Contour.jl/blob/0160a4137bab2bb05480a01769b847cf5073caa5/src/Contour.jl#L295C2-L322C1
Removing the iteration and choosing the specific index as an initial box leaves you with one single contour line, namely that of the point (index) in question.

However, in my case I am looking for the contours through a previously calculated saddle point (hence, two contour lines). If I understand the algorithm correctly then getting those two lines directly will be impossible, for different reasons depending on the discretisation of the grid.

If the saddle point lies exactly on a grid point (e.g. point coordinates (x,y) = (0,0), i.e. grid point with index (2,2)) in the example below), then the two traced contour lines both run through it. However, the cell indexed (2,2) only gets called for one of the lines. Whereas for the other line the coordinates (0,0) become part of the curve as a result of the interpolation.
So, if I want to find the two lines that runs through point (0,0) I need to trace all contour lines and then check if they happen to intersect with it.

image

If the saddle point lies in between grid points (e.g. point (0,0) lies inside the cell indexed (2,2)), then the respective cell will be correctly identified it as a saddle point. The two traced contour lines will run along the edges of the cell and therefore not intersect with each other and also not exactly pass through the saddle point, making further analysis difficult. (Especially for the case of low resolution)

image

I would have thought one could somehow speed up the calculation of the contour lines through the saddle points by only tracing the contours starting from it, but seems like that's not possible ...

Cheers!