Quadtree Algorithm for Implicit Curve Drawing
Implicit Curve
Background
The function which is defined as is known as implicit curve, eg. is an implict curve. Similarly, the function which is in the form of is called implicit surface. Sometimes it is possible to convert an implicit reprentation into the explicit form, as can be written as , or into parmeterized form, such as the same equation can be written as but in some cases transformation can be hard, as in .
Explicit and parameterised curves are comparatively easier to plot than the implicit curve. To plot which is an explict function, we have to evalute at discrete location where may be horizontal resolution of the viewport, on the other hand we need to evaluate at different location in brute force attempt to plot implicit curves.
We can tackle the problem using two methods : A. Finding the solution of and thereafter following the curve, B. Marching cube. The first method start by solving and then exploiting gradient information to move towards the best direction. It works good in practice, but it doesn’t produce desirable result when gradient vanishes (singular points), the curve is highly twisted, or the curve is dense. The marching cube algorithm divides the viewport into small sqaures and evaluate the function at each vertex. Evaluated function value at each vertex, if function is well defined at the vetex, can either be , or . Ignoring where at the vertex, there are sixteen possible combination of the status of four vertex. We mark each vertex of square with . The square which has at least one vertex which sign differs from all other vertex or where will definitely have a curve segment if the function is continuous at every point in the square. Following figure shows different possible configuration. First and ninth squares are empty whereas eighth and sixteenth show ambiguous configuration. Marching square is a better approach than curve following however it fails handle singularties and saddle points correctly. Furtheremore, it has to evaluate at each vertex of the square. The evaluation may be costly.
Figure 1: Sixteen possible combinations: Circles represent
Quadtree Algorithm for Implicit Curve
The quadtree algorithm is an extention of marching square algorithm. The space is
explored recursively by the algorithm to ensure that if the curve passes through the
square. The algorithm maintain two variable SEARCH_DEPTH
and
PLOT_DEPTH
. All square cells are examined to the SEARCH_DEPTH
without any function evalution. Thereafter the algorithm starts testing if a sqaure
cell has a curve segment. The square cells with curve segments are explored further up toPLOT_DEPTH
then the curve segment is added to the path.
Figure 2: Space exploration for |x| - |y| = 0
Digression
I implemented this algorithm for GeoGebra which supports a range of platform including desktop and web. The implemented algorithm worked fine on desktop however gui often became unresponsive when I tested the algorithm on GeoGebra Web. I tried some optimizations but they failed to work. Finally, I ran these diagonstics for java and javascript separately to discover the actual difference in performance on my 2.7 GHz, 8 GB Quad Core Dell notebook. It prohabited the algorithm from exploring the tree deeply in web view.
Bisection vs Linear Interpolation
Suppose the algorithm has detected a curve segment passing between two points and . That is, the value evaluated at point and have opposite sign. How can we approximate the curve between and . There are two method - bisection, linear interpolation. In bisection method we take the mid-point of and . Intuitively, it is not a good method, because if the value of funtion at is more close to zero than that of function at then it is more likely that the curve is close to point .
Let’s assume that is parallel to x-axis and that and . Let be a point on where function evaluate to zero and be the mid point of and .
The approximation at the right hand side follows because and higher order term have been ignored. Notice that I have dropped y term from the Taylor series expansion because of the assumption that the is parallel to x-axis that is y is a fixed constant. Similarly at mid point M
We can easily notice that in bisection method error is summed up and halved. We can do better using linear interpolation. For simplicity Let’s denote and
Here the error term in approxmation is which is quadratic and therfore smaller than that of the bisection method for
Limitations
Quadtree algorithm performs better than marching cube algorithm, however it still suffers from certain limitations. It fails to correctly plot curve which is entirely in a single square cell, which has saddle or bifurcation point, or which intersects a square cell twice. We can handle singularities or bifurcation point by maintaining gradient information of curve, because gradient vanishes at singularities. Problem of twice intersection can be handled by communicating information among neighborhood square. However the first problem can’t be solve without exploring the tree further.
Quadtree and marching cube algorithm fails when a function changes sign but doesn’t approach to zero or a function doesn’t change sign but become zero evantually between two point. For example is discontinous at , and it changes sign at without having any segment there. Similarly represents a circle with radius and center however the implicit equation never become negative.
Improvement in quadtree
To improve the algorithm we need to maintain gradient information and share information among neighbors. Both can increase the complexity if evaluated at each level of the tree.Therefore, combined idea of marching cube and quadtree is used. The function and its gradient is evalauted at the SEARCH_DEPTH
. The gradients tend to zero near singularity. If gradients are too close to zero the algorithm mark the cell as singular. The algorithm when proceed beyond the SEARCH_DEPTH
, it checks the neiborhood and mark them whenever it add a segment.
Javascript implementation of quadtree algorithm
Try interactive demo here