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);