High-Level Template for Code Examples

   



Rendering Nested Triangles via Recursion

Consider the image displayed in Figure 16.1, which is a recursion-based example that implements the code template in Listing 16.1.

click to expand
Figure 16.1: A set of nested triangles.

The SVG document in Listing 16.2 demonstrates how to define an SVG document that generates a set of nested triangles.

Listing 16.2 nestedTriangles1.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     = 0.;     var currentX       = 0.;     var currentY       = 0.;     var offsetX        = 0.0;     var offsetY        = 0.0;     var level          = 5.;     var triangleWidth  = 800.;     var triangleHeight = 300.;     var vertexCount    = 3.;     var xPts           = Array(vertexCount);     var yPts           = Array(vertexCount);     var newXPts        = Array(vertexCount);     var newYPts        = Array(vertexCount);     var pointPath      = "";     var ellipseColors  = ['red','green',                           'blue','yellow'];     var colorCount     = 4.;     var triangleNode   = null;     var svgDocument    = null;     var target         = null;     var gcNode         = null;     function init(event)     {        target = event.getTarget();        svgDocument = target.getOwnerDocument();        gcNode = svgDocument.getElementById("gc");        initializeTriangle();        drawPattern(level, xPts, yPts);     }     function initializeTriangle()     {        // clockwise from top vertex...        xPts[0] = basePointX;        yPts[0] = basePointY;        xPts[1] = basePointX+triangleWidth/2;        yPts[1] = basePointY+triangleHeight;        xPts[2] = basePointX-triangleWidth/2;        yPts[2] = basePointY+triangleHeight;     } // initializeTriangle     function drawPattern(level, oldXPts, oldYPts)     {        if( level >= 0 )        {                       // arrays for inner triangle...           newXPts = Array(vertexCount);           newYPts = Array(vertexCount);           for(v=0; v<vertexCount; v++)           {              // clockwise from upper-left vertex...              newXPts[v] = (oldXPts[v]+                           oldXPts[(v+1)%vertexCount])/2;              newYPts[v] = (oldYPts[v]+                           oldYPts[(v+1)%vertexCount])/2;           }           pointPath = "";           for(var v=0; v<vertexCount; v++)           {              pointPath += newXPts[v]+","+newYPts[v]+" ";           }           fillColor  = "fill:";           fillColor += ellipseColors[level%colorCount];           triangleNode = svgDocument.createElement(                                              "polygon");           triangleNode.setAttribute("points",pointPath);           triangleNode.setAttribute("style", fillColor);           gcNode.appendChild(triangleNode);           drawPattern(level-1, newXPts, newYPts);        }     } // 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

The key idea in Listing 16.2 involves creating a new triangle whose vertices are the midpoints of the sides of the current triangle, as illustrated in the following code fragment:

   // arrays for inner triangle... newXPts = Array(vertexCount); newYPts = Array(vertexCount); for(var v=0; v<vertexCount; v++) {    // clockwise from upper-left vertex...    newXPts[v] = (oldXPts[v]+                   oldXPts[(v+1)%vertexCount])/2;    newYPts[v] = (oldYPts[v]+                   oldYPts[(v+1)%vertexCount])/2; }

If you use the same arrays for the current triangle and the nested triangle instead of creating new arrays for the vertices of the nested triangle, you will clobber the values of the vertices of the current triangle and the result will not be what you expected. If you are curious, though, try replacing the existing loop with the code fragment given below:

for(var v=0; v<vertexCount; v++) {     // clockwise from upper-left vertex...     oldXPts[v] = (oldXPts[v]+                    oldXPts[(v+1)%vertexCount])/2;     oldYPts[v] = (oldYPts[v]+                    oldYPts[(v+1)%vertexCount])/2; }

Don't forget to replace the other occurrences of newXPts and newYPts with oldXPts and oldYPts, respectively.



   



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