@@ -141,6 +141,8 @@ const NS, NE, NW = N|S, N|E, N|W
141141const SN, SE, SW = S| N, S| E, S| W
142142const EN, ES, EW = E| N, E| S, E| W
143143const WN, WS, WE = W| N, W| S, W| E
144+ const NWSE = NW | 0x10 # special (ambiguous case)
145+ const NESW = NE | 0x10 # special (ambiguous case)
144146
145147const dirStr = [" N" , " S" , " NS" , " E" , " NE" , " NS" , " Invalid crossing" ,
146148 " W" , " NW" , " SW" , " Invalid crossing" , " WE" ]
@@ -151,20 +153,42 @@ const dirStr = ["N", "S", "NS", "E", "NE", "NS", "Invalid crossing",
151153# the type of crossing that a cell contains. While most
152154# cells will have only one crossing, cell type 5 and 10 will
153155# have two crossings.
154- struct Cell
155- crossings:: Vector{UInt8}
156+ function get_next_edge! (cells:: Dict , xi, yi, entry_edge:: UInt8 )
157+ key = (xi,yi)
158+ cell = cells[key]
159+ if iszero (cell & 0x10 )
160+ next_edge = cell ⊻ entry_edge
161+ delete! (cells, key)
162+ return next_edge
163+ else # ambiguous case flag
164+ if cell == NWSE
165+ if ! iszero (NW & entry_edge)
166+ cells[key] = SE
167+ return NW ⊻ entry_edge
168+ elseif ! iszero (SE & entry_edge)
169+ cells[key] = NW
170+ return SE ⊻ entry_edge
171+ end
172+ elseif cell == NESW
173+ if ! iszero (NE & entry_edge)
174+ cells[key] = SW
175+ return NE ⊻ entry_edge
176+ elseif ! iszero (SW & entry_edge)
177+ cells[key] = NE
178+ return SW ⊻ entry_edge
179+ end
180+ end
181+ end
156182end
157183
158- function get_next_edge! (cell:: Cell , entry_edge:: UInt8 )
159- for (i, edge) in enumerate (cell. crossings)
160- if ! iszero (edge & entry_edge)
161- next_edge = edge ⊻ entry_edge
162- deleteat! (cell. crossings, i)
163-
164- return next_edge
165- end
184+ function get_first_crossing (cell)
185+ if iszero (cell & 0x10 )
186+ return cell
187+ elseif cell == NWSE
188+ return NW
189+ elseif cell == NESW
190+ return NE
166191 end
167- error (" There is no edge containing " , entry_edge)
168192end
169193
170194# Maps cell type to crossing types for non-ambiguous cells
@@ -179,7 +203,7 @@ function _get_case(z, h)
179203end
180204
181205function get_level_cells (z, h:: Number )
182- cells = Dict {( Tuple{Int,Int}),Cell } ()
206+ cells = Dict {Tuple{Int,Int},UInt8 } ()
183207 xi_max, yi_max = size (z)
184208
185209 @inbounds for xi in 1 : xi_max - 1
@@ -196,18 +220,18 @@ function get_level_cells(z, h::Number)
196220 # a bilinear interpolation of the cell-center value.
197221 if case == 0x05
198222 if 0.25 * sum (elts) >= h
199- cells[(xi, yi)] = Cell ([NW, SE])
223+ cells[(xi, yi)] = NWSE
200224 else
201- cells[(xi, yi)] = Cell ([NE, SW])
225+ cells[(xi, yi)] = NESW
202226 end
203227 elseif case == 0x0a
204228 if 0.25 * sum (elts) >= h
205- cells[(xi, yi)] = Cell ([NE, SW])
229+ cells[(xi, yi)] = NESW
206230 else
207- cells[(xi, yi)] = Cell ([NW, SE])
231+ cells[(xi, yi)] = NWSE
208232 end
209233 else
210- cells[(xi, yi)] = Cell ([ edge_LUT[case]])
234+ cells[(xi, yi)] = edge_LUT[case]
211235 end
212236 end
213237 end
219243
220244const fwd, rev = (UInt8 (0 )), (UInt8 (1 ))
221245
222- @inline function add_vertex! (curve:: Curve2{T} , pos:: Tuple{T,T} , dir:: UInt8 ) where {T}
246+ function add_vertex! (curve:: Curve2{T} , pos:: Tuple{T,T} , dir:: UInt8 ) where {T}
223247 if dir == fwd
224248 push! (curve. vertices, SVector {2,T} (pos... ))
225249 else
@@ -284,11 +308,7 @@ function chase!(cells, curve, x, y, z, h, xi_start, yi_start, entry_edge, xi_max
284308 loopback_edge = entry_edge
285309
286310 while true
287- cell = cells[(xi, yi)]
288- exit_edge = get_next_edge! (cell, entry_edge)
289- if length (cell. crossings) == 0
290- delete! (cells, (xi, yi))
291- end
311+ exit_edge = get_next_edge! (cells, xi, yi, entry_edge)
292312
293313 add_vertex! (curve, interpolate (x, y, z, h, xi, yi, exit_edge), dir)
294314
@@ -313,18 +333,10 @@ function chase!(cells, curve, x, y, z, h, xi_start, yi_start, entry_edge, xi_max
313333end
314334
315335
316- function trace_contour (x, y, z, h:: Number , cells:: Dict{(Tuple{Int,Int}),Cell} )
336+ function trace_contour (x, y, z, h:: Number , cells:: Dict )
317337
318338 contours = ContourLevel (h)
319339
320- local yi:: Int
321- local xi:: Int
322- local xi_0:: Int
323- local yi_0:: Int
324-
325- local xi_max:: Int
326- local yi_max:: Int
327-
328340 (xi_max, yi_max) = size (z)
329341
330342 # When tracing out contours, this algorithm picks an arbitrary
@@ -340,7 +352,7 @@ function trace_contour(x, y, z, h::Number, cells::Dict{(Tuple{Int,Int}),Cell})
340352 (xi, yi) = (xi_0, yi_0)
341353
342354 # Pick a starting edge
343- crossing = first (cell. crossings )
355+ crossing = get_first_crossing (cell)
344356 starting_edge = UInt8 (0 )
345357 for edge in (N, S, E, W)
346358 if ! iszero (edge & crossing)
0 commit comments