Rendering Sierpinski Curves

   



Rendering Ellipses with Recursion

Consider the set of ellipses displayed in Figure 16.3.

click to expand
Figure 16.3: A set of recursion-based ellipses.

The SVG document in Listing 16.4 demonstrates how to define an SVG document that generates a set of recursion-based ellipses.

Listing 16.4 nestedShadowEllipses1.svg

start example
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="100%" height="100%" onload="init(evt)"   xmlns="http://www.w3.org/2000/svg"> <script type="text/ecmascript">  <![CDATA[   var width          = 800.;   var height         = 500.;   var basePointX     = 300.;   var basePointY     = 180.;   var currentX       = 0.;   var currentY       = 0.;   var shiftX         = 15.;   var shiftY         = 15.;   var scale          = 0.90;   var maxLevel       = 10.;   var level          = maxLevel;   var majorAxis      = 200.;   var minorAxis      = 100.;   var pointPath      = "";   var ellipseColors  = ['red','green','blue',                         'white','yellow','red',                         'magenta','black','green'];   var colorCount     = 9.;   var style          = "";   var strokeWidth    = 1.;   var dashStyle      = "4 4 4 4";   var ellipseNode    = null;   var svgDocument    = null;   var target         = null;   var gcNode         = null;   function init(event)   {      target = event.getTarget();      svgDocument = target.getOwnerDocument();      gcNode = svgDocument.getElementById("gc");      drawPattern(maxLevel,                  basePointX, basePointY,                  majorAxis, minorAxis);   }   function drawPattern(level, xCoord, yCoord,                        majorAxis, minorAxis)   {      if( level >= 0 )      {         // draw "shadow" ellipse...         style = "fill:black;";         ellipseNode = svgDocument.createElement(                                            "ellipse");         ellipseNode.setAttribute("cx", xCoord+shiftX);         ellipseNode.setAttribute("cy", yCoord+shiftY);         ellipseNode.setAttribute("rx", majorAxis);         ellipseNode.setAttribute("ry", minorAxis);         ellipseNode.setAttribute("style", style);         gcNode.appendChild(ellipseNode);         drawPattern(level-1, xCoord, yCoord,                        scale*minorAxis, scale*majorAxis);         // draw white ellipse...         style  = "fill:none";         style += ";stroke:white";         style += ";stroke-width:"+strokeWidth;         style += ";stroke-dasharray:"+dashStyle;         ellipseNode = svgDocument.createElement(                                              "ellipse");         ellipseNode.setAttribute("cx", xCoord+shiftX);         ellipseNode.setAttribute("cy", yCoord+shiftY);         ellipseNode.setAttribute("rx", majorAxis-shiftX);         ellipseNode.setAttribute("ry", minorAxis-shiftY);         ellipseNode.setAttribute("style", style);         gcNode.appendChild(ellipseNode);         // draw "regular" ellipse...         style  = "fill:";         style += ellipseColors[level%colorCount];         ellipseNode = svgDocument.createElement(                                        "ellipse");         ellipseNode.setAttribute("cx", xCoord);         ellipseNode.setAttribute("cy", yCoord);         ellipseNode.setAttribute("rx", majorAxis);         ellipseNode.setAttribute("ry", minorAxis);         ellipseNode.setAttribute("style", style);         gcNode.appendChild(ellipseNode);         drawPattern(level-1, xCoord, yCoord,                     scale*minorAxis, scale*majorAxis);      }   } // drawPattern  ]]> </script> <!-- ============================ --> <g  transform="translate(10,10)">    <rect x="0" y="0"          width="800" height="500"          fill="none" stroke="none"/>  </g> </svg>
end example

Remarks

Listing 16.4 demonstrates a simple yet useful point regarding recursively invoked functions: you can embed all sorts of non-recursive elements in them. In Listing 16.4, a 'shadow' ellipse is rendered as a dark ellipse, followed by a recursive invocation, then a dashed white ellipse is followed by yet another recursive invocation. Obviously you are not limited to rendering only ellipses; you could also include recursive invocations of other geometric objects (such as polygons), or even have two functions recursively invoke each other. As you can see, there is virtually no limit to the variations you can add to recursively invoked functions, but remember that you can make a relatively small change in your code that can significantly reduce the performance. In the SVG/ECMAScript environment, the most significant performance decrease tends to occur with recursion that involves rendering a large number of ellipses, elliptic arcs, or Bezier curves (or some combination thereof), whereas performance will not be adversely affected to the same extent when you render a comparable number of polygons. This performance difference tends to be true even when recursion is not involved, but in such cases you need to dynamically generate a much greater number of objects in order to produce a performance penalty that is comparable to that of the absented recursion.



   



Fundamentals of SVG Programming. Concepts to Source Code
Fundamentals of SVG Programming: Concepts to Source Code (Graphics Series)
ISBN: 1584502983
EAN: 2147483647
Year: 2003
Pages: 362

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net