From 6dd457d5a989f7566ca0ac5a2cebc11ee422ffbd Mon Sep 17 00:00:00 2001 From: schillic Date: Sun, 8 Jul 2018 22:30:23 +0200 Subject: [PATCH 01/15] change load order --- src/LazySets.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LazySets.jl b/src/LazySets.jl index 95fe4464c3..5a5196e948 100644 --- a/src/LazySets.jl +++ b/src/LazySets.jl @@ -26,8 +26,8 @@ include("AbstractPointSymmetric.jl") include("AbstractPointSymmetricPolytope.jl") include("AbstractHyperrectangle.jl") include("AbstractPolygon.jl") -include("AbstractHPolygon.jl") include("AbstractSingleton.jl") +include("AbstractHPolygon.jl") # ============================= # Types representing basic sets From 7ed293d2451e8291eccf069f9472d6c35da2a634 Mon Sep 17 00:00:00 2001 From: schillic Date: Mon, 9 Jul 2018 21:59:59 +0200 Subject: [PATCH 02/15] conversion from line segment to half-space --- src/HalfSpace.jl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index e402283a1e..60c207d22e 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -116,3 +116,30 @@ We just check if ``x`` satisfies ``a⋅x ≤ b``. function ∈(x::AbstractVector{N}, hs::HalfSpace{N})::Bool where {N<:Real} return dot(x, hs.a) <= hs.b end + +""" + halfspace_left(p::AbstractVector{N}, + q::AbstractVector{N})::HalfSpace{N} where {N<:Real} + +Return a half-space describing the 'left' of a line segment through two points. + +### Input + +- `p` -- first point +- `q` -- second point + +### Output + +The half-space whose boundary goes through the two points `p` and `q` and which +describes the left-hand side of the line segment `pq`. + +### Algorithm + +The implementation is simple: `a = [dy, -dx]` and `b = dot(p, a)`. +""" +function halfspace_left(p::AbstractVector{N}, + q::AbstractVector{N})::HalfSpace{N} where {N<:Real} + @assert p != q "the points must not be equal" + a = [q[2] - p[2], p[1] - q[1]] + return HalfSpace(a, dot(p, a)) +end From 4f0138330784c5de5a3cc602a09467d330bbfc3b Mon Sep 17 00:00:00 2001 From: schillic Date: Mon, 9 Jul 2018 22:00:48 +0200 Subject: [PATCH 03/15] conversion from singleton to HPolygon --- src/convert.jl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/convert.jl b/src/convert.jl index c5f0660c20..50e5fed5f5 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -89,6 +89,34 @@ function convert(::Type{Zonotope}, H::AbstractHyperrectangle{N}) where {N} return Zonotope{N}(center(H), diagm(radius_hyperrectangle(H))) end +""" + convert(::Type{HPOLYGON}, S::AbstractSingleton{N} + ) where {N, HPOLYGON<:AbstractHPolygon} + +Convert from singleton to polygon in H-representation. + +### Input + +- `type` -- target type +- `S` -- singleton + +### Output + +A polygon in constraint representation with the minimal number of constraints +(three). +""" +function convert(::Type{HPOLYGON}, S::AbstractSingleton{N} + ) where {N, HPOLYGON<:AbstractHPolygon} + constraints_list = Vector{LinearConstraint{N}}(3) + o = one(N) + z = zero(N) + v = element(S) + constraints_list[1] = LinearConstraint([o, o], v[1] + v[2]) + constraints_list[2] = LinearConstraint([-o, z], -v[1]) + constraints_list[3] = LinearConstraint([z, -o], -v[2]) + return HPOLYGON{N}(constraints_list) +end + import IntervalArithmetic.AbstractInterval """ From 51b69c11c7ce4eef700a9b71519163bab11ef1b5 Mon Sep 17 00:00:00 2001 From: schillic Date: Mon, 9 Jul 2018 22:01:06 +0200 Subject: [PATCH 04/15] conversion from line segment to HPolygon --- src/convert.jl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/convert.jl b/src/convert.jl index 50e5fed5f5..7c0ff85cd3 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -117,6 +117,36 @@ function convert(::Type{HPOLYGON}, S::AbstractSingleton{N} return HPOLYGON{N}(constraints_list) end +""" + convert(::Type{HPOLYGON}, L::LineSegment{N} + ) where {N, HPOLYGON<:AbstractHPolygon} + +Convert from line segment to polygon in H-representation. + +### Input + +- `type` -- target type +- `L` -- line segment + +### Output + +A flat polygon in constraint representation with the minimal number of +constraints (four). +""" +function convert(::Type{HPOLYGON}, L::LineSegment{N} + ) where {N, HPOLYGON<:AbstractHPolygon} + H = HPOLYGON{N}() + c = halfspace_left(L.p, L.q) + addconstraint!(H, c) + addconstraint!(H, LinearConstraint(-c.a, -c.b)) + line_dir = L.q - L.p + c = LinearConstraint(line_dir, dot(L.q, line_dir)) + addconstraint!(H, c) + line_dir = -line_dir + addconstraint!(H, LinearConstraint(line_dir, dot(L.p, line_dir))) + return H +end + import IntervalArithmetic.AbstractInterval """ From 31767198c8dc99fc923d0dda5da51a9a2d47d48a Mon Sep 17 00:00:00 2001 From: schillic Date: Mon, 9 Jul 2018 22:02:16 +0200 Subject: [PATCH 05/15] tohrep from VPolygon --- src/VPolygon.jl | 57 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/src/VPolygon.jl b/src/VPolygon.jl index 71a6e534df..db0d0507b0 100644 --- a/src/VPolygon.jl +++ b/src/VPolygon.jl @@ -59,20 +59,69 @@ function tovrep(P::VPolygon{N})::VPolygon{N} where {N<:Real} end """ - tohrep(P::VPolygon{N})::AbstractHPolygon{N} where {N<:Real} + tohrep(P::VPolygon{N}, ::Type{HPOLYGON}=HPolygon + )::AbstractHPolygon{N} where {N<:Real, HPOLYGON<:AbstractHPolygon} Build a constraint representation of the given polygon. ### Input -- `P` -- polygon in vertex representation +- `P` -- polygon in vertex representation +- `HPOLYGON` -- (optional, default: `HPolygon`) type of target polygon ### Output The same polygon but in constraint representation, an `AbstractHPolygon`. """ -function tohrep(P::VPolygon{N})::AbstractHPolygon{N} where {N<:Real} - error("this function is not implemented yet, see issue #5") +function tohrep(P::VPolygon{N}, ::Type{HPOLYGON}=HPolygon + )::AbstractHPolygon{N} where {N<:Real, HPOLYGON<:AbstractHPolygon} + n = length(vertices_list(P)) + if n == 0 + # no vertex -> no constraint + constraints_list = Vector{LinearConstraint{N}}(0) + elseif n == 1 + # only one vertex -> use function for singletons + return convert(HPOLYGON, Singleton(P.vertices_list[1])) + elseif n == 2 + # only two vertices -> use function for line segments + return convert(HPOLYGON, LineSegment(P.vertices_list[1], P.vertices_list[2])) + else + # find right-most vertex + i = div(n, 2) + x = P.vertices_list[i][1] + while i > 1 && P.vertices_list[i-1][1] > x + # search forward in list + i = i - 1 + x = P.vertices_list[i][1] + end + while i < n && P.vertices_list[i+1][1] > x + # search backward in list + i = i + 1 + x = P.vertices_list[i][1] + end + + # create constraints counter-clockwise + constraints_list = Vector{LinearConstraint{N}}(n) + j = 1 + i_start = i + i_stop = n + for it in 1:2 + while i < i_stop + constraints_list[j] = + halfspace_left(P.vertices_list[i], P.vertices_list[i+1]) + j += 1 + i += 1 + end + if it == 1 + constraints_list[j] = + halfspace_left(P.vertices_list[n], P.vertices_list[1]) + j += 1 + i = 1 + i_stop = i_start + end + end + end + return HPOLYGON{N}(constraints_list) end From 158455d62f137569514dd7af97167382fe19144e Mon Sep 17 00:00:00 2001 From: schillic Date: Mon, 9 Jul 2018 22:04:34 +0200 Subject: [PATCH 06/15] add docs --- docs/src/lib/representations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/lib/representations.md b/docs/src/lib/representations.md index 3a5504719a..96f64d5626 100644 --- a/docs/src/lib/representations.md +++ b/docs/src/lib/representations.md @@ -98,6 +98,7 @@ dim(::HalfSpace{Float64}) σ(::AbstractVector{Float64}, ::HalfSpace{Float64}) an_element(::HalfSpace{Float64}) ∈(::AbstractVector{Float64}, ::HalfSpace{Float64}) +halfspace_left(::AbstractVector, ::AbstractVector) ``` ## Hyperplane From d87b8f9508e1de6433e6836b9db6a03bdb282aa4 Mon Sep 17 00:00:00 2001 From: schillic Date: Wed, 11 Jul 2018 10:40:06 +0200 Subject: [PATCH 07/15] generalize unit tests --- test/unit_Polygon.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit_Polygon.jl b/test/unit_Polygon.jl index 314b3bb6ba..3bae461083 100644 --- a/test/unit_Polygon.jl +++ b/test/unit_Polygon.jl @@ -33,9 +33,9 @@ for N in [Float64, Float32, Rational{Int}] HPolytope(po) # support vector of empty polygon - @test_throws ErrorException σ([0.], HPolygon()) - @test_throws ErrorException σ([0.], HPolygonOpt(HPolygon())) - @test_throws ErrorException σ([0.], HPolytope()) + @test_throws ErrorException σ(N[0.], HPolygon{N}()) + @test_throws ErrorException σ(N[0.], HPolygonOpt(HPolygon{N}())) + @test_throws ErrorException σ(N[0.], HPolytope{N}()) # HPolygon/HPolygonOpt tests for p in [p, po] From eb40247145cf0761d3b5cf8b694b567174db9fc5 Mon Sep 17 00:00:00 2001 From: schillic Date: Wed, 11 Jul 2018 10:40:28 +0200 Subject: [PATCH 08/15] add unit tests for tohrep --- test/unit_Polygon.jl | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/unit_Polygon.jl b/test/unit_Polygon.jl index 3bae461083..976b2003d7 100644 --- a/test/unit_Polygon.jl +++ b/test/unit_Polygon.jl @@ -145,6 +145,45 @@ for N in [Float64, Float32, Rational{Int}] @test vi <= v[j] end end + + # hrep conversion + v1 = to_N(N, [0.9, 0.2]) + v2 = to_N(N, [0.4, 0.6]) + v3 = to_N(N, [0.2, 0.1]) + v4 = to_N(N, [0.1, 0.3]) + points5 = [v1, v2, v3, v4] + for i in [0, 1, 2, 4] + points = i == 0 ? Vector{Vector{N}}() : points5[1:i] + vp = VPolygon(points, apply_convex_hull=i > 0) + h1 = tohrep(vp) + if i == 0 + @test isempty(h1.constraints) + elseif i == 1 + @test v1 ∈ h1 + elseif i == 2 + c = h1.constraints[1] + @test c.a ≈ to_N(N, [0.4, 0.5])&& c.b ≈ to_N(N, (0.46)) + c = h1.constraints[3] + @test c.a ≈ to_N(N, [-0.4, -0.5])&& c.b ≈ to_N(N, (-0.46)) + elseif i == 4 + @test length(h1.constraints) == 4 + c = h1.constraints[1] + @test c.a ≈ to_N(N, [0.4, 0.5])&& c.b ≈ to_N(N, (0.46)) + c = h1.constraints[2] + @test c.a ≈ to_N(N, [-0.3, 0.3])&& c.b ≈ to_N(N, (0.06)) + c = h1.constraints[3] + @test c.a ≈ to_N(N, [-0.2, -0.1])&& c.b ≈ to_N(N, (-0.05)) + c = h1.constraints[4] + @test c.a ≈ to_N(N, [0.1, -0.7])&& c.b ≈ to_N(N, (-0.05)) + end + + # check that constraints are sorted correctly + h2 = HPolygon{N}() + for c in h1.constraints + addconstraint!(h2, c) + end + @test h1.constraints == h2.constraints + end end # default Float64 constructors From 9a9c6f917077acede60169ea143d5fea5874c9a1 Mon Sep 17 00:00:00 2001 From: mforets Date: Fri, 20 Jul 2018 14:29:32 -0300 Subject: [PATCH 09/15] minor add-on for halfspace_left Algorithm docstring --- src/HalfSpace.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index 60c207d22e..1962d57766 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -131,11 +131,14 @@ Return a half-space describing the 'left' of a line segment through two points. ### Output The half-space whose boundary goes through the two points `p` and `q` and which -describes the left-hand side of the line segment `pq`. +describes the left-hand side of the directed line segment `pq`. ### Algorithm -The implementation is simple: `a = [dy, -dx]` and `b = dot(p, a)`. +The implementation is simple: the half-space ``a⋅x ≤ b`` is calculated as +`a = [dy, -dx]`, where ``d = (dx, dy)`` denotes the line segment +`pq`, that is, ``\\vec{d} = \\vec{p} - \\vec{q}``, and `b = dot(p, a)` because +`p` is on this line (we can equally choose `q` instead of `p`). """ function halfspace_left(p::AbstractVector{N}, q::AbstractVector{N})::HalfSpace{N} where {N<:Real} From 884a35eeb3f23e757f9b45bc13b89e3bad7ce54d Mon Sep 17 00:00:00 2001 From: mforets Date: Fri, 20 Jul 2018 16:12:55 -0300 Subject: [PATCH 10/15] fix docstring call --- docs/src/lib/representations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/lib/representations.md b/docs/src/lib/representations.md index 96f64d5626..a7be7beb71 100644 --- a/docs/src/lib/representations.md +++ b/docs/src/lib/representations.md @@ -98,7 +98,7 @@ dim(::HalfSpace{Float64}) σ(::AbstractVector{Float64}, ::HalfSpace{Float64}) an_element(::HalfSpace{Float64}) ∈(::AbstractVector{Float64}, ::HalfSpace{Float64}) -halfspace_left(::AbstractVector, ::AbstractVector) +LazySets.halfspace_left(::AbstractVector{Float64}, ::AbstractVector{Float64}) ``` ## Hyperplane From 30824a2a81333734b18e2fc08a9075a379316675 Mon Sep 17 00:00:00 2001 From: mforets Date: Fri, 20 Jul 2018 17:06:36 -0300 Subject: [PATCH 11/15] add 2D assertion and update docstring --- src/HalfSpace.jl | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index 1962d57766..ce26f5cb23 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -121,7 +121,8 @@ end halfspace_left(p::AbstractVector{N}, q::AbstractVector{N})::HalfSpace{N} where {N<:Real} -Return a half-space describing the 'left' of a line segment through two points. +Return a half-space describing the 'left' of a two-dimensional line segment through +two points. ### Input @@ -137,11 +138,45 @@ describes the left-hand side of the directed line segment `pq`. The implementation is simple: the half-space ``a⋅x ≤ b`` is calculated as `a = [dy, -dx]`, where ``d = (dx, dy)`` denotes the line segment -`pq`, that is, ``\\vec{d} = \\vec{p} - \\vec{q}``, and `b = dot(p, a)` because -`p` is on this line (we can equally choose `q` instead of `p`). +`pq`, that is, ``\\vec{d} = \\vec{p} - \\vec{q}``, and `b = dot(p, a)`. + +### Examples + +The left half-space of the "east" and "west" directions in two-dimensions are the +upper and lower half-spaces: + +```jldoctest halfspace_left +julia> import LazySets.halfspace_left + +julia> halfspace_left([0.0, 0.0], [1.0, 0.0]) +LazySets.HalfSpace{Float64}([0.0, -1.0], 0.0) + +julia> halfspace_left([0.0, 0.0], [-1.0, 0.0]) +LazySets.HalfSpace{Float64}([0.0, 1.0], 0.0) +``` + +We create a box from the sequence of line segments that describe its edges: + +```jldoctest halfspace_left +julia> H1 = halfspace_left([-1.0, -1.0], [1.0, -1.0]); + +julia> H2 = halfspace_left([1.0, -1.0], [1.0, 1.0]); + +julia> H3 = halfspace_left([1.0, 1.0], [-1.0, 1.0]); + +julia> H4 = halfspace_left([-1.0, 1.0], [-1.0, -1.0]); + +julia> H = HPolygon([H1, H2, H3, H4]); + +julia> B = BallInf([0.0, 0.0], 1.0); + +julia> B ⊆ H && H ⊆ B +true +``` """ function halfspace_left(p::AbstractVector{N}, q::AbstractVector{N})::HalfSpace{N} where {N<:Real} + @assert length(p) == length(q) == 2 "the points must be two-dimensional" @assert p != q "the points must not be equal" a = [q[2] - p[2], p[1] - q[1]] return HalfSpace(a, dot(p, a)) From d6af0f0b3063774ccfbfbd63a1d50f79c1105a4d Mon Sep 17 00:00:00 2001 From: mforets Date: Fri, 20 Jul 2018 17:06:49 -0300 Subject: [PATCH 12/15] add algorithm text --- src/VPolygon.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/VPolygon.jl b/src/VPolygon.jl index db0d0507b0..9f29702b3c 100644 --- a/src/VPolygon.jl +++ b/src/VPolygon.jl @@ -72,6 +72,13 @@ Build a constraint representation of the given polygon. ### Output The same polygon but in constraint representation, an `AbstractHPolygon`. + +### Algorithm + +The algorithms consists of adding an edge for each consecutive pair of vertices. +Since the vertices are already ordered in counter-clockwise fashion (CWW), the +constraints will be sorted automatically (CCW) if we start with the first edge +between the first and second vertex. """ function tohrep(P::VPolygon{N}, ::Type{HPOLYGON}=HPolygon )::AbstractHPolygon{N} where {N<:Real, HPOLYGON<:AbstractHPolygon} From 5247e5c5d3bf68671336509aa5a528f1d5323f4a Mon Sep 17 00:00:00 2001 From: mforets Date: Sun, 22 Jul 2018 17:18:28 -0300 Subject: [PATCH 13/15] use XX_hull in VPolygon tohrep --- src/VPolygon.jl | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/src/VPolygon.jl b/src/VPolygon.jl index 9f29702b3c..3b6c48492c 100644 --- a/src/VPolygon.jl +++ b/src/VPolygon.jl @@ -82,51 +82,37 @@ between the first and second vertex. """ function tohrep(P::VPolygon{N}, ::Type{HPOLYGON}=HPolygon )::AbstractHPolygon{N} where {N<:Real, HPOLYGON<:AbstractHPolygon} - n = length(vertices_list(P)) + vl = vertices_list(P) + n = length(vl) if n == 0 # no vertex -> no constraint constraints_list = Vector{LinearConstraint{N}}(0) elseif n == 1 # only one vertex -> use function for singletons - return convert(HPOLYGON, Singleton(P.vertices_list[1])) + return convert(HPOLYGON, Singleton(vl[1])) elseif n == 2 # only two vertices -> use function for line segments - return convert(HPOLYGON, LineSegment(P.vertices_list[1], P.vertices_list[2])) + return convert(HPOLYGON, LineSegment(vl[1], vl[2])) else # find right-most vertex i = div(n, 2) - x = P.vertices_list[i][1] - while i > 1 && P.vertices_list[i-1][1] > x + x = vl[i][1] + while i > 1 && vl[i-1][1] > x # search forward in list i = i - 1 - x = P.vertices_list[i][1] + x = vl[i][1] end - while i < n && P.vertices_list[i+1][1] > x + while i < n && vl[i+1][1] > x # search backward in list i = i + 1 - x = P.vertices_list[i][1] + x = vl[i][1] end - # create constraints counter-clockwise - constraints_list = Vector{LinearConstraint{N}}(n) - j = 1 - i_start = i - i_stop = n - for it in 1:2 - while i < i_stop - constraints_list[j] = - halfspace_left(P.vertices_list[i], P.vertices_list[i+1]) - j += 1 - i += 1 - end - if it == 1 - constraints_list[j] = - halfspace_left(P.vertices_list[n], P.vertices_list[1]) - j += 1 - i = 1 - i_stop = i_start - end - end + # create constraints ordered in CCW starting at the right-most index + upper_hull = [halfspace_left(vl[j], vl[j+1]) for j in i:length(vl)-1] + mid_hull = [halfspace_left(vl[end], vl[1])] + lower_hull = [halfspace_left(vl[j], vl[j+1]) for j in 1:i-1] + constraints_list = vcat(upper_hull, mid_hull, lower_hull) end return HPOLYGON{N}(constraints_list) end From 85b6b32b71d8f2063897d2f1c8a0825a618a4108 Mon Sep 17 00:00:00 2001 From: mforets Date: Sun, 22 Jul 2018 17:33:02 -0300 Subject: [PATCH 14/15] add halfspace_right and function for LineSegment --- docs/src/lib/representations.md | 3 +++ src/HalfSpace.jl | 26 ++++++++++++++++++++++++++ src/LineSegment.jl | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/docs/src/lib/representations.md b/docs/src/lib/representations.md index a7be7beb71..c63ab2de66 100644 --- a/docs/src/lib/representations.md +++ b/docs/src/lib/representations.md @@ -99,6 +99,7 @@ dim(::HalfSpace{Float64}) an_element(::HalfSpace{Float64}) ∈(::AbstractVector{Float64}, ::HalfSpace{Float64}) LazySets.halfspace_left(::AbstractVector{Float64}, ::AbstractVector{Float64}) +LazySets.halfspace_right(::AbstractVector{Float64}, ::AbstractVector{Float64}) ``` ## Hyperplane @@ -165,6 +166,8 @@ LineSegment dim(::LineSegment{Float64}) σ(::AbstractVector{Float64}, ::LineSegment{Float64}) ∈(::AbstractVector{Float64}, ::LineSegment{Float64}) +LazySets.halfspace_left(::LineSegment) +LazySets.halfspace_right(::LineSegment) ``` ## Polygons diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index ce26f5cb23..68c2c3263f 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -181,3 +181,29 @@ function halfspace_left(p::AbstractVector{N}, a = [q[2] - p[2], p[1] - q[1]] return HalfSpace(a, dot(p, a)) end + +""" + halfspace_right(p::AbstractVector{N}, + q::AbstractVector{N})::HalfSpace{N} where {N<:Real} + +Return a half-space describing the 'right' of a two-dimensional line segment through +two points. + +### Input + +- `p` -- first point +- `q` -- second point + +### Output + +The half-space whose boundary goes through the two points `p` and `q` and which +describes the right-hand side of the directed line segment `pq`. + +### Algorithm + +See the documentation of `halfspace_left`. +""" +function halfspace_right(p::AbstractVector{N}, + q::AbstractVector{N})::HalfSpace{N} where {N<:Real} + return halfspace_right(q, p) +end \ No newline at end of file diff --git a/src/LineSegment.jl b/src/LineSegment.jl index 31681941cb..255f876d04 100644 --- a/src/LineSegment.jl +++ b/src/LineSegment.jl @@ -144,3 +144,7 @@ function ∈(x::AbstractVector{N}, L::LineSegment{N})::Bool where {N<:Real} return min(L.p[1], L.q[1]) <= x[1] <= max(L.p[1], L.q[1]) && min(L.p[2], L.q[2]) <= x[2] <= max(L.p[2], L.q[2]) end + +halfspace_left(L::LineSegment) = halfspace_left(L.p, L.q) + +halfspace_right(L::LineSegment) = halfspace_right(L.p, L.q) \ No newline at end of file From c42b8a4e640753f5b3ef3e89e37484a8dab9e825 Mon Sep 17 00:00:00 2001 From: mforets Date: Sun, 22 Jul 2018 17:48:46 -0300 Subject: [PATCH 15/15] add spaces and docs --- src/HalfSpace.jl | 2 +- src/LineSegment.jl | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/HalfSpace.jl b/src/HalfSpace.jl index 68c2c3263f..5ae5f7033c 100644 --- a/src/HalfSpace.jl +++ b/src/HalfSpace.jl @@ -206,4 +206,4 @@ See the documentation of `halfspace_left`. function halfspace_right(p::AbstractVector{N}, q::AbstractVector{N})::HalfSpace{N} where {N<:Real} return halfspace_right(q, p) -end \ No newline at end of file +end diff --git a/src/LineSegment.jl b/src/LineSegment.jl index 255f876d04..64aefab152 100644 --- a/src/LineSegment.jl +++ b/src/LineSegment.jl @@ -145,6 +145,36 @@ function ∈(x::AbstractVector{N}, L::LineSegment{N})::Bool where {N<:Real} min(L.p[2], L.q[2]) <= x[2] <= max(L.p[2], L.q[2]) end +""" + halfspace_left(L::LineSegment) + +Return a half-space describing the 'left' of a two-dimensional line segment through +two points. + +### Input + + - `L` -- line segment + +### Output + +The half-space whose boundary goes through the two points `p` and `q` and which +describes the left-hand side of the directed line segment `pq`. +""" halfspace_left(L::LineSegment) = halfspace_left(L.p, L.q) -halfspace_right(L::LineSegment) = halfspace_right(L.p, L.q) \ No newline at end of file +""" + halfspace_right(L::LineSegment) + +Return a half-space describing the 'right' of a two-dimensional line segment through +two points. + +### Input + + - `L` -- line segment + +### Output + +The half-space whose boundary goes through the two points `p` and `q` and which +describes the right-hand side of the directed line segment `pq`. +""" +halfspace_right(L::LineSegment) = halfspace_right(L.p, L.q)