diff --git a/src/Geometry/Geometry.jl b/src/Geometry/Geometry.jl new file mode 100644 index 00000000..580e2bbd --- /dev/null +++ b/src/Geometry/Geometry.jl @@ -0,0 +1,26 @@ +#= + +Definition of basic geometrical concepts. + +=# + + +""" + ambient_dimension(x) + +Dimension of the ambient space where `x` lives. For geometrical objects this can +differ from its [`geometric_dimension`](@ref); for example a triangle in `ℝ³` +has ambient dimension `3` but geometric dimension `2`, while a curve in `ℝ³` has +ambient dimension 3 but geometric dimension 1. +""" +function ambient_dimension end + +""" + geometric_dimension(x) + +Number of independent coordinates needed to describe `x`. Lines have geometric +dimension 1, triangles have geometric dimension 2, etc. +""" +function geometric_dimension end + +include("referenceshapes.jl") diff --git a/src/Geometry/referenceshapes.jl b/src/Geometry/referenceshapes.jl new file mode 100644 index 00000000..58fbb4b1 --- /dev/null +++ b/src/Geometry/referenceshapes.jl @@ -0,0 +1,72 @@ +""" + abstract type AbstractReferenceShape + +A fixed reference domain/shape. Used mostly for defining more complex shapes as +transformations mapping an `AbstractReferenceShape` to some region of `ℜᴹ`. + +See e.g. [`ReferenceLine`](@ref) or [`ReferenceTriangle`](@ref) for some +examples of concrete subtypes. +""" +abstract type AbstractReferenceShape end + +""" + struct ReferenceTriangle + +Singleton type representing the triangle with vertices `(0,0),(1,0),(0,1)` +""" +struct ReferenceTriangle <: AbstractReferenceShape end +geometric_dimension(::ReferenceTriangle) = 2 +ambient_dimension(::ReferenceTriangle) = 2 +vertices(::ReferenceTriangle) = SVector(0, 0), SVector(1, 0), SVector(0, 1) +Base.in(x, ::ReferenceTriangle) = 0 ≤ x[1] ≤ 1 && 0 ≤ x[2] ≤ 1 - x[1] +center(::ReferenceTriangle) = svector(i -> 1 / 3, 3) + +""" + struct ReferenceTetrahedron + +Singleton type representing the tetrahedron with vertices +`(0,0,0),(0,0,1),(0,1,0),(1,0,0)` +""" +struct ReferenceTetrahedron <: AbstractReferenceShape end +geometric_dimension(::ReferenceTetrahedron) = 3 +ambient_dimension(::ReferenceTetrahedron) = 3 +vertices(::ReferenceTetrahedron) = SVector(0, 0, 0), SVector(1, 0, 0), SVector(0, 1, 0), SVector(0, 0, 1) +Base.in(x,::ReferenceTetrahedron) = 0 ≤ x[1] ≤ 1 && 0 ≤ x[2] ≤ 1 - x[1] && 0 ≤ x[3] ≤ 1 - x[1] - x[2] +center(::ReferenceTetrahedron) = svector(i -> 1 / 4, 4) + + +# TODO: generalize structs above to `ReferenceSimplex{N}` and + +""" + struct ReferenceHyperCube{N} <: AbstractReferenceShape{N} + +Singleton type representing the axis-aligned hypercube in `N` dimensions with +the lower corner at the origin and the upper corner at `(1,1,…,1)`. +""" +struct ReferenceHyperCube{N} <: AbstractReferenceShape end +geometric_dimension(::ReferenceHyperCube{N}) where {N} = N +ambient_dimension(::ReferenceHyperCube{N}) where {N} = N +vertices(::ReferenceHyperCube{N}) where {N} = ntuple(i -> SVector(ntuple(j -> (i >> j) & 1, N)), 2^N) +Base.in(x, ::ReferenceHyperCube{N}) where {N} = all(0 .≤ x .≤ 1) +center(::ReferenceHyperCube{N}) where {N} = svector(i -> 0.5, N) + +""" + const ReferenceLine = ReferenceHyperCube{1} + +Singleton type representing the `[0,1]` segment. +""" +const ReferenceLine = ReferenceHyperCube{1} + +""" + const ReferenceSquare = ReferenceHyperCube{2} + +Singleton type representing the unit square `[0,1]²`. +""" +const ReferenceSquare = ReferenceHyperCube{2} + +""" + const ReferenceCube = ReferenceHyperCube{3} + +Singleton type representing the unit cube `[0,1]³`. +""" +const ReferenceCube = ReferenceHyperCube{3} diff --git a/src/utils.jl b/src/utils.jl new file mode 100644 index 00000000..1a19fe39 --- /dev/null +++ b/src/utils.jl @@ -0,0 +1,13 @@ +#= + +Utility functions that have nowhere obvious to go. + +=# + +""" + svector(f,n) + +Create an `SVector` of length n, computing each element as f(i), where i is the +index of the element. +""" +svector(f,n)= ntuple(f,n) |> SVector diff --git a/test/Geometry/referenceshapes_test.jl b/test/Geometry/referenceshapes_test.jl new file mode 100644 index 00000000..882355f4 --- /dev/null +++ b/test/Geometry/referenceshapes_test.jl @@ -0,0 +1,37 @@ +using Test +import Inti +using StaticArrays + +@testset "Line" begin + l = Inti.ReferenceLine() + @test Inti.ambient_dimension(l) == 1 + @test Inti.geometric_dimension(l) == 1 + x = SVector(0.5) + @test x ∈ l + x = SVector(1.0) + @test x ∈ l + x = SVector(1.1) + @test !in(x, l) +end +@testset "Triangle" begin + t = Inti.ReferenceTriangle() + @test Inti.ambient_dimension(t) == 2 + @test Inti.geometric_dimension(t) == 2 + x = SVector(0.5, 0.5) + @test x ∈ t + x = SVector(1.0, 0.0) + @test x ∈ t + x = SVector(1.1, 0.0) + @test !in(x, t) +end +@testset "Tetrahedron" begin + t = Inti.ReferenceTetrahedron() + @test Inti.ambient_dimension(t) == 3 + @test Inti.geometric_dimension(t) == 3 + x = SVector(0.5, 0.5, 0.0) + @test x ∈ t + x = SVector(1.0, 0.0, 0.0) # point on edge + @test x ∈ t + x = SVector(1.1, 0.0, 0.0) + @test !in(x, t) +end diff --git a/test/aqua_test.jl b/test/aqua_test.jl new file mode 100644 index 00000000..19bfbfeb --- /dev/null +++ b/test/aqua_test.jl @@ -0,0 +1,7 @@ +using Inti +using Test +using Aqua + +@testset "Aqua" begin + Aqua.test_all(Inti) +end