1 /**
  2 * YMath utilities Not instanciable.
  3 * @constructor
  4 */
  5 var YMath={
  6 	unPow:function(primary,result){
  7 		return Math.log(result)/Math.log(primary);
  8 	},
  9 	_realRFCTo:function(operation,value,step){
 10 		if(step==0)return value;
 11 		var mop = operation=='round'||operation=='floor'||operation=='ceil' ? operation : 'round' ;
 12 		if(step==1)return Math[operation](value);
 13 		var rval = mop=='round' ? YMath.roundTo(value,step) : (mop=='floor'?YMath.roundTo(value,step):YMath.roundTo(value,step)) ;
 14 		var rvst = rval+"";
 15 		if(rvst.indexOf('.')==-1)return rval;
 16 		var zzz="000",aaa="999";
 17 		var errindx = rvst.lastIndexOf(zzz),errindx2 = rvst.lastIndexOf(aaa);
 18 		if(errindx>-1&&errindx!=rvst.indexOf('.')+1&&rvst.charAt(rvst.length-1)!='0'&&errindx==rvst.length-zzz.length-1){
 19 			var evst = "this.ravalue = "+rvst.substring(0,errindx)+";";
 20 			eval(evst);
 21 			return this.ravalue;
 22 		}else if(errindx2>-1&&errindx2!=rvst.indexOf('.')+1&&rvst.charAt(rvst.length-1)!='0'&&errindx2==rvst.length-aaa.length-1){
 23 			//var evst = "this.ravalue = "+(-rval+"").substring(0,errindx2+(rval>0?-1:1))+";";
 24 			var evst = "this.ravalue = "+rvst.substring(0,errindx2)+";";
 25 			eval(evst);
 26 			return this.ravalue;
 27 		}else return rval;
 28 /*		if( (errindx==-1||errindx==rvst.indexOf('.')+1||rvst.charAt(rvst.length-1)=='0'||errindx!=rvst.length-zzz.length-1)&&
 29 			(errindx2==-1||errindx2==rvst.indexOf('.')+1||rvst.charAt(rvst.length-1)=='0'||errindx2!=rvst.length-aaa.length-1))return rval;
 30 		var evst = "this.ravalue = "+rvst.substring(0,errindx)+";";
 31 		eval(evst);
 32 		return this.ravalue;*/
 33 	},
 34 	roundTo:function(value,step){		return step==0?value:Math.round(value/step)*step;	},
 35 	floorTo:function(value,step){		return step==0?value:Math.floor(value/step)*step;	},
 36 	ceilTo:function(value,step){		return step==0?value:Math.ceil(value/step)*step;	},
 37 	roundAt:function(value,exponent){	return YMath.roundTo(value,Math.pow(10,exponent));	},
 38 	floorAt:function(value,exponent){	return YMath.floorTo(value,Math.pow(10,exponent));	},
 39 	ceildAt:function(value,exponent){	return YMath.ceildTo(value,Math.pow(10,exponent));	},
 40 	realRoundTo:function(value,step){		return YMath._realRFCTo('round',value,step);	},
 41 	realFloorTo:function(value,step){		return YMath._realRFCTo('floor',value,step);	},
 42 	realCeilTo:function(value,step){		return YMath._realRFCTo('ceil',value,step);	},
 43 	realRoundAt:function(value,exponent){	return YMath.realRoundTo(value,Math.pow(10,exponent));	},
 44 	realFloorAt:function(value,exponent){	return YMath.realFloorTo(value,Math.pow(10,exponent));	},
 45 	realCeilAt:function(value,exponent){	return YMath.realCeilTo(value,Math.pow(10,exponent));	},
 46 	bezierFactors:[
 47 		function(perc){	return 0;	},
 48 		function(perc){	return 0;	},
 49 		function(perc){	return [ 1-perc , perc];	},
 50 		function(perc){	return [ Math.pow(1-perc,2) , 2*perc*(1-perc) , Math.pow(perc,2) ];	},
 51 		function(perc){	return [ Math.pow(1-perc,3) , 3*perc*Math.pow(1-perc,2) , 3*Math.pow(perc,2)*(1-perc), Math.pow(perc,3) ];	}
 52 	],
 53 	/**
 54 	* YMath.v2d utilities Not instanciable.
 55 	* @constructor
 56 	*/
 57 	v2d:{
 58 		/**
 59 		@param {array[2]} vxy
 60 		@param {number} factor
 61 		@return {array[2]} factor*vxy
 62 		 */
 63 		mult:function(vxy,factor){
 64 			return [vxy[0]*factor,vxy[1]*factor];
 65 		},
 66 		/**
 67 		@param {array[2]} vxyA
 68 		@param {array[2]} vxyB
 69 		@return {array[2]} vxyA+vxyB
 70 		 */
 71 		add:function(vxyA,vxyB){
 72 			return [vxyA[0]+vxyB[0],vxyA[1]+vxyB[1]];
 73 		},
 74 		/**
 75 		@param {array[2]} vxyA
 76 		@param {array[2]} vxyB
 77 		@return {array[2]} vxyA-vxyB
 78 		 */
 79 		to:function(vxyFrom,vxyTo){
 80 			return [vxyTo[0]-vxyFrom[0],vxyTo[1]-vxyFrom[1]];
 81 		},
 82 		normalise:function(vxy){
 83 			var n = YMath.v2d.length(vxy[0],vxy[1]);
 84 			if(n==0)return [0,0];
 85 			return YMath.v2d.mult(vxyz,1/n);
 86 		},
 87 		length:function(x,y){
 88 			if(x&&x.join)return YMath.v2d.length(x[0],x[1]);
 89 			return Math.sqrt(x*x+y*y);
 90 		},
 91 		polToCart:function(angle,length){
 92 			if(angle&&angle.join)return YMath.v2d.polToCart(angle[0],angle[1]);
 93 			return [Math.cos(angle)*length,Math.sin(angle)*length];
 94 		},
 95 		cartToPol:function(x,y){
 96 			if(x&&x.join)return YMath.v2d.cartToPol(x[0],x[1]);
 97 			var dist = YMath.v2d.length(x,y);
 98 			if(dist==0){	angl = 0;
 99 			}else if(x==0){	angl = (Math.PI*0.5)*(Math.abs(y)/y);
100 			}else if(y==0){	angl = (Math.PI*0.5)*(1-Math.abs(x)/x);
101 			}else{			angl = Math.acos(x/dist)*Math.abs(y)/y;	}
102 			return [angl,dist];
103 		},
104 		extrapolate:function(vxyzA,vxyzB,perc){
105 			return [	vxyzA[0]*(1-perc)+vxyzB[0]*perc,
106 						vxyzA[1]*(1-perc)+vxyzB[1]*perc];
107 		},
108 		fit : function(size_from,size_to,outside,domElement){
109 			var factor		= (outside?size_to[0]/size_from[0]>size_to[1]/size_from[1]:size_to[0]/size_from[0]<size_to[1]/size_from[1])?
110 				size_to[0]/size_from[0]:size_to[1]/size_from[1];
111 			var new_size	= [Math.round(size_from[0]*factor),Math.round(size_from[1]*factor)];
112 			var new_offset	= [0.5*(size_to[0]-new_size[0]),0.5*(size_to[1]-new_size[1])];
113 			var result		= [new_offset[0],new_offset[1],new_size[0],new_size[1]];
114 			result.size		= new_size;
115 			result.offset	= new_offset;
116 			if(domElement&&domElement.style){
117 				var props	= ["marginLeft","marginTop","width","height"];
118 				for(var i in props)domElement.style[props[i]]=result[i]+"px";
119 			}
120 			return result;
121 		},
122 		fitInside : function(size_from,size_to,domElement){
123 			return this.fit(size_from,size_to,false,domElement);
124 		},
125 		fitOutside : function(size_from,size_to,domElement){
126 			return this.fit(size_from,size_to,true,domElement);
127 		},
128 		bezier:function(vlist,perc){
129 			var f = YMath.bezierFactors[vlist.length](perc);
130 			var r=[0,0];
131 			for(var i=0;i<f.length;i++){
132 				r[0]+=vlist[i][0]*f[i];
133 				r[1]+=vlist[i][1]*f[i];
134 			}
135 			return r;
136 		}
137 	},
138 	/**
139 	* YMath.v3d utilities Not instanciable.
140 	* @constructor
141 	*/
142 	v3d:{
143 		/**
144 		@param {array[3]} vxyz
145 		@param {number} factor
146 		@return {array[3]} factor*vxyz
147 		 */
148 		mult:function(vxyz,factor){
149 			return [vxyz[0]*factor,vxyz[1]*factor,vxyz[2]*factor];
150 		},
151 		/**
152 		@param {array[3]} vxyA
153 		@param {array[3]} vxyB
154 		@return {array[3]} vxyA+vxyB
155 		 */
156 		add:function(vxyzA,vxyzB){
157 			return [vxyzA[0]+vxyzB[0],vxyzA[1]+vxyzB[1],vxyzA[2]+vxyzB[2]];
158 		},
159 		/**
160 		@param {array[3]} vxyA
161 		@param {array[3]} vxyB
162 		@return {array[3]} vxyA-vxyB
163 		 */
164 		sub:function(vxyzA,vxyzB){
165 			return [vxyzA[0]-vxyzB[0],vxyzA[1]-vxyzB[1],vxyzA[2]-vxyzB[2]];
166 		},
167 		min:function(vxyzA,vxyzB){
168 			return [Math.min(vxyzA[0],vxyzB[0]),Math.min(vxyzA[1],vxyzB[1]),Math.min(vxyzA[2],vxyzB[2])];
169 		},
170 		max:function(vxyzA,vxyzB){
171 			return [Math.max(vxyzA[0],vxyzB[0]),Math.max(vxyzA[1],vxyzB[1]),Math.max(vxyzA[2],vxyzB[2])];
172 		},
173 		minmax:function(vxyzA,vxyzB){
174 			return [YMath.v3d.min(vxyzA,vxyzB),YMath.v3d.max(vxyzA,vxyzB)];
175 		},
176 		box:function(vxyzA,vxyzB){
177 			var mm = YMath.v3d.minmax(vxyzA,vxyzB);
178 			return [mm[0][0],mm[0][1],mm[0][2],
179 					mm[1][0]-mm[0][0],mm[1][1]-mm[0][1],mm[1][2]-mm[0][2]];
180 		},
181 		rotateX:function(vxyz,angle){
182 			var cosin = [Math.cos(angle),Math.sin(angle)];
183 			return [vxyz[0],cosin[0]*vxyz[1]-cosin[1]*vxyz[2],cosin[1]*vxyz[1]+cosin[0]*vxyz[2]];
184 		},
185 		rotateY:function(vxyz,angle){
186 			var cosin = [Math.cos(angle),Math.sin(angle)];
187 			return [cosin[0]*vxyz[2]-cosin[1]*vxyz[0],vxyz[1],cosin[1]*vxyz[2]+cosin[0]*vxyz[0]];
188 		},
189 		rotateZ:function(vxyz,angle){
190 			var cosin = [Math.cos(angle),Math.sin(angle)];
191 			return [cosin[0]*vxyz[0]-cosin[1]*vxyz[1],cosin[1]*vxyz[0]+cosin[0]*vxyz[1],vxyz[2]];
192 		},
193 		normalise:function(vxyz,length){
194 			var nl = typeof(length)=='number'?length:1;
195 			var l= YMath.v3d.length(vxyz);
196 			if(l==0)return [nl,0,0];
197 			return YMath.v3d.mult(vxyz,Math.abs(nl/l));
198 		},
199 		product:function(vA,vB){
200 			return [
201 				vA[1]*vB[2]	- vA[2]*vB[1],
202 				vA[2]*vB[0]	- vA[0]*vB[2],
203 				vA[0]*vB[1]	- vA[1]*vB[0]
204 			]
205 		},
206 		/** 
207 		vector projection vA on vB
208 		*/
209 		project:function(vA,vB){
210 			var pMat = [	vB[0]*vB[0],vB[0]*vB[1],vB[0]*vB[2],
211 							vB[1]*vB[0],vB[1]*vB[1],vB[1]*vB[2],
212 							vB[2]*vB[0],vB[2]*vB[1],vB[2]*vB[2]
213 							];
214 			return [	vA[0]*pMat[0]+vA[1]*pMat[2]+vA[2]*pMat[6],
215 							vA[0]*pMat[1]+vA[1]*pMat[4]+vA[2]*pMat[7],
216 							vA[0]*pMat[2]+vA[1]*pMat[5]+vA[2]*pMat[8]
217 							 ];
218 		},
219 		/** 
220 		vector reflection vA on vB
221 		*/
222 		normalReflect:function(vA,vB){
223 			var prj = this.project(vA,vB);
224 			return [vA[0]-2*prj[0],vA[1]-2*prj[1],vA[2]-2*prj[2]]
225 		},
226 		length:function(x,y,z){
227 			if(x&&x.join)return YMath.v2d.length(x[0],x[1],x[2]);
228 			return Math.sqrt(x*x+y*y+z*z);
229 		},
230 		extrapolateRad:function(vxyzA,vxyzB,perc){
231 			var result = [];
232 			for(var i=0;i<3;i++){
233 				var va = vxyzA[i];
234 				var vb = vxyzB[i];
235 				while(Math.abs(va-vb)>Math.PI){
236 					if(va>vb){	vb+=Math.PI*2;
237 					}else{		va+=Math.PI*2;	}
238 				}
239 				result[i]=va*(1-perc)+vb*perc;
240 			}
241 			return result;
242 		},
243 		extrapolate:function(vxyzA,vxyzB,perc){
244 			return [	vxyzA[0]*(1-perc)+vxyzB[0]*perc,
245 						vxyzA[1]*(1-perc)+vxyzB[1]*perc,
246 						vxyzA[2]*(1-perc)+vxyzB[2]*perc];
247 		},
248 		bezier:function(vlist,perc){
249 			var f = YMath.bezierFactors[vlist.length](perc);
250 			var r=[0,0,0];
251 			for(var i=0;i<f.length;i++){
252 				r[0]+=vlist[i][0]*f[i];
253 				r[1]+=vlist[i][1]*f[i];
254 				r[2]+=vlist[i][2]*f[i];
255 			}
256 			return r;
257 		}
258 	}
259 	
260 };
261 var YMath_abstract_vector_convert = function(dimension){
262 	var xyzi={x:0,y:1,z:2,w:3};
263 	
264 	var v_i={};
265 	for(var k in xyzi)if(xyzi[k]>=dimension)break;else v_i[k]=xyzi[k];
266 	
267 	var parsearrayblock=function(strret){
268 		var blocks={
269 			"{":{opener:true,twin:"}",nb:0,chief:"{"},
270 			"}":{opener:false,twin:"{",nb:0,chief:"{"},
271 			"(":{opener:true,twin:")",nb:0,chief:"("},
272 			")":{opener:false,twin:"(",nb:0,chief:"("},
273 			"[":{opener:true,twin:"]",nb:0,chief:"["},
274 			"]":{opener:false,twin:"[",nb:0,chief:"["}
275 		}
276 		var level=0,splitpoints=[];
277 		for(var i=0;i<strret.length;i++){
278 			var chr=strret.charAt(i);
279 			if(blocks[chr]){
280 				blocks[blocks[chr].chief].nb+=blocks[chr].opener?1:-1;
281 			}else if(chr==","&&blocks["("].nb==0&&blocks["["].nb==0&&blocks["{"].nb==0){
282 				splitpoints.push(i);
283 			}
284 			if(blocks["["].nb<0){
285 				splitpoints.push(i);
286 				break;
287 			}
288 		}
289 		if(splitpoints.length!=dimension)return "["+strret;
290 		var vout=[];
291 		for(var i=0;i<splitpoints.length;i++){
292 			var from = i==0?0:splitpoints[i-1]+1;
293 			var to = splitpoints[i];
294 			vout.push(strret.substring(from,to));
295 		}
296 		for(var k in v_i)vout[v_i[k]]=k+":("+vout[v_i[k]]+")";
297 		var nustrarr="{"+vout.join(" , ")+"}";
298 		return nustrarr+strret.substring(splitpoints[dimension-1]+1);
299 	};
300 	var funkstr="";
301 	for(var i in YMath["v"+dimension+"d"]){
302 		var str=""+YMath["v"+dimension+"d"][i];
303 		var args = str.split(")")[0].split("(")[1].split(",");
304 		for(var j in args){
305 			for(var k in v_i){
306 				str=str.split(args[j]+"["+v_i[k]+"]").join(args[j]+"."+k);
307 			}
308 		}
309 		str=str.split("YMath.v"+dimension+"d").join("YMath.vector"+dimension);
310 		var ri = 0;
311 		if(ri = Math.max(str.indexOf("return["),str.indexOf("return ["))>-1){
312 			var smpl=str.indexOf("return[")==ri?"return[":"return [";
313 			var xpld = str.split(smpl);
314 			for(var s=1;s<xpld.length;s++){
315 				xpld[s] = "return "+parsearrayblock(xpld[s]);
316 			}
317 			str=xpld.join("");
318 		}
319 		
320 		str="this."+i+" = "+str;
321 		funkstr+=str+";\n";
322 	}
323 //	alert(funkstr);
324 	eval(funkstr);
325 }
326 YMath.vector2=new YMath_abstract_vector_convert(2);
327 YMath.vector3=new YMath_abstract_vector_convert(3);