The Journal of Online Mathematics and Its Applications, Volume 7 (2007)
Scalable Vector Graphics, David Lane

Complete source code for the Thales example


<?xml version="1.0"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 	"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   width="500" height="300"
   onload="Init( evt )" >

<script type="text/ecmascript">
    //<![CDATA[

var svgXLink = "http://www.w3.org/1999/xlink";
var svgNS = "http://www.w3.org/2000/svg";
var svgRoot;
var mouseP, newP, circP;
var bmousedown=0;
var rightline, leftline, radline;
var circpoint, circpointlabel, square;

function Init(){
   svgRoot = document.documentElement;
   mouseP = svgRoot.createSVGPoint();
   newP = svgRoot.createSVGPoint();
   circP = svgRoot.createSVGPoint();
   rightline = document.getElementById("rightline");
   leftline = document.getElementById("leftline");
   radline = document.getElementById("radline");
   circpoint = document.getElementById("circpoint");
   circpointlabel = document.getElementById("circpointlabel");
   square = document.getElementById("square");
   }

/*
* Returns the mouse coordinates as an SVGPoint
*/
function getMouse(evt){
   var position = svgRoot.createSVGPoint();
   position.x = evt.clientX;
   position.y = evt.clientY;
   return position;
   }

/*
* Converts a mouse point to svg "user coordinates".
*/
function getUserCoordinates(p1){
   var p1;
   var p2 = svgRoot.createSVGPoint();
   p2.x = p1.x - 250;
   p2.y = 250 -p1.y;
   return p2;
   }

/*
* Mouse functions for the "canvas" event listeners
*/
function onMouseDown(evt){
   bmousedown=1;
   mouseP=getMouse(evt);
   newP=getUserCoordinates(mouseP);
   doUpdate();
   }

function onMouseMove(evt){
   if(bmousedown){
   	mouseP=getMouse(evt);
   	newP=getUserCoordinates(mouseP);
   	doUpdate();
   	}
   }

function onMouseUp(evt){
   bmousedown=0;
   }

function doUpdate(){
   var angle, angled, rotatestring;
   angled = 180*getAngle(newP)/Math.PI;
   if(angled <= 15){
   	angled = 15;
   } else if (angled >= 165) {
   	angled = 165;
   }
   circP.x = 200*Math.cos(angled*Math.PI/180);
   circP.y = 200*Math.sin(angled*Math.PI/180);
   circpoint.setAttributeNS(null, "cx", circP.x );
   circpoint.setAttributeNS(null, "cy", circP.y );
   circpointlabel.setAttributeNS(null, "x", 1.07*circP.x );
   circpointlabel.setAttributeNS(null, "y", -1.07*circP.y );
   radline.setAttributeNS(null, "x2", circP.x );
   radline.setAttributeNS(null, "y2", circP.y );
   leftline.setAttributeNS(null, "x2", circP.x );
   leftline.setAttributeNS(null, "y2", circP.y );
   rightline.setAttributeNS(null, "x2", circP.x );
   rightline.setAttributeNS(null, "y2", circP.y );
   square.setAttributeNS(null, "x", circP.x );
   square.setAttributeNS(null, "y", circP.y );
   angle = 180+angled/2;
   rotatestring="rotate("+angle+","+circP.x+","+circP.y+")";
   square.setAttributeNS(null, "transform", rotatestring);
   }

function getAngle(p){
   var p, a;
   a=Math.atan2(p.y, p.x);
   return a;
   }

// ]]></script>

<defs>
<style type="text/css"><![CDATA[
   .axes { fill:none;stroke:#333333;stroke-width:1.6 }
   .pointlabels { font-size:16px; font-family: Arial; font-style: italic;
  		 stroke:none; fill:#000000; text-anchor: middle }
   .point{ fill:#000000; stroke:white; stroke-width:1 }
   .outline{ fill:#ffffdd; stroke:#0077bb; stroke-width:3 }
   .thinline{ stroke:#770000; stroke-dasharray: 12,4; stroke-width:1.6 }
   .thickline{ fill:none; stroke:#ff2222; stroke-width:3.5 }
   ]]>
</style>

</defs>

<g transform="matrix(1, 0, 0, -1, 250, 250)">
 	<line class="axes" x1="-240" y1="0" x2="240" y2="0"/>
 	<path class="outline" d="M -200,0 A200,200 0 0,0 200,0 L -200,0"/>
 	<rect id="square" transform="rotate(225,0,200)"
   	x="0" y="200" width="20" height="20" style="fill:#ffffff;   stroke:#000000; stroke-width:1.6"/>
 	<line id="rightline" class="thickline" x1="200" y1="0" x2="0" y2="200" />
 	<line id="leftline" class="thickline" x1="-200" y1="0" x2="0" y2="200" />
 	<line id="radline" class="thinline" x1="0" y1="0" x2="0" y2="200" />
 	<circle id="circpoint" class="point" cx="0" cy="200" r="5"/>
 	<circle class="point" cx="0" cy="0" r="5"/>
 	<circle class="point" cx="-200" cy="0" r="5"/>
 	<circle class="point" cx="200" cy="0" r="5"/>
 	<text id = "circpointlabel" class="pointlabels" x="0" y="-214" transform="scale(1,-1)">B</text>
 	<text class="pointlabels" x="-210" y="20" transform="scale(1,-1)">A</text>
 	<text class="pointlabels" x="210" y="20" transform="scale(1,-1)">C</text>
 	<text class="pointlabels" x="0" y="20" transform="scale(1,-1)">D</text>
 	<rect id="canvas" x="-250" y="2" width="500" height="240" opacity="0"
   	pointer-events="visible"
   	onmousedown="onMouseDown(evt)"
   	onmousemove="onMouseMove(evt)"
   	onmouseup="onMouseUp(evt)"/>
 </g>
 </svg>