This paper by Tupper details a method for graphing two-dimensional implicit equations and inequalities. This package gives an implementation of the paper's basic algorithms to allow the julia user to naturally represent and easily render graphs of implicit functions and equations.
The basic idea is to express a equation in $x$ and $y$ variables in terms of a function of two variables as a predicate. The plot function Plots is used to plot these predicates.
For example, the Devils curve is graphed over the default region as follows:
In [ ]:
using Plots, ImplicitEquations
pyplot()
a,b = -1,2
f(x,y) = y^4 - x^4 + a*y^2 + b*x^2
r = (f==0)
plot(r)
Out[ ]:
The f == 0 expression above creates a Predicate that is graphed by plot. For all but the case of f==g (for two functions) Predicates are generated by overloading the logical operators for functions on the left and real values or functions on the right: <, <= (\le<tab>), \Equal<tab>, \lessgtr<tab>, >= (\ge<tab>), and > . As == and != can already be used to compare functions in a different way, we use either eq(f,g) or neq(f,g) for these comparisons. Should infix notation be preferred, the Unicode operators f \Equal<tab> g or f \lessgtr<tab> g may be used.
For example, the Trident of Newton can be represented in Cartesian form as follows:
In [ ]:
## trident of Newton
c,d,e,h = 1,1,1,1
f(x,y) = x*y
g(x,y) =c*x^3 + d*x^2 + e*x + h
plot(eq(f,g)) ## aka f ⩵ g (using Unicode\Equal<tab>)
Out[ ]:
Inequalities can be graphed as well
In [ ]:
f(x,y) = x - y
plot(f < 0)
Out[ ]:
This example is from Tupper's paper:
In [ ]:
f(x,y) = (y-5)* cos(4sqrt((x-4)^2 +y^2))
g(x,y) = x * sin(2*sqrt(x^2 + y^2))
plot(f > g, (-10, 10), (-10, 10))
Out[ ]:
This graph illustrates the algorithm employed to graph f == 0 where f(x,y) = y - sqrt(x):
The basic algorithm is to initially break up the graphing region into square regions. (This uses the number of pixels, which are specified by W and H above.)
These regions are checked for the predicate.
The graph plots each "black" region as a "pixel". The "red" regions may optionally be colored, if a named color is passed through the keyword red.
For example, the Devil's curve is a bit different with red coloring:
In [ ]:
a,b = -1,2
f(x,y) = y^4 - x^4 + a*y^2 + b*x^2
r = (f==0)
plot(r, red=:red) # show undecided regions in red
Out[ ]:
The plot function accepts the usual keywords of Plots and also:
plot(pred, (a,b), (c, d))plot(pred, N=4, M=5). The default is M=8 by N=8 or 256 x 256.red and black.This example, the Batman equation, Uses a few new things: the screen function is used to restrict ranges and logical operators to combine predicates.
In [ ]:
f0(x,y) = ((x/7)^2 + (y/3)^2 - 1) * screen(abs(x)>3) * screen(y > -3*sqrt(33)/7)
f1(x,y) = ( abs(x/2)-(3 * sqrt(33)-7) * x^2/112 -3 +sqrt(1-(abs((abs(x)-2))-1)^2)-y)
f2(x,y) = y - (9 - 8*abs(x)) * screen((abs(x)>= 3/4) & (abs(x) <= 1) )
f3(x,y) = y - (3*abs(x) + 3/4) * I_((1/2 < abs(x)) & (abs(x) < 3/4)) # alternate name for screen
f4(x,y) = y - 2.25 * I_(abs(x) <= 1/2)
f5(x,y) = (6 * sqrt(10)/7 + (1.5-.5 * abs(x)) - 6 * sqrt(10)/14 * sqrt(4-(abs(x)-1)^2) -y) * screen(abs(x) >= 1)
r = (f0==0) | (f1==0) | (f2== 0) | (f3==0) | (f4==0) | (f5==0)
plot(r, (-7, 7), (-4, 4), red=:black)
Out[ ]:
The above example illustrates a few things:
&, |. Use ! for negation.screen function can be used to restrict values according to some predicate call.(abs(x) >= 3/4) & (abs(x) <= 1) within screen are not typical in that one can't write 3/4 <= abs(x) <= 1, a convenient Julian syntax. This is due to the fact that the "xs" being evaluated are not numbers, rather intervals via ValidatedNumerics. For intervals, values may be true, false or "maybe" so a different interpretation of the logical operators is given that doesn't lend itself to the more convenient notation.(1-x^2)*(2-y^2) and csc(1-x^2)*cot(2-y^2) can be 10 times.)A common calculus problem is to find the tangent line using implicit differentiation. We can plot the predicate to create the implicit graph, then add a layer with plot!:
In [ ]:
f(x,y) = x^2 + y^2
plot(f == 2*3^2)
## now add tangent at (3,3)
a,b = 3,3
dydx(a,b) = -b/a # implicit differentiate to get dy/dx =-y/x
tl(x) = b + dydx(a,b)*(x-a)
plot!(tl, linewidth=3)
Out[ ]:
Many such plots are simply a single level of a contour plot. Contour plots can be drawn with the Plots package too. A simple contour plot will be faster than this package.
The SymPy package exposes SymPy's plot_implicit feature that will implicitly plot a symbolic expression in 2 variables including inequalities. The algorithm there also follows Tupper and uses interval arithmetic, as possible.
LOTS:
mod, or ± to be defined.