var svgns="http://www.w3.org/2000/svg"; var svgelement=document.getElementsByTagNameNS(svgns,"svg").item(0); var buttonState, lastMouseX, lastMouseY,deltaX,deltaY,dragged; var xyk = new Array(2); var Exp=4; //exponent of the superhyperboloid. Should always be odd and positive. The greater it is the squarer the projected space is. var referenceTree, referenceDoc, targetTree; function toKlein(xy) { // denominator=Math.sqrt(1+xy[0]*xy[0]+xy[1]*xy[1]); denominator=Math.pow(1+Math.pow(xy[0],Exp)+Math.pow(xy[1],Exp),1./Exp); xy[0]/=denominator; xy[1]/=denominator; } function init() { /* // make a copy of the original coordinates referenceDoc=document.rootElement.cloneNode(true); referenceTree=referenceDoc.getElementById("shape"); // FF1.5 reports "SVGSVGElement.getElementById not implemented" targetTree=document.getElementById("shape"); if (referenceTree==targetTree) alert("same ref/target trees!"); // find all the shapes in g[@id="shape"] and transform coordinates convertCoordsToKlein2(targetTree,referenceTree,0,0); */ // make a copy of the original tree. This is because of roundoff erros // when performing the Klein conversion. The referenceTree coordinates // are only updated when the objects are translated by a user dragging // the targetTree's coordinates are the projected coords of the reference // tree. They are recomputed everytime things move. referenceTree=document.getElementById("shape").cloneNode(true); // FF1.5 reports "SVGSVGElement.getElementById not implemented" targetTree=document.getElementById("shape"); if (referenceTree==targetTree) alert("buggy SVG implementation: same ref/target trees!"); // find all the shapes in g[@id="shape"] and transform coordinates convertCoordsToKlein2(targetTree,referenceTree,0,0); } function initDrag (evt) { buttonState = 1; dragged=0; lastMouseX=evt.clientX; lastMouseY=evt.clientY; } function drag (evt) { if (buttonState==1) { deltaX=evt.clientX-lastMouseX; deltaY=evt.clientY-lastMouseY; lastMouseX=evt.clientX; lastMouseY=evt.clientY; convertCoordsToKlein2(targetTree, referenceTree, deltaX/100,deltaY/100); // convertCoordsToKlein2(targetTree, referenceTree, 0,0); dragged=1; } } function endDrag(evt) { buttonState=0; if (dragged==0) { // this is just a click. Retrieve coordinates of click, then translate all coordinates var matrix=evt.target.getCTM(); var x=1-evt.screenX/matrix.e; var y=1-evt.screenX/matrix.e; // screen space // now we want to convert to klein? // panElement(document.getElementById("shape"),(matrix.e-evt.screenX)/matrix.e,(matrix.f-evt.screenY)/matrix.f); convertCoordsToKlein2(targetTree, referenceTree, (matrix.e-evt.screenX)/matrix.e,(matrix.f-evt.screenY)/matrix.f); // opera.postError("click: "+evt.screenX+", "+evt.screenY); // opera.postError("click: "+evt.clientX+", "+evt.clientY); // opera.postError("move: "+((matrix.e-evt.screenX)/matrix.e)+", "+((matrix.f-evt.screenY)/matrix.f)); // opera.postError("["+matrix.a+", "+matrix.b+", "+matrix.c+", "+matrix.d+", "+matrix.e+", "+matrix.f+"]"); } } function convertCoordsToKlein2(target, reference, deltax, deltay) // convert the coordinates value found in the "reference" tree and update // "target" with the new values. // deltax, deltay: offset to apply to reference (when objects move) { // opera.postError("1. reference node: "+reference); // opera.postError("2. target node: "+target); if (reference.firstChild) { for (var x=0;reference.childNodes.item(x); x++) { convertCoordsToKlein2(target.childNodes.item(x), reference.childNodes.item(x),deltax,deltay); } } if (reference.tagName == "polygon" || reference.tagName=="polyline") { var matrix=referenceTree.getTransformToElement(reference); var ps=reference.points, ts=target.points; var nps=ps.numberOfItems; for (var i=0; i