"use strict";
///////////////////////////////////////////////UT/////////////////////////////////////////////////////////

var vpi = Math.PI;
var arrowth = torad(180 - 17);
var epsilon = 1E-15;
var ccursor = "default";
function download(filename, text) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);

    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
}
// eg  download ("hello.txt","[a,b,c]")
function readfile(filename, callfunc) {
    var xhr = new XMLHttpRequest();
    //xhr.open("GET", "/bar/foo.txt", true);
    xhr.open("GET", filename, true);
    xhr.onload = function (e) {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                /// console.log(xhr.responseText);
                //return xhr.responseText;
                callfunc(xhr.responseText)
            } else {
                //console.error(xhr.statusText);
                alert("error read " + name)
            }
        }
    };


    xhr.onerror = function (e) {
        console.error(xhr.statusText);
    };
    xhr.send(null);

}

function callfuncalert(st) {
    download("hello from js", st);
}
////readfile("js/agogoi.js",callfuncalert);
function bezier(t,pts,offset,res){
    var k0=Math.pow(1-t,3);
    var k1=3*t*Math.pow(1-t,2);
    var k2=3*(1-t)*t*t;
    var k3=Math.pow(t,3);
    res[0]=k0*pts[0+offset]+k1*pts[2+offset]+k2*pts[4+offset]+k3*pts[6+offset];
    res[1]=k0*pts[1+offset]+k1*pts[3+offset]+k2*pts[5+offset]+k3*pts[7+offset];
}

function crossproduct(a1, a2, a3, b1, b2, b3) {
    return([a2 * b3 - a3 * b2, a3 * b1 - a1 * b3, a1 * b2 - a2 * b1])
}

function setarrowth(deg) {
    arrowth = torad(180 - deg);
}
//  use with to decimal for display
function step(n, astep) {
    if (astep === 0)
        return toround(n);
    return Math.round(n / astep) * astep;

}
function Task(type, period, life) {
    this.t = 0;
    this.period = period;
    this.life = life;
    this.type = type;
}
Task.prototype.update = function () {
    if (this.life > 0)
        this.life -= this.dt;
    this.act();
}
Task.prototype.act = function () {
    var frm = this.form;
    var t = this.t;
    frm.x += 0.4;
    frm.y += 0.3;
}

function todeg(v) {
    return v * 180 / vpi;
}
function torad(v) {
    return v * vpi / 180;
}
// from -pi to pi
function anglefix(th) {
    if (th > vpi)
        return th - 2 * vpi;
    if (th < -vpi)
        return th + 2 * vpi;
    return th;
}
function angleabs(th){
    var res=th;
    if (th<0) res=2*Math.PI+th;
    return res;
}
function length(x1, y1, x2, y2) {

    return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
function angle(x1, y1, x2, y2) {

    return Math.atan2(y2 - y1, x2 - x1);
}
function distancenom(x0, y0, x1, y1, x2, y2) {

    return Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1);//////length(x1,y1,x2,y2);
}
function distancepointline(x0, y0, x1, y1, x2, y2) {
    var tol = 0.1;
    var le = length(x1, y1, x2, y2);
    if (le < tol)
        return length(x0, y0, x1, y1);
    return distancenom(x0, y0, x1, y1, x2, y2) / le;

}
function insegment(x0, y0, x1, y1, x2, y2, tol) {

    if (length(x0, y0, (x1 + x2) / 2, (y1 + y2) / 2) > length(x1, y1, x2, y2) / 2)
        return false;
    tol = tol || 1;

    return distancepointline(x0, y0, x1, y1, x2, y2) < tol;


}



//var pm={x:444,y:444,r:64,w:164,h:164,ticks:5,min:0,max:20,value:0,dmin:3*Math.PI/4,dmax:9*Math.PI/4,dvalue:3*Math.PI/4};
// from value to dev
function random(v1, v2) {
    v2 = v2 || 0;
    return v1 + (v2 - v1) * Math.random();
}
function getdev(p) {
    var dv = p.dmin + (p.value - p.min) / (p.max - p.min) * (p.dmax - p.dmin);

    return dv;

}
function getvalue(p) {
    var value = p.min + (p.dvalue - p.dmin) / (p.dmax - p.dmin) * (p.max - p.min);
    return value;

}


function getallmethods(obj) {
    /// array
    var ar = Object.getOwnPropertyNames(obj);
    return ar;
}

function getallproperties(obj) {
    /// array
    var ar = Object.keys(obj);
    return ar;
}
function jsoncopy(src) {
    return JSON.parse(JSON.stringify(src));
}
function jsonstringify(src) {
    return JSON.stringify(src);
}
var Value = function (v) {
    this.value = v;
    this.min = v;
    this.max = v;
    this.prev = v;
    this.first = v;

}



function changecursor(nc) {

    if (nc !== ccursor) {
        document.body.style.cursor = nc;
        ccursor = nc;
    }


}
function getepsilon() {
    return epsilon;
}

function equals(a,b,tol){
    return((abs(a)-abs(b))<abs(tol))
}
function iszero(n) {
    return Math.abs(n) < epsilon;
}

function toggle(x) {

    if (x.style.display === "none") {
        x.style.display = "block";
    } else {
        x.style.display = "none";
    }
}
function showelement(x) {


    x.style.display = "block";



}
function hideelement(x) {


    x.style.display = "none";



}
function printto(id, st) {
    var el = document.getElementById(id);
    el.innerHTML = st;
}


function getelement(st) {
    return document.getElementById(st);
}
function scaleelement(el, wi, hi) {

    var st = 'scale(' + wi + ',' + hi + ')';
    el.style.transform = st;
    el.style['-o-transform'] = st;
    el.style['-webkit-transform'] = st;
    el.style['-moz-transform'] = st;
}
///
/// math


function getpolar(x, y, r, th, array) {
    array[0] = x + r * cos(th);
    array[1] = y + r * sin(th);

}
function abs(n) {
    return Math.abs(n)
}
function sin(n) {
    return Math.sin(n)
}
function cos(n) {
    return Math.cos(n)
}
function tan(n) {
    return Math.tan(n)
}
function pi() {
    return Math.PI
}
;
function todecimal(n, digits) {


    return n.toFixed(digits)

    ///return num.toLocaleString();
}

function toround(n) {
    return Math.round(n);

}

function sign(x) {
    if (x > 0)
        return 1;
    if (x < 0)
        return -1;
    return 0;
}

function toint(x) {
    return parseInt(x);
}

function tofloat(str) {
    return parseFloat(str);
}

function rgb(r, g, b) {
    return ("rgb(" + r.toString() + "," + g.toString() + "," + b.toString() + ")");
}

function rgba(r, g, b, a) {
    return ("rgba(" + r.toString() + "," + g.toString() + "," + b.toString() + "," + a.toString() + ")");
}

function concat() {
    var st = "";
    for (var i = 0; i < arguments.length; i++) {
        st += " " + arguments[i];
    }
    return st;
}
;
//// dom elements support
function getattr(el, str) {
    return el.getAttribute(str);
}

function setattr(el, str) {
    el.setAttribute(str);
}
/// string for id comma sep childs
function appendchilds() {
    var el = getelement(arguments[0]);
    for (var i = 1; i < arguments.length; i++) {
        el.appendChild(arguments[i]);
    }
}

function setbackimage(el, str) {
    el.style.backgroundImage = "url(" + str + ")";
}

function setbackcolor(el, str) {
    el.style.backgroundColor = str;
}

function setelementpos(d, x_pos, y_pos) {
    d.style.position = "absolute";
    d.style.left = x_pos + 'px';
    d.style.top = y_pos + 'px';
}
/////----------------- global functions 
/// ed loaders 
//
function loadgltf(frm, str) {



    var loader = new THREE.GLTFLoader();

// Optional: Provide a DRACOLoader instance to decode compressed mesh data
//THREE.DRACOLoader.setDecoderPath( '/examples/js/libs/draco' );
//loader.setDRACOLoader( new THREE.DRACOLoader() );

// Load a glTF resource

    loader.load(
            // resource URL'models/gltf/duck/duck.gltf'
            str,
            // called when the resource is loaded
                    function (gltf) {
                        alert(str)
                        ///frm.scene.add(gltf.scene);

                        gltf.animations; // Array<THREE.AnimationClip>
                        var object = gltf.scene; // THREE.Scene
                        gltf.scenes; // Array<THREE.Scene>
                        gltf.cameras; // Array<THREE.Camera>
                        gltf.asset; // Object
                        ////// 
                        var animations = gltf.animations;

                        if (animations && animations.length) {

                            frm.mixer = new THREE.AnimationMixer(object);

                            for (var i = 0; i < animations.length; i++) {

                                var animation = animations[ i ];

                                animation.duration = 233;//sceneInfo.animationTime

                                var action = frm.mixer.clipAction(animation);


                                action.play();

                            }

                        }

                        frm.scene.add(object);





                    },
                    // called while loading is progressing
                            function (xhr) {

                                console.log((xhr.loaded / xhr.total * 100) + '% loaded');

                            },
                            // called when loading has errors
                                    function (error) {
                                        alert("gltfe error")
                                        //console.log( 'An error happened' );

                                    }
                            );

                        }

//////  3 d    g e o m e t r y /////////////////////////////////////////////////
                function arrow(length) {
                    //var dir = new THREE.Vector3(0, 0, 1);
                    //normalize the direction vector (convert to vector of length 1)
                    //dir.normalize();
                    var origin = new THREE.Vector3(0, 0, 0);
                    length = length || 1;
                    return new THREE.Arrow(0, 0, 1, origin, length, 0x336633, 0.08, 0.04, 0.01);
                }
                function arrow2(len, width, headlen) {


                    return new Arrow2(new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 0, 0), len, width, headlen);
                }
                function plane(w, h, mat) {


                    var geometry = new THREE.PlaneGeometry(w, h);
                    return new THREE.Mesh(geometry, mat);

                }
                function sphere(radius, s1, s2, mat) {
                    var geometry = new THREE.SphereBufferGeometry(radius, s1, s2);
                    return new THREE.Mesh(geometry, mat);
                }

                function box(x1, y1, z1, mat) {
                    var geometry = new THREE.BoxGeometry(x1, y1, z1);
                    return new THREE.Mesh(geometry, mat);
                }

                function cylinder(radtop, radbot, height, segments, mat) {
                    var geometry = new THREE.CylinderBufferGeometry(radtop, radbot, height, segments);
                    //geometry.translate(0, +height/2, 0);
                    return new THREE.Mesh(geometry, mat);
                }

                function line(mat) {
                    var geometry = new THREE.Geometry();
                    geometry.vertices.push(new THREE.Vector3(0, 0, 0));
                    geometry.vertices.push(new THREE.Vector3(1, 0, 0));
                    return new THREE.Line(geometry, mat);
                }

                function lineupdate(aline) {
                    aline.geometry.verticesNeedUpdate = true;
                    if (aline.material.isLineDashedMaterial) {
                        aline.computeLineDistances();
                        aline.geometry.lineDistancesNeedUpdate = true;
                    }
                }

                function lineset(aline, x1, y1, z1, x2, y2, z2) {
                    aline.geometry.vertices[0].set(x1, y1, z1);
                    aline.geometry.vertices[1].set(x2, y2, z2);
                    lineupdate(aline)
                }

                function linestart(aline, x1, y1, z1) {
                    aline.geometry.vertices[0].set(x1, y1, z1);
                    lineupdate(aline)
                }

                function lineend(aline, x1, y1, z1) {
                    aline.geometry.vertices[1].set(x1, y1, z1);
                    lineupdate(aline)
                }

                function ngon(radius, num, mat) {
                    var geometry = new THREE.Geometry();
                    for (var i = 0; i <= num; i++) {
                        var th = i * 2.0 * Math.PI / num;
                        var x = radius * Math.cos(th);
                        var y = radius * Math.sin(th);
                        geometry.vertices.push(new THREE.Vector3(x, y, 0));
                    }
                    return new THREE.Line(geometry, mat);
                }

                function helix(radius, num, turns, mat) {
                    var geometry = new THREE.Geometry();
                    for (var i = 0; i <= num * turns; i++) {
                        var th = i * 2.0 * Math.PI / num;
                        var x = radius * Math.cos(th);
                        var y = radius * Math.sin(th);
                        geometry.vertices.push(new THREE.Vector3(x, y, 1 * i / turns / num));
                    }
                    return new THREE.Line(geometry, mat);
                }

                function concat() {
                    var st = "";
                    for (var i = 0; i < arguments.length; i++) {
                        st += " " + arguments[i];
                    }
                    return st;
                }
                ;
//// path gen
//
/// returns loops+1 * move to 

                function springout(len, r, loops) {
                    var p = [];
                    var x = 0;
                    var y = 0;

                    var d = len / (loops + 1);
                    var d1 = r / 3;


                    x += d / 2; // continue
                    var i;
                    for (i = 0; i < loops; i++) {
                        p.push(x, y - r); //move to
                        p.push(x + d1, y - r, x + d / 2 + d1, y + r, x + d / 2, y + r);
                        x += d;
                    }

                    p.push(x, y - r); // move to 
                    p.push(x + d1, y - r, x + d / 2, y - d1, x + d / 2, y);// bezier Curve start
                    return p;

                }
                function springin(len, r, loops) {
                    var p = [];
                    var x = 0;
                    var y = 0;

                    var d = len / (loops + 1);
                    var d1 = r / 3;
                    p.push(x, y); // move to 
                    p.push(x, y - d1, x + d / 2 - d1, y - r, x + d / 2, y - r);// bezier Curve start

                    x += d;
                    var i;
                    for (i = 0; i < loops; i++) {
                        p.push(x, y + r); //move to
                        p.push(x - d1, y + r, x + d / 2 - d1, y - r, x + d / 2, y - r);
                        x += d;
                    }

                    return p;

                }
                function drawspringin(ctx, len, r, loops, x, y, th) {
                    var p = springin(len, r, loops);

                    var tr = new Transform();

                    tr.translate(x, y);
                    tr.rotate(th);
                    p = tr.transformPolygon(p);
                    var i, j;
                    for (j = 0; j <= loops; j++) {
                        i = 8 * j;
                        ctx.beginPath();
                        ctx.moveTo(p[i], p[i + 1]);
                        ctx.bezierCurveTo(p[i + 2], p[i + 3], p[i + 4], p[i + 5], p[i + 6], p[i + 7]);
                        ctx.stroke();
                    }


                }
                function drawspringout(ctx, len, r, loops, x, y, th) {
                    var p = springout(len, r, loops);
                    var tr = new Transform();

                    tr.translate(x, y);
                    tr.rotate(th);
                    p = tr.transformPolygon(p);
                    var i, j;
                    for (j = 0; j <= loops; j++) {
                        i = 8 * j;
                        ctx.beginPath();
                        ctx.moveTo(p[i], p[i + 1]);
                        ctx.bezierCurveTo(p[i + 2], p[i + 3], p[i + 4], p[i + 5], p[i + 6], p[i + 7]);
                        ctx.stroke();
                    }


                }
///////////---------drawing functions -------------------------
                function linedash(ctx, ar) {
                    ctx.setLineDash(ar);
                }
                function strokestyle(ctx, stst) {
                    ctx.strokeStyle = stst;
                }
                function fillstyle(ctx, fst) {
                    ctx.fillStyle = fst;
                }
// if one parameter both stroke and fill same 
                function styles(ctx, stst, fst) {
                    ctx.strokeStyle = stst;

                    ctx.fillStyle = fst || stst;
                }

                function linewidth(ctx, lw) {
                    ctx.lineWidth = lw;
                }


                function wraptext(ctx, text, x, y, maxWidth, lineHeight) {
                    var words = text.split(' ');
                    var line = '';

                    for (var n = 0; n < words.length; n++) {
                        var wo = words[n];
                        if (wo === "#") {
                            words[n] = '';

                            ctx.fillText(line, x, y);
                            line = '';
                            y += lineHeight;

                        }
                        var testLine = line + words[n] + ' ';
                        if (wo === "#")
                            testLine = line;
                        var metrics = ctx.measureText(testLine);
                        var testWidth = metrics.width;
                        if (testWidth > maxWidth && n > 0) {
                            ctx.fillText(line, x, y);
                            line = words[n] + ' ';
                            y += lineHeight;
                        } else {
                            line = testLine;
                        }
                    }
                    ctx.fillText(line, x, y);
                }
                function drawroundrect(ctx, x, y, width, height, radius, filled, strokestyle, fillstyle) {
                    // filled =0 only line 1 only fill 2 both
                    ctx.beginPath();

                    if (strokestyle)
                        ctx.strokeStyle = strokestyle;
                    if (fillstyle)
                        ctx.fillStyle = fillstyle;
                    ctx.moveTo(x, y + radius);
                    ctx.lineTo(x, y + height - radius);
                    ctx.arcTo(x, y + height, x + radius, y + height, radius);
                    ctx.lineTo(x + width - radius, y + height);
                    ctx.arcTo(x + width, y + height, x + width, y + height - radius, radius);
                    ctx.lineTo(x + width, y + radius);
                    ctx.arcTo(x + width, y, x + width - radius, y, radius);
                    ctx.lineTo(x + radius, y);
                    ctx.arcTo(x, y, x, y + radius, radius);
                    ctx.closePath();
                    if (filled === 0 || filled === 2)
                        ctx.stroke();
                    if (filled === 1 || filled === 2)
                        ctx.fill();
                }

                function settransform(ctx, tr) {
                    ctx.setTransform(tr.m[0], tr.m[1], tr.m[2], tr.m[3], tr.m[4], tr.m[5]);
                }

                function drawline(ctx, x1, y1, x2, y2, linestyle) {
                    if (linestyle)
                        ctx.strokeStyle = linestyle;
                    ctx.beginPath();

                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.stroke();
                }

                function drawpolar(ctx, x, y, r, thrad) {
                    ctx.beginPath();

                    ctx.moveTo(x, y);
                    ctx.lineTo(x + r * Math.cos(thrad), y + r * Math.sin(thrad));
                    ctx.stroke();
                }

                function drawvector(ctx, x1, y1, x2, y2) {
                    var thrad = Math.atan2(y2 - y1, x2 - x1);
                    //var r=Math.hypot(y2-y1,x2-x1);
                    var r = Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
                    drawpolar(ctx, x1, y1, r, thrad);
                    drawpolar(ctx, x2, y2, 16, thrad + arrowth);
                    drawpolar(ctx, x2, y2, 16, thrad - arrowth);
                }

                function drawvectorpolar(ctx, x, y, r, thrad, linestyle) {
                    drawvector(ctx, x, y, x + r * Math.cos(thrad), y + r * Math.sin(thrad));
                }

                function drawrect(ctx, x1, y1, w, h, filled) {
                    ctx.beginPath();
                    //if (linestyle) ctx.strokeStyle = linestyle;
                    ctx.rect(x1, y1, w, h);
                    if (filled === 1 || filled === 2)
                        ctx.fill();
                    if (filled === 0 || filled === 2)
                        ctx.stroke();
                    //ctx.stroke();
                }



                function drawarcfilled(ctx, xo, yo, r, st, en, anticlock, linestyle) {
                    ctx.beginPath();
                    ctx.moveTo(xo, yo);
                    if (linestyle)
                        ctx.fillStyle = linestyle;
                    ctx.arc(xo, yo, r, st, en, anticlock);
                    ctx.fill();
                }
///////////////////////new 


                function drawarc(ctx, xo, yo, r, st, en, anticlock, closed, filled) {
                    ctx.beginPath();
                    //if (linestyle) ctx.strokeStyle = linestyle;
                    ctx.arc(xo, yo, r, st, en, anticlock);
                    //ctx.stroke();
                    if (closed)
                        ctx.closePath();
                    if (filled === 1 || filled === 2)
                        ctx.fill();
                    if (filled === 0 || filled === 2)
                        ctx.stroke();

                }
                function drawcircle(ctx, xo, yo, r) {
                    drawarc(ctx, xo, yo, r, 0, 2 * Math.PI, false, false, 0, 1);
                }

                function drawcirclefilled(ctx, xo, yo, r, linestyle) {
                    drawarcfilled(ctx, xo, yo, r, 0, 2 * Math.PI, false, linestyle);
                }
// fill text centered at x y 
                function drawtext(ctx, text, x, y, size, centerleft) {
                    size = size || 20;
                    centerleft = centerleft || false;
                    ctx.font = size + "px Helvetica";
                    ctx.textAlign = "center";

                    if (centerleft)
                        ctx.textAlign = "left";

                    ctx.textBaseline = "middle";

                    ctx.fillText(text, x, y);
                }
// draw polygon p [x,y,x,y]
//filled =0 stroke 1 filled 2 str & filled
//percent 
                function drawpolygon(ctx, p, filled, closed, percent, st, len) {

                    var filled = filled || 0;
                    var closed = closed || 0;
                    var percent = percent || 1.0;
                    var st = st || 0;
                    var len0 = percent * p.length / 2
                    if (len !== undefined)
                        len0 = len / 2;
                    ctx.beginPath();
                    ctx.moveTo(p[st], p[st + 1]);
                    var i;
                    for (i = 1; i < len0; i++) {
                        ctx.lineTo(p[st + i * 2], p[st + i * 2 + 1]);
                    }
                    if (closed)
                        ctx.closePath();
                    if (filled === 1 || filled === 2)
                        ctx.fill();
                    if (filled === 0 || filled === 2)
                        ctx.stroke();
                }
                function drawarrow(ctx, x, y, len, th, arh, d, filled) {
                    if (len < 0.01)
                        return;
                    //var arh=appw/50;
                    // var d=arh/3;
                    var ars = len - arh;
                    var d2 = 2 * d;
                    if (ars < 0)
                        ars = 0;
                    var tr = new Transform();
                    var p = [];

                    tr.translate(x, y);
                    tr.rotate(th);


                    p.push(0, 0, 0, d, ars, d, ars, d + d2, len, 0, ars, -d - d2, ars, -d, 0, -d, 0, 0);
                    p = tr.transformPolygon(p);
                    drawpolygon(ctx, p, filled);
                }
// center xo yo , half len
                function drawdistance(ctx, x, y, len, th, arh, d, filled) {
                    drawarrow(ctx, x, y, len, th, arh, d, filled);
                    drawarrow(ctx, x, y, len, th + Math.PI, arh, d, filled);
                }

                var Particle = {
                    m: 1, x: 110, y: 110,
                    xp: 110, yp: 110,
                    vxp: 10, vyp: 10,
                    vx: 10, vy: 10, v: 140, dir: 1.7, K: 11,
                    rx: 2,
                    ry: 2,
                    fs: 0.1, fsmax: 0.2, drag: 0.1,
                    r: 111, g: 111, b: 111


                }
// dw dh image width use when particles in eimitter
                var ParticleSystem = {
                    dw: 0, dh: 0,

                    image: undefined,
                    images: [],
                    shape: "rect,oval,line",

                    t: 0, rate: 55,
                    n: 13,
                    ndis: 100,
                    nactive: 0,
                    size1: 1, size2: 10, life1: 3, life2: 6,
                    stream: "0:burst 1 stream",
                    drag: 0,
                    gry: 10, grx: 0,
                    v1: 33, v2: 66, th1: 0.0, th2: Math.PI * 2,

                    r1: 0, g1: 0, b1: 0,
                    r2: 222, g2: 256, b2: 222,
                    emx1: 0, emy1: 0, emx2: 166, emy2: 3,
                    emtype: "rect,oval,line",
                    em: [0, 0, 100, 0],
                    p: [],
                    x1: 0, y1: 0, x2: 640, y2: 480


                }
                function emit(ps, p) {
                    particleInit(p, ps);

                    p.x = random(ps.emx1, ps.emx2 - ps.dw);
                    p.y = random(ps.emy1, ps.emy2 - ps.dh);
                }
                function psStep(ps, dt) {
                    var i;
                    ps.t += dt;
                    if (ps.nactive < ps.p.length) {

                        var cp = ps.nactive;
                        var ni = toint(ps.t * ps.rate);
                        // printto("debug",concat (ps.t,ni))

                        for (i = 0; i < ni - cp; i++) {
                            if (ps.p.length > ps.nactive) {
                                ps.nactive++;
                                emit(ps, ps.p[cp + i]);

                            }

                        }

                    }
                    for (i = 0; i < ps.p.length; i++) {
                        var p = ps.p[i];
                        p.t += dt;
                        if (p.t > p.life)
                            emit(ps, p);
                        p.x += p.vx * dt;
                        ///p.vy += 0.1 ;//gravity
                        p.y += (p.vy + 0.01) * dt;

                        ps.image = ps.images[ toint(p.t / p.life * ps.images.length)];
                    }

                }
                function particleInit(p, ps) {
                    var th = random(ps.th1, ps.th2);
                    var v = random(ps.v1, ps.v2);

                    p.vx = v * Math.cos(th);
                    p.vy = v * Math.sin(th);
                    p.life = random(ps.life1, ps.life2);
                    p.r = random(ps.r1, ps.r2);
                    p.g = random(ps.g1, ps.g2);
                    p.b = random(ps.b1, ps.b2);
                    p.life = random(ps.life1, ps.life2);
                    p.t = 0;
                }
                function psInit(ps) {
                    var i;
                    ps.p = [];
                    for (i = 0; i < ps.n; i++) {
                        var np = jsoncopy(Particle);
                        ps.p.push(np);
                        np.x = random(ps.x1, ps.x2);
                        np.y = random(ps.y1, ps.y2);
                        particleInit(np, ps);
                        np.t = 1e33;
                    }



                }
                function psStepBounce(ps, dt) {
                    var i;
                    for (i = 0; i < ps.p.length; i++) {
                        var p = ps.p[i];
                        p.x += p.vx * dt;
                        p.y += p.vy * dt;
                        if (p.x > ps.x2) {
                            p.x = ps.x2;
                            p.vx = -1 * p.vx;

                        }
                        if (p.y > ps.y2) {
                            p.y = ps.y2;
                            p.vy = -1 * p.vy;
                        }
                        if (p.x < ps.x1) {
                            p.x = ps.x1;
                            p.vx *= -1;

                        }

                        if (p.y < ps.y1) {
                            p.y = ps.y1;
                            p.vy *= -1;

                        }
                    }

                }

                function psDraw(ps, frm) {
                    var i;

                    for (i = 0; i < ps.nactive; i++) {

                        var p = ps.p[i];

                        styles(frm.ctx, "black", "white")
                        frm.drawimageto(ps.image, p.x, p.y);



                    }

                }
                function psStepgas(ps, dt) {
                    ps.nactive = ps.ndis;
                    var i, te;
                    if (Math.random() > 0.9) {
                        //te=p.vx;
                        //  p.vx=p.vy;
                        //  p.vy=te;

                        // p.vx*=-1;
                        //   p.vy*=-1;
                        var n1 = toint(random(ps.ndis));
                        var n2 = toint(random(ps.ndis));
                        te = ps.p[n1].vx;
                        ps.p[n1].vx = ps.p[n2].vx;
                        ps.p[n2].vx = te;
                        te = ps.p[n1].vy;
                        ps.p[n1].vy = ps.p[n2].vy;
                        ps.p[n2].vy = te;

                    }
                    for (i = 0; i < ps.p.length; i++) {
                        //for (i = 0; i < ps.ndis; i++) {
                        var p = ps.p[i];


                        p.x += p.vx * dt;
                        p.y += p.vy * dt;
                        if (p.x > ps.x2) {
                            p.x = ps.x2;
                            p.vx = -1 * p.vx;

                        }


                        var yz = 25 - 0.0025 * Math.pow(p.x - 0.5 * ps.x2, 2);
                        if (p.y > ps.y2 + yz) {

                            p.yz = yz;
                            //if ((ps.y>ps.y2+yz)&& p.vy>0) 


                            p.y = ps.y2 + yz;
                            p.vy = -1 * p.vy;



                        }
                        if (p.x < ps.x1) {
                            p.x = ps.x1;
                            p.vx *= -1;

                        }

                        if (p.y < ps.y1) {


                            p.y = ps.y1;
                            p.vy *= -1;

                        }
                    }

                }



                var Curve = {
                    label: "T1",
                    x: [],
                    y: [],
                    ls: "blue",
                    fs: "#FFB8EB",
                    filled: 0,
                    lw: 1.5,
                    dotp: [],
                    dotsize: 4,
                    drawdots: true
                }


                var Graph = {
                    label: "general",
                    x0: 200,
                    y0: 300,
                    axisx: undefined,
                    axisy: undefined,
                    ls: "black",
                    fs: "black",
                    lw: 1.5,
                    lsgrid: "cyan",
                    lwgrid: 1,
                    curves: [],
                    cpx: 0, cpy: 0,
                    cpsize: 8,
                    cpsdraw: true,
                    cpscoordsdraw: true

                }

                function graphInit(gr, label) {
                    gr.label = label;
                    gr.axisx = jsoncopy(Axis);
                    gr.axisy = jsoncopy(Axis);
                    gr.axisx.graph = gr;
                    gr.axisy.graph = gr;
                    gr.axisx.fsde = 14;
                    gr.axisy.fsde = 14;

                }
                function graphDraw(gr, frm) {

                    frm.ctx.lineWidth = gr.lw;
                    var ticks3 = toint(gr.axisy.len1 / gr.axisy.gridlen / gr.axisy.ppv);
                    var ticks4 = toint(gr.axisy.len2 / gr.axisy.gridlen / gr.axisy.ppv);

                    gr.axisx.len3 = ticks3 * gr.axisy.gridlen * gr.axisy.ppv;// 
                    gr.axisx.len4 = ticks4 * gr.axisy.gridlen * gr.axisy.ppv;//  

                    ticks3 = toint(gr.axisx.len1 / gr.axisx.gridlen / gr.axisx.ppv);
                    ticks4 = toint(gr.axisx.len2 / gr.axisx.gridlen / gr.axisx.ppv);

                    gr.axisy.len3 = ticks3 * gr.axisx.gridlen * gr.axisx.ppv;// 
                    gr.axisy.len4 = ticks4 * gr.axisx.gridlen * gr.axisx.ppv;//  


                    axisxDraw(gr, frm);
                    axisyDraw(gr, frm);

                    /// draw curves

                    var i, j;
                    for (i = 0; i < gr.curves.length; i++) {
                        var cc = gr.curves[i];
                        frm.ctx.lineWidth = cc.lw;
                        //for(j=0;j<cc.x.length;j++){

                        //    frm.drawtext(concat(toint(cc.x[j]),toint(cc.y[j])),i*64,96+j*13,12);
                        // }

                        styles(frm.ctx, cc.ls, cc.fs);
                        if (cc.filled === 0) {
                            for (j = 0; j < cc.x.length; j++) {

                                if (j > 0)
                                    frm.drawline(cc.x[j - 1], cc.y[j - 1], cc.x[j], cc.y[j])

                            }
                        }
                        if (cc.filled === 1) {

                            frm.drawcurve(cc.x, cc.y, 1, false);

                        }



                    }

                }
                function graphSetCurve(gr, crv, arx, ary) {
                    crv.x = [];
                    crv.y = [];
                    var i;
                    for (i = 0; i < arx.length; i++) {
                        var xx = gr.x0 + arx[i] * gr.axisx.ppv;
                        var yy = gr.y0 - ary[i] * gr.axisy.ppv;
                        crv.x.push(xx);
                        crv.y.push(yy);
                    }
                }
                function graphPoint(gr, frm, x, y, rx, ry) {
                    frm.ctx.lineWidth = gr.lw;
                    var xx = gr.x0 + x * gr.axisx.ppv;
                    var yy = gr.y0 - y * gr.axisy.ppv;
                    //styles(frm.ctx,"red","yellow")
                    frm.drawrect(xx - rx / 2, yy - ry / 2, rx, ry, 2);


                }

                function graphNewCurve(gr) {
                    var nc = jsoncopy(Curve);
                    gr.curves.push(nc);
                    return nc;
                }
                function graphAddCurve(gr, arx, ary, pos) {

                    var scx = gr.axisx.ppv;
                    var scy = gr.axisy.ppv;

                    var nc = jsoncopy(Curve);

                    var i;
                    for (i = 0; i < arx.length; i++) {
                        nc.x.push(arx[i] * scx + gr.x0);
                        nc.y.push(-ary[i] * scy + gr.y0);
                    }

                    if (!pos)
                        gr.curves.push(nc);
                    else
                        gr.curves.splice(pos, 0, nc);


                    return nc;

                }

/// ppv pix per value 
// all attrs in logical units
// value len to add to value 0
                var Axis = {
                    len3: 1200,
                    len4: 1200,
                    graph: undefined,
                    label: "Vlit",
                    len1: 320,
                    ppv: 300 / 20,
                    gridlen: 5,
                    valuelen: 5,

                    value0: 0,

                    fontsize: 14,
                    fsde: 14


                }
                function axisSet(ax, label, len1, len2, ppv, gridlen, value0, valuelen) {
                    ax.label = label;
                    ax.len1 = len1;
                    ax.len2 = len2;
                    ax.ppv = ppv;
                    ax.gridlen = gridlen;
                    ax.value0 = value0;
                    ax.valuelen = valuelen;

                }
                function axisxDraw(gr, frm) {

                    var ax = gr.axisx;
                    var fsde = ax.fsde;
                    var x0 = gr.x0;
                    var y0 = gr.y0;

                    /// draw 1 ticks
                    var i, xs, ys;
                    var gridpix = ax.gridlen * ax.ppv;
                    var ticks1 = toint(ax.len1 / gridpix);
                    var ticks2 = toint(ax.len2 / gridpix);
                    var ticklen = ax.gridlen * ax.ppv;
                    var valuestep = toint(ax.valuelen / ax.gridlen);
                    frm.styles(gr.lsgrid, gr.fs);
                    frm.drawtext(ax.value0, x0 - fsde, y0 + fsde, ax.fontsize)
                    for (i = 1; i <= ticks1; i++) {
                        xs = x0 + i * ticklen;
                        ys = y0;


                        frm.drawpolar(xs, ys, ax.len3, -Math.PI / 2);
                        frm.drawpolar(xs, ys, ax.len4, +Math.PI / 2);
                        if ((i % valuestep) === 0) {


                            var val = ax.value0 + i / valuestep * ax.valuelen;//ax.vlen1/ticks1;
                            frm.drawtext(val, xs, ys + fsde, ax.fontsize)
                        }
                    }
                    for (i = 1; i <= ticks2; i++) {

                        xs = x0 - i * ticklen;
                        ys = y0;
                        frm.drawpolar(xs, ys, ax.len3, -Math.PI / 2);
                        frm.drawpolar(xs, ys, ax.len4, +Math.PI / 2);

                        if ((i % valuestep) === 0) {


                            var val = ax.value0 - i / valuestep * ax.valuelen;
                            frm.drawtext(val, xs, ys + fsde, ax.fontsize)


                        }


                    }
                    frm.drawtext(ax.label, x0 + ax.len1 + 2 * fsde, y0, 1.5 * ax.fontsize)
                    frm.styles(gr.ls, gr.fs);
                    frm.drawpolar(x0, y0, ax.len1, 0);
                    frm.drawpolar(x0, y0, ax.len2, Math.PI);

                }

                function axisyDraw(gr, frm) {


                    var ax = gr.axisy;
                    var x0 = gr.x0;
                    var y0 = gr.y0;
                    var fsde = ax.fsde;
                    /// draw 1 ticks
                    var i, xs, ys;
                    var gridpix = ax.gridlen * ax.ppv;
                    var ticks1 = toint(ax.len1 / gridpix);
                    var ticks2 = toint(ax.len2 / gridpix);
                    var ticklen = ax.gridlen * ax.ppv;
                    var valuestep = toint(ax.valuelen / ax.gridlen);
                    frm.styles(gr.lsgrid, gr.fs);

                    for (i = 1; i <= ticks1; i++) {
                        xs = x0;
                        ys = y0 - i * ticklen;
                        frm.drawpolar(xs, ys, ax.len3, 0);
                        frm.drawpolar(xs, ys, ax.len4, Math.PI);
                        if ((i % valuestep) === 0) {


                            var val = ax.value0 + i / valuestep * ax.valuelen;
                            frm.drawtext(val, xs - fsde, ys, ax.fontsize)
                        }

                    }
                    for (i = 1; i <= ticks2; i++) {
                        xs = x0;
                        ys = y0 + i * ticklen;
                        frm.drawpolar(xs, ys, ax.len3, 0);
                        frm.drawpolar(xs, ys, ax.len4, Math.PI);
                        if ((i % valuestep) === 0) {

                            var val = ax.value0 - i / valuestep * ax.valuelen;//i*ax.vlen1/ticks1;
                            frm.drawtext(val, xs - fsde, ys, ax.fontsize)
                        }
                    }
                    frm.drawtext(ax.label, x0 - fsde, y0 - ax.len1 - 2 * fsde, 1.5 * ax.fontsize)
                    frm.styles(gr.ls, gr.fs);
                    frm.drawpolar(x0, y0, ax.len1, -Math.PI / 2);
                    frm.drawpolar(x0, y0, ax.len2, Math.PI / 2);
                }





