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

Iterator api #3

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ version = "1.1.0"
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"

[compat]
ColorSchemes = "3"
Colors = "0.12"
DocStringExtensions = "0.8, 0.9"
GeometryBasics = "0.4"
StaticArraysCore = "1.4"
julia = "1.6"
8 changes: 8 additions & 0 deletions src/GridVisualizeTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ import ColorSchemes

using DocStringExtensions: SIGNATURES, TYPEDEF, TYPEDSIGNATURES
using StaticArraysCore: SVector
using GeometryBasics: Point

include("colors.jl")
export region_cmap, bregion_cmap, rgbtuple

include("extraction.jl")
export extract_visible_cells3D, extract_visible_bfaces3D

include("linearsimplex.jl")
export LinearSimplex, LinearSimplexIterator
export LinearEdge, LinearTriangle, LinearTetrahedron
export testloop

include("marching.jl")
include("marching_iterators.jl")
export marching_tetrahedra, marching_triangles


include("markerpoints.jl")
export markerpoints

Expand Down
95 changes: 95 additions & 0 deletions src/linearsimplex.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
struct LinearSimplex{D,N,Tv}
points::SVector{N,Point{D,Tv}}
values::SVector{N,Tv}
end

values(s::LinearSimplex)=s.values
points(s::LinearSimplex)=s.points


function LinearSimplex(::Type{Val{D}},points::Union{Vector,Tuple}, values::Union{Vector,Tuple}) where {D}
spoints=SVector{D+1,Point{D,Float32}}(points...)
svalues=SVector{D+1,Float32}(values...)
LinearSimplex(spoints,svalues)
end

function LinearSimplex(::Type{Val{1}},points::AbstractMatrix, values::AbstractVector)
@views spoints=SVector{2,Point{1,Float32}}(points[:,1],points[:,2])
svalues=SVector{2,Float32}(values[1],values[2])
LinearSimplex(spoints,svalues)
end

function LinearSimplex(::Type{Val{2}},points::AbstractMatrix, values::AbstractVector)
@views spoints=SVector{3,Point{2,Float32}}(points[:,1],points[:,2],points[:,3])
svalues=SVector{3,Float32}(values[1],values[2],values[3])
LinearSimplex(spoints,svalues)
end

function LinearSimplex(::Type{Val{3}},points::AbstractMatrix, values::AbstractVector)
@views spoints=SVector{4,Point{3,Float32}}(points[:,1],points[:,2],points[:,3],points[:,4])
svalues=SVector{4,Float32}(values[1],values[2],values[3],values[4])
LinearSimplex(spoints,svalues)
end


function LinearSimplex(::Type{Val{1}},points::AbstractMatrix, values::AbstractVector,coordscale)
@views spoints=SVector{2,Point{1,Float32}}(points[:,1]*coordscale,points[:,2]*coordscale)
svalues=SVector{2,Float32}(values[1],values[2])
LinearSimplex(spoints,svalues)
end

function LinearSimplex(::Type{Val{2}},points::AbstractMatrix, values::AbstractVector,coordscale)
@views spoints=SVector{3,Point{2,Float32}}(points[:,1]*coordscale,points[:,2]*coordscale,points[:,3]*coordscale)
svalues=SVector{3,Float32}(values[1],values[2],values[3])
LinearSimplex(spoints,svalues)
end

function LinearSimplex(::Type{Val{3}},points::AbstractMatrix, values::AbstractVector,coordscale)
@views spoints=SVector{4,Point{3,Float32}}(points[:,1]*coordscale,points[:,2]*coordscale,points[:,3]*coordscale,points[:,4]*coordscale)
svalues=SVector{4,Float32}(values[1],values[2],values[3],values[4])
LinearSimplex(spoints,svalues)
end

LinearEdge(points,values)=LinearSimplex(Val{1},points,values)
LinearTriangle(points,values)=LinearSimplex(Val{2},points,values)
LinearTetrahedron(points,values)=LinearSimplex(Val{3},points,values)


"""
abstract type LinearSimplexIterator{D}

Iterator over D-dimensional linear simplices.

Any subtype `TSub` should comply with the [iteration interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration)
and implement
```julia
Base.iterate(vs::TSub{D}, state):: (LinearSimplex{D}, state) where D
```
The optional methods (in particular, size, length) are not needed.
"""
abstract type LinearSimplexIterator{D} end

"""
testloop(iterators::AbstractVector{T}) where T<:LinearSimplexIterator

Sum up all values passed via the iterator. Designed for testing iterators.

Useful for:
- Consistency test - e.g. when passing constant ones, the sum can be calculated by
other means and compared to the return value of testloop
- Allocation test. `testloop` itself does allocate only a few (<1000) bytes in
very few (<10) allocations. So any allocations beyond this from a
call to `testloop` hint at possibilities to improve an iterator implementation.
"""
function testloop(iterators::AbstractVector{T}) where T<:LinearSimplexIterator
threads=map(iterators) do iterator
begin
local x=0.0
for vt in iterator
x+=sum(vt.values)
end
x
end
end
sum(fetch.(threads))
end
63 changes: 63 additions & 0 deletions src/marching_iterators.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
function pushintersection!(intersection_points,triangle::LinearSimplex{2},levels)
f = values(triangle)
coord=points(triangle)

(n1, n2, n3) = (1, 2, 3)

f[1] <= f[2] ? (n1, n2) = (1, 2) : (n1, n2) = (2, 1)
f[n2] <= f[3] ? n3 = 3 : (n2, n3) = (3, n2)
f[n1] > f[n2] ? (n1, n2) = (n2, n1) : nothing

dx31 = coord[n3][1] - coord[n1][1]
dx21 = coord[n2][1] - coord[n1][1]
dx32 = coord[n3][1] - coord[n2][1]

dy31 = coord[n3][2] - coord[n1][2]
dy21 = coord[n2][2] - coord[n1][2]
dy32 = coord[n3][2] - coord[n2][2]

df31 = f[n3] != f[n1] ? 1 / (f[n3] - f[n1]) : 0.0
df21 = f[n2] != f[n1] ? 1 / (f[n2] - f[n1]) : 0.0
df32 = f[n3] != f[n2] ? 1 / (f[n3] - f[n2]) : 0.0

for level ∈ levels
if (f[n1] <= level) && (level < f[n3])
α = (level - f[n1]) * df31
x1 = coord[n1][1] + α * dx31
y1 = coord[n1][2] + α * dy31

if (level < f[n2])
α = (level - f[n1]) * df21
x2 = coord[n1][1] + α * dx21
y2 = coord[n1][2] + α * dy21
else
α = (level - f[n2]) * df32
x2 = coord[n2][1] + α * dx32
y2 = coord[n2][2] + α * dy32
end
push!(intersection_points, Point{2,Float32}(x1, y1))
push!(intersection_points, Point{2,Float32}(x2, y2))
end
end
end

function intersections(triangles::T,levels) where T<:LinearSimplexIterator{2}
local intersection_points = Vector{Point{2,Float32}}(undef, 0)
for triangle in triangles
pushintersection!(intersection_points,triangle,levels)
end
intersection_points
end

function marching_triangles(triangle_iterators::Vector{T},levels) where T<:LinearSimplexIterator{2}
if Threads.nthreads()==1
map(triangle_iterators) do triangles
intersections(triangles,levels)
end
else
threads=map(triangle_iterators) do triangles
Threads.@spawn intersections(triangles,levels)
end
fetch.(threads)
end
end
Loading