Skip to content
This repository has been archived by the owner on Oct 23, 2022. It is now read-only.

Added a new "Surface" type: ConvexPolygon which support planner simple convex polygons #213

Merged
merged 7 commits into from
Jul 9, 2021

Conversation

galran
Copy link
Collaborator

@galran galran commented Jul 1, 2021

added two new libraries dependencies - one is part of the Julia basic libs, the other one is for fast processing of 2D polygons.

Added a new "Surface" child: ConvexPolygon which support planner simple convex polygons. These can be used to create non-symmetric paraxial lenses.
Moved a couple of utility functions form the Emitters module to the Geometry module where they belong. These include right, up, forward and origins for type Transform.
Also added some tests for the new ConvexPolygon type.

… libs, the other one is for fast processing of 2D polygons.

Added a new "Surface" child: ConvexPolygon which support planner simple convex polygons. These can be used to create non-symmetric paraxial lenses.
Moved a couple of utility functions form the Emitters module to the Geometry module where they belong. These include right, up, forward and origins for type Transform.
Also added some tests for the new ConvexPolygon type.
@codecov-commenter
Copy link

codecov-commenter commented Jul 1, 2021

Codecov Report

Merging #213 (f3597b6) into main (47052fa) will increase coverage by 0.13%.
The diff coverage is 67.24%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #213      +/-   ##
==========================================
+ Coverage   56.55%   56.69%   +0.13%     
==========================================
  Files          67       68       +1     
  Lines        6372     6420      +48     
==========================================
+ Hits         3604     3640      +36     
- Misses       2768     2780      +12     
Impacted Files Coverage Δ
src/Geometry/Geometry.jl 2.04% <ø> (ø)
src/Geometry/Primitives/NonCSG/Ellipse.jl 52.38% <ø> (+0.81%) ⬆️
src/Geometry/Primitives/NonCSG/Hexagon.jl 67.50% <ø> (+1.64%) ⬆️
src/Geometry/Primitives/NonCSG/Rectangle.jl 68.62% <ø> (+1.31%) ⬆️
src/Optical/Emitters/Emitters.jl 100.00% <ø> (+20.00%) ⬆️
src/utilities.jl 86.84% <ø> (ø)
src/Optical/Paraxial.jl 60.37% <20.00%> (-3.63%) ⬇️
src/Geometry/Primitives/NonCSG/ConvexPolygon.jl 71.42% <71.42%> (ø)
src/Geometry/Transform.jl 52.44% <75.00%> (+1.73%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 47052fa...f3597b6. Read the comment docs.

struct ConvexPolygon{T} <: Surface{T}
plane::Plane{T,3}
local_frame::Transform{T}
local_points::Vector{Vector{T}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local_points should probably be SVector{SVector}. Vectors will be allocated on the heap which will lead to allocations and will probably also be slower. If we expected large convex polygons then Vector might be appropriate. But this class is going to be used for polygons with less than 20-30 points. If you change to SVector probably should document that should only have small number of points.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced it with Vector{SVector{2, T}}.
I can't find a convenient way to define an static array of static arrays. Please send me an example if you have one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you'd have to do something like this:

struct ConvexPolygon{N,T<:Real} <: Surface{T}
local_points::SVector{N,SVector{2,T}}

or maybe even better

struct ConvexPolygon{Npoints,Dim,T<:Real} <: Surface{T}
local_points::SVector{Npoints,SVector{Dim,T}}

where Dim is the dimension of the points, and Npoints is the number of points.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rgal does my suggestion for defined SVector{SVector} work for this case?

Copy link
Collaborator Author

@galran galran Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting the following error when trying it:
ERROR: LoadError: TypeError: in ConvexPolygon, in N, expected N<:Int64, got a value of type Int64.
this is my entire test:

using StaticArrays

struct ConvexPolygon{N<:Int64, T<:Real} 
    local_points::SVector{N, SVector{2, T}}

    function ConvexPolygon(points::SVector{N, SVector{2, T}}) where {N<:Int64, T<:Real}
        new{N, T}(points)
    end

end

points = SVector(SVector(1.0, 1.0), SVector(2.0, 2.0), SVector(3.0, 3.0))
p = ConvexPolygon{3, Float64}(points)

Copy link
Contributor

@BrianGun BrianGun Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want this:

struct ConvexPolygon{N<:Int64,T<:Real}

you want this:

struct ConvexPolygon{N,T<:Real}

The first statement is saying you want N to be a subtype of Int64, which is the same as saying a type equal to Int64 because there are no subtypes of Int64. But the argument you will use in the constructor is a number, not a type.

you'll want to get rid of the N<:Int64 in the ConvexPolygonn constructor as well. I made those two changes and the code worked. This should do it:

struct ConvexPolygon{N, T<:Real} 
    local_points::SVector{N, SVector{2, T}}

    function ConvexPolygon(points::SVector{N, SVector{2, T}}) where {N, T<:Real}
        new{N, T}(points)
    end

end

) where {T<:Real}

@assert length(local_polygon_points) > 3 # need at least 3 points to define apolygon
@assert size(local_polygon_points[1])[1] == 2 # check that first point is a 2D point
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you use SVector instead of Vector then you can specify vector size variable declaration and can eliminate this assert.

centroid(poly::ConvexPolygon{T}) where {T<:Real} = poly.plane.pointonplane
interface(poly::ConvexPolygon{T}) where {T<:Real} = interface(poly.plane)
normal(poly::ConvexPolygon{T}) where {T<:Real} = normal(poly.plane)
normal(poly::ConvexPolygon{T}, ::T, ::T) where {T<:Real} = normal(poly)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this function for? If you really need two then the reason should probably be in a documentation string for the normal function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied it from the Hexagon example. I think that its just a matter of interface support.
You can have a normal for the surface and a normal for each point on the surface in the case when it's not planer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that all the shapes have the same interface - i think that normal without parameters is the one that should be removed but on the other hand what point would you give to a shape that doesn't have a natural parametrization.

p = point(intersect)

local_p = world2local(poly.local_frame) * p
@assert abs(local_p[3]) < 0.00001 # need to find a general epsilon - check that the point lies on the plain
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this assert is necessary. If we have a ray/plane intersection then local_p should always be a valid point. An absolute test is subject to problems with scale, if the convex polygons become large for some reason. Could lead to erroneous failures.

triangles = []
for i in 1:l
p1 = poly.local_points[i]
p2 = poly.local_points[mod(i,l) + 1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might want to use a variable name other than l here since it looks almost exactly the same as 1 in the code font. Maybe len instead of l?

end


function makemesh(poly::ConvexPolygon{T}, ::Int = 0) where {T<:Real}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is makemesh used for drawing the convex poly in 3D? Maybe a documentation string as to the purpose of this function.

@@ -233,6 +234,15 @@ function Transform(rotation::AbstractArray{T,2}, translation::AbstractArray{T,1}
translation[1], translation[2], translation[3], one(T))
end


# define some utility functions
right(t::Transform{<:Real}) = normalize(Vec3(t[1,1], t[2,1], t[3,1]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation strings would be helpful here to explain what these functions do and what they are used for. Graphics people will know but optics people might not.

src/utilities.jl Outdated


# some place holders for package level function names
function origin end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation string would be useful otherwise few people will understand what this function definition is for. Maybe show an example of overloading this function?

…or{2, T}.

Computed the inverse of the local frame once in the constructor instead of inside the ray intersection test - should be more efficient.
@BrianGun
Copy link
Contributor

BrianGun commented Jul 3, 2021 via email

@galran
Copy link
Collaborator Author

galran commented Jul 3, 2021

Depends on what you mean by convenient. SVector{N,SVector{2,T}} where N is whatever the number of 2vectors is. Is this what you were asking or did I misunderstand?

I tried it and could not make it work:

-----------------------------------------------------

using StaticArrays
function func(points::SVector{N,SVector{2,T}}) where {N<:Int64, T<:Real}
println(points)
end
v = SVector(SVector(1.0, 1.0), SVector(2.0, 2.0), SVector(3.0, 3.0))
func(v)

-----------------------------------------------------

resulting in the error:
ERROR: LoadError: MethodError: no method matching func(::SVector{3, SVector{2, Float64}})
Closest candidates are:
func(::SArray{Tuple{N}, SVector{2, T}, 1, N}) where {N<:Int64, T<:Real} at d:\Projects\Rays\Github\galran\Polygons\Try5.jl:4
Stacktrace:
[1] top-level scope
@ d:\Projects\Rays\Github\galran\Polygons\Try5.jl:10
in expression starting at d:\Projects\Rays\Github\galran\Polygons\Try5.jl:10

what am i doing wrong here?

…used to test whether a 2D point lies inside a convex polygon but was using too many allocations during the test.

I implemented the actual test and removed all the allocations.
normal(poly::ConvexPolygon{T}) where {T<:Real} = normal(poly.plane)
normal(poly::ConvexPolygon{T}, ::T, ::T) where {T<:Real} = normal(poly)

centroid(poly::ConvexPolygon{N, T}) where {N, T<:Real} = poly.plane.pointonplane
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since N and T are not being used on the right hand side of the = you shouldn't need them. Should still generate efficient code if you remove them.

@@ -17,10 +17,10 @@ ParaxialLensConvexPoly(focaldistance, local_frame, local_polygon_points, local_c
```
"""
struct ParaxialLens{T} <: Surface{T}
shape::Union{Rectangle{T},Ellipse{T},Hexagon{T},ConvexPolygon{T}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this will do what you want. I think this will define a ConvexPolygon whose first type argument is T. This might be what you want:

shape::Union{Rectangle{T},Ellipse{T},Hexagon{T},ConvexPolygon{N,T}} where{N}

Then for sure the T type argument to ConvexPolygon is in the right place.

Copy link
Contributor

@BrianGun BrianGun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@galran I think the ConvexPolygon{T} thing will cause problems since that puts the T type argument in the first place, where the N argument should go.

Ran Gal and others added 4 commits July 7, 2021 16:23
…an SVector{N SVector{2, T}} due to the ripple effects that addition of N in the system.

Currently, this change leads to ParaxielLens which hold a union of shapes iw now referencing the ALL the shape because if the variable nature of ConvexPolygon. Didn't notice a huge difference in speed but we need to be aware of it.
removed the unused T type declaration from some functions.
@BrianGun BrianGun enabled auto-merge (squash) July 9, 2021 02:58
@BrianGun BrianGun merged commit e2e6ae2 into main Jul 9, 2021
@BrianGun BrianGun deleted the galran/simplePolygon branch July 9, 2021 03:11
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants