-
Notifications
You must be signed in to change notification settings - Fork 87
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
Introducing iteration on vertices #1133
Conversation
Thank you @ghyatzo for the contribution. To facilitate the usage of this iterator, we just need to implement a new For the |
Hi, yes absolutely can do. Regarding flatten, I've done some tries, but the
flatten requires an iterator of iterators, which means that we have to build an iterator for each subelement in the multigeometry. |
@ghyatzo I meant that we simply need to define the function eachvertex(p::Polytope) = (v for v in vertices(p)) The geometry that will benefit the most is the |
The reason why I didn't use simply a generator It should still be generic enough since underneat we are calling Please let me know if there is anything I overlooked or wrong with my reasoning. |
I've improved the flatten approach using a generator of generators and not an array as I was naively doing before. julia> eachvertex_custom(e::Union{Mesh,Polytope,Multi}) = VertexItr(e)
julia> eachvertex_gen(p::Polytope) = (v for v in vertices(p))
julia> eachvertex_flat(e::Multi) = Iterators.flatten(eachvertex_gen(g) for g in e.geoms)
eachvertex_flat (generic function with 1 method)
julia> m
MultiNgon
├─ Triangle((x: 0.0119639 m, y: 0.139913 m), (x: 0.347587 m, y: 0.958666 m), (x: 0.145339 m, y: 0.109886 m))
└─ Hexagon((x: 0.25018 m, y: 0.85677 m), ..., (x: 0.57332 m, y: 0.3497 m))
julia> @btime begin
s = 0
for _ in eachvertex_flat($m)
s+=1
end
s
end
1.104 μs (39 allocations: 2.95 KiB)
9
julia> @btime begin
s = 0
for _ in eachvertex_custom($m)
s+=1
end
s
end
497.851 ns (9 allocations: 288 bytes)
9 those 9 allocations are from an Anyway, I completely understand prefering the simpler solution. Also: is it enough to just have the |
Isn't ok to define eachvertex(m::Multi) = (v for g in m.geoms for v in vertices(g)) in the |
is shorthand for
from lowering the code:
and has similar performances
|
Yes, but please restrict to
Interesting. Thanks for clarifying this. |
Appreciate if you can keep it simple for now without an auxiliary iterator struct. Please define the We can reconsider the auxiliary iterator struct in the future. I understand it allocates a fixed amount no matter the size of the |
Alright, will do. shall I make a separate PR and keep this as draft with the struct approach? |
Feel free to update the PR here directly. You can copy the VertexIter struct in the comments to save it for future reference. |
For future reference: struct VertexItr{T}
el::T
end
_v_iterate(el::Polytope, i) =
(@inline; (i - 1) % UInt < nvertices(el) % UInt ? (@inbounds vertex(el, i), i + 1) : nothing)
_v_iterate(el::Mesh, i) =
(@inline; (i - 1) % UInt < nvertices(el) % UInt ? (@inbounds vertex(el, i), i + 1) : nothing)
Base.iterate(itr::VertexItr{<:Mesh}, i=1) = _v_iterate(itr.el, i)
Base.iterate(itr::VertexItr{<:Polytope}, i=1) = _v_iterate(itr.el, i)
Base.iterate(itr::VertexItr{<:MultiPolytope}, state=(1, 1)) = begin
ig, ivg = state
ig > length(itr.el.geoms) && return nothing
is = _v_iterate(itr.el.geoms[ig], ivg)
is === nothing && return Base.iterate(itr, (ig + 1, 1))
v, ivg = is
return (v, (ig, ivg))
end
Base.length(itr::VertexItr{<:Mesh}) = nvertices(T)
Base.length(itr::VertexItr{<:Polytope}) = nvertices(T)
Base.length(itr::VertexItr{<:MultiPolytope}) = sum(nvertices, itr.el.geoms)
Base.IteratorSize(itr::VertexItr) = Base.HasLength()
Base.eltype(::VertexItr) = Point
eachvertex(e::T) where {T} = error("Vertex iterator not implemented for type $T")
eachvertex(e::Union{Mesh,Polytope,MultiPolytope}) = VertexItr(e) |
I would like some pointers WRT the new tests, I'm a bit unsure where best to put them I've also took the liberty of rewriting some |
You can add tests in the corresponding test files. For instance,
I shared a comment above about that. Just a test that uses the
Does it lead to the same type inference? I know that list comprehensions are very efficient, and that the compiler can do magic with them. I am not sure if this is the case with the |
Co-authored-by: Júlio Hoffimann <[email protected]>
I'll do some tests, but I expect it does, since I have the sneaking suspicion that doing Edit:
|
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
Co-authored-by: Elias Carvalho <[email protected]>
ok accepted everything, can we close this up now? |
Not yet, I will add more tests before merging. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1133 +/- ##
==========================================
+ Coverage 87.69% 87.71% +0.02%
==========================================
Files 191 191
Lines 6005 6007 +2
==========================================
+ Hits 5266 5269 +3
+ Misses 739 738 -1 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
Co-authored-by: Júlio Hoffimann <[email protected]>
Thank you @ghyatzo for initiating this work, and @eliascarv for finishing it up! We will work on the final detail now with |
Hi,
following #1127 and #1131 I'm starting this draft PR.
I've added the main iteration logic for single geometry and multi geometry types.
This si incomplete as I would require some input on the following points
in particular, I am not very familiar with all the nomenclature and type system structure used in this package, so I would appreciate an indication of which types we are interested in and/or for which onese we want to be able to call
vertices
.WRT to point 2, I've gone for stuffing all iteration related code into a single file for now, let me know if this has to change.
cheers!