- From: Fred P. <fprog26@hotmail.com>
- Date: Mon, 12 May 2003 03:13:22 -0400
- To: www-svg@w3.org
- Cc: Kim.Marriott@infotech.monash.edu.au, arazdow@mathsoft.com
I think the arguments of Professor Kim Marriott describes exactly what some of the things that we tried to achieve. Especially his formal PDF article on one-way constrained SVG. This is especially true for rendering UML diagrams using SVG, similar to Visio or Rational Rose, using an SVG web client. Let's take a simple case of springs: 0 1 2 3 (0,0) 012345678901234567890123456789012345 0+----------------------------------+ 1| z z | 2| (9,3) z (22,3) z | 3| +---+ +---+ | 4|zzzzzzzz| A |zzzzzzzz| B |zzzzzzzz| 5| +---+ +---+ | 6| z z | 7| z z | 8+----------------------------------+ (W,H) Spring conversion into one-way constraint functions can be derived with some low level logic: Notice that any thing calculation are integer based mostly using floor(x) A.x = (document.width - A.width - B.width) * 1/3 + 1 = (35 - 5 - 5) * 1/3 + 1 = (25 ) * 1/3 + 1 = 8.33 + 1 = 8 + 1 = 9 A.y = (document.height - A.height - B.height) * 1/2 + 1 = (8 - 3) / 2 + 1 = 5 /2 + 1 = 2.5 + 1 = 2 + 1 = 3 B.x = (document.width - A.width - B.width) * 2/3 + A.width + 1 = (35 - 5 - 5) * 2/3 + 5 + 1 = (25 ) * 2/3 + 5 + 1 = 16.67 + 6 = 16 + 6 = 22 B.y = (document.height - A.height - B.height) * 1/2 + 1 = (8 - 3) / 2 + 1 = 5 /2 + 1 = 2.5 + 1 = 2 + 1 = 3 <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE svg SYSTEM "http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd"> <svg height="300" width="300" xmlns:xlink="http://www.w3.org/2000/xlink/namespace/" > <defs> <!-- Assuming you want 10px spacing between the box border and the text --> <constant id="offset" value="10px"/> </defs> <rect id="A" x="eval( (document.width - A.width - B.width ) * 1/3 + 1 );" y="eval( (document.height - A.height - B.height) * 1/2 + 1 );" width="eval( offset + textA.width + offset );" height="eval( offset + textA.height + offset );" style="fill:#00FFFF; stroke:#000000; stroke-width:1; shape-rendering: optimizeSpeed;" /> <rect id="B" x="eval( (document.width - A.width - B.width ) * 2/3 + A.width + 1 );" y="eval( (document.height - A.height - B.height) * 1/2 + 1 );" width="eval( offset + textB.width + offset );" height="eval( offset + textB.height + offset );" style="fill:#00FFFF; stroke:#000000; stroke-width:1; shape-rendering: optimizeSpeed;" /> <text id="textA" x="eval( A.x + offset );" y="eval( A.y + offset );" style="font:arial; font-size:8pt; text-rendering:optimizeSpeed;" >A</text> <text id="textB" x="eval( B.x + offset );" y="eval( B.y + offset );" style="font:arial; font-size:8pt; text-rendering:optimizeSpeed;" >B</text> </svg> Acyclic Dependancy: =================== A.width --> textA.width A.height --> textA.height B.width --> textB.width B.height --> textB.height textA.x --> A.x --> document.width | A.width | B.width --> textA.width | textB.width textA.y --> A.y --> document.height | A.height | B.height --> textA.height | textB.height textB.x --> B.x --> document.width | A.width | B.width --> textA.width | textB.width textB.y --> B.y --> document.height | A.height | B.height --> textA.height | textB.height As you can see, it's quite straight-forword to derive expression for GUI widget spring equations, at least for square box spacing approximation of complex shapes like a cloud or triangle and similar. For your <path/> example, I think something like this should make everyone happy: <path d="M {if {viewport.right-viewport.left > 10px} then {viewport.left+10px} else {0.5*viewport.right+0.5*viewport.left}}...."/> becomes: <path d="M eval( if ( viewport.right-viewport.left > 10px ) { return new Point( viewport.left+10px, 10px ); } else { return new Point( 0.5*viewport.right+0.5*viewport.left, 10px ); } ); l 1 0 l 0 1 l -1 0z"/> The following notation might be needed: <defs> <expression id='len' value='eval( viewport.width/2 + 10px );' /> </defs> <path d="M eval( if ( viewport.right-viewport.left > 10px ) { return new Point( viewport.left+10px, 10px ); } else { return new Point( 0.5*viewport.right+0.5*viewport.left, 10px ); } ); l eval( len ) 0 l 0 eval( len ) l eval( -1 * len ) 0z"/> Here we see clearly why eval( x ) is needed to not confound the l 'el' relative line command and the variable name len. or use { } as mentionned: <path d="M {eval( if ( viewport.right-viewport.left > 10px ) { return new Point( viewport.left+10px, 10px ); } else { return new Point( 0.5*viewport.right+0.5*viewport.left, 10px ); } ); } l 1 0 l 0 1 l -1 0z"/> The following might be needed: <defs> <expression id='len' value='eval( viewport.width/2 + 10px );' /> </defs> <path d="M {eval( if ( viewport.right-viewport.left > 10px ) { return new Point( viewport.left+10px, 10px ); } else { return new Point( 0.5*viewport.right+0.5*viewport.left, 10px ); } ); } l {eval( len )} 0 l 0 {eval( len )} l {eval( -1 * len )} 0z"/> or simply <path d="M {eval( if ( viewport.right-viewport.left > 10px ) { return new Point( viewport.left+10px, 10px ); } else { return new Point( 0.5*viewport.right+0.5*viewport.left, 10px ); } ); } l {len} 0 l 0 {len} l {-len} 0z"/> Anybody else, would be enthusiast to have such functionality? BTW, all those inlined calculation could be ECMAScript based and therefore hooked-up directly to existing embedded SVG ECMAscript engines, allowing for 'safe' recursive functions. Sincerely yours, Fred. _________________________________________________________________ Add photos to your messages with MSN 8. Get 2 months FREE*. http://join.msn.com/?page=features/featuredemail
Received on Monday, 12 May 2003 03:13:30 UTC