Skip to content
julia
module Predicates
    using ExactPredicates, ExactPredicates.Codegen
    import ExactPredicates: ext
    import ExactPredicates.Codegen: group!, @genpredicate
    import GeometryOps: _False, _True, _booltype, _tuple_point
    import GeoInterface as GI

    #= Determine the orientation of c with regards to the oriented segment (a, b).
    Return 1 if c is to the left of (a, b).
    Return -1 if c is to the right of (a, b).
    Return 0 if c is on (a, b) or if a == b. =#
    orient(a, b, c; exact) = _orient(_booltype(exact), a, b, c)

If exact is true, use ExactPredicates to calculate the orientation.

julia
    _orient(::_True, a, b, c) = ExactPredicates.orient(_tuple_point(a, Float64), _tuple_point(b, Float64), _tuple_point(c, Float64))

If exact is false, calculate the orientation without using ExactPredicates.

julia
    function _orient(exact::_False, a, b, c)
        a = a .- c
        b = b .- c
        return _cross(exact, a, b)
    end

    #= Determine the sign of the cross product of a and b.
    Return 1 if the cross product is positive.
    Return -1 if the cross product is negative.
    Return 0 if the cross product is 0. =#
    cross(a, b; exact) = _cross(_booltype(exact), a, b)

    #= If `exact` is `true`, use exact cross product calculation created using
    `ExactPredicates`generated predicate. Note that as of now `ExactPredicates` requires
    Float64 so we must convert points a and b. =#
    _cross(::_True, a, b) = _cross_exact(_tuple_point(a, Float64), _tuple_point(b, Float64))

Exact cross product calculation using ExactPredicates.

julia
    @genpredicate function _cross_exact(a :: 2, b :: 2)
        group!(a...)
        group!(b...)
        ext(a, b)
    end

If exact is false, calculate the cross product without using ExactPredicates.

julia
    function _cross(::_False, a, b)
        c_t1 = GI.x(a) * GI.y(b)
        c_t2 = GI.y(a) * GI.x(b)
        c_val = if isapprox(c_t1, c_t2)
            0
        else
            sign(c_t1 - c_t2)
        end
        return c_val
    end

end

import .Predicates

If we want to inject adaptivity, we would do something like:

function cross(a, b, c) # try Predicates._cross_naive(a, b, c) # check the error bound there # then try Predicates._cross_adaptive(a, b, c) # then try Predicates._cross_exact end


This page was generated using Literate.jl.