Using objects in your code


Constructing and working with objects:

You can move the red and blue points below.

image of a circle
Your browser did not display the SVG image. It is showing a standard image as a fallback.
Source of intersect.svg:Hide line numbers
001: <svg version="1.1" baseProfile="full"
002:      xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
003:      width="600px" height="400px" viewBox="0 0 600 400"
004:      onload="updateAll()" onmousemove="drag(evt)" onmouseup="release(evt)">
005: 
006: <script>
007: //<![CDATA[
008: 
009: // Setup PPoint class for "Projective Geometry Points"
010: function PPoint (x, y, z) {
011:     this.x = x;
012:     this.y = y;
013:     this.z = z;
014: }
015: 
016: // Setup PLine class for "Projective Geometry Line"
017: function PLine (x, y, z) {
018:     this.x = x;
019:     this.y = y;
020:     this.z = z;
021: }
022: 
023: // Joins two PPoints to make a line:
024: function join(p,q) {
025:    return new PLine(p.y*q.z-p.z*q.y, p.z*q.x-p.x*q.z, p.x*q.y-p.y*q.x);
026: }
027: 
028: // Intersects two PPLines to get a PPpoint:
029: function intersect(p,q) {
030:    return new PPoint(p.y*q.z-p.z*q.y, p.z*q.x-p.x*q.z, p.x*q.y-p.y*q.x);
031: }
032: 
033: // Creates a PPoint from the data of a use element described by its id.
034: function pointFromID(useElementId) {
035:    var elt = document.getElementById(useElementId);
036:    var x=parseFloat(elt.getAttributeNS(null, "x"));
037:    var y=parseFloat(elt.getAttributeNS(null, "y"));
038:    return new PPoint(x, y, 1);
039: }
040: 
041: 
042: ///////////// Functions that interface with the SVG graphic:
043: 
044: // Use the coordinates of two use elements to update a line element 
045: function updateLine(lineId, useId1, useId2) {
046:    var line = document.getElementById(lineId);
047:    var p1 = document.getElementById(useId1);
048:    var p2 = document.getElementById(useId2);
049:    line.setAttributeNS(null, "x1", p1.getAttributeNS(null, "x"));
050:    line.setAttributeNS(null, "y1", p1.getAttributeNS(null, "y"));
051:    line.setAttributeNS(null, "x2", p2.getAttributeNS(null, "x"));
052:    line.setAttributeNS(null, "y2", p2.getAttributeNS(null, "y"));
053: }
054: 
055: // Updates all line segments and C* points:
056: function updateAll() {
057:    updateLine("lA", "A1", "A2");
058:    updateLine("lB", "B1", "B2");
059:    var lA = join(pointFromID("A1"), pointFromID("A2"));
060:    var lB = join(pointFromID("B1"), pointFromID("B2"));
061:    var pC = intersect(lA, lB);
062:    
063:    var elt = document.getElementById("C1");
064:    elt.setAttributeNS(null, "x", ""+(pC.x/pC.z));
065:    elt.setAttributeNS(null, "y", ""+(pC.y/pC.z));
066: }
067: 
068: // Global variables for dragging
069: var dragging=false;
070: var drag_elt;
071: var lastx, lasty;
072: 
073: // Initiate a drag given a mouse event and the id of a use element.
074: function startDrag(evt,id) {
075:    dragging=true;
076:    drag_elt=document.getElementById(id);
077:    
078:    // Get the mouse location:
079:    var position = document.rootElement.createSVGPoint();
080:    position.x = evt.clientX;
081:    position.y = evt.clientY;
082:    var matrix = drag_elt.getScreenCTM();
083:    var correctPosition=position.matrixTransform(matrix.inverse());
084:    lastx = correctPosition.x;
085:    lasty = correctPosition.y;
086: }
087: 
088: 
089: function drag(evt) {
090:    if (dragging) {
091:       // Get the mouse location:
092:       var position = document.rootElement.createSVGPoint();
093:       position.x = evt.clientX;
094:       position.y = evt.clientY;
095:       var matrix = drag_elt.getScreenCTM();
096:       var correctPosition = position.matrixTransform(matrix.inverse());
097:       newx = correctPosition.x;
098:       newy = correctPosition.y;
099:       
100:       if ( (newx != lastx) || (newy != lasty) ) {
101:          var curx=parseFloat(drag_elt.getAttributeNS(null, "x"));         
102:          var x=curx+newx-lastx;
103:          var cury=parseFloat(drag_elt.getAttributeNS(null, "y"));         
104:          var y =cury+newy-lasty;
105: 
106:          drag_elt.setAttributeNS(null,"x",""+x);
107:          drag_elt.setAttributeNS(null,"y",""+y);       
108:          
109:          lastx=newx;
110:          lasty=newy;
111:          updateAll();
112:       }      
113:    }
114: }
115: function release(evt) {
116:    dragging=false;
117: }
118: 
119: // ]]>
120: </script>
121: 
122: <defs>
123:    <circle id="A" cx="0" cy="0" r="5" fill="red" stroke="black"/>
124:    <circle id="B" cx="0" cy="0" r="5" fill="blue" stroke="black"/>
125:    <circle id="C" cx="0" cy="0" r="5" fill="yellow" stroke="black"/>
126: </defs>
127: 
128: <g id="lines">
129:    <line id="lA" stroke-width="1px" stroke="black"/>
130:    <line id="lB" stroke-width="1px" stroke="black"/>
131: </g>
132: <g id="points">
133:    <use id="A1" xlink:href="#A" x="10" y="10" onmousedown="startDrag(evt,'A1')" cursor="pointer"/>
134:    <use id="A2" xlink:href="#A" x="590" y="390" onmousedown="startDrag(evt,'A2')" cursor="pointer"/>
135:    <use id="B1" xlink:href="#B" x="300" y="10" onmousedown="startDrag(evt,'B1')" cursor="pointer"/>
136:    <use id="B2" xlink:href="#B" x="10" y="390" onmousedown="startDrag(evt,'B2')" cursor="pointer"/>
137:    <use id="C1" xlink:href="#C"/>
138: </g>
139: </svg>
140: 

Adding functions to objects:

The following adds some functions to the objects created in the previous example. For example, if p is a PPoint, we will be able to call p.getX() to get the Euclidean (as opposed to projective) x-coordinate.

The following example demonstrates Pappus' Theorem. This theotem states that if the red points are colinear and the blue points are colinear, then the constructed green points will be colinear.

image of a circle
Your browser did not display the SVG image. It is showing a standard image as a fallback.
Source of pappus3.svg:Hide line numbers
001: <svg version="1.1" baseProfile="full"
002:      xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
003:      width="600px" height="400px" viewBox="0 0 600 400"
004:      onload="setup()" onmousemove="drag(evt)" onmouseup="release(evt)">
005: 
006: <script>
007: //<![CDATA[
008: 
009: ///// PPoint Objects:
010: 
011: // Setup PPoint class for "Projective Geometry Points"
012: function PPoint (x, y, z) {
013:     this.x = x;
014:     this.y = y;
015:     this.z = z;
016: }
017: 
018: // Add functions to the PPoint class:
019: 
020: // toString() a string representation of the PPoint:
021: PPoint.prototype.toString = function() {
022:     return ""+this.x+":"+this.y+":"+this.z;
023: };
024: 
025: // getX() returns the non-projective x-coordinate
026: PPoint.prototype.getX = function() {
027:     return this.x/this.z;
028: };
029: 
030: // getY() returns the non-projective y-coordinate
031: PPoint.prototype.getY = function() {
032:     return this.y/this.z;
033: };
034: // updateUse(useElementId) updates the x- and y-coordinates
035: // of the use element associated to an id to match the point.
036: PPoint.prototype.updateUse = function(useElementId) {
037:     var elt = document.getElementById(useElementId);
038:     elt.setAttributeNS(null, "x", this.getX());
039:     elt.setAttributeNS(null, "y", this.getY());
040: };
041: 
042: 
043: ///////////////// PLine objects:
044: // Setup PLine class for "Projective Geometry Line"
045: function PLine (x, y, z) {
046:     this.x = x;
047:     this.y = y;
048:     this.z = z;
049: }
050: 
051: /////////  Extra Functions for working with PPoints and PLines:
052: 
053: // Creates a PPoint from the data of a use element described by its id.
054: function pointFromID(useElementId) {
055:    var elt = document.getElementById(useElementId);
056:    var x=parseFloat(elt.getAttributeNS(null, "x"));
057:    var y=parseFloat(elt.getAttributeNS(null, "y"));
058:    return new PPoint(x, y, 1);
059: }
060: // Joins two points to make a line:
061: function join(p,q) {
062:    return new PLine(p.y*q.z-p.z*q.y, p.z*q.x-p.x*q.z, p.x*q.y-p.y*q.x);
063: }
064: // Intersects two lines to get a point:
065: function intersect(p,q) {
066:    return new PPoint(p.y*q.z-p.z*q.y, p.z*q.x-p.x*q.z, p.x*q.y-p.y*q.x);
067: }
068: 
069: 
070: 
071: ///////////// Functions that interface with the SVG graphic:
072: 
073: // Use the coordinates of two use elements to update a line element 
074: function updateLine(lineId, useId1, useId2) {
075:    var line = document.getElementById(lineId);
076:    var p1 = document.getElementById(useId1);
077:    var p2 = document.getElementById(useId2);
078:    line.setAttributeNS(null, "x1", p1.getAttributeNS(null, "x"));
079:    line.setAttributeNS(null, "y1", p1.getAttributeNS(null, "y"));
080:    line.setAttributeNS(null, "x2", p2.getAttributeNS(null, "x"));
081:    line.setAttributeNS(null, "y2", p2.getAttributeNS(null, "y"));
082: }
083: 
084: function setup() {
085:    updateAll();
086: }
087: 
088: // Updates all line segments and C* points:
089: function updateAll() {
090:    c3=intersect(join(pointFromID("A1"),pointFromID("B2")),join(pointFromID("A2"),pointFromID("B1")));
091:    c3.updateUse("C3");
092:    c2=intersect(join(pointFromID("A1"),pointFromID("B3")),join(pointFromID("A3"),pointFromID("B1")));
093:    c2.updateUse("C2");
094:    c1=intersect(join(pointFromID("A3"),pointFromID("B2")),join(pointFromID("A2"),pointFromID("B3")));
095:    c1.updateUse("C1");
096: 
097:    updateLine("A1B2","A1","B2");
098:    updateLine("A1B3","A1","B3");
099:    updateLine("A2B1","A2","B1");
100:    updateLine("A2B3","A2","B3");
101:    updateLine("A3B1","A3","B1");
102:    updateLine("A3B2","A3","B2");
103: 
104:    updateLine("A1A3","A1","A3");
105:    updateLine("B1B3","B1","B3");
106:    updateLine("C1C3","C1","C3");
107: }
108: 
109: // Global variables for dragging
110: var dragging=false;
111: var drag_elt;
112: var lastx, lasty;
113: 
114: function startDrag(evt,id) {
115:    dragging=true;
116:    drag_elt=document.getElementById(id);
117:    
118:    // Get the mouse location:
119:    var position = document.rootElement.createSVGPoint();
120:    position.x = evt.clientX;
121:    position.y = evt.clientY;
122:    var matrix = drag_elt.getScreenCTM();
123:    var correctPosition=position.matrixTransform(matrix.inverse());
124:    lastx = correctPosition.x;
125:    lasty = correctPosition.y;
126: }
127: 
128: 
129: function drag(evt) {
130:    if (dragging) {
131:       // Get the mouse location:
132:       var position = document.rootElement.createSVGPoint();
133:       position.x = evt.clientX;
134:       position.y = evt.clientY;
135:       var matrix = drag_elt.getScreenCTM();
136:       var correctPosition = position.matrixTransform(matrix.inverse());
137:       newx = correctPosition.x;
138:       newy = correctPosition.y;
139:       
140:       if ( (newx != lastx) || (newy != lasty) ) {
141:          var curx=parseFloat(drag_elt.getAttributeNS(null, "x"));         
142:          var x=curx+newx-lastx;
143:          var cury=parseFloat(drag_elt.getAttributeNS(null, "y"));         
144:          var y =cury+newy-lasty;
145: 
146:          drag_elt.setAttributeNS(null,"x",""+x);
147:          drag_elt.setAttributeNS(null,"y",""+y);       
148:         
149:          lastx=newx;
150:          lasty=newy;
151:          updateAll();
152:       }      
153:    }
154: }
155: function release(evt) {
156:    dragging=false;
157: }
158: 
159: // ]]>
160: </script>
161: 
162: 
163: <defs>
164:    <circle id="A" cx="0" cy="0" r="5" fill="red" stroke="black"/>
165:    <circle id="B" cx="0" cy="0" r="5" fill="blue" stroke="black"/>
166:    <circle id="C" cx="0" cy="0" r="5" fill="green" stroke="black"/>
167: </defs>
168: 
169: <g>
170:    <line id="A1B2" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
171:    <line id="A1B3" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
172:    <line id="A2B1" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
173:    <line id="A2B3" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
174:    <line id="A3B1" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
175:    <line id="A3B2" stroke-width="1px" stroke="grey" stroke-dasharray="3 3"/>
176: 
177:    <line id="A1A3" stroke-width="1px" stroke="black"/>
178:    <line id="B1B3" stroke-width="1px" stroke="black"/>
179:    <line id="C1C3" stroke-width="1px" stroke="black"/>
180: </g>
181: 
182: <use id="A1" xlink:href="#A" x="10" y="10" onmousedown="startDrag(evt,'A1')"/>
183: <use id="A2" xlink:href="#A" x="300" y="10" onmousedown="startDrag(evt,'A2')"/>
184: <use id="A3" xlink:href="#A" x="590" y="10" onmousedown="startDrag(evt,'A3')"/>
185: <use id="B1" xlink:href="#B" x="10" y="390" onmousedown="startDrag(evt,'B1')"/>
186: <use id="B2" xlink:href="#B" x="300" y="390" onmousedown="startDrag(evt,'B2')"/>
187: <use id="B3" xlink:href="#B" x="590" y="390" onmousedown="startDrag(evt,'B3')"/>
188: <use id="C3" xlink:href="#C" x="155" y="200"/>
189: <use id="C2" xlink:href="#C" x="300" y="200"/>
190: <use id="C1" xlink:href="#C" x="445" y="200"/>
191: </svg>
192: 

References:


This presentation is part of a SVG Tutorial for Mathematics Students.


© 2013 by W. Patrick Hooper. This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. Creative Commons License Valid XHTML 1.0 Strict Valid CSS!