BrainMeta'   Connectomics'  

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> Syntax Tree Drawer In SVG
Guest
post Feb 10, 2006, 04:45 PM
Post #1


Unregistered









Syntax Tree Drawer in SVG

This software consists of an XSLT stylesheet and a recursive algorithm in ECMAScript that create dynamic SVG images of tree data structures. It is intended for syntacticians since drawing trees is a very common activity in Linguistics and they quickly become tiresome and tedious.

DIRECTIONS: COPY CODE BELOW TO FILE, SAVE AS "TEST.SVG", AND NOW OPEN FILE IN BROWSER.



<?xml version="1.0" encoding="UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg" onload="init()">
<style type="text/css">
<![CDATA[
g text {
text-anchor:middle;
font-family:'Lucida Console Unicode', Arial, Helvetica, Serif;
font-size:20px;
}

g line {
stroke:black;
}
]]>
</style>
<script type="text/ecmascript">
<![CDATA[
var fontSize = 20;
var wordSpacing = 20; //wordSpacing/2 == text padding
var marginLeft = 10;
var marginTop = 0;
var width = 0; //read only
var height = 0; //read only
var branchHeight = fontSize;
var branchPaddingTop = fontSize/4;
var branchPaddingBottom = 0;



var rootNode;
function init(){
var gElements = document.getElementsByTagName('g');
rootNode = gElements.item(0);
drawTree();
}


//positions all the nodes in a tree structure
var buffer = '';
function drawTree(){
r_drawTree(rootNode, null, false, marginLeft, marginTop + fontSize, 0);

}
function dump(obj){
var buffer = '';
for(key in obj){
buffer += key + ' = ' + obj[key] + "\n";
}
return buffer;
}
function r_drawTree(containerNode, parentLabel, isEmptyParent, shiftLeft, shiftTop, parentWidth){//returns the width of node's children
var isEmpty = false;
var isParent = (containerNode.getElementsByTagName('g').length ? true : false);
var childrenWidth = 0;
var childrenLabels = Array();
var nodeLabel;
var nodeBranch;
var nodeExtendBranch;
var nodeLabelWidth;
var leafY;

//get and handle children ============================
for(var i = 0; i < containerNode.childNodes.length; i++){
if(containerNode.childNodes.item(i).nodeName == 'text'){
nodeLabel = containerNode.childNodes.item(i);

//determine the width of the label
if(!nodeLabel.firstChild || !nodeLabel.firstChild.nodeValue || nodeLabel.firstChild.nodeValue.match(/^\s*$/) ){
nodeLabelWidth = wordSpacing;
isEmpty = true;
}
else {
nodeLabelWidth = wordSpacing + nodeLabel.getComputedTextLength();
isEmpty = false;
}
if(nodeLabelWidth < parentWidth)
nodeLabelWidth = parentWidth;
}
//connecting branch
else if(containerNode.childNodes.item(i).nodeName == "line"){
nodeBranch = containerNode.childNodes.item(i);
}
//children nodes
else if(containerNode.childNodes.item(i).nodeName == "g"){
var returned = r_drawTree(containerNode.childNodes.item(i), nodeLabel, isEmpty, shiftLeft + childrenWidth, shiftTop + (isEmpty ? branchHeight : branchHeight + fontSize), nodeLabelWidth);
childrenLabels.push(returned[0]);
childrenWidth += returned[1];
}
}

//draw label, children, and branches ==================
if(!childrenWidth) //there are no children; this is the branch end
childrenWidth = nodeLabelWidth;
if(nodeLabel == null)
throw Error("Error: Every child must have a label (every <g> must contain a <text>, even if it is empty). Revise your XSLT stylesheet.");

//position label
var thisY = shiftTop;
var thisX;
if(childrenLabels.length){
var firstChild = parseFloat(childrenLabels[0].label.getAttribute('x'));
var lastChild = parseFloat(childrenLabels[childrenLabels.length-1].label.getAttribute('x'));
thisX = firstChild + (lastChild - firstChild)/2;
}
else
thisX = shiftLeft + childrenWidth/2;
if(thisY > height)
height = thisY;
if(shiftLeft + childrenWidth > width)
width = shiftLeft + childrenWidth;
nodeLabel.setAttribute('y', thisY + 'px');
nodeLabel.setAttribute('x', thisX + 'px');

//connect branches from child labels to parent label
leafY = thisY;
for(var i = 0; i < childrenLabels.length; i++){
childrenLabels[i].branch.setAttribute('x1', thisX + 'px');
childrenLabels[i].branch.setAttribute('y1', (thisY + (isEmpty ? -fontSize : branchPaddingTop)) + 'px');
}

//below root: anchor one end of the branch to the label
if(containerNode != rootNode){
if(nodeBranch){
nodeBranch.setAttribute('x2', nodeLabel.getAttribute('x'));
nodeBranch.setAttribute('y2', (parseFloat(nodeLabel.getAttribute('y')) - fontSize - branchPaddingBottom) + 'px');
}
}
//else if(nodeBranch) //hide it if it was accidentally included in the source code
// nodeBranch.style.display = 'none';
return Array({label:nodeLabel, branch:nodeBranch}, childrenWidth);
}
]]>
</script>
<g transform = "translate(15,0) scale(1,1)">
<g id="tree">
<text>ROOT</text>
<g>
<text>TEST</text>
<line/>
</g>
<g>
<text>TEST2</text>
<line/>
<g>
<text>C</text>
<line/>
<g>
<text>is<tspan style="baseline-shift:sub; font-size:smaller;">i</tspan></text>
<line/>
</g>
</g>
<g>
<text>T″</text>
<line/>
<g>
<text>D″</text>
<line/>
<g>
<text>D″</text>
<line/>
<g>
<text/>
<line/>
</g>
<g>
<text>D′</text>
<line/>
<g>
<text>D</text>
<line/>
<g>
<text>the</text>
<line/>
</g>
</g>
<g>
<text>N″</text>
<line/>
<g>
<text>N′</text>
<line/>
<g>
<text>N</text>
<line/>
<g>
<text>boy</text>
<line/>
</g>
</g>
</g>
</g>
</g>
</g>
<g>
<text>D′</text>
<line/>
<g>
<text>D</text>
<line/>
<g>
<text>'s</text>
<line/>
</g>
</g>
<g>
<text>N″</text>
<line/>
<g>
<text>N′</text>
<line/>
<g>
<text>N</text>
<line/>
<g>
<text>mother</text>
<line/>
</g>
</g>
</g>
</g>
</g>
</g>
<g>
<text>T′</text>
<line/>
<g>
<text>T</text>
<line/>
<g>
<text>t<tspan style="baseline-shift:sub; font-size:smaller;">i</tspan></text>
<line/>
</g>
</g>
<g>
<text>V″</text>
<line/>
<g>
<text/>
<line/>
</g>
<g>
<text>V′</text>
<line/>
<g>
<text>V</text>
<line/>
<g>
<text>baking</text>
<line/>
</g>
</g>
<g>
<text>t<tspan style="baseline-shift:sub; font-size:smaller;">ii</tspan></text>
<line/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
Go to the top of the page
+Quote Post
Rick
post Feb 10, 2006, 05:21 PM
Post #2


Supreme God
*******

Group: Basic Member
Posts: 5916
Joined: Jul 23, 2004
From: Sunny Southern California
Member No.: 3068



Did that. Just get the code in the browser (MSIE 6.0). Must need a plugin, I suppose.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Guest
post Feb 10, 2006, 08:20 PM
Post #3


Unregistered









sorry to hear that. Wasn't sure if IE needed a plugin or not. Should work without a plugin in Firefox 1.5 or later.
Go to the top of the page
+Quote Post
Guest
post Feb 10, 2006, 09:27 PM
Post #4


Unregistered









hey Rick, try this:

in the same directory are "TEST.SVG", create a new file called "TEST.HTML", add the following, save, and try opening in your browser. Let me know if does not work.


"TEST.HTML"
---------------------
---------------------

<html><body leftmargin=0 topmargin=0 scroll=no> <embed width=100% height=100% fullscreen=yes src="TEST.SVG"></body></html>




Go to the top of the page
+Quote Post
Rick
post Feb 13, 2006, 11:51 AM
Post #5


Supreme God
*******

Group: Basic Member
Posts: 5916
Joined: Jul 23, 2004
From: Sunny Southern California
Member No.: 3068



It did not work. I just got a page with a little picture icon in it.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
cerebral
post Feb 13, 2006, 12:38 PM
Post #6


Overlord
****

Group: Full Member
Posts: 286
Joined: Jan 20, 2004
Member No.: 957



Firefox 1.5 has native SVG support. With IE, you may need a plugin.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



Lo-Fi Version Time is now: 23rd November 2017 - 09:32 PM


Home     |     About     |    Research     |    Forum     |    Feedback  


Copyright BrainMeta. All rights reserved.
Terms of Use  |  Last Modified Tue Jan 17 2006 12:39 am

Consciousness Expansion · Brain Mapping · Neural Circuits · Connectomics  ·  Neuroscience Forum  ·  Brain Maps Blog
 · Connectomics · Connectomics  ·  shawn mikula  ·  shawn mikula  ·  articles