1 /*!
  2 *
  3 *   JSBeams : Numerical solution of beam structures in JavaScript
  4 *                      version 0.5.1 (2011-10-15)
  5 *
  6 *                 Copyright (C)  2011  Jan Stransky
  7 *
  8 *      Czech Technical University, Faculty of Civil Engineering,
  9 *  Department of Structural Mechanics, 166 29 Prague, Czech Republic
 10 *
 11 *
 12 *  This program is free software: you can redistribute it and/or modify
 13 *  it under the terms of the GNU General Public License as published by
 14 *  the Free Software Foundation, either version 3 of the License, or
 15 *  (at your option) any later version.
 16 *
 17 *  This program is distributed in the hope that it will be useful,
 18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20 *  GNU General Public License for more details.
 21 *
 22 *  You should have received a copy of the GNU General Public License
 23 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 /**
 27 * @fileOverview JavaScript implementation of numerical solution (direct stiffness methos) of beam structures. Modeled structures consists of nodes and beams. Nodes have only geometrical meaning and contains only coordinates, dofs and their values are stored in beams. Different static schemes and methods (clamped vs. pin ends, rigid arms, master x slave nodes etc.) can be modeled by special using of beam DOFs. Requires <a href="http://mech.fsv.cvut.cz/~stransky/software/jsmatrix/">jsmatrix.js</a> loaded before loading this file. For more information see <a href="http://mech.fsv.cvut.cz/~stransky/software/jsbeams/">project homepage</a>.
 28 <br /><br/>JSBeams is a free software distributed under <a href='http://www.gnu.org/licenses/gpl.html'>GNU GPL license</a>.
 29 * @author <a href="http://mech.fsv.cvut.cz/~stransky">Jan Stránský</a>
 30 * @version 0.5.1 (2011-10-15)
 31 */
 32 
 33 // constants for easier manipulation
 34 /**constant*/ var JSB2D_CLAMPED_CLAMPED = 0; // should be 0
 35 /**constant*/ var JSB2D_CC              = 0;
 36 /**constant*/ var JSB2D_CLAMPED_HINGE   = 1;
 37 /**constant*/ var JSB2D_CH              = 1;
 38 /**constant*/ var JSB2D_HINGE_CLAMPED   = 2;
 39 /**constant*/ var JSB2D_HC              = 2;
 40 /**constant*/ var JSB2D_HINGE_HINGE     = 3;
 41 /**constant*/ var JSB2D_HH              = 3;
 42 /**constant*/ var JSB2D_TRUSS           = 3;
 43 
 44 
 45 /** Returns elements of a that are not in b (Matlab-like function), ret = a - b
 46 * @param {Array} a
 47 * @param {Array} b
 48 * @returns {Array} array of elements of a that are not in b
 49 * @example a = [1,2,3,4,5,6];
 50 * b = [2,5,1,99,54];
 51 * c = setdiff(a,b) // c = [3,4,6]*/
 52 setdiff = function(A,B) {
 53 	var ret = [];
 54 	for (a=0; a<A.length; a++) {
 55 		var noMatch = 1;
 56 		for (var b=0; b<B.length; b++) {
 57 			if (A[a] == B[b]) { noMatch = 0; break; }
 58 		}
 59 		if (noMatch) { ret.push(A[a]); }
 60 	}
 61 	return ret;
 62 }
 63 
 64 
 65 /** 2d xz plane node implementation. The meaning of current implementation is only geometric, because DOFs itself are stored in beams (for both computational and graphic postprocessing part)
 66 * @class represents nodes in 2d zx plane
 67 * @param {float} x x coordinate of node
 68 * @param {float} y y coordinate of node
 69 * @param {float} z z coordinate of node
 70 * @property {float} x x coordinate
 71 * @property {float} y y coordinate
 72 * @property {float} z z coordinate*/
 73 Node = function(x,y,z) {
 74 	this.x = x || 0.;
 75 	this.y = y || 0.;
 76 	this.z = z || 0.;
 77 }
 78 /**#@+
 79 * @function
 80 * @memberOf Node#
 81 */
 82 Node.prototype = {
 83 	/** String representation
 84 	* @returns {String} string representation*/
 85 	toString: function() {
 86 		return "Node ( "+this.x+", "+this.y+", "+this.z+" )";
 87 	},
 88 
 89 	/** Sets new position to receiver
 90 	* @param {float} x x coordinate of new position
 91 	* @param {float} y y coordinate of new position
 92 	* @param {float} z z coordinate of new position*/
 93 	setXYZ: function(x,y,z) {
 94 		this.x = x; this.y = y; this.z = z;
 95 	},
 96 
 97 	/** Sets new position to receiver
 98 	* @param {float} x x coordinate of new position
 99 	* @param {float} z z coordinate of new position*/
100 	setXZ: function(x,z) {
101 		this.x = x; this.z = z;
102 	},
103 
104 	/** Sets new position to receiver
105 	* @param {float} y y coordinate of new position
106 	* @param {float} z z coordinate of new position*/
107 	setYZ: function(y,z) {
108 		this.y = y; this.z = z;
109 	},
110 
111 	/** Set new x coordinate to receiver
112 	* @param x x coordinate of new position*/
113 	setX: function(x) {
114 		this.x = x;
115 	},
116 
117 	/** Set new x coordinate to receiver
118 	* @param y y coordinate of new position*/
119 	setY: function(y) {
120 		this.y = y;
121 	},
122 
123 	/** Set new z coordinate to receiver
124 	* @param z z coordinate of new position*/
125 	setZ: function(z) {
126 		this.z = z;
127 	},
128 
129 	/** Change position of receiver by given values
130 	* @param {float} dx length of translation in x direction
131 	* @param {float} dy length of translation in y direction
132 	* @param {float} dz length of translation in z direction*/
133 	translate: function(dx,dy,dz) {
134 		this.x += dx;
135 		this.y += dy;
136 		this.z += dz;
137 	},
138 
139 	/** Change position of receiver by given values
140 	* @param {float} dx length of translation in x direction
141 	* @param {float} dz length of translation in z direction*/
142 	translateXZ: function(dx,dz) {
143 		this.x += dx;
144 		this.z += dz;
145 	},
146 
147 	/** Change position of receiver by given values
148 	* @param {float} dy length of translation in y direction
149 	* @param {float} dz length of translation in z direction*/
150 	translateYZ: function(dy,dz) {
151 		this.y += dy;
152 		this.z += dz;
153 	},
154 
155 	/** Change horizontal position of receiver by given values
156 	* @param {float} dx length of translation in x direction*/
157 	translateX: function(dx) {
158 		this.x += dx;
159 	},
160 
161 	/** Change horizontal position of receiver by given values
162 	* @param {float} dy length of translation in y direction*/
163 	translateY: function(dy) {
164 		this.y += dy;
165 	},
166 
167 	/** Change vertical position of receiver by given values
168 	* @param {float} dz length of translation in z direction*/
169 	translateZ: function(dz) {
170 		this.z += dz;
171 	},
172 
173 	/** Returns difference between receiver and given node
174 	* @param {Node} n node to be substracted
175 	* @returns {Node} difference this-node*/
176 	sub: function(n) {
177 		return new Node(this.x-n.x,this.y-n.y,this.z-n.z);
178 	},
179 
180 	/** Returns sum of receiver and given node
181 	* @param {Node} n node to be substracted
182 	* @returns {Node} difference this+node*/
183 	add: function(n) {
184 		return new Node(this.x+n.x,this.y+x.y,this.z+n.z);
185 	},
186 
187 	/** Returns receiver multiplied by given number
188 	* @param {float} f multiplicator
189 	* @returns {Node} product of multiplication f*this*/
190 	mulf: function(f) {
191 		return new Node(f*this.x,f*this.y,f*this.z);
192 	},
193 
194 	/**  Returns cross product of receiver and given node
195 	* @param {Node} n node to be crossed
196 	* @returns {Node} cross product this x node*/
197 	cross: function(n) {
198 		return new Node(this.y*n.z-this.z*n.y, this.z*n.x-this.x*n.z, this.x*n.y-this.y*n.x);
199 	},
200 
201 	/**  Returns dot product of receiver and given node
202 	* @param {Node} n node to be crossed
203 	* @returns {float} dot product this . node*/
204 	dot: function(n) {
205 		return this.x*n.x + this.y*n.y + this.z*n.z;
206 	},
207 
208 	/**  Returns square norm of receiver this.dot(this)
209 	* @returns {float} squared norm of receiver*/
210 	squaredNorm: function() {
211 		return this.dot(this);
212 	},
213 
214 	/**  Returns (Eucleidian) norm of receiver sqrt(this.dit(this))
215 	* @returns {float} norm of receiver*/
216 	norm: function() {
217 		return Math.sqrt(this.dot(this));
218 	},
219 	/**#@-*/
220 }
221 /** Constructor, see {@link Node} for input parameters description
222 * @returns {Node} new Node object*/
223 Node.create = function(x,y,z) {
224 	return new Node(x,y,z);
225 }
226 
227 
228 
229 
230 /** 2d beam implementation
231 * @class represents structural 2d beam with 3 degrees of freedom in each node
232 * @param {Node} node1 1st node
233 * @param {Node} node2 2nd node
234 * @param {Object} [params={}] object of parameters in format {param1:val1,param2:val2}, i.e. beam=Beam2d(n1,n2,{dofs:[1,2,3,4],ea:4}); 
235 * @param {int} [params.type=JSB2D_CC] type of beam. JSB2D_CC for both ends clamped, JSB2D_HC for hinge-clamped, JSB2D_CH for clamped-hinge, JSB2D_HH for hinge-hinge (truss)
236 * @param {[ints]} [params.dofs=[0,1,2,3,4,5]] degrees of freedom on both ends. number (6,5,4) should correscpond to this.type
237 * @param {float} [params.ei=1.] bending stiffness [Nm2]
238 * @param {float} [params.ea=1.] normal stiffness [N]
239 * @param {bool} [params.hasBodyLoad=false] if some body (continuous force or temperature) load is present
240 * @param {float} [params.fzloc=0.] constant continuous load parallel to local z coordinate [N/m]
241 * @param {float} [params.fxloc=0.] constant continuous load parallel to local x coordinate [N/m]
242 * @param {float} [params.mu=1.] length mass [kg/m]
243 * @param {float} [params.dT=0.] positiv temperature change (=warming) of beam center line [K]
244 * @param {float} [params.dTh=0.] (temperature of bottom fibers - temperature of top fibers)/height ((Tb-Tt)/h) [K/m]
245 * @param {float} [params.alpha=12e-6] thermal dillatation coefficient [K-1]
246 * @property {Node} node1 1st node
247 * @property {Node} node2 2nd node
248 * @property {[ints]} dofs degrees of freedom on both ends
249 * @property {bool} hasBodyLoad if some body (continuous force or temperature) load is present
250 * @property {float} ei bending stiffness [Nm2]
251 * @property {float} ea normal stiffness [N]
252 * @property {float} fzloc constant continuous load parallel to local z coordinate [N/m]
253 * @property {float} fxloc constant continuous load parallel to local x coordinate [N/m]
254 * @property {float} mu length mass [kg/m]
255 * @property {float} dT positive temperature change (=warming) of beam center line [K]
256 * @property {float} dTh (temperature of bottom fibers - temperature of top fibers)/height ((Tb-Tt)/h) [K/m]
257 * @property {float} alpha thermal dillatation coefficient [K-1]
258 * @property {Matrix} kloc stiffness matrix in local coordinate system, computed by setStiffAndTrsfMats method
259 * @property {Matrix} t transformation matrix (from global to local), computed by setStiffAndTrsfMats method
260 * @property {Matrix} tt transposed transformation matrix (from local to global), computed by setStiffAndTrsfMats method
261 * @property {Matrix} mloc mass matrix in local coordinate system, computed by setMassMats method
262 * @property {Matrix} m mass matrix in global coordinate system, computed by setMassMats method
263 * @property {Vector} load vector of end forces
264 * @property {Vector} dspl vector of end displacements
265 * @property {[Vectors]} eigShapes array of eigenshapes
266 * @property {float} len length of the beam
267 * @property {float} sin sin of node1->node2 vector
268 * @property {float} cos cos of node1->node2 vector*/
269 // example?
270 Beam2d = function(node1,node2,params) {
271 	var params = params==undefined? {} : params;
272 	this.node1 = node1 || null;
273 	this.node2 = node2 || null;
274 	this.type = params.type || JSB2D_CC;
275 	this.dofs = params.dofs || [0,1,2,3,4,5];
276 	this.ei = params.ei || 1.;
277 	this.ea = params.ea || 1.;
278 	this.hasBodyLoad = params.hasBodyLoad || false;
279 	this.fzloc = params.fzloc || 0.;
280 	this.fxloc = params.fxloc || 0.;
281 	this.mu = params.mu || 1.;
282 	this.dT = params.dT || 0.;
283 	this.dTh = params.dTh || 0.;
284 	this.alpha = params.alpha || 12e-6;
285 	this.kloc = null;
286 	this.a    = null;
287 	this.b    = null;
288 	this.kaa  = null;
289 	this.kab  = null;
290 	this.kba  = null;
291 	this.kbb  = null;
292 	this.t    = new Matrix();
293 	this.tt   = new Matrix();
294 	this.mloc = new Matrix();
295 	this.m    = new Matrix();
296 	this.load = Vector.Zeros(6);
297 	this.loadCC = Vector.Zeros(6);
298 	this.dspl = Vector.Zeros(6);
299 	this.eigShapes = [];
300 	this.len = null;
301 	this.sin = null;
302 	this.cos = null;
303 
304 	this.setGeom();
305 }
306 /**#@+
307 * @function
308 * @memberOf Beam2d#
309 */
310 Beam2d.prototype = {
311 	/** Sets geometric parameters of received according to node positions*/
312 	setGeom: function() {
313 		var dx = (this.node2.x - this.node1.x);
314 		var dz = (this.node2.z - this.node1.z);
315 		this.len = Math.sqrt(dx*dx + dz*dz);
316 		this.cos = dx/this.len;
317 		this.sin = dz/this.len;
318 	},
319 
320 	/** Sets stiffness matrices in local and global coordinate system according to stored material and crossection parameters and transformation matrix and its transposition according to stored geometry*/
321 	setStiffAndTrsfMats: function() {
322 		var l = this.len;
323 		var eal = this.ea/l;
324 		var eil = this.ei/l;
325 		var eil2 = eil/l;
326 		var eil3 = eil2/l;
327 		var s = this.sin;
328 		var c = this.cos;
329 		// T - from gloal to local, TT - from local to global
330 		switch (this.type) {
331 			case JSB2D_HC:
332 				this.t.fromArray([[c,s,0,0,0],[-s,c,0,0,0],[0,0,c,s,0],[0,0,-s,c,0],[0,0,0,0,1]]);
333 				this.tt.fromArray([[c,-s,0,0,0],[s,c,0,0,0],[0,0,c,-s,0],[0,0,s,c,0],[0,0,0,0,1]]);
334 				break;
335 			case JSB2D_CH:
336 				this.t.fromArray([[c,s,0,0,0],[-s,c,0,0,0],[0,0,1,0,0],[0,0,0,c,s],[0,0,0,-s,c]]);
337 				this.tt.fromArray([[c,-s,0,0,0],[s,c,0,0,0],[0,0,1,0,0],[0,0,0,c,-s],[0,0,0,s,c]]);
338 				break;
339 			case JSB2D_HH:
340 				this.t.fromArray([[c,s,0,0],[-s,c,0,0],[0,0,c,s],[0,0,-s,c]]);
341 				this.tt.fromArray([[c,-s,0,0],[s,c,0,0],[0,0,c,-s],[0,0,s,c]]);
342 				break;
343 			default: // c-c
344 				this.t.fromArray([[c,s,0,0,0,0],[-s,c,0,0,0,0],[0,0,1,0,0,0],[0,0,0,c,s,0],[0,0,0,-s,c,0],[0,0,0,0,0,1]]);
345 				this.tt.fromArray([[c,-s,0,0,0,0],[s,c,0,0,0,0],[0,0,1,0,0,0],[0,0,0,c,-s,0],[0,0,0,s,c,0],[0,0,0,0,0,1]]);
346 		}
347 		var k = Matrix.create([
348 			[ eal,   0     ,  0     , -eal,   0     ,  0     ],
349 			[ 0  ,  12*eil3, -6*eil2,  0  , -12*eil3, -6*eil2],
350 			[ 0  , - 6*eil2,  4*eil ,  0  ,   6*eil2,  2*eil ],
351 			[-eal,   0     ,  0     ,  eal,   0     ,  0     ],
352 			[ 0  , -12*eil3,  6*eil2,  0  ,  12*eil3,  6*eil2],
353 			[ 0  , - 6*eil2,  2*eil ,  0  ,   6*eil2,  4*eil ]]);
354 		if (this.type) { // type is not c-c
355 			switch (this.type) {
356 				case JSB2D_HC: // hinged-clamped
357 					this.a = [0,1,3,4,5];
358 					this.b = [2];
359 					break;
360 				case JSB2D_CH: // clamped hinge
361 					this.a = [0,1,2,3,4];
362 					this.b = [5];
363 					break;
364 				case JSB2D_HH: // truss
365 					this.a = [0,1,3,4];
366 					this.b = [2,5];
367 					break;
368 			}
369 			this.kaa = k.getsm(this.a,this.a);
370 			this.kab = k.getsm(this.a,this.b);
371 			this.kba = k.getsm(this.b,this.a);
372 			this.kbbinv = k.getsm(this.b,this.b).inv();
373 			this.kloc = this.kaa.sub(this.kab.mulm(this.kbbinv).mulm(this.kba))
374 		}
375 		else { this.kloc = k; }
376 	},
377 
378 	/** Computes stiffness matrix in global coordinates system
379 	* @return Matrix stiffness matrix and corresponding dofs*/
380 	computeGlobStiffMatrix: function() {
381 		return this.tt.mulm(this.kloc).mulm(this.t);
382 	},
383 
384 	/** Sets mass matrices in local and gloal coordinate system from stored material and geometric parameters*/
385 	setMassMats: function() {
386 		var l = this.len;
387 		var mu = this.mu;
388 		var a = mu*l/420;
389 		var s = this.sin;
390 		var c = this.cos;
391 		this.Mloc.fromArray([
392 			[ 140*a, 0     , 0      , 70*a , 0     , 0      ],
393 			[ 0    , 156*a ,-22*l*a , 0    , 54*a  , 13*a*l ],
394 			[ 0    ,-22*l*a, 4*a*l*l, 0    ,-13*a*l,-3*a*l*l],
395 			[ 70*a , 0     , 0      , 140*a, 0     , 0      ],
396 			[ 0    , 54*a  ,-13*a*l , 0    , 156*a , 22*a*l ],
397 			[ 0    , 13*a*l,-3*a*l*l, 0    , 22*a*l, 4*a*l*l]]);
398 		/*this.M.fromArray([
399 			[ 140*a*c*c + 156*a*s*s,              16*a*c*s, -22*a*l*s,   70*a*c*c + 54*a*s*s,             -16*a*c*s, 13*a*l*s],
400 			[              16*a*c*s, 156*a*c*c + 140*a*s*s, -22*a*c*l,             -16*a*c*s,   54*a*c*c + 70*a*s*s, 13*a*c*l],
401 			[             -22*a*l*s,             -22*a*c*l,   4*a*l*l,             -13*a*l*s,             -13*a*c*l, -3*a*l*l],
402 			[   70*a*c*c + 54*a*s*s,             -16*a*c*s, -13*a*l*s, 140*a*c*c + 156*a*s*s,              16*a*c*s, 22*a*l*s],
403 			[             -16*a*c*s,   54*a*c*c + 70*a*s*s, -13*a*c*l,              16*a*c*s, 156*a*c*c + 140*a*s*s, 22*a*c*l],
404 			[              13*a*l*s,              13*a*c*l,  -3*a*l*l,              22*a*l*s,              22*a*c*l,  4*a*l*l]]);*/
405 	},
406 
407 	/** Sets geometry, stiffness matrices and "beam" load (end forces induced by continuous load and temperature load)*/
408 	linearStaticPreproc: function() {
409 		this.setGeom();
410 		this.setStiffAndTrsfMats();
411 		this.load.zero();
412 		if (this.hasBodyLoad) {
413 			this.loadCC.fromArray([
414 				this.ea*this.alpha*this.dT - 0.5*this.fxloc*this.len ,
415 				-.5*this.fzloc*this.len ,
416 				this.fzloc*this.len*this.len/12. + this.ei*this.alpha*this.dTh,
417 				-this.ea*this.alpha*this.dT ,
418 				-.5*this.fzloc*this.len - 0.5*this.fxloc*this.len ,
419 				-this.fzloc*this.len*this.len/12. - this.ei*this.alpha*this.dTh ]);
420 			if (this.type) {
421 				this.load.zero();
422 				this.load.setsv(this.a,this.loadCC.getsv(this.a).sub(this.kab.mulm(this.kbbinv).mulv(this.loadCC.getsv(this.b))))
423 			}
424 			else {
425 				this.load = this.loadCC;
426 			}
427 		}
428 	},
429 
430 	/** Computes end displacement in local coordinate system from given global components and respective end local end forces
431 	* @param {Vector} dspl vector of beam displacement in globalComponents (if global param is true) or local (if globalComponents param is false) coordinate system
432 	* @param {bool} [globalComponents=true] if true, dspl is considered in global coordinate system. If false, dspl is considered in local coordinate system*/
433 	linearStaticPostpro: function(dspl,globalComponents) {
434 		var globalComponents = globalComponents || true;
435 		var dspl = globalComponents? this.t.mulv(dspl) : dspl;
436 		if (this.type) {
437 			this.dspl.zero();
438 			this.dspl.setsv(this.a,dspl);
439 			this.dspl.setsv(this.b,this.kbbinv.mulv(this.loadCC.getsv(this.b).add(this.kba.mulv(dspl))).negated());
440 			this.load.zero();
441 			this.load.setsv(this.a,this.kloc.mulv(dspl).add(this.loadCC.getsv(this.a).sub(this.kab.mulm(this.kbbinv).mulv(this.loadCC.getsv(this.b)))))
442 		}
443 		else {
444 			this.dspl = dspl;
445 			this.load = this.kloc.mulv(this.dspl).add(this.loadCC);
446 		}
447 	},
448 
449 	/** Sets geometry and stiffness and mass matrices*/
450 	eigenvalueDynamicPreproc: function() {
451 		this.setGeom();
452 		this.setStiffAndTrsfMats();
453 		this.setMassMats();
454 	},
455 
456 	/** Compute local components of given eigenshape
457 	* @param {int} eigMode number of assumed eigenshape - numbering from 0
458 	* @param {Vector} eigShape eigMode-th eigenshape in global coordinate system*/
459 	eigenvalueDynamicPostpro: function(eigMode,eigShape) {
460 		this.eigShapes[eigMode] = this.TT.mulv(eigShape);
461 	},
462 
463 	/** Returns middle deflection of receiver due to continuous load (clamped ends are assumed)
464 	* @returns {float} middle deflection from continuous load*/
465 	giveMidDeflFromLoad: function() { // local z deflection in the middle of doble-clamped beam from fzloc
466 		return this.fzloc*this.len*this.len*this.len*this.len / (384*this.ei);
467 	},
468 
469 	/** Returns middle deflection of receiver due to end displacement (no load is assumed)
470 	* @returns {float} middle deflection from end displacement*/
471 	giveMidDeflFromDspl: function() { // local z deflection in the middle of the beam form nodal dspl and fzloc=0
472 		return .5*(this.dspl.get(1) + this.dspl.get(4)) + this.len/8*( -this.dspl.get(2) + this.dspl.get(5));
473 	},
474 
475 	/** Returns middle deflection of receiver
476 	* @returns {float} middle deflection*/
477 	giveMidDefl: function() {
478 		return this.giveMidDeflFromDspl() + this.giveMidDeflFromLoad();
479 	},
480 	
481 	/** Returns middle deflection of receiver of eigMode-th eigenshape
482 	* @param {int} eigMode number of asumed eigenshape - numbering from 0
483 	* @returns {float} middle deflection of eigMode-th eigenshape*/
484 	giveMidDeflOfEigShape: function(eigMode) { // local z deflection in the middle of the beam of eigMode-th eigenShape
485 		var s = this.eigShapes[eigMode];
486 		return .5*(s.get(1) + s.get(4)) + this.len/8*( -s.get(2) + s.get(5));
487 	},
488 
489 	/** Returns middle bending of receiver
490 	* @returns {float} middle deflection*/
491 	giveMidMoment: function() { // bending moment in the middle of the beam
492 		return -this.load.get(2) - this.load.get(1)*this.len*.5 - this.fzloc*this.len*this.len*.125;
493 	},
494 	/**#@-*/
495 }
496 
497 /** Constructor, see {@link Beam2d} for input parameters description
498 * @returns {Beam2d} new Beam2d object*/
499 Beam2d.create = function(node1,node2,params) {
500 	return new Beam2d(node1,node2,params);
501 }
502 
503 
504 
505 /** Linear static solver implementation
506 * @class represents linear static solver
507 * @param {[Beams]} beams array of beams to include
508 * @param {[ints]} u array of unsupported dofs
509 * @param {[ints]} p array of supported dofs
510 * @param {Vector} nodalLoad vector of external load in nodes (load from beams, i.e. linear load, temperature etc. will be added separately from beams)
511 * @param {bool} [withPrescribedDspl=true] if there is some nonzero prescribed displacement of support
512 * @param {bool} [computeReactions=false] compute global reactions or not
513 * @property {[Beams]} beams array of beams to include
514 * @property {[ints]} u array of unsupported dofs
515 * @property {[ints]} p array of supported dofs
516 * @property {int} nDofs total number of degrees of freedom of solved structure
517 * @property {Vector} nodalLoad vector of external load in nodes (load from beams, i.e. linear load, temperature etc. will be added separately from beams)
518 * @property {bool} [withPrescribedDspl=false] if there is some nonzero prescribed displacement of support
519 * @property {Matrix} K global stiffnesss matrix of whole structure
520 * @property {Vector} dspl displacement vector
521 * @property {Vector} beamLoad vector of "beam loads", i.e. end forces from beam continuous load and temperature load
522 * @property {Vector} load total load (sum od nodalLoad and beamLoad)
523 * @example TODO*/
524 LinearStaticSolver = function(beams,u,p,dspl,nodalLoad,withPrescribedDspl,computeReactions) {
525 	this.beams = beams;
526 	this.u = u;
527 	this.p = p;
528 	this.nDofs = this.u.length + this.p.length;
529 	this.nodalLoad = nodalLoad==undefined? Vector.Zeros(this.nDofs) : nodalLoad;
530 	this.withPrescribedDspl = withPrescribedDspl==undefined? false : withPrescribedDspl;
531 	this.computeReactions = computeReactions==undefined? false : computeReactions;
532 	this.k = Matrix.Zeros(this.nDofs,this.nDofs);
533 	this.dspl = dspl==undefined? Vector.Zeros(this.nDofs) : dspl;
534 	this.beamLoad = Vector.Zeros(this.nDofs);
535 	this.load = Vector.Zeros(this.nDofs);
536 }
537 /**#@+
538 * @function
539 * @memberOf LinearStaticSolver#
540 */
541 LinearStaticSolver.prototype = {
542 
543 	/** Assembles global stiffness matrix of whole structure from stiffness matrices of particular beams*/
544 	assembly: function() {
545 		this.k.zero();
546 		for (var beamNum=0; beamNum<this.beams.length; beamNum++) {
547 			var beam = this.beams[beamNum];
548 			var dofs = beam.dofs;
549 			this.k.incrsm(dofs,dofs,beam.computeGlobStiffMatrix());
550 		}
551 	},
552 
553 	/** Solves unknown displacements and forces*/
554 	solve: function() {
555 		this.load = this.nodalLoad.add(this.beamLoad);
556 		var kuu = this.k.getsm(this.u,this.u);
557 		var kpu = this.k.getsm(this.p,this.u);
558 		var fu = this.load.getsv(this.u);
559 		if (this.withPrescribedDspl) {
560 			var kup = this.k.getsm(this.u,this.p);
561 			var kpp = this.k.getsm(this.p,this.p);
562 			var rp = this.dspl.getsv(this.p);
563 			this.dspl.setsv(this.u,kuu.solveForRhs(fu.sub(kup.mulv(rp))));
564 			if (this.computeReactions) { this.load.setsv(this.p,kpu.mulv(this.dspl.getsv(this.u)).add(kpp.mulv(rp))); }
565 		}
566 		else {
567 			this.dspl.setsv(this.u,kuu.solveForRhs(fu));
568 			if (this.computeReactions) { this.load.setsv(this.p,kpu.mulv(this.dspl.getsv(this.u))); }
569 		}
570 	},
571 
572 	/** Preprocesses all beams (sets their "beam load" and assemble it to global load vecor, set their geometric parameters and stiffness matrices*/
573 	preprocBeams: function() {
574 		this.beamLoad.zero()
575 		for (var beamNum=0; beamNum<this.beams.length; beamNum++) {
576 			var beam = this.beams[beamNum];
577 			beam.linearStaticPreproc();
578 			if (beam.type) {
579 				this.beamLoad.decrsv(beam.dofs,beam.tt.mulv(beam.load.getsv(beam.a)));
580 			} else {
581 				this.beamLoad.decrsv(beam.dofs,beam.tt.mulv(beam.load));
582 			}
583 		}
584 	},
585 
586 	/** Postprocesses all beams (sets appropriate displacements to them)*/
587 	updateBeams: function() {
588 		for (var beamNum=0; beamNum<this.beams.length; beamNum++) {
589 			var beam = this.beams[beamNum];
590 			beam.linearStaticPostpro(this.dspl.getsv(beam.dofs));
591 		}
592 	},
593 
594 	/** Gloal function for whole simulation process*/
595 	up: function(preprocBeams,updateBeams) {
596 		var preprocBeams = preprocBeams==undefined? true : preprocBeams;
597 		var updateBeams = updateBeams==undefined? true : updateBeams;
598 		if (preprocBeams) { this.preprocBeams(); }
599 		this.assembly();
600 		this.solve();
601 		if (updateBeams) { this.updateBeams(); }
602 	},
603 	/**#@-*/
604 }
605 /** Constructor, see {@link LinearStaticSolver} for input parameters description
606 * @returns {LinearStaticSolver} new LinearStaticSolver object*/
607 LinearStaticSolver.create = function(beams,u,p,dspl,nodalLoad,withPrescribedDspl) {
608 	return new LinearStaticSolver(beams,u,p,dspl,nodalLoad,withPrescribedDspl);
609 }
610 
611 
612 
613 
614 /** Eigenvalue dynamic solver implementation
615 * @class represents eigenvalue dynamic solver
616 * @param {[Beams]} beams array of beams to include
617 * @param {[ints]} u array of unsupported dofs
618 * @param {[ints]} p array of supported dofs
619 * @param {int} [nEigModes=1] number of first eigenvalues and eigenvectors to be solved
620 * @param {Vector} [concMass=Vector.Zeros] Vector of concentrated mass for each Dof (default zero Vector)
621 * @property {[Beams]} beams array of beams to include
622 * @property {[ints]} u array of unsupported dofs
623 * @property {[ints]} p array of supported dofs
624 * @property {int} nDofs total number of degrees of freedom of solved structure
625 * @property {int} [nEigModes=1] number of first eigenvalues and eigenvectors to be solved
626 * @property {Vector} [concMass=Vector.Zeros] Vector of concentrated mass for each Dof (default zero Vector)
627 * @property {Matrix} K global stiffness matrix
628 * @property {Matrix} M global mass matrix
629 * @property {[floats]} eigFreqs computed eigenfrequencies
630 * @property {[Vectors]} eigShapes computed eigenshapes
631 * @example TODO*/
632 EigenValueDynamicSolver = function(beams,u,p,nEigModes,concMass) {
633 	this.beams = beams;
634 	this.u = u;
635 	this.p = p;
636 	this.nDofs = this.u.length + this.p.length;
637 	this.nEigModes = nEigModes==undefined? 1 : nEigModes;
638 	this.concMass = concMass==undefined? Vector.Zeros(this.nDofs) : concMass;
639 	this.K = Matrix.Zeros(this.nDofs,this.nDofs);
640 	this.M = Matrix.Zeros(this.nDofs,this.nDofs);
641 	this.eigFreqs = [];
642 	for (var eigMode=0; eigMode<this.nEigModes; eigMode++) { this.eigFreqs[eigMode] = 0.; }
643 	this.eigShapes = [];
644 	for (var eigMode=0; eigMode<this.nEigModes; eigMode++) { this.eigShapes[eigMode] = Vector.Zeros(this.nDofs); }
645 }
646 /**#@+
647 * @function
648 * @memberOf EigenValueDynamicSolver#
649 */
650 EigenValueDynamicSolver.prototype = {
651 
652 	/** Assembles global stiffness and mass matrix of whole structure from stiffness and mass matrices of particular beams and concMass attribute*/
653 	assembly: function() {
654 		this.K.zero();
655 		this.M.zero()
656 		for (var beamNum=0; beamNum<this.beams.length; beamNum++) {
657 			var beam = this.beams[beamNum];
658 			var dofs = beam.dofs;
659 			this.K.incrsm(dofs,dofs,beam.K);
660 			this.M.incrsm(dofs,dofs,beam.M);
661 		}
662 		for (var i=0; i<this.nDofs; i++) { this.M.incr(i,i,this.concMass.get(i)); }
663 	},
664 
665 	/** Solves unknown eigenfrequencies and eigenshapes*/
666 	solve: function() {
667 		var kuu = this.k.getsm(this.u,this.u);
668 		var kuu = this.m.getsm(this.u,this.u);
669 		var results = eigSolve(Kuu,Muu,this.nEigModes);
670 		for (var eigMode=0; eigMode<this.nEigModes; eigMode++) {
671 			this.eigFreqs[eigMode] = results[0][eigMode];
672 			this.eigShapes[eigMode].setsv(this.u,results[1][eigMode]);
673 		}
674 	},
675 
676 	/** Preprocesses all beams (sets their "beam load" and assemble it to global load vecor, set their geometric parameters and stiffness matrices*/
677 	preprocBeams: function() {
678 		for (var beamNum = 0; beamNum<this.beams.length; beamNum++) { this.beams[beamNum].eigenvalueDynamicPreproc(); }
679 	},
680 
681 	/** Postprocesses all beams (from computed eigenshapes sets appropriate displacements to them)*/
682 	updateBeams: function() {
683 		for (var eigMode = 0; eigMode<this.nEigModes; eigMode++) {
684 			for (var beamNum=0; beamNum<this.beams.length; beamNum++) {
685 				var beam = this.beams[beamNum];
686 				beam.eigenvalueDynamicPostpro(eigMode,this.eigShapes[eigMode].getsv(beam.dofs));
687 			}
688 		}
689 	},
690 
691 	/** Global function for whole simulation process*/
692 	up: function(preprocBeams,updateBeams) {
693 		var preprocBeams = preprocBeams==undefined? true : preprocBeams;
694 		var updateBeams = updateBeams==undefined? true : updateBeams;
695 		if (preprocBeams) { this.preprocBeams(); }
696 		this.assembly();
697 		this.solve();
698 		if (updateBeams) { this.updateBeams(); }
699 	},
700 	/**#@-*/
701 }
702 /** Constructor, see {@link EigenValueDynamicSolver} for input parameters description
703 * @returns {EigenValueDynamicSolver} new EigenValueDynamicSolver object*/
704 EigenValueDynamicSolver.create = function(beams,u,p,nEigModes,concMass) {
705 	return new EigenValueDynamicSolver(beams,u,p,nEigModes,concMass);
706 }
707 
708 
709 
710 
711 
712 
713 
714 
715 
716 
717 /** Cross section implementation
718 * @class represents (so far polygonal only) cross section
719 * @param {[Nodes]} nodes array of nodes to create yz (!!) polygon in anti-clockwise (!!) order
720 * @param {[[Nodes]]} [holes=[[]]] array of arrays of nodes representing holes in polygon created by nodes
721 * @property {[Nodes]} nodes array of polygon nodes in yz plane ( this.nodes[0]==this.nodes[this.nodes.length-1] )
722 * @property {float} [a=null] area
723 * @property {float} [sy=null] static moment (first moment of mass) with respect to y coordinate (global)
724 * @property {float} [sz=null] static moment (first moment of mass) with respect to z coordinate (global)
725 * @property {float} [cy=null] y coordinate of center of mass
726 * @property {float} [cz=null] z coordinate of center of mass
727 * @property {float} [iy=null] moment of inertia (second moment of area) with respect to y coordinate (local)
728 * @property {float} [iz=null] moment of inertia (second moment of area) with respect to z coordinate (local)
729 * @property {float} [dyz=null] deviation (product) moment of inertia with respect to yz coordinate system
730 * @property {float} [i1=null] first principal value of moment of inertia (i1>i2)
731 * @property {float} [i2=null] second principal value of moment of inertia (i1>i2)
732 * @property {float} [beta=null] angle from global axes to principal inertia orientation
733 * @property {[Nodes]} [core=null] core of cross section
734 * @example TODO*/
735 CrossSection = function(nodes,holes) {
736 	this.nodes = nodes;
737 	if (this.nodes[this.nodes.length-1] != this.nodes[0]) { this.nodes.push(this.nodes[0]); }
738 	this.holes = holes || [[]];
739 	this.a = null;
740 	this.sy = null;
741 	this.sz = null;
742 	this.cy = null;
743 	this.cz = null;
744 	this.iy = null;
745 	this.iz = null;
746 	this.dyz = null;
747 	this.i1 = null;
748 	this.i2 = null;
749 	this.beta = null;
750 	this.core = null;
751 }
752 /**#@+
753 * @function
754 * @memberOf CrossSection#
755 */
756 CrossSection.prototype = {
757 	/** Reset receiver (sets all values to null)*/
758 	reset: function() {
759 		this.a = null;
760 		this.sy = null;
761 		this.sz = null;
762 		this.cy = null;
763 		this.cz = null;
764 		this.iy = null;
765 		this.iz = null;
766 		this.dyz = null;
767 		this.i1 = null;
768 		this.i2 = null;
769 		this.beta = null;
770 		this.convexHull = null;
771 		this.core = null;
772 	},
773 
774 	/** Computes area of receiver
775 	* @returns {float} area of receiver*/
776 	computeA: function() {
777 		var ret = 0.;
778 		var n0, nL;
779 		for (var i=0; i<this.nodes.length-1; i++) {
780 			n0 = this.nodes[i];
781 			nL = this.nodes[i+1];
782 			ret += n0.y*nL.z - nL.y*n0.z;
783 		}
784 		return .5*ret;
785 	},
786 
787 	/** Computes static moment (first order moment of mass) of receiver with respect to y coordinate axis
788 	* @param {bool} [local=false] if computed with respect to this.cy center of mass or global yz coordinates
789 	* @returns {float} Sy of receiver*/
790 	computeSy: function(local) {
791 		var local = local==undefined? false : local;
792 		var zc = 0.;
793 		if (local) {
794 			if (this.cz==null) { return null; }
795 			zc = this.cz;
796 		}
797 		var ret = 0.;
798 		var n0, nL, y0, yL, z0, zL;
799 		for (var i=0; i<this.nodes.length-1; i++) {
800 			n0 = this.nodes[i];
801 			nL = this.nodes[i+1];
802 			y0 = n0.y; yL = nL.y;
803 			z0 = n0.z-zc; zL = nL.z-zc;
804 			ret += (zL+z0)*(y0*zL-yL*z0);
805 		}
806 		return 1/6.*ret;
807 	},
808 
809 	/** Computes static moment (first order moment of mass) of receiver with respect to z coordinate axis
810 	* @param {bool} [local=false] if computed with respect to this.cz center of mass or global yz coordinates
811 	* @returns {float} Sz of receiver*/
812 	computeSz: function(local) {
813 		var local = local==undefined? false : local;
814 		var yc = 0.;
815 		if (local) {
816 			if (this.cy==null) { return null; }
817 			yc = this.cy;
818 		}
819 		var ret = 0.;
820 		var n0, nL, y0, yL, z0, zL;
821 		for (var i=0; i<this.nodes.length-1; i++) {
822 			n0 = this.nodes[i];
823 			nL = this.nodes[i+1];
824 			y0 = n0.y-yc; yL = nL.y-yc;
825 			z0 = n0.z; zL = nL.z;
826 			ret += (y0+yL)*(y0*zL-yL*z0);
827 		}
828 		return 1/6.*ret;
829 	},
830 
831 	/** Computes y coordinate of center of mass of receiver
832 	* @returns {float} Cy of receiver*/
833 	computeCy: function() {
834 		var a = this.a==null? this.computeA() : this.a;
835 		var sz = this.sz==null? this.computeSz() : this.sz;
836 		return sz/a;
837 	},
838 
839 	/** Computes z coordinate of center of mass of receiver
840 	* @returns {float} Cz of receiver*/
841 	computeCz: function() {
842 		var a = this.a==null? this.computeA() : this.a;
843 		var sy = this.sy==null? this.computeSy() : this.sy;
844 		return sy/a;
845 	},
846 
847 	/** Computes moment of inertia (second moment of area) of receiver with respect to y coordinate axis
848 	* @param {bool} [local=true] if computed with respect to this.cy center of mass or global yz coordinates
849 	* @returns {float} moment of inertia (y) of receiver*/
850 	computeIy: function(local) {
851 		var local = local==undefined? true : local;
852 		var zc = 0.;
853 		if (local) {
854 			if (this.cz==null) { return null; }
855 			zc = this.cz;
856 		}
857 		var ret = 0.;
858 		var n0, nL, y0, yL, z0, zL;
859 		for (var i=0; i<this.nodes.length-1; i++) {
860 			n0 = this.nodes[i];
861 			nL = this.nodes[i+1];
862 			y0 = n0.y; yL = nL.y;
863 			z0 = n0.z-zc; zL = nL.z-zc;
864 			ret += (z0*z0+z0*zL+zL*zL)*(y0*zL-yL*z0);
865 		}
866 		return 1/12.*ret;
867 	},
868 
869 	/** Computes moment of inertia (second moment of area) of receiver with respect to z coordinate axis
870 	* @param {bool} [local=true] if computed with respect to this.cz center of mass or global yz coordinates
871 	* @returns {float} moment of inertia (z) of receiver*/
872 	computeIz: function(local) {
873 		var local = local==undefined? true : local;
874 		var yc = 0.;
875 		if (local) {
876 			if (this.cy==null) { return null; }
877 			yc = this.cy;
878 		}
879 		var ret = 0.;
880 		var n0, nL, y0, yL, z0, zL;
881 		for (var i=0; i<this.nodes.length-1; i++) {
882 			n0 = this.nodes[i];
883 			nL = this.nodes[i+1];
884 			y0 = n0.y-yc; yL = nL.y-yc;
885 			z0 = n0.z; zL = nL.z;
886 			ret += (y0*y0+y0*yL+yL*yL)*(y0*zL-yL*z0);
887 		}
888 		return 1/12.*ret;
889 	},
890 
891 	/** Computes deviation (prodict) moment of inertia of receiver with respect to yz coordinates
892 	* @param {bool} [local=true] if computed with respect to this.cy and this.cz (center of mass) or global yz coordinates
893 	* @returns {float} deviation (product) moment of inertia (yz) of receiver*/
894 	computeDyz: function(local) {
895 		var local = local==undefined? true : local;
896 		var yc = 0.;
897 		var zc = 0.;
898 		if (local) {
899 			if (this.cy==null) { return null; }
900 			yc = this.cy;
901 			if (this.cz==null) { return null; }
902 			zc = this.cz;
903 		}
904 		var ret = 0.;
905 		var n0, nL, y0, yL, z0, zL;
906 		for (var i=0; i<this.nodes.length-1; i++) {
907 			n0 = this.nodes[i];
908 			nL = this.nodes[i+1];
909 			y0 = n0.y-yc; yL = nL.y-yc;
910 			z0 = n0.z-zc; zL = nL.z-zc;
911 			ret += (y0*zL+2*y0*z0+2*yL*zL+yL*z0)*(y0*zL-yL*z0);
912 		}
913 		return 1/24.*ret;
914 	},
915 
916 	/** Computes polar moment of inertia of receiver with respect to yz coordinate axis
917 	* @returns {float polar} moment of inertia (yz) of receiver*/
918 	computeI0: function() {
919 		var iy = this.iy==null? this.computeIy() : this.iy;
920 		var iz = this.iz==null? this.computeIz() : this.iz;
921 		return iy+iz;
922 	},
923 
924 	/** Computes moment of inertia tensor of receiver (i.e. [[Iy,-Dyz],[-Dyz,Iz]] )
925 	* @returns {[[float,float],[float,float]]} moment of inertia tensor (yz) of receiver*/
926 	computeInertiaTensor: function() {
927 		var iy = this.iy==null? this.computeIy() : this.iy;
928 		var iz = this.iz==null? this.computeIz() : this.iz;
929 		var dyz = this.dyz==null? this.computeDyz() : this.dyz;
930 		return [[iy,-dyz],[-dyz,iz]];
931 	},
932 
933 	/** Computes principal inertia values and angle from global axes to principal inertia orientation
934 	* @returns {[float,float,float]} principal values and angle of principal direction [I1,I2,angle], I1 > I2 */
935 	computePrincipalValues: function() {
936 		var iy = this.iy==null? this.computeIy() : this.iy;
937 		var iz = this.iz==null? this.computeIz() : this.iz;
938 		var dyz = this.dyz==null? this.computeDyz() : this.dyz;
939 		if (iy==iz) { return [iy,iz,0.]; }
940 		if (dyz == 0.) {
941 			if (iy>iz) { return [iy,iz,0.]; }
942 			else { return [iz,iy,.5*Math.PI]; }
943 		}
944 		var beta = 0.5*Math.atan(2*dyz/(iz-iy));
945 		var c = Math.cos(beta)
946 		var s = Math.sin(beta)
947 		var i1 = c*c*iy + s*s*iz - 2*c*s*dyz;
948 		var i2 = s*s*iy + c*c*iz + 2*c*s*dyz;
949 		if (i1>i2) { return [i1,i2,beta]; }
950 		else { return [i2,i1,beta+0.5*Math.PI]; }
951 	},
952 
953 	/** Computes normal stress at certain point with coordinates x and y
954 	* @param {float} y y coordinate of desired point
955 	* @param {float} z z coordinate of desired point
956 	* @param {float} N normal force
957 	* @param {float} My moment y
958 	* @param {float} Mz moment z
959 	* @param {bool} [local=false] if y z are local coordinates or not
960 	* @returns {float} stress at [x,z] caused by N,My,Mz*/
961 	computeStress: function(y,z,N,My,Mz,local) {
962 		var local = local || false;
963 		var a = this.a==null? this.computeA() : this.a;
964 		var iy = this.iy==null? this.computeIy() : this.iy;
965 		var iz = this.iz==null? this.computeIz() : this.iz;
966 		var dyz = this.dyz==null? this.computeDyz() : this.dyz;
967 		if (local) { var y=y; var z=z; }
968 		else {
969 			var y = y - (this.cy==null? this.computeCy() : this.cy);
970 			var z = z - (this.cz==null? this.computeCz() : this.cz);
971 		}
972 		return N/a + (My*iz+Mz*dyz)/(iy*iz-dyz*dyz)*z - (Mz*iy+My*dyz)/(iy*iz-dyz*dyz)*y;
973 	},
974 
975 	/** Computes normal stress at certain polygon node
976 	* @param {Node} node polygon node
977 	* @param {float} N normal force
978 	* @param {float} My moment y
979 	* @param {float} Mz moment z
980 	* @returns {float} stress at node caused by N,My,Mz*/
981 	computeStressInNode: function(node,N,My,Mz) {
982 		return this.computeStress(node.y,node.z,N,My,Mz);
983 	},
984 
985 	/** Computes neutral axis
986 	* @param {float} N normal force
987 	* @param {float} My moment y
988 	* @param {float} Mz moment z
989 	* @param {bool} [local=false] if returned equation is in local coordinates or not
990 	* @returns {[float,float,float]} [a,b,c] as ay+bz+c=0;*/
991 	computeNeutralAxis: function(N,My,Mz,local) {
992 		var local = local || false;
993 		var a = this.a==null? this.computeA() : this.a;
994 		var iy = this.iy==null? this.computeIy() : this.iy;
995 		var iz = this.iz==null? this.computeIz() : this.iz;
996 		var dyz = this.dyz==null? this.computeDyz() : this.dyz;
997 		var aa = -(Mz*iy+My*dyz)/(iy*iz-dyz*dyz);
998 		var bb = (My*iz+Mz*dyz)/(iy*iz-dyz*dyz);
999 		var cc = N/a;
1000 		if (local) {
1001 			var yc = this.cy==null? this.computeCy() : this.cy;
1002 			var zc = this.cz==null? this.computeCz() : this.cz;
1003 			cc += aa*yc+bb*zc;
1004 		}
1005 		return [aa,bb,cc];
1006 	},
1007 
1008 	/** Returns those nodes of receiver that forms the convex hull
1009 	* @returns {[Nodes]} those nodes that forms convex hull (ret[0]==ret[ret.length-1])*/
1010 	giveConvexHull: function() {
1011 		if (this.nodes.length <= 4) { return this.nodes.slice(); }
1012 		// choose two nodes (most lower-left and upper-right) that for sure forms a convex part
1013 		var c1 = this.nodes[0];
1014 		var c2 = this.nodes[0];
1015 		var i1 = 0;
1016 		var i2 = 0;
1017 		for (var i=1; i<this.nodes.length; i++) {
1018 			if (this.nodes[i].z < c1.z) { c1 = this.nodes[i]; i1 = i; continue; }
1019 			if (this.nodes[i].z > c2.z) { c2 = this.nodes[i]; i2 = i; continue; }
1020 			if (this.nodes[i].z == c1.z && this.nodes[i].y < c1.y) { c1 = this.nodes[i]; i1 = i; }
1021 			if (this.nodes[i].z == c2.z && this.nodes[i].y > c2.y) { c2 = this.nodes[i]; i2 = i; }
1022 		}
1023 
1024 		n = this.nodes.slice(0,this.nodes.length-1)
1025 		var nodes12 = i1<i2? n.slice(i1,i2) : n.slice(i1).concat(n.slice(0,i2));
1026 		var nodes21 = i2<i1? n.slice(i2,i1) : n.slice(i2).concat(n.slice(0,i1));
1027 		nodes12.push(c2); nodes21.push(c1);
1028 
1029 		var v, c, s, cMin, iCur, cCur, vCur, l12 = nodes12.length, l21 = nodes21.length;
1030 		var ret12 = []
1031 		iCur = 0;
1032 		if (l12 > 2) {
1033 			do {
1034 				ret12.push(nodes12[iCur]);
1035 				cCur = nodes12[iCur]
1036 				v = c2.sub(cCur)
1037 				cMin = 1e20;
1038 				for (var i=iCur+1; i<l12; i++) {
1039 					vCur = nodes12[i].sub(cCur)
1040 					c = vCur.dot(v)/(vCur.norm()*v.norm())
1041 					if (c <= cMin) { if (vCur.cross(v).x >= 0.) { iCur = i; cMin=c; } }
1042 				}
1043 			} while (iCur<l12-1)
1044 		} else { ret12 = [c1]; }
1045 
1046 		var ret21 = [];
1047 		iCur = 0;
1048 		if (l21 > 2) {
1049 			do {
1050 				ret21.push(nodes21[iCur]);
1051 				cCur = nodes21[iCur]
1052 				v = c1.sub(cCur)
1053 				cMin = 1e20;
1054 				for (var i=iCur+1; i<l21; i++) {
1055 					vCur = nodes21[i].sub(cCur)
1056 					c = vCur.dot(v)/(vCur.norm()*v.norm())
1057 					if (c <= cMin) { if (vCur.cross(v).x >= 0.) { iCur = i; cMin=c; } }
1058 				}
1059 			} while (iCur<l21-1)
1060 		} else { ret21 = [c2]; }
1061 		return ret12.concat(ret21).concat(c1)
1062 	},
1063 
1064 	/** Computes core (area, where applied force in x direction causes no tension)
1065 	* @param {bool} [local=false] if computed with respect to this.cx center of mass or global yz coordinates
1066 	* @returns {[Nodes]} array of nodes creating core polygon*/
1067 	computeCore: function(local) {
1068 		var core = [];
1069 		var nodes = this.convexHull==null? this.giveConvexHull() : this.convexHull;
1070 		var local = local || false;
1071 		var a = this.a==null? this.computeA() : this.a;
1072 		var iy = this.iy==null? this.computeIy() : this.iy;
1073 		var iz = this.iz==null? this.computeIz() : this.iz;
1074 		var dyz = this.dyz==null? this.computeDyz() : this.dyz;
1075 		var yc = this.cy==null? this.computeCy() : this.cy;
1076 		var zc = this.cz==null? this.computeCz() : this.cz;
1077 		var y,z,n1,n2,y1,y2,z1,z2,cc;
1078 		for (var i=0; i<nodes.length-1; i++) {
1079 			n1 = nodes[i];
1080 			n2 = nodes[i+1];
1081 			y1 = n1.y - yc;
1082 			y2 = n2.y - yc;
1083 			z1 = n1.z - zc;
1084 			z2 = n2.z - zc;
1085 			//y = iz2*(z1-z2)/(y1*z2-y2*z1);
1086 			//z = iy2*(y2-y1)/(y1*z2-y2*z1);
1087 			cc = a*(y1*z2-y2*z1);
1088 			y = (dyz*(y2-y1)+iz*(z1-z2))/cc;
1089 			z = (dyz*(z1-z2)+iy*(y2-y1))/cc;
1090 			core[i] = local? new Node(0.,y,z) : new Node(0.,y+yc,z+zc);
1091 		}
1092 		return core;
1093 	},
1094 
1095 	/** computes all values (a,sy,sz,cy,cz,iy,iz,dyz,i1,i2,beta,core) within one function call*/
1096 	up: function() {
1097 		this.a = this.computeA();
1098 		this.sy = this.computeSy();
1099 		this.sz = this.computeSz();
1100 		this.cy = this.computeCy();
1101 		this.cz = this.computeCz();
1102 		this.iy = this.computeIy();
1103 		this.iz = this.computeIz();
1104 		this.dyz = this.computeDyz();
1105 		var princ = this.computePrincipalValues();
1106 		this.i1 = princ[0];
1107 		this.i2 = princ[1];
1108 		this.beta = princ[2];
1109 		this.convexHull = this.giveConvexHull();
1110 		this.core = this.computeCore();
1111 	},
1112 	/**#@-*/
1113 }
1114 /** Constructor, see {@link CrossSection} for input parameters description
1115 * @returns {CrossSection} new CrossSection object*/
1116 CrossSection.create = function(nodes,holes) {
1117 	return new CrossSection(nodes,holes);
1118 }
1119