This package provides types and methods that are useful for working with curves and regions in the (extended) complex plane.

Most functionality is provided through Julia types (roughly equivalent to classes in an object-oriented language). Per Julia conventions, these are all capitalized. You use these capitalized names to create values of the type; e.g., Segment and Circle.

Other functions (methods, in Julia terms) may create values of these types, but since they are not distinct types themselves, they are not capitalized. For example, the rectangle method creates a Polygon.

The methods in this package should work not only with the built-in Complex type, but also with the Polar and Spherical types from the ComplexValues package, which it re-exports.

Abstract types

All abstract types have names starting with Abstract. You probably won't encounter them unless you want to extend the provided functionality.

An abstract type cannot itself be instantiated as a value. They serve as supertypes that collect common-denominator functionality, much like an interface in other languages. For example, any AbstractCurve is supposed to provide functions for finding points, tangents, and normals along the curve. Specific subtypes such as a Ray or Arc provide additional specialized functionalities appropriate to the subtypes.

Curve, Path, and Region

A curve is meant to be a smooth, non-self-intersecting curve in the extended complex plane. There is a generic Curve type that requires you to specify an explicit parameterization that is not checked for smoothness or even continuity. Implementations are given for more specific types of curve.

A path is a piecewise-continuous complex-valued path. In practice a Path can be specified as an array of curves. The path is checked for continuity at creation time. The most important provided specific path types are Polygon and CircularPolygon.

Both curves and paths have closed variants. These are additionally checked that the initial and final points are the same.

One atypical aspect of curves and paths, even "closed" ones, is that they lie in the extended or compactified complex plane and thus may be unbounded. For instance, a line in the plane may be interpreted as a circle on the Riemann sphere, and is thus a "closed" curve passing through infinity.

A region is an open region in the extended plane bounded by a closed curve or path.

Some examples:

julia> ℓ = Line(1/2,1/2+1im)  # line through 0.5 and 0.5+1i
Line{Complex{Float64}} in the complex plane:
   through (0.5 + 0.0im) parallel to (0.0 + 1.0im)

julia> c = 1 / ℓ          # a circle
Circle{Complex{Float64}} in the complex plane:
   centered at (1.0 + 0.0im) with radius 1.0, negatively oriented

julia> intersect(ℓ,c)
2-element Array{Complex{Float64},1}:
 0.5 + 0.8660254037844386im
 0.5 - 0.8660254037844386im

julia> plot(ℓ); plot!(c)
Plot{Plots.GRBackend() n=2}

line and circle

julia> plot(Spherical(ℓ)); plot!(Spherical(c))
Plot{Plots.GRBackend() n=40}

line and circle on Riemann sphere

julia> reflect(-1,c)       # reflection of a point through the circle
0.5 + 0.0im

julia> plot(interior(ℓ))   # plot a half-plane
Plot{Plots.GRBackend() n=1}


julia> h = n_gon(7)
Polygon with 7 vertices:
   1.0 + 0.0im, interior angle 0.7142857142857143⋅π
   0.6234898018587336 + 0.7818314824680298im, interior angle 0.7142857142857143⋅π
   -0.22252093395631434 + 0.9749279121818236im, interior angle 0.7142857142857143⋅π
   -0.900968867902419 + 0.43388373911755823im, interior angle 0.7142857142857143⋅π
   -0.9009688679024191 - 0.433883739117558im, interior angle 0.7142857142857143⋅π
   -0.2225209339563146 - 0.9749279121818236im, interior angle 0.7142857142857143⋅π
   0.6234898018587334 - 0.7818314824680299im, interior angle 0.7142857142857143⋅π

julia> plot(h);

julia> for k in 1:7
       	z = exp(k*2im*π/20)
       	plot!(z*h - 0.5k - 0.1im*k^2)


julia> p = Polygon([0,-1im,(0,0),1im,(pi,pi)])      # channel with a step
Polygon with 5 vertices:
   0.0 + 0.0im, interior angle 1.5⋅π
   0.0 - 1.0im, interior angle 0.5⋅π
   Inf + 0.0im, interior angle 0.0⋅π
   0.0 + 1.0im, interior angle 1.0⋅π
   Inf + 0.0im, interior angle 0.0⋅π

julia> plot(interior(p))
Plot{Plots.GRBackend() n=1}

channel with step


Boundaries and endpoints are not well-posed ideas in floating-point, since an arbitrarily small perturbation to a value can move a point on or off of them. Thus many concepts in the package such as intersection or continuity are checked only up to a small tolerance. This value can be set on a per-call basis, or by using global defaults.

Global defaults

For work at the REPL, it's convenient to be able to set an influential parameter just once rather than in multiple calls. This mechanism is provided via ComplexRegions.default. You can see all the default parameters and values as follows:

julia> ComplexRegions.default()
Dict{Symbol,Float64} with 1 entry:
  :tol => 1.0e-12

Changing them is done with the same function:

julia> ComplexRegions.default(tol=1e-8)
[ Info: Default value of `tol` set to 1.0e-8.

Be advised that this type of "stateful" computing brings some subtle undesirable consequences. For example, if the global default tol is changed in a future release of the package, existing code could give different results when testing for interior points. If maximum reproducibility is a concern, you should develop the habit of setting all defaults yourself at the beginning of your code.