<commit_before>!function () {

var _ = Number.prototype

_.divmod = function (a) {
  var _ = this.valueOf(), q, r

  a = a || 0
  if (a === 0) {
    return [0, _]
  }

  r = _ % a; r < 0 && (r += a)
  q = (_ - r) / a
  return [q, r]
}
_.div =function (a) {
  return this.divmod(a)[0]
}
_.mod =function (a) {
  return this.divmod(a)[1]
}
_.gcd = function (a) {
  var _ = this.valueOf(), __

  a = a || 0
  while (a !== 0) {
    __ = [a, _ % a]; _ = __[0]; a = __[1]
  }
  return _
}
_.lcm = function (a) {
  var _ = this.valueOf()

  a = a || 1
  return _ * a / _.gcd(a)
}
_._inv = function (a) {
  var _ = this.valueOf(), x = 1, z = 0, __, q, r

  a = a || 0
  if (a === 0 && _ === -1)
    return -1

  while (a !== 0) {
    __ = _.divmod(a); q = __[0]; r = __[1]
    __ = [a, r, z, x - q * z]
    _ = __[0]; a = __[1]; x = __[2]; z = __[3]
  }
  return x
}
_.unit = function () {
  return this < 0 ? -1 : 1
}
_.body = function () {
  return Math.abs(this)
}
_.ub = function (a) {
  var _ = this.valueOf(), b = 1, d

  a = a || 0
  if (_ * a === 0) {
    return [_.unit(), _.body()]
  }
  while (true) {
    d = _.gcd(a)
    if (d === 1) {
      break
    }
    _ /= d; b *= d
  }
  return [_, b]
}

_.toArray = function () {
  var _ = [], i = 0; while (i < this) _.push(i++); return _
}
_.forEach = function (a) {
  this.toArray().forEach(a)
}
_.map = function (a) {
  return this.toArray().map(a)
}

}()

var
Complex = function (ord, arg) {
  var _ = this, __

  ord = ord || 0; arg = arg || 0
  arg %= 1; arg < 0 && (arg += 1)
  _.ord = ord; _.arg = arg
  __ = arg; __ < 0.5 || (__ -= 1); __ *= this.pi2
  _._arg = __
  ord === 0 && arg === 0 && (_.isUnity = true)
},
parseComplex = function (a) {
  var _ = a.split('.'), ord, arg

  _ = [0, 1, 2].map(function (i) {
    return _[i] || '0'
  })
  ord = parseFloat(_[0] + '.' + _[1])
  arg = parseFloat(      '0.' + _[2])
  _ = new Complex(ord, arg)
  return a.indexOf('X') === -1 ? _.log() : _
}

Complex.precision = 8

!function () {

var _ = Complex.prototype

_.pi2 = Math.PI * 2

_.shift = function () {
  var _ = this

  return new Complex(_.ord + 1, _.arg)
}
_.succ = function () {
  return this.exp().shift().log()
}
_.conjugate = function () {
  var _ = this

  return new Complex(_.ord, -_.arg)
}

_.eql = function (a) {
  var _ = this

  return a !== 0 && _.ord === a.ord && _.arg === a.arg
}
_.inv = function () {
  var _ = this

  return new Complex(-_.ord, -_.arg)
}
_.mul = function (a) {
  var _ = this

  return a === 0 ? 0 : new Complex(_.ord + a.ord, _.arg + a.arg)
}
_.neg = function () {
  var _ = this

  return new Complex(_.ord, _.arg + 0.5)
}
_.add = function (a) {
  var _ = this

  return a === 0        ? _        :
         _.neg().eql(a) ? 0        :
         _.ord < a.ord  ? a.add(_) :
         _.mul(_.inv().mul(a).succ())
}
_.log = function () {
  var _ = this

  return _.isUnity ? 0 :
         new Complex(
           Math.log  (_.ord * _.ord + _._arg * _._arg) * 0.5,
           Math.atan2(_._arg, _.ord) / _.pi2
         )
}
_.exp = function () {
  var _ = this, __ = Math.exp(_.ord)

  return new Complex(
           __ * Math.cos(_._arg),
           __ * Math.sin(_._arg) / _.pi2
         )
}
_.toString = function () {
  var _ = this, ord, arg

  ord = _.ord.toFixed(Complex.precision).split('.')
  arg = _.arg.toFixed(Complex.precision).split('.')
  ord[1] = ord[1] || '0'
  arg[1] = arg[1] || '0'
  return ord[0] + '.' + ord[1] + '.' + arg[1] + 'X'
}

}()

var
Adele = function (r, s, n) {
  var _ = this, __, u

  r = r || 0; s = s || 1; n = n || 0

  ｎ = n.body()
  __ = s.ub(n); u = __[0]; s = __[1]
  r = (r * u._inv(n)).mod(n * s)

  _.r = r; _.s = s; _.n = n

  _._r = n === 0 ? r :
         r < n/2 ? r :
         r - n
}

!function () {

_ = Adele.prototype

var nil = new Adele(0, 0, 1)

_.finalize = function () {
  var _ = this, __, _r, _s

  if (_.n === 1 || _.s === 0) {
    return nil
  }

  __ = _.r.gcd(_.s); _r = _.r.div(__); _s = _.s.div(__)

  return new Adele(_r, _s, _.n)
}

_.coerce = function (a) {
  var _ = this, __, n, _u, _s, au, as, s, _r, ar

  n = _.n.gcd(a.n)

  if (n === 1) {
    return [nil, nil]
  }

  __ = _.s.ub(n); _u = __[0]; _s = __[1]
  __ = a.s.ub(n); au = __[0]; as = __[1]
  s = _s.lcm(as)
  _r = _.r * _u._inv(n) * s.div(_s)
  ar = a.r * au._inv(n) * s.div(as)
  _ = new Adele(_r, s, n)
  a = new Adele(ar, s, n)

  return [a, _]
}
_.eql = function (a) {
  var _ = this

  return _.n === a.n && _.r === a.r && _.s === a.s
}
_.zero = function () {
  var _ = this

  return new Adele(0, _.s, _.n)
}
_.neg = function () {
  var _ = this

  return _.eql(nil) ? nil : new Adele(-_.r, _.s, _.n)
}
_.res = function () {
  var _ = this, __, u, n

  // return if unit? in ruby
  __ = _.r.ub(_.n); u = __[0]; n = __[1]
  return new Adele(0, 1, n)
}
_.add = function (a) {
  return this._add(a).finalize()
}
_._add = function (a) {
  var __ = this.coerce(a)

  return __[0].__add(__[1])
}
_.__add = function (a) {
  var _ = this

  return _.eql(nil) ? nil :
         new Adele(_.r + a.r, _.s, _.n)
}
_.unity = function () {
  var _ = this

  return new Adele(_.s, _.s, _.n)
}
_.inv = function () {
  var _ = this, r, s, __, u

  if (_.r === 0) {
    return nil
  }
  __ = _.r.ub(_.n); u = __[0]; s = __[1]
  r = _.s * u._inv(_.n)
  return new Adele(r, s, _.n)
}
_.mul = function (a) {
  return this._mul(a).finalize()
}
_._mul = function (a) {
  var __ = this.coerce(a)

  return __[0].__mul(__[1])
}
_.__mul = function (a) {
  var _ = this

  return _.eql(nil) ? nil :
         new Adele(_.r * a.r, _.s * a.s, _.n)
}
_.unit = function () {
  var _ = this, __

  __ = _.r.ub(_.n); r = __[0]
  return new Adele(r, 1, _.n)
}
_.body = function () {
  var _ = this, __

  __ = _.r.ub(_.n); r = __[1]
  return new Adele(r, _.s, 0)
}
_.isZero = function () {
  var _ = this

  return _.eql(_.zero())
}
_.isUnit = function () {
  var _ = this

  return _.eql(_.unit())
}

_.toString = function () {
  var _ = this, __ = ''

  if (_.eql(nil)) {
    return 'nil'
  }

  _.n === 0 || (__ +=       _.n.toString() + '\\')
                __ +=       _.r.toString()
  _.s === 1 || (__ += '/' + _.s.toString())

  return __
}

}()
<commit_msg>add var to _ = Adele.prototype<commit_after>!function () {

var _ = Number.prototype

_.divmod = function (a) {
  var _ = this.valueOf(), q, r

  a = a || 0
  if (a === 0) {
    return [0, _]
  }

  r = _ % a; r < 0 && (r += a)
  q = (_ - r) / a
  return [q, r]
}
_.div =function (a) {
  return this.divmod(a)[0]
}
_.mod =function (a) {
  return this.divmod(a)[1]
}
_.gcd = function (a) {
  var _ = this.valueOf(), __

  a = a || 0
  while (a !== 0) {
    __ = [a, _ % a]; _ = __[0]; a = __[1]
  }
  return _
}
_.lcm = function (a) {
  var _ = this.valueOf()

  a = a || 1
  return _ * a / _.gcd(a)
}
_._inv = function (a) {
  var _ = this.valueOf(), x = 1, z = 0, __, q, r

  a = a || 0
  if (a === 0 && _ === -1)
    return -1

  while (a !== 0) {
    __ = _.divmod(a); q = __[0]; r = __[1]
    __ = [a, r, z, x - q * z]
    _ = __[0]; a = __[1]; x = __[2]; z = __[3]
  }
  return x
}
_.unit = function () {
  return this < 0 ? -1 : 1
}
_.body = function () {
  return Math.abs(this)
}
_.ub = function (a) {
  var _ = this.valueOf(), b = 1, d

  a = a || 0
  if (_ * a === 0) {
    return [_.unit(), _.body()]
  }
  while (true) {
    d = _.gcd(a)
    if (d === 1) {
      break
    }
    _ /= d; b *= d
  }
  return [_, b]
}

_.toArray = function () {
  var _ = [], i = 0; while (i < this) _.push(i++); return _
}
_.forEach = function (a) {
  this.toArray().forEach(a)
}
_.map = function (a) {
  return this.toArray().map(a)
}

}()

var
Complex = function (ord, arg) {
  var _ = this, __

  ord = ord || 0; arg = arg || 0
  arg %= 1; arg < 0 && (arg += 1)
  _.ord = ord; _.arg = arg
  __ = arg; __ < 0.5 || (__ -= 1); __ *= this.pi2
  _._arg = __
  ord === 0 && arg === 0 && (_.isUnity = true)
},
parseComplex = function (a) {
  var _ = a.split('.'), ord, arg

  _ = [0, 1, 2].map(function (i) {
    return _[i] || '0'
  })
  ord = parseFloat(_[0] + '.' + _[1])
  arg = parseFloat(      '0.' + _[2])
  _ = new Complex(ord, arg)
  return a.indexOf('X') === -1 ? _.log() : _
}

Complex.precision = 8

!function () {

var _ = Complex.prototype

_.pi2 = Math.PI * 2

_.shift = function () {
  var _ = this

  return new Complex(_.ord + 1, _.arg)
}
_.succ = function () {
  return this.exp().shift().log()
}
_.conjugate = function () {
  var _ = this

  return new Complex(_.ord, -_.arg)
}

_.eql = function (a) {
  var _ = this

  return a !== 0 && _.ord === a.ord && _.arg === a.arg
}
_.inv = function () {
  var _ = this

  return new Complex(-_.ord, -_.arg)
}
_.mul = function (a) {
  var _ = this

  return a === 0 ? 0 : new Complex(_.ord + a.ord, _.arg + a.arg)
}
_.neg = function () {
  var _ = this

  return new Complex(_.ord, _.arg + 0.5)
}
_.add = function (a) {
  var _ = this

  return a === 0        ? _        :
         _.neg().eql(a) ? 0        :
         _.ord < a.ord  ? a.add(_) :
         _.mul(_.inv().mul(a).succ())
}
_.log = function () {
  var _ = this

  return _.isUnity ? 0 :
         new Complex(
           Math.log  (_.ord * _.ord + _._arg * _._arg) * 0.5,
           Math.atan2(_._arg, _.ord) / _.pi2
         )
}
_.exp = function () {
  var _ = this, __ = Math.exp(_.ord)

  return new Complex(
           __ * Math.cos(_._arg),
           __ * Math.sin(_._arg) / _.pi2
         )
}
_.toString = function () {
  var _ = this, ord, arg

  ord = _.ord.toFixed(Complex.precision).split('.')
  arg = _.arg.toFixed(Complex.precision).split('.')
  ord[1] = ord[1] || '0'
  arg[1] = arg[1] || '0'
  return ord[0] + '.' + ord[1] + '.' + arg[1] + 'X'
}

}()

var
Adele = function (r, s, n) {
  var _ = this, __, u

  r = r || 0; s = s || 1; n = n || 0

  ｎ = n.body()
  __ = s.ub(n); u = __[0]; s = __[1]
  r = (r * u._inv(n)).mod(n * s)

  _.r = r; _.s = s; _.n = n

  _._r = n === 0 ? r :
         r < n/2 ? r :
         r - n
}

!function () {

var _ = Adele.prototype, nil = new Adele(0, 0, 1)

_.finalize = function () {
  var _ = this, __, _r, _s

  if (_.n === 1 || _.s === 0) {
    return nil
  }

  __ = _.r.gcd(_.s); _r = _.r.div(__); _s = _.s.div(__)

  return new Adele(_r, _s, _.n)
}

_.coerce = function (a) {
  var _ = this, __, n, _u, _s, au, as, s, _r, ar

  n = _.n.gcd(a.n)

  if (n === 1) {
    return [nil, nil]
  }

  __ = _.s.ub(n); _u = __[0]; _s = __[1]
  __ = a.s.ub(n); au = __[0]; as = __[1]
  s = _s.lcm(as)
  _r = _.r * _u._inv(n) * s.div(_s)
  ar = a.r * au._inv(n) * s.div(as)
  _ = new Adele(_r, s, n)
  a = new Adele(ar, s, n)

  return [a, _]
}
_.eql = function (a) {
  var _ = this

  return _.n === a.n && _.r === a.r && _.s === a.s
}
_.zero = function () {
  var _ = this

  return new Adele(0, _.s, _.n)
}
_.neg = function () {
  var _ = this

  return _.eql(nil) ? nil : new Adele(-_.r, _.s, _.n)
}
_.res = function () {
  var _ = this, __, u, n

  // return if unit? in ruby
  __ = _.r.ub(_.n); u = __[0]; n = __[1]
  return new Adele(0, 1, n)
}
_.add = function (a) {
  return this._add(a).finalize()
}
_._add = function (a) {
  var __ = this.coerce(a)

  return __[0].__add(__[1])
}
_.__add = function (a) {
  var _ = this

  return _.eql(nil) ? nil :
         new Adele(_.r + a.r, _.s, _.n)
}
_.unity = function () {
  var _ = this

  return new Adele(_.s, _.s, _.n)
}
_.inv = function () {
  var _ = this, r, s, __, u

  if (_.r === 0) {
    return nil
  }
  __ = _.r.ub(_.n); u = __[0]; s = __[1]
  r = _.s * u._inv(_.n)
  return new Adele(r, s, _.n)
}
_.mul = function (a) {
  return this._mul(a).finalize()
}
_._mul = function (a) {
  var __ = this.coerce(a)

  return __[0].__mul(__[1])
}
_.__mul = function (a) {
  var _ = this

  return _.eql(nil) ? nil :
         new Adele(_.r * a.r, _.s * a.s, _.n)
}
_.unit = function () {
  var _ = this, __

  __ = _.r.ub(_.n); r = __[0]
  return new Adele(r, 1, _.n)
}
_.body = function () {
  var _ = this, __

  __ = _.r.ub(_.n); r = __[1]
  return new Adele(r, _.s, 0)
}
_.isZero = function () {
  var _ = this

  return _.eql(_.zero())
}
_.isUnit = function () {
  var _ = this

  return _.eql(_.unit())
}

_.toString = function () {
  var _ = this, __ = ''

  if (_.eql(nil)) {
    return 'nil'
  }

  _.n === 0 || (__ +=       _.n.toString() + '\\')
                __ +=       _.r.toString()
  _.s === 1 || (__ += '/' + _.s.toString())

  return __
}

}()
<|endoftext|>


<commit_before>$(document).ready(function(){

function online(){

	setInterval(function() {
	var x=navigator.onLine;

if(x==true){

	$("#box").fadeOut(700);
  $('#status').html("Online");
  $('#toast').css("background","#4caf50");
	}

else if(x==false)
	{

$("#box").fadeIn(700);
 $('#status').html("Offline");
 $('#toast').css("background","#bab8bb");
	}
	}, 10 * 10);

}
online();

});

<commit_msg>Delete my.js<commit_after><|endoftext|>


<commit_before>/**
 * Animable.js
 *
 * https://github.com/JWhile/Animable.js
 *
 * version 1.3.1
 */

var anime,stopAnime,smooth;

(function(){ // namespace

// class Animation
function Animation(id, from, to, time, update, smooth)
{
    this.id = id; // :int

    this.from = from; // :float
    this.diff = to - from; // :float

    this.start = Date.now(); // :long
    this.time = time; // :int

    this.update = update; // :function

    this.smooth = smooth; // :function
}
// function next(long now):boolean
Animation.prototype.next = function(now)
{
    var currTime = now - this.start;

    if(currTime >= this.time)
    {
        this.update(this.diff + this.from);

        return true;
    }

    this.update(this.from + this.smooth(currTime, this.diff, this.time));

    return false;
};

var lastAnimId = 0; // :int
var animations = []; // :Array<Animation>
var loop = false; // :boolean

// function next():void
var next = function()
{
    loop = (animations.length > 0);

    if(loop)
    {
        newFrame(next);

        var now = Date.now();

        for(var i = 0; i < animations.length; ++i)
        {
            if(animations[i].next(now))
            {
                animations.splice(i, 1);

                --i;
            }
        }
    }
};

// var smooth:Map<String, function>
smooth = {

    // function(int currTime, float endValue, int endTime):float
    'Line': function(currTime, endValue, endTime)
    {
        return currTime / endTime * endValue;
    },

    // function(int currTime, float endValue, int endTime):float
    'In': function(currTime, endValue, endTime)
    {
        var progression = currTime / endTime;

        return progression * progression * endValue;
    },

    // function(int currTime, float endValue, int endTime):float
    'Out': function(currTime, endValue, endTime)
    {
        var progression = currTime / endTime;

        return progression * (progression - 2) * endValue * -1;
    },

    // function(int currTime, float endValue, int endTime):float
    'InOut': function(currTime, endValue, endTime)
    {
        var progression = currTime / (endTime / 2);

        if(progression < 1)
        {
            return endValue / 2 * progression * progression;
        }

        --progression;

        return -endValue / 2 * (progression * (progression - 2) - 1);
    },

/**
 * Les effets qui suivent sont basés sur les *Easing Functions* de *Robert Panner* <http://robertpenner.com/easing/>
 *
 * t = currTime
 * c = endValue
 * d = endTime
 */
    'CubicIn': function(t, c, d)
    {
        t /= d;

        return c * t * t * t;
    },

    'CubicOut': function(t, c, d)
    {
        t /= d;
        t--;

        return c * (t * t * t + 1);
    },

    'CubicInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return c / 2 * t * t * t;
        }

        t -= 2;

        return c / 2 * (t * t * t + 2);
    }
};

// function anime(function update, float from, float to, int time, function userSmooth = null):int
anime = function(update, from, to, time, userSmooth)
{
    animations.push(new Animation(++lastAnimId, from, to, time, update, (typeof userSmooth === 'function')? userSmooth : smooth.Line));

    if(!loop)
    {
        newFrame(next);
    }

    return lastAnimId;
};

// function stopAnime(int id):void
stopAnime = function(id)
{
    for(var i = 0; i < animations.length; ++i)
    {
        if(animations[i].id === id)
        {
            animations.splice(i, 1);

            --i;
        }
    }
};

if(typeof Builder === 'function')
{
    // function anime(String property, int to, int time, function callback = null, function userSmooth = null):@Chainable
    Builder.prototype.anime = function(property, to, time, callback, userSmooth)
    {
        this.stopAnime(''+ property);

        var self = this;

        var style = Builder.getStyle(this.node, property);
        var unit = (style.match(/em$|px$|%$/i) || [''])[0];

        this._animations[property] = anime(function(value)
        {
            if(value === to)
            {
                delete self._animations[property];

                if(callback != null)
                {
                    callback();
                }
            }

            self.node.style[property] = value + unit;

        }, parseInt(style), to, time, userSmooth);

        return this;
    };

    // function stopAnime(String property = null):void
    Builder.prototype.stopAnime = function(property)
    {
        this._animations = this._animations || {}; // Map<String, int>

        if(typeof property === 'string')
        {
            if(this._animations[property])
            {
                stopAnime(this._animations[property]);

                delete this._animations[property];
            }
        }
        else
        {
            for(var key in this._animations)
            {
                if(this._animations.hasOwnProperty(key))
                {
                    stopAnime(this._animations[key]);
                }
            }

            this._animations = {};
        }
    };
}

})();
<commit_msg>Add Robert Panner's Easing Functions as smooth effect<commit_after>/**
 * Animable.js
 *
 * https://github.com/JWhile/Animable.js
 *
 * version 1.3.1
 */

var anime,stopAnime,smooth;

(function(){ // namespace

// class Animation
function Animation(id, from, to, time, update, smooth)
{
    this.id = id; // :int

    this.from = from; // :float
    this.diff = to - from; // :float

    this.start = Date.now(); // :long
    this.time = time; // :int

    this.update = update; // :function

    this.smooth = smooth; // :function
}
// function next(long now):boolean
Animation.prototype.next = function(now)
{
    var currTime = now - this.start;

    if(currTime >= this.time)
    {
        this.update(this.diff + this.from);

        return true;
    }

    this.update(this.from + this.smooth(currTime, this.diff, this.time));

    return false;
};

var lastAnimId = 0; // :int
var animations = []; // :Array<Animation>
var loop = false; // :boolean

// function next():void
var next = function()
{
    loop = (animations.length > 0);

    if(loop)
    {
        newFrame(next);

        var now = Date.now();

        for(var i = 0; i < animations.length; ++i)
        {
            if(animations[i].next(now))
            {
                animations.splice(i, 1);

                --i;
            }
        }
    }
};

// var smooth:Map<String, function>
smooth = {

    // function(int currTime, float endValue, int endTime):float
    'Line': function(currTime, endValue, endTime)
    {
        return currTime / endTime * endValue;
    },

    // function(int currTime, float endValue, int endTime):float
    'In': function(currTime, endValue, endTime)
    {
        var progression = currTime / endTime;

        return progression * progression * endValue;
    },

    // function(int currTime, float endValue, int endTime):float
    'Out': function(currTime, endValue, endTime)
    {
        var progression = currTime / endTime;

        return progression * (progression - 2) * endValue * -1;
    },

    // function(int currTime, float endValue, int endTime):float
    'InOut': function(currTime, endValue, endTime)
    {
        var progression = currTime / (endTime / 2);

        if(progression < 1)
        {
            return endValue / 2 * progression * progression;
        }

        --progression;

        return -endValue / 2 * (progression * (progression - 2) - 1);
    },

/**
 * Les effets qui suivent sont basés sur les *Easing Functions* de *Robert Panner* <http://robertpenner.com/easing/>
 *
 * t = currTime
 * c = endValue
 * d = endTime
 */
    'CubicIn': function(t, c, d)
    {
        t /= d;

        return c * t * t * t;
    },

    'CubicOut': function(t, c, d)
    {
        t /= d;
        t--;

        return c * (t * t * t + 1);
    },

    'CubicInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return c / 2 * t * t * t;
        }

        t -= 2;

        return c / 2 * (t * t * t + 2);
    },

    'QuartIn': function(t, c, d)
    {
        t /= d;

        return c * t * t * t * t;
    },

    'QuartOut': function(t, c, d)
    {
        t /= d;
        t--;

        return -c * (t * t * t * t - 1);
    },

    'QuartInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return c / 2 * t * t * t * t;
        }

        t -= 2;

        return -c / 2 * (t * t * t * t - 2);
    },

    'QuintIn': function(t, c, d)
    {
        t /= d;

        return c * t * t * t * t * t;
    },

    'QuintOut': function(t, c, d)
    {
        t /= d;
        t--;

        return c * (t * t * t * t * t + 1);
    },

    'QuintInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return c / 2 * t * t * t * t * t;
        }

        t -= 2;

        return c / 2 * (t * t * t * t * t + 2);
    },

    'SineIn': function(t, c, d)
    {
        return -c * Math.cos(t / d * (Math.PI / 2)) + c;
    },

    'SineOut': function(t, c, d)
    {
        return c * Math.sin(t / d * (Math.PI / 2));
    },

    'SineInOut': function(t, c, d)
    {
        return -c / 2 * (Math.cos(Math.PI * t/d) - 1);
    },

    'ExpoIn': function(t, c, d)
    {
        return c * Math.pow(2, 10 * (t / d - 1));
    },

    'ExpoOut': function(t, c, d)
    {
        return c * (-Math.pow(2, -10 * t/d) + 1);
    },

    'ExpoInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return c / 2 * Math.pow(2, 10 * (t - 1));
        }

        t--;

        return c / 2 * (-Math.pow(2, -10 * t) + 2);
    },

    'CircIn': function(t, c, d)
    {
        t /= d;

        return -c * (Math.sqrt(1 - t * t) - 1);
    },

    'CircOut': function(t, c, d)
    {
        t /= d;
        t--;

        return c * Math.sqrt(1 - t * t);
    },

    'CircInOut': function(t, c, d)
    {
        t /= d / 2;

        if(t < 1)
        {
            return -c / 2 * (Math.sqrt(1 - t * t) - 1);
        }

        t -= 2;

        return c / 2 * (Math.sqrt(1 - t * t) + 1);
    }
};

// function anime(function update, float from, float to, int time, function userSmooth = null):int
anime = function(update, from, to, time, userSmooth)
{
    animations.push(new Animation(++lastAnimId, from, to, time, update, (typeof userSmooth === 'function')? userSmooth : smooth.Line));

    if(!loop)
    {
        newFrame(next);
    }

    return lastAnimId;
};

// function stopAnime(int id):void
stopAnime = function(id)
{
    for(var i = 0; i < animations.length; ++i)
    {
        if(animations[i].id === id)
        {
            animations.splice(i, 1);

            --i;
        }
    }
};

if(typeof Builder === 'function')
{
    // function anime(String property, int to, int time, function callback = null, function userSmooth = null):@Chainable
    Builder.prototype.anime = function(property, to, time, callback, userSmooth)
    {
        this.stopAnime(''+ property);

        var self = this;

        var style = Builder.getStyle(this.node, property);
        var unit = (style.match(/em$|px$|%$/i) || [''])[0];

        this._animations[property] = anime(function(value)
        {
            if(value === to)
            {
                delete self._animations[property];

                if(callback != null)
                {
                    callback();
                }
            }

            self.node.style[property] = value + unit;

        }, parseInt(style), to, time, userSmooth);

        return this;
    };

    // function stopAnime(String property = null):void
    Builder.prototype.stopAnime = function(property)
    {
        this._animations = this._animations || {}; // Map<String, int>

        if(typeof property === 'string')
        {
            if(this._animations[property])
            {
                stopAnime(this._animations[property]);

                delete this._animations[property];
            }
        }
        else
        {
            for(var key in this._animations)
            {
                if(this._animations.hasOwnProperty(key))
                {
                    stopAnime(this._animations[key]);
                }
            }

            this._animations = {};
        }
    };
}

})();
<|endoftext|>


<commit_before>(function() {

    "use strict";

    var seedrandom = require('seedrandom');
    var randomSeed = (new Date()).getTime();

    // must be first
    seedrandom(randomSeed, {
        global: true
    });

    var chalk = require('chalk');
    var math = require('mathjs');
    var jpeg = require('jpeg-js');
    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    var clr = require('./color');

    var path = require('path');
    var promise = require("bluebird");
    var fs = promise.promisifyAll(require('fs'));

    var isDev = /Apple_Terminal|iterm\.app/i.test(process.env.TERM_PROGRAM);

    // load jpeg

    function loadJpeg(filename) {

        var jpegData = fs.readFileSync(filename);

        var rawImageData = jpeg.decode(jpegData);

        var data = R.times(() => [], rawImageData.height);

        var rawData = rawImageData.data;
        var w = rawImageData.width;
        var h = rawImageData.height;

        for (var d = 0; d < rawImageData.width * rawImageData.height * 4; d += 4) {
            let rgb = {};

            rgb.r = rawData[d];
            rgb.g = rawData[d + 1];
            rgb.b = rawData[d + 2];

            let d1 = d / 4;

            let x = math.floor(d1 / w);
            let y = d1 - x * w;

            data[y][x] = {
                rgb: rgb
            };
        }

        return {
            data: data,
            width: w,
            height: h
        };
    }

    function num2hex(d) {
        return (d < 16 ? "0" : "") + d.toString(16);
    }

    function randomColor(params, maxLightness) {
        let k = math.randomInt(params.xy.length);
        let yy = params.xy[k].y;
        let xx = params.xy[k].x;

        let x = xx + params.dimensions.inputWidth / 2 - params.dimensions.outputWidth / 2;
        let y = yy + params.dimensions.inputHeight / 2 - params.dimensions.outputHeight / 2;
        let rgb = params.data[x][y].rgb;

        let color = `0x${num2hex(math.floor(rgb.r * maxLightness))}${num2hex(math.floor(rgb.g * maxLightness))}${num2hex(math.floor(rgb.b * maxLightness))}`;

        return color;
    }

    // ------------ output to html+three.js

    var create3d = function(filename) {

        return new promise(function(resolve) {

            console.log(chalk.yellow(filename));

            var jpeg = loadJpeg(filename);

            let data = jpeg.data;
            let inputWidth = jpeg.width;
            let inputHeight = jpeg.height;

            let outputFilename = filename.replace(/\.jpg/, '.html');

            let outputWidth = inputWidth;
            let outputHeight = inputHeight;

            let dimensions = {
                inputWidth,
                inputHeight,
                outputWidth,
                outputHeight
            };

            let maxz = 100 + Rp.bandomInt(outputHeight - 100, 3);

            let maxRadius = 1 + Rp.bandomInt(128, 2);
            let maxRadius2 = (math.random() < 0.5 ? maxRadius : 1 + Rp.bandomInt(128, 2));

            let maxShininess = math.randomInt(0, 256);

            let spotLights = math.randomInt(1, 4);

            let segments = math.randomInt(1, 65);

            let wireframe = (maxRadius > 12) &&  (math.random() < 0.25);

            let minOpacity = math.round(100 * math.random()) / 100;
            let maxOpacity = 1;

            if (wireframe) {
              maxOpacity = math.round(100 * math.random(minOpacity, 1)) / 100;
            }

            let params = {
                maxz,
                maxRadius,
                maxRadius2,
                maxShininess,
                spotLights,
                segments,
                wireframe,
                minOpacity,
                maxOpacity
            };

            console.log('params ', JSON.stringify(params, null, 2));

            params.dimensions = dimensions;

            try {
                var outf = fs.createWriteStream(`${outputFilename}`);

                outf.write(`<!DOCTYPE html>
                <html lang='en'>
                <head>
                    <meta charset='UTF-8'>
                    <title>${outputFilename}</title>
                    <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js'></script>
                </head>
                <body style='margin:0; padding:0; overflow: hidden'>\n`);

                outf.write(`<script>\n`);

                // add line
                outf.write(`
                function ln(scene, x3, y3, z3, color) {
                  var geometry = new THREE.Geometry();

                  geometry.vertices.push(
                    new THREE.Vector3( x3, y3, 0 ),
                    new THREE.Vector3( x3, y3, z3 )
                  );

                  var material = new THREE.LineBasicMaterial({
                    color: color
                  });

                  var line = new THREE.Line( geometry, material );

                  scene.add(line);
                }
                \n`);

                // add cylinder
                // todo: open/closed ends. vary radius.

                outf.write(`
                function cyl(scene, options) {

                  var geometry = new THREE.CylinderGeometry(options.radius, options.radius2, options.z, ${params.segments}, 4);

                  var materials = [
                  new THREE.MeshPhongMaterial( {
                    color: options.color,
                    opacity: options.opacity,
                    transparent: true,
                    shininess: options.shininess,
                  } )
                ];
                \n`);

                if (params.wireframe) {
                  outf.write(`
                    materials.push(

                      new THREE.MeshBasicMaterial( {
                        color: options.color,
                        wireframe: true
                      } )

                    );
                  \n`);
                }

                outf.write(`
                  var cylinder = new THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

                  cylinder.position.x = options.x;
                  cylinder.position.y = options.y;
                  cylinder.position.z = 0;

                  scene.add(cylinder);
                }
                \n`);

                outf.write(`
                  draw();

                  function draw() {

                      var width = ${dimensions.outputWidth};
                      var height = ${dimensions.outputHeight};

                      var scene = new THREE.Scene();
                      var s = scene;
                \n`);

                let xy = [];

                for (let y = 0; y < dimensions.outputHeight; y++) {

                    for (let x = 0; x < dimensions.outputWidth; x++) {
                        xy.push({
                            x: x,
                            y: y
                        });
                    }
                }

                // use a small % of points otherwise too big to render

                // 0.4 for lines

                let sample = (isDev ? 1 : 1);

                let maxRadius = Math.max(params.maxRadius, params.maxRadius2);

                sample = sample / (maxRadius * maxRadius);

                xy = R.sortBy(() => math.random(), xy);
                xy = R.take(xy.length * sample, xy);

                for (let k = 0; k < xy.length; k++) {

                    let yy = xy[k].y;
                    let xx = xy[k].x;

                    let x = xx + dimensions.inputWidth / 2 - dimensions.outputWidth / 2;
                    let y = yy + dimensions.inputHeight / 2 - dimensions.outputHeight / 2;
                    let rgb = data[x][y].rgb;

                    let hsl = clr.rgb2hsl(rgb);

                    // 3d coords
                    let x3 = (x / dimensions.inputWidth) * dimensions.outputWidth - dimensions.outputWidth / 2;
                    let y3 = -((y / dimensions.inputHeight) * dimensions.outputHeight - dimensions.outputHeight / 2);

                    let z3 = math.round(hsl.l * maxz, 0); /// outputHeight;

                    let radius = params.maxRadius;
                    let radius2 = params.maxRadius2;

                    let opacity = params.minOpacity + (params.maxOpacity - params.minOpacity) * hsl.l;

                    let shininess = params.maxShininess;

                    outf.write(`cyl(s, {
                      x: ${x3},
                      y: ${y3},
                      z: ${z3},
                      color: 0x${num2hex(rgb.r)}${num2hex(rgb.g)}${num2hex(rgb.b)},
                      radius: ${radius},
                      radius2: ${radius2},
                      opacity: ${opacity},
                      shininess: ${shininess}
                    });
                    \n`);
                }

                // end

                let backgroundColor = '0x000000';

                params.xy = xy;
                params.data = data;

                outf.write(`
                  var renderer = new THREE.WebGLRenderer();

                  var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );

                  camera.position.x = ${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()};
                  camera.position.y = ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()};
                  camera.position.z = ${ Rp.bandomInt(1000, -2)};

                  camera.lookAt(s.position);
                  \n`);

                for (let i = 0; i < spotLights; i++) {
                    outf.write(`
                  var spotLight${i} = new THREE.SpotLight(${randomColor(params, 1)});
                  spotLight${i}.position.set(${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()}, ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()}, ${ Rp.bandomInt(1000, -2)});
                  scene.add(spotLight${i});
                  \n`);
                }

                outf.write(`
                  var ambientLight = new THREE.AmbientLight(${randomColor(params, 0.25)});
                  scene.add(ambientLight);

                  renderer.setClearColor(new THREE.Color(${backgroundColor}));

                  renderer.setSize( width, height );

                  document.body.appendChild( renderer.domElement );

                  renderer.render( scene, camera );
                \n`);

                outf.write(`}\n`); // end draw()

                outf.write(`</script>\n`);

                outf.write(`
                  </body>
                  </html>
                  \n`);

                data = null;
                jpeg.data = null;
                jpeg = null;
                xy = null;

                outf.end(function() {
                    outf = null;
                    resolve();
                });
            } catch (ex) {
                console.log(chalk.red('error'), ex);

                resolve();
            }

        });
    };

    // process file

    var processFiles = function() {

        if (process.argv.length > 2) {

            var files = R.tail(R.tail(process.argv));

            files = R.filter((f) => path.extname(f) === '.jpg', files);

            // console.log(files);

            promise.each(files, create3d).then(function() {});
        }
        else {
            console.log('usage: node 3d-image path ...');
        }

    };

    // kick off

    processFiles();

}());
<commit_msg>less pointy<commit_after>(function() {

    "use strict";

    var seedrandom = require('seedrandom');
    var randomSeed = (new Date()).getTime();

    // must be first
    seedrandom(randomSeed, {
        global: true
    });

    var chalk = require('chalk');
    var math = require('mathjs');
    var jpeg = require('jpeg-js');
    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    var clr = require('./color');

    var path = require('path');
    var promise = require("bluebird");
    var fs = promise.promisifyAll(require('fs'));

    var isDev = /Apple_Terminal|iterm\.app/i.test(process.env.TERM_PROGRAM);

    // load jpeg

    function loadJpeg(filename) {

        var jpegData = fs.readFileSync(filename);

        var rawImageData = jpeg.decode(jpegData);

        var data = R.times(() => [], rawImageData.height);

        var rawData = rawImageData.data;
        var w = rawImageData.width;
        var h = rawImageData.height;

        for (var d = 0; d < rawImageData.width * rawImageData.height * 4; d += 4) {
            let rgb = {};

            rgb.r = rawData[d];
            rgb.g = rawData[d + 1];
            rgb.b = rawData[d + 2];

            let d1 = d / 4;

            let x = math.floor(d1 / w);
            let y = d1 - x * w;

            data[y][x] = {
                rgb: rgb
            };
        }

        return {
            data: data,
            width: w,
            height: h
        };
    }

    function num2hex(d) {
        return (d < 16 ? "0" : "") + d.toString(16);
    }

    function randomColor(params, maxLightness) {
        let k = math.randomInt(params.xy.length);
        let yy = params.xy[k].y;
        let xx = params.xy[k].x;

        let x = xx + params.dimensions.inputWidth / 2 - params.dimensions.outputWidth / 2;
        let y = yy + params.dimensions.inputHeight / 2 - params.dimensions.outputHeight / 2;
        let rgb = params.data[x][y].rgb;

        let color = `0x${num2hex(math.floor(rgb.r * maxLightness))}${num2hex(math.floor(rgb.g * maxLightness))}${num2hex(math.floor(rgb.b * maxLightness))}`;

        return color;
    }

    // ------------ output to html+three.js

    var create3d = function(filename) {

        return new promise(function(resolve) {

            console.log(chalk.yellow(filename));

            var jpeg = loadJpeg(filename);

            let data = jpeg.data;
            let inputWidth = jpeg.width;
            let inputHeight = jpeg.height;

            let outputFilename = filename.replace(/\.jpg/, '.html');

            let outputWidth = inputWidth;
            let outputHeight = inputHeight;

            let dimensions = {
                inputWidth,
                inputHeight,
                outputWidth,
                outputHeight
            };

            let maxz = 100 + Rp.bandomInt(outputHeight - 100, 3);

            let maxRadius = 1 + Rp.bandomInt(128, 2);
            let maxRadius2 = (math.random() < 0.5 ? maxRadius : 1 + Rp.bandomInt(128, 2));

            let maxShininess = math.randomInt(0, 256);

            let spotLights = math.randomInt(1, 4);

            let segments = math.randomInt(1, 65);

            let wireframe = (maxRadius > 12) &&  (math.random() < 0.25);

            let minOpacity = math.round(100 * math.random()) / 100;
            let maxOpacity = 1;

            if (wireframe) {
              maxOpacity = math.round(100 * math.random(minOpacity, 1)) / 100;
            }

            let openEnded = false;

            let params = {
                maxz,
                maxRadius,
                maxRadius2,
                maxShininess,
                spotLights,
                segments,
                wireframe,
                minOpacity,
                maxOpacity,
                openEnded
            };

            console.log('params ', JSON.stringify(params, null, 2));

            params.dimensions = dimensions;

            try {
                var outf = fs.createWriteStream(`${outputFilename}`);

                outf.write(`<!DOCTYPE html>
                <html lang='en'>
                <head>
                    <meta charset='UTF-8'>
                    <title>${outputFilename}</title>
                    <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js'></script>
                </head>
                <body style='margin:0; padding:0; overflow: hidden'>\n`);

                outf.write(`<script>\n`);

                // add line
                outf.write(`
                function ln(scene, x3, y3, z3, color) {
                  var geometry = new THREE.Geometry();

                  geometry.vertices.push(
                    new THREE.Vector3( x3, y3, 0 ),
                    new THREE.Vector3( x3, y3, z3 )
                  );

                  var material = new THREE.LineBasicMaterial({
                    color: color
                  });

                  var line = new THREE.Line( geometry, material );

                  scene.add(line);
                }
                \n`);

                // add cylinder
                // todo: open/closed ends. vary radius.

                outf.write(`
                function cyl(scene, options) {

                  var geometry = new THREE.CylinderGeometry(options.radius, options.radius2, options.z, ${params.segments}, 1, ${params.openEnded});

                  var materials = [
                  new THREE.MeshPhongMaterial( {
                    color: options.color,
                    opacity: options.opacity,
                    transparent: true,
                    shininess: options.shininess,
                  } )
                ];
                \n`);

                if (params.wireframe) {
                  outf.write(`
                    materials.push(

                      new THREE.MeshBasicMaterial( {
                        color: options.color,
                        wireframe: true
                      } )

                    );
                  \n`);
                }

                outf.write(`
                  var cylinder = new THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

                  cylinder.position.x = options.x;
                  cylinder.position.y = options.y;
                  cylinder.position.z = 0;

                  scene.add(cylinder);
                }
                \n`);

                outf.write(`
                  draw();

                  function draw() {

                      var width = ${dimensions.outputWidth};
                      var height = ${dimensions.outputHeight};

                      var scene = new THREE.Scene();
                      var s = scene;
                \n`);

                let xy = [];

                for (let y = 0; y < dimensions.outputHeight; y++) {

                    for (let x = 0; x < dimensions.outputWidth; x++) {
                        xy.push({
                            x: x,
                            y: y
                        });
                    }
                }

                // use a small % of points otherwise too big to render

                // 0.4 for lines

                let sample = (isDev ? 1 : 1);

                let maxRadius = Math.max(params.maxRadius, params.maxRadius2);

                sample = sample / (maxRadius * maxRadius);

                xy = R.sortBy(() => math.random(), xy);
                xy = R.take(xy.length * sample, xy);

                for (let k = 0; k < xy.length; k++) {

                    let yy = xy[k].y;
                    let xx = xy[k].x;

                    let x = xx + dimensions.inputWidth / 2 - dimensions.outputWidth / 2;
                    let y = yy + dimensions.inputHeight / 2 - dimensions.outputHeight / 2;
                    let rgb = data[x][y].rgb;

                    let hsl = clr.rgb2hsl(rgb);

                    // 3d coords
                    let x3 = (x / dimensions.inputWidth) * dimensions.outputWidth - dimensions.outputWidth / 2;
                    let y3 = -((y / dimensions.inputHeight) * dimensions.outputHeight - dimensions.outputHeight / 2);

                    let z3 = math.round(hsl.l * maxz, 0); /// outputHeight;

                    let radius = params.maxRadius;
                    let radius2 = params.maxRadius2;

                    let opacity = params.minOpacity + (params.maxOpacity - params.minOpacity) * hsl.l;

                    let shininess = params.maxShininess;

                    outf.write(`cyl(s, {
                      x: ${x3},
                      y: ${y3},
                      z: ${z3},
                      color: 0x${num2hex(rgb.r)}${num2hex(rgb.g)}${num2hex(rgb.b)},
                      radius: ${radius},
                      radius2: ${radius2},
                      opacity: ${opacity},
                      shininess: ${shininess}
                    });
                    \n`);
                }

                // end

                let backgroundColor = '0x000000';

                params.xy = xy;
                params.data = data;

                outf.write(`
                  var renderer = new THREE.WebGLRenderer();

                  var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );

                  camera.position.x = ${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()};
                  camera.position.y = ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()};
                  camera.position.z = ${ Rp.bandomInt(1000, -2)};

                  camera.lookAt(s.position);
                  \n`);

                for (let i = 0; i < spotLights; i++) {
                    outf.write(`
                  var spotLight${i} = new THREE.SpotLight(${randomColor(params, 1)});
                  spotLight${i}.position.set(${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()}, ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()}, ${ Rp.bandomInt(1000, -2)});
                  scene.add(spotLight${i});
                  \n`);
                }

                outf.write(`
                  var ambientLight = new THREE.AmbientLight(${randomColor(params, 0.25)});
                  scene.add(ambientLight);

                  renderer.setClearColor(new THREE.Color(${backgroundColor}));

                  renderer.setSize( width, height );

                  document.body.appendChild( renderer.domElement );

                  renderer.render( scene, camera );
                \n`);

                outf.write(`}\n`); // end draw()

                outf.write(`</script>\n`);

                outf.write(`
                  </body>
                  </html>
                  \n`);

                data = null;
                jpeg.data = null;
                jpeg = null;
                xy = null;

                outf.end(function() {
                    outf = null;
                    resolve();
                });
            } catch (ex) {
                console.log(chalk.red('error'), ex);

                resolve();
            }

        });
    };

    // process file

    var processFiles = function() {

        if (process.argv.length > 2) {

            var files = R.tail(R.tail(process.argv));

            files = R.filter((f) => path.extname(f) === '.jpg', files);

            // console.log(files);

            promise.each(files, create3d).then(function() {});
        }
        else {
            console.log('usage: node 3d-image path ...');
        }

    };

    // kick off

    processFiles();

}());
<|endoftext|>


<commit_before>(function() {

    "use strict";

    var seedrandom = require('seedrandom');
    var randomSeed = (new Date()).getTime();

    // must be first
    seedrandom(randomSeed, {
        global: true
    });

    var chalk = require('chalk');
    var math = require('mathjs');
    var jpeg = require('jpeg-js');
    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    var clr = require('./color');

    var path = require('path');
    var promise = require("bluebird");
    var fs = promise.promisifyAll(require('fs'));

    var isDev = /Apple_Terminal|iterm\.app/i.test(process.env.TERM_PROGRAM);

    // load jpeg

    function loadJpeg(filename) {

        var jpegData = fs.readFileSync(filename);

        var rawImageData = jpeg.decode(jpegData);

        var data = R.times(() => [], rawImageData.height);

        var rawData = rawImageData.data;
        var w = rawImageData.width;
        var h = rawImageData.height;

        for (var d = 0; d < rawImageData.width * rawImageData.height * 4; d += 4) {
            let rgb = {};

            rgb.r = rawData[d];
            rgb.g = rawData[d + 1];
            rgb.b = rawData[d + 2];

            let d1 = d / 4;

            let x = math.floor(d1 / w);
            let y = d1 - x * w;

            data[y][x] = {
                rgb: rgb
            };
        }

        return {
            data: data,
            width: w,
            height: h
        };
    }

    function num2hex(d) {
        return (d < 16 ? "0" : "") + d.toString(16);
    }

    function randomColor(params, maxLightness) {
        let k = math.randomInt(params.xy.length);
        let yy = params.xy[k].y;
        let xx = params.xy[k].x;

        let x = xx + params.dimensions.inputWidth / 2 - params.dimensions.outputWidth / 2;
        let y = yy + params.dimensions.inputHeight / 2 - params.dimensions.outputHeight / 2;
        let rgb = params.data[x][y].rgb;

        let color = `0x${num2hex(math.floor(rgb.r * maxLightness))}${num2hex(math.floor(rgb.g * maxLightness))}${num2hex(math.floor(rgb.b * maxLightness))}`;

        return color;
    }

    // ------------ output to html+three.js

    var create3d = function(filename) {

        return new promise(function(resolve) {

            console.log(chalk.yellow(filename));

            var jpeg = loadJpeg(filename);

            let data = jpeg.data;
            let inputWidth = jpeg.width;
            let inputHeight = jpeg.height;

            let outputFilename = filename.replace(/\.jpg/, '.html');

            let outputWidth = inputWidth;
            let outputHeight = inputHeight;

            let dimensions = {
                inputWidth,
                inputHeight,
                outputWidth,
                outputHeight
            };

            let maxz = 100 + Rp.bandomInt(outputHeight - 100, 3);

            let maxRadius = 1 + Rp.bandomInt(128, 2);
            let maxRadius2 = (math.random() < 0.5 ? maxRadius : 1 + Rp.bandomInt(128, 2));

            let maxShininess = math.randomInt(0, 256);

            let spotLights = math.randomInt(1, 4);

            let segments = math.randomInt(1, 65);

            let wireframe = (maxRadius > 12) &&  (math.random() < 0.25);

            let minOpacity = math.round(100 * math.random()) / 100;
            let maxOpacity = 1;

            if (wireframe) {
              maxOpacity = math.round(100 * math.random(minOpacity, 1)) / 100;
            }

            let openEnded = false;

            let params = {
                maxz,
                maxRadius,
                maxRadius2,
                maxShininess,
                spotLights,
                segments,
                wireframe,
                minOpacity,
                maxOpacity,
                openEnded
            };

            console.log('params ', JSON.stringify(params, null, 2));

            params.dimensions = dimensions;

            try {
                var outf = fs.createWriteStream(`${outputFilename}`);

                outf.write(`<!DOCTYPE html>
                <html lang='en'>
                <head>
                    <meta charset='UTF-8'>
                    <title>${outputFilename}</title>
                    <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js'></script>
                </head>
                <body style='margin:0; padding:0; overflow: hidden'>\n`);

                outf.write(`<script>\n`);

                // add line
                outf.write(`
                function ln(scene, x3, y3, z3, color) {
                  var geometry = new THREE.Geometry();

                  geometry.vertices.push(
                    new THREE.Vector3( x3, y3, 0 ),
                    new THREE.Vector3( x3, y3, z3 )
                  );

                  var material = new THREE.LineBasicMaterial({
                    color: color
                  });

                  var line = new THREE.Line( geometry, material );

                  scene.add(line);
                }
                \n`);

                // add cylinder
                // todo: open/closed ends. vary radius.

                outf.write(`
                function cyl(scene, options) {

                  var geometry = new THREE.CylinderGeometry(options.radius, options.radius2, options.z, ${params.segments}, 1, ${params.openEnded});

                  var materials = [
                  new THREE.MeshPhongMaterial( {
                    color: options.color,
                    opacity: options.opacity,
                    transparent: true,
                    shininess: options.shininess,
                  } )
                ];
                \n`);

                if (params.wireframe) {
                  outf.write(`
                    materials.push(

                      new THREE.MeshBasicMaterial( {
                        color: options.color,
                        wireframe: true
                      } )

                    );
                  \n`);
                }

                outf.write(`
                  var cylinder = new THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

                  cylinder.position.x = options.x;
                  cylinder.position.y = options.y;
                  cylinder.position.z = 0;

                  scene.add(cylinder);
                }
                \n`);

                outf.write(`
                  draw();

                  function draw() {

                      var width = ${dimensions.outputWidth};
                      var height = ${dimensions.outputHeight};

                      var scene = new THREE.Scene();
                      var s = scene;
                \n`);

                let xy = [];

                for (let y = 0; y < dimensions.outputHeight; y++) {

                    for (let x = 0; x < dimensions.outputWidth; x++) {
                        xy.push({
                            x: x,
                            y: y
                        });
                    }
                }

                // use a small % of points otherwise too big to render

                // 0.4 for lines

                let sample = (isDev ? 1 : 1);

                let maxRadius = Math.max(params.maxRadius, params.maxRadius2);

                sample = sample / (maxRadius * maxRadius);

                xy = R.sortBy(() => math.random(), xy);
                xy = R.take(xy.length * sample, xy);

                for (let k = 0; k < xy.length; k++) {

                    let yy = xy[k].y;
                    let xx = xy[k].x;

                    let x = xx + dimensions.inputWidth / 2 - dimensions.outputWidth / 2;
                    let y = yy + dimensions.inputHeight / 2 - dimensions.outputHeight / 2;
                    let rgb = data[x][y].rgb;

                    let hsl = clr.rgb2hsl(rgb);

                    // 3d coords
                    let x3 = (x / dimensions.inputWidth) * dimensions.outputWidth - dimensions.outputWidth / 2;
                    let y3 = -((y / dimensions.inputHeight) * dimensions.outputHeight - dimensions.outputHeight / 2);

                    let z3 = math.round(hsl.l * maxz, 0); /// outputHeight;

                    let radius = params.maxRadius;
                    let radius2 = params.maxRadius2;

                    let opacity = params.minOpacity + (params.maxOpacity - params.minOpacity) * hsl.l;

                    let shininess = params.maxShininess;

                    outf.write(`cyl(s, {
                      x: ${x3},
                      y: ${y3},
                      z: ${z3},
                      color: 0x${num2hex(rgb.r)}${num2hex(rgb.g)}${num2hex(rgb.b)},
                      radius: ${radius},
                      radius2: ${radius2},
                      opacity: ${opacity},
                      shininess: ${shininess}
                    });
                    \n`);
                }

                // end

                let backgroundColor = '0x000000';

                params.xy = xy;
                params.data = data;

                outf.write(`
                  var renderer = new THREE.WebGLRenderer();

                  var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );

                  camera.position.x = ${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()};
                  camera.position.y = ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()};
                  camera.position.z = ${ Rp.bandomInt(1000, -2)};

                  camera.lookAt(s.position);
                  \n`);

                for (let i = 0; i < spotLights; i++) {
                    outf.write(`
                  var spotLight${i} = new THREE.SpotLight(${randomColor(params, 1)});
                  spotLight${i}.position.set(${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()}, ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()}, ${ Rp.bandomInt(1000, -2)});
                  scene.add(spotLight${i});
                  \n`);
                }

                outf.write(`
                  var ambientLight = new THREE.AmbientLight(${randomColor(params, 0.25)});
                  scene.add(ambientLight);

                  renderer.setClearColor(new THREE.Color(${backgroundColor}));

                  renderer.setSize( width, height );

                  document.body.appendChild( renderer.domElement );

                  renderer.render( scene, camera );
                \n`);

                outf.write(`}\n`); // end draw()

                outf.write(`</script>\n`);

                outf.write(`
                  </body>
                  </html>
                  \n`);

                data = null;
                jpeg.data = null;
                jpeg = null;
                xy = null;

                outf.end(function() {
                    outf = null;
                    resolve();
                });
            } catch (ex) {
                console.log(chalk.red('error'), ex);

                resolve();
            }

        });
    };

    // process file

    var processFiles = function() {

        if (process.argv.length > 2) {

            var files = R.tail(R.tail(process.argv));

            files = R.filter((f) => path.extname(f) === '.jpg', files);

            // console.log(files);

            promise.each(files, create3d).then(function() {});
        }
        else {
            console.log('usage: node 3d-image path ...');
        }

    };

    // kick off

    processFiles();

}());
<commit_msg>open ended<commit_after>(function() {

    "use strict";

    var seedrandom = require('seedrandom');
    var randomSeed = (new Date()).getTime();

    // must be first
    seedrandom(randomSeed, {
        global: true
    });

    var chalk = require('chalk');
    var math = require('mathjs');
    var jpeg = require('jpeg-js');
    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    var clr = require('./color');

    var path = require('path');
    var promise = require("bluebird");
    var fs = promise.promisifyAll(require('fs'));

    var isDev = /Apple_Terminal|iterm\.app/i.test(process.env.TERM_PROGRAM);

    // load jpeg

    function loadJpeg(filename) {

        var jpegData = fs.readFileSync(filename);

        var rawImageData = jpeg.decode(jpegData);

        var data = R.times(() => [], rawImageData.height);

        var rawData = rawImageData.data;
        var w = rawImageData.width;
        var h = rawImageData.height;

        for (var d = 0; d < rawImageData.width * rawImageData.height * 4; d += 4) {
            let rgb = {};

            rgb.r = rawData[d];
            rgb.g = rawData[d + 1];
            rgb.b = rawData[d + 2];

            let d1 = d / 4;

            let x = math.floor(d1 / w);
            let y = d1 - x * w;

            data[y][x] = {
                rgb: rgb
            };
        }

        return {
            data: data,
            width: w,
            height: h
        };
    }

    function num2hex(d) {
        return (d < 16 ? "0" : "") + d.toString(16);
    }

    function randomColor(params, maxLightness) {
        let k = math.randomInt(params.xy.length);
        let yy = params.xy[k].y;
        let xx = params.xy[k].x;

        let x = xx + params.dimensions.inputWidth / 2 - params.dimensions.outputWidth / 2;
        let y = yy + params.dimensions.inputHeight / 2 - params.dimensions.outputHeight / 2;
        let rgb = params.data[x][y].rgb;

        let color = `0x${num2hex(math.floor(rgb.r * maxLightness))}${num2hex(math.floor(rgb.g * maxLightness))}${num2hex(math.floor(rgb.b * maxLightness))}`;

        return color;
    }

    // ------------ output to html+three.js

    var create3d = function(filename) {

        return new promise(function(resolve) {

            console.log(chalk.yellow(filename));

            var jpeg = loadJpeg(filename);

            let data = jpeg.data;
            let inputWidth = jpeg.width;
            let inputHeight = jpeg.height;

            let outputFilename = filename.replace(/\.jpg/, '.html');

            let outputWidth = inputWidth;
            let outputHeight = inputHeight;

            let dimensions = {
                inputWidth,
                inputHeight,
                outputWidth,
                outputHeight
            };

            let maxz = 100 + Rp.bandomInt(outputHeight - 100, 3);

            let maxRadius = 1 + Rp.bandomInt(128, 2);
            let maxRadius2 = (math.random() < 0.5 && maxRadius > 10) ? maxRadius : 1 + Rp.bandomInt(128, 2);

            let maxShininess = math.randomInt(0, 256);

            let spotLights = math.randomInt(1, 4);

            let segments = math.randomInt(1, 65);

            let wireframe = (maxRadius > 12) &&  (math.random() < 0.25);

            let minOpacity = math.round(100 * math.random()) / 100;
            let maxOpacity = 1;

            if (wireframe) {
              maxOpacity = math.round(100 * math.random(minOpacity, 1)) / 100;
            }

            let openEnded = (math.random() < 0.5);

            let params = {
                maxz,
                maxRadius,
                maxRadius2,
                maxShininess,
                spotLights,
                segments,
                wireframe,
                minOpacity,
                maxOpacity,
                openEnded
            };

            console.log('params ', JSON.stringify(params, null, 2));

            params.dimensions = dimensions;

            try {
                var outf = fs.createWriteStream(`${outputFilename}`);

                outf.write(`<!DOCTYPE html>
                <html lang='en'>
                <head>
                    <meta charset='UTF-8'>
                    <title>${outputFilename}</title>
                    <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js'></script>
                </head>
                <body style='margin:0; padding:0; overflow: hidden'>\n`);

                outf.write(`<script>\n`);

                // add line
                outf.write(`
                function ln(scene, x3, y3, z3, color) {
                  var geometry = new THREE.Geometry();

                  geometry.vertices.push(
                    new THREE.Vector3( x3, y3, 0 ),
                    new THREE.Vector3( x3, y3, z3 )
                  );

                  var material = new THREE.LineBasicMaterial({
                    color: color
                  });

                  var line = new THREE.Line( geometry, material );

                  scene.add(line);
                }
                \n`);

                // add cylinder
                // todo: open/closed ends. vary radius.

                outf.write(`
                function cyl(scene, options) {

                  var geometry = new THREE.CylinderGeometry(options.radius, options.radius2, options.z, ${params.segments}, 1, ${params.openEnded});

                  var materials = [
                  new THREE.MeshPhongMaterial( {
                    color: options.color,
                    opacity: options.opacity,
                    transparent: true,
                    shininess: options.shininess
                  } )
                ];
                \n`);

                if (params.wireframe) {
                  outf.write(`
                    materials.push(

                      new THREE.MeshBasicMaterial( {
                        color: options.color,
                        wireframe: true
                      } )

                    );
                  \n`);
                }

                outf.write(`
                  var cylinder = new THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

                  cylinder.position.x = options.x;
                  cylinder.position.y = options.y;
                  cylinder.position.z = 0;

                  scene.add(cylinder);
                }
                \n`);

                outf.write(`
                  draw();

                  function draw() {

                      var width = ${dimensions.outputWidth};
                      var height = ${dimensions.outputHeight};

                      var scene = new THREE.Scene();
                      var s = scene;
                \n`);

                let xy = [];

                for (let y = 0; y < dimensions.outputHeight; y++) {

                    for (let x = 0; x < dimensions.outputWidth; x++) {
                        xy.push({
                            x: x,
                            y: y
                        });
                    }
                }

                // use a small % of points otherwise too big to render

                // 0.4 for lines

                let sample = (isDev ? 1 : 1);

                let maxRadius = Math.max(params.maxRadius, params.maxRadius2);

                sample = sample / (maxRadius * maxRadius);

                xy = R.sortBy(() => math.random(), xy);
                xy = R.take(xy.length * sample, xy);

                for (let k = 0; k < xy.length; k++) {

                    let yy = xy[k].y;
                    let xx = xy[k].x;

                    let x = xx + dimensions.inputWidth / 2 - dimensions.outputWidth / 2;
                    let y = yy + dimensions.inputHeight / 2 - dimensions.outputHeight / 2;
                    let rgb = data[x][y].rgb;

                    let hsl = clr.rgb2hsl(rgb);

                    // 3d coords
                    let x3 = (x / dimensions.inputWidth) * dimensions.outputWidth - dimensions.outputWidth / 2;
                    let y3 = -((y / dimensions.inputHeight) * dimensions.outputHeight - dimensions.outputHeight / 2);

                    let z3 = math.round(hsl.l * maxz, 0); /// outputHeight;

                    let radius = params.maxRadius;
                    let radius2 = params.maxRadius2;

                    let opacity = params.minOpacity + (params.maxOpacity - params.minOpacity) * hsl.l;

                    let shininess = params.maxShininess;

                    outf.write(`cyl(s, {
                      x: ${x3},
                      y: ${y3},
                      z: ${z3},
                      color: 0x${num2hex(rgb.r)}${num2hex(rgb.g)}${num2hex(rgb.b)},
                      radius: ${radius},
                      radius2: ${radius2},
                      opacity: ${opacity},
                      shininess: ${shininess}
                    });
                    \n`);
                }

                // end

                let backgroundColor = '0x000000';

                params.xy = xy;
                params.data = data;

                outf.write(`
                  var renderer = new THREE.WebGLRenderer();

                  var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 );

                  camera.position.x = ${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()};
                  camera.position.y = ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()};
                  camera.position.z = ${ Rp.bandomInt(1000, -2)};

                  camera.lookAt(s.position);
                  \n`);

                for (let i = 0; i < spotLights; i++) {
                    outf.write(`
                  var spotLight${i} = new THREE.SpotLight(${randomColor(params, 1)});
                  spotLight${i}.position.set(${Rp.bandomInt(dimensions.outputWidth / 2, 2) * Rp.randomSign()}, ${Rp.bandomInt(dimensions.outputHeight / 2, 2) * Rp.randomSign()}, ${ Rp.bandomInt(1000, -2)});
                  scene.add(spotLight${i});
                  \n`);
                }

                outf.write(`
                  var ambientLight = new THREE.AmbientLight(${randomColor(params, 0.25)});
                  scene.add(ambientLight);

                  renderer.setClearColor(new THREE.Color(${backgroundColor}));

                  renderer.setSize( width, height );

                  document.body.appendChild( renderer.domElement );

                  renderer.render( scene, camera );
                \n`);

                outf.write(`}\n`); // end draw()

                outf.write(`</script>\n`);

                outf.write(`
                  </body>
                  </html>
                  \n`);

                data = null;
                jpeg.data = null;
                jpeg = null;
                xy = null;

                outf.end(function() {
                    outf = null;
                    resolve();
                });
            } catch (ex) {
                console.log(chalk.red('error'), ex);

                resolve();
            }

        });
    };

    // process file

    var processFiles = function() {

        if (process.argv.length > 2) {

            var files = R.tail(R.tail(process.argv));

            files = R.filter((f) => path.extname(f) === '.jpg', files);

            // console.log(files);

            promise.each(files, create3d).then(function() {});
        }
        else {
            console.log('usage: node 3d-image path ...');
        }

    };

    // kick off

    processFiles();

}());
<|endoftext|>


<commit_before>

function sortIx( a, b ) { return b.parameter - a.parameter; }

function splitPath( _ixs, other ) {
    other = other || false;
    var i, j, k, l, len, ixs, ix, path, crv, vals;
    var ixPoint, nuSeg;
    var paths = {}, lastPathId = null;
    for (i = 0, l = _ixs.length; i < l; i++) {
        ix = ( other )? _ixs[i].getIntersection() : _ixs[i];
        if( !paths[ix.path.id] ){
            paths[ix.path.id] = ix.path;
        }
        if( !ix.curve._ixParams ){ix.curve._ixParams = []; }
        ix.curve._ixParams.push( { parameter: ix.parameter, pair: ix.getIntersection() } );
    }
    for (k in paths) {
        if( !paths.hasOwnProperty( k ) ){ continue; }
        path = paths[k];
        var lastNode = path.lastSegment, firstNode = path.firstSegment;
        var nextNode = null, left = null, right = null, parts = null, isLinear;
        var handleIn, handleOut;
        while( nextNode !== firstNode){
            nextNode = ( nextNode )? nextNode.previous: lastNode;
            if( nextNode.curve._ixParams ){
                ixs = nextNode.curve._ixParams;
                ixs.sort( sortIx );
                crv = nextNode.curve;
                isLinear = crv.isLinear();
                crv = vals = null;
                for (i = 0, l = ixs.length; i < l; i++) {
                    ix = ixs[i];
                    crv = nextNode.curve;
                    if( !vals ) vals = crv.getValues();
                    if( ix.parameter === 0.0 || ix.parameter === 1.0 ){
                        // Intersection is on an existing node
                        // no need to create a new segment,
                        // we just link the corresponding intersections together
                        nuSeg = ( ix.parameter === 0.0 )? crv.segment1 : crv.segment2;
                        nuSeg._ixPair = ix.pair;
                        nuSeg._ixPair._segment = nuSeg;
                    } else {
                        parts = Curve.subdivide( vals, ix.parameter );
                        left = parts[0];
                        right = parts[1];
                        handleIn = handleOut = null;
                        ixPoint = new Point( right[0], right[1] );
                        if( !isLinear ){
                            crv.segment1.handleOut = new Point( left[2] - left[0], left[3] - left[1] );
                            crv.segment2.handleIn = new Point( right[4] - right[6], right[5] - right[7] );
                            handleIn = new Point( left[4] - ixPoint.x, left[5] - ixPoint.y );
                            handleOut = new Point( right[2] - ixPoint.x, right[3] - ixPoint.y );
                        }
                        nuSeg = new Segment( ixPoint, handleIn, handleOut );
                        nuSeg._ixPair = ix.pair;
                        nuSeg._ixPair._segment = nuSeg;
                        path.insert( nextNode.index + 1,  nuSeg );
                    }
                    for (j = i + 1; j < l; j++) {
                        ixs[j].parameter = ixs[j].parameter / ix.parameter;
                    }
                    vals = left;
                }
            }
        }
    }
}

/**
 * To deal with a HTML canvas requirement where CompoundPaths' child contours
 * has to be of different winding direction for correctly filling holes.
 * But if some individual countours are disjoint, i.e. islands, we have to
 * reorient them so that
 *   the holes have opposit winding direction ( already handled by paperjs )
 *   islands has to have same winding direction ( as the first child of the path )
 *
 * Does NOT handle selfIntersecting CompoundPaths.
 *
 * @param  {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
 * @return {boolean}      the winding direction of the base contour( true if clockwise )
 */
 function reorientCompoundPath( path ){
    if( !(path instanceof CompoundPath) ){
        path.closed = true;
        return path.clockwise;
    }
    var children = path.children, len = children.length, baseWinding;
    var bounds = new Array( len );
    var tmparray = new Array( len );
    baseWinding = children[0].clockwise;
    // Omit the first path
    for (i = 0; i < len; i++) {
        children[i].closed = true;
        bounds[i] = children[i].bounds;
        tmparray[i] = 0;
    }
    for (i = 0; i < len; i++) {
        var p1 = children[i];
        for (j = 0; j < len; j++) {
            var p2 = children[j];
            if( i !== j && bounds[i].contains( bounds[j] ) ){
                tmparray[j]++;
            }
        }
    }
    for (i = 1; i < len; i++) {
        if ( tmparray[i] % 2 === 0 ) {
            children[i].clockwise = baseWinding;
        }
    }
    return baseWinding;
}

function reversePath( path ){
    var baseWinding;
    if( path instanceof CompoundPath ){
        var children = path.children, i, len;
        for (i = 0, len = children.length; i < len; i++) {
            children[i].reverse();
            children[i]._curves = null;
        }
        baseWinding = children[0].clockwise;
    } else {
        path.reverse();
        baseWinding = path.clockwise;
        path._curves = null;
    }
    return baseWinding;
}

function computeBoolean( path1, path2, operator, _splitCache ){
    var _path1, _path2, path1Clockwise, path2Clockwise;
    var ixs, path1Id, path2Id;
    // We do not modify the operands themselves
    // The result might not belong to the same type
    // i.e. subtraction( A:Path, B:Path ):CompoundPath etc.
    _path1 = path1.clone();
    _path2 = path2.clone();
    _path1.style = _path2.style = null;
    _path1.selected = _path2.selected = false;
    path1Clockwise = reorientCompoundPath( _path1 );
    path2Clockwise = reorientCompoundPath( _path2 );
    path1Id = _path1.id;
    path2Id = _path2.id;
    // Calculate all the intersections
    ixs = ( _splitCache && _splitCache.intersections )?
        _splitCache.intersections : _path1.getIntersections( _path2 );
    // if we have a empty _splitCache object as an operand,
    // skip calculating boolean and cache the intersections
    if( _splitCache && !_splitCache.intersections ){
        _splitCache.intersections = ixs;
        return;
    }
    splitPath( ixs );
    splitPath( ixs, true );
    path1Id = _path1.id;
    path2Id = _path2.id;
    // Do operator specific calculations before we begin
    if( operator.name === "subtraction" ) {
        path2Clockwise = reversePath( _path2 );
    }

    var i, j, len, path, crv;
    var paths = [];
    if( _path1 instanceof CompoundPath ){
        paths = paths.concat( _path1.children );
    } else {
        paths = [ _path1 ];
    }
    if( _path2 instanceof CompoundPath ){
        paths = paths.concat( _path2.children );
    } else {
        paths.push( _path2 );
    }

    // step 1: discard invalid links according to the boolean operator
    var lastNode, firstNode, nextNode, midPoint, insidePath1, insidePath2;
    var thisId, thisWinding, contains, subtractionOp = (operator.name === 'subtraction');
    for (i = 0, len = paths.length; i < len; i++) {
        insidePath1 = insidePath2 = false;
        path = paths[i];
        thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
        thisWinding = path.clockwise;
        lastNode = path.lastSegment;
        firstNode = path.firstSegment;
        nextNode = null;
        while( nextNode !== firstNode){
            nextNode = ( nextNode )? nextNode.previous: lastNode;
            crv = nextNode.curve;
            midPoint = crv.getPoint( 0.5 );
            if( thisId !== path1Id ){
                contains = _path1.contains( midPoint );
                insidePath1 = (thisWinding === path1Clockwise || subtractionOp )? contains :
                contains && !testOnCurve( _path1, midPoint );
            }
            if( thisId !== path2Id ){
                contains = _path2.contains( midPoint );
                insidePath2 = (thisWinding === path2Clockwise )? contains :
                contains && !testOnCurve( _path2, midPoint );
            }
            if( !operator( thisId === path1Id, insidePath1, insidePath2 ) ){
                crv._INVALID = true;
                // markPoint( midPoint, '+' );
            }
        }
    }

    // Final step: Retrieve the resulting paths from the graph
    var boolResult = new CompoundPath();
    var node, nuNode, nuPath, nodeList = [], handle;
    for (i = 0, len = paths.length; i < len; i++) {
        nodeList = nodeList.concat( paths[i].segments );
    }
    for (i = 0, len = nodeList.length; i < len; i++) {
        node = nodeList[i];
        if( node.curve._INVALID || node._visited ){ continue; }
        path = node.path;
        thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
        thisWinding = path.clockwise;
        nuPath = new Path();
        firstNode = null;
        firstNode_ix = null;
        if( node.previous.curve._INVALID ) {
            node.handleIn = ( node._ixPair )?
            node._ixPair.getIntersection()._segment.handleIn : [ 0, 0 ];
        }
        while( node && !node._visited && ( node !== firstNode && node !== firstNode_ix ) ){
            // markPoint( node.point, node.index );
            // view.draw()

            node._visited = true;
            firstNode = ( firstNode )? firstNode: node;
            firstNode_ix = ( !firstNode_ix && firstNode._ixPair )?
                firstNode._ixPair.getIntersection()._segment: firstNode_ix;
            nextNode = ( node._ixPair && node.curve._INVALID )? node._ixPair.getIntersection()._segment : node;
            if( node._ixPair ) {
                // node._ixPair is this node's intersection CurveLocation object
                // node._ixPair._ixPair is the other CurveLocation object this node intersects with
                nextNode._visited = true;
                nuNode = new Segment( node.point, node.handleIn, nextNode.handleOut );
                nuPath.add( nuNode );
                node = nextNode;
                path = node.path;
                thisWinding = path.clockwise;
            } else {
                nuPath.add( node );
            }
            node = node.next;
        }
        nuPath.closed = true;
        boolResult.addChild( nuPath, true );
    }
    // if( operator.name === 'intersection' ){
    //     window.p = boolResult.reduce();
    // }
    // window.a = _path1;
    // window.b = _path2;
    // Delete the proxies
    _path1.remove();
    _path2.remove();
    // And then, we are done.
    return boolResult.reduce();
}

function testOnCurve( path, point ){
    var res = 0;
    var crv = path.getCurves();
    var i = 0;
    var bounds = path.bounds;
    if( bounds && bounds.contains( point ) ){
        for( i = 0; i < crv.length && !res; i++ ){
            var crvi = crv[i];
            if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
                res = 1;
            }
        }
    }
    return res;
}

/**
 * A boolean operator is a binary operator function of the form
 * f( isPath1:boolean, isInsidePath1:Boolean, isInsidePath2:Boolean ) :Boolean
 *
 * Boolean operator determines whether a curve segment in the operands is part
 * of the boolean result, and will be called for each curve segment in the graph after
 * all the intersections between the operands are calculated and curves in the operands
 * are split at intersections.
 *
 * These functions should have a name ( "union", "subtraction" etc. below ), if we need to
 * do operator specific operations on paths inside the computeBoolean function.
 *  for example: if the name of the operator is "subtraction" then we need to reverse the second
 *                  operand. Subtraction is neither associative nor commutative.
 *
 *  The boolean operator should return a Boolean value indicating whether to keep the curve or not.
 *  return true - keep the curve
 *  return false - discard the curve
 */

 function unite( path1, path2 ){
    var unionOp = function union( isPath1, isInsidePath1, isInsidePath2 ){
        return ( isInsidePath1 || isInsidePath2 )? false : true;
    };
    return computeBoolean( path1, path2, unionOp );
}

function intersect( path1, path2 ){
    var intersectionOp = function intersection( isPath1, isInsidePath1, isInsidePath2 ){
        return ( !isInsidePath1 && !isInsidePath2 )? false : true;
    };
    return computeBoolean( path1, path2, intersectionOp );
}

function subtract( path1, path2 ){
    var subtractionOp = function subtraction( isPath1, isInsidePath1, isInsidePath2 ){
        return ( (isPath1 && isInsidePath2) || (!isPath1 && !isInsidePath1) )? false : true;
    };
    return computeBoolean( path1, path2, subtractionOp );
}

<commit_msg>Add exclusion operator<commit_after>

function sortIx( a, b ) { return b.parameter - a.parameter; }

function splitPath( _ixs, other ) {
    other = other || false;
    var i, j, k, l, len, ixs, ix, path, crv, vals;
    var ixPoint, nuSeg;
    var paths = {}, lastPathId = null;
    for (i = 0, l = _ixs.length; i < l; i++) {
        ix = ( other )? _ixs[i].getIntersection() : _ixs[i];
        if( !paths[ix.path.id] ){
            paths[ix.path.id] = ix.path;
        }
        if( !ix.curve._ixParams ){ix.curve._ixParams = []; }
        ix.curve._ixParams.push( { parameter: ix.parameter, pair: ix.getIntersection() } );
    }
    for (k in paths) {
        if( !paths.hasOwnProperty( k ) ){ continue; }
        path = paths[k];
        var lastNode = path.lastSegment, firstNode = path.firstSegment;
        var nextNode = null, left = null, right = null, parts = null, isLinear;
        var handleIn, handleOut;
        while( nextNode !== firstNode){
            nextNode = ( nextNode )? nextNode.previous: lastNode;
            if( nextNode.curve._ixParams ){
                ixs = nextNode.curve._ixParams;
                ixs.sort( sortIx );
                crv = nextNode.getCurve();
                isLinear = crv.isLinear();
                crv = vals = null;
                for (i = 0, l = ixs.length; i < l; i++) {
                    ix = ixs[i];
                    crv = nextNode.getCurve();
                    if( !vals ) vals = crv.getValues();
                    if( ix.parameter === 0.0 || ix.parameter === 1.0 ){
                        // Intersection is on an existing node
                        // no need to create a new segment,
                        // we just link the corresponding intersections together
                        nuSeg = ( ix.parameter === 0.0 )? crv.segment1 : crv.segment2;
                        nuSeg._ixPair = ix.pair;
                        nuSeg._ixPair._segment = nuSeg;
                    } else {
                        parts = Curve.subdivide( vals, ix.parameter );
                        left = parts[0];
                        right = parts[1];
                        handleIn = handleOut = null;
                        ixPoint = new Point( right[0], right[1] );
                        if( !isLinear ){
                            crv.segment1.handleOut = new Point( left[2] - left[0], left[3] - left[1] );
                            crv.segment2.handleIn = new Point( right[4] - right[6], right[5] - right[7] );
                            handleIn = new Point( left[4] - ixPoint.x, left[5] - ixPoint.y );
                            handleOut = new Point( right[2] - ixPoint.x, right[3] - ixPoint.y );
                        }
                        nuSeg = new Segment( ixPoint, handleIn, handleOut );
                        nuSeg._ixPair = ix.pair;
                        nuSeg._ixPair._segment = nuSeg;
                        path.insert( nextNode.index + 1,  nuSeg );
                    }
                    for (j = i + 1; j < l; j++) {
                        ixs[j].parameter = ixs[j].parameter / ix.parameter;
                    }
                    vals = left;
                }
            }
        }
    }
}

/**
 * To deal with a HTML canvas requirement where CompoundPaths' child contours
 * has to be of different winding direction for correctly filling holes.
 * But if some individual countours are disjoint, i.e. islands, we have to
 * reorient them so that
 *   the holes have opposit winding direction ( already handled by paperjs )
 *   islands has to have same winding direction ( as the first child of the path )
 *
 * Does NOT handle selfIntersecting CompoundPaths.
 *
 * @param  {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
 * @return {boolean}      the winding direction of the base contour( true if clockwise )
 */
 function reorientCompoundPath( path ){
    if( !(path instanceof CompoundPath) ){
        path.closed = true;
        return path.clockwise;
    }
    var children = path.children, len = children.length, baseWinding;
    var bounds = new Array( len );
    var tmparray = new Array( len );
    baseWinding = children[0].clockwise;
    // Omit the first path
    for (i = 0; i < len; i++) {
        children[i].closed = true;
        bounds[i] = children[i].bounds;
        tmparray[i] = 0;
    }
    for (i = 0; i < len; i++) {
        var p1 = children[i];
        for (j = 0; j < len; j++) {
            var p2 = children[j];
            if( i !== j && bounds[i].contains( bounds[j] ) ){
                tmparray[j]++;
            }
        }
    }
    for (i = 1; i < len; i++) {
        if ( tmparray[i] % 2 === 0 ) {
            children[i].clockwise = baseWinding;
        }
    }
    return baseWinding;
}

function reversePath( path ){
    var baseWinding;
    if( path instanceof CompoundPath ){
        var children = path.children, i, len;
        for (i = 0, len = children.length; i < len; i++) {
            children[i].reverse();
            children[i]._curves = null;
        }
        baseWinding = children[0].clockwise;
    } else {
        path.reverse();
        baseWinding = path.clockwise;
        path._curves = null;
    }
    return baseWinding;
}

function computeBoolean( path1, path2, operator, _splitCache ){
    var _path1, _path2, path1Clockwise, path2Clockwise;
    var ixs, path1Id, path2Id;
    // We do not modify the operands themselves
    // The result might not belong to the same type
    // i.e. subtraction( A:Path, B:Path ):CompoundPath etc.
    _path1 = path1.clone();
    _path2 = path2.clone();
    _path1.style = _path2.style = null;
    _path1.selected = _path2.selected = false;
    path1Clockwise = reorientCompoundPath( _path1 );
    path2Clockwise = reorientCompoundPath( _path2 );
    path1Id = _path1.id;
    path2Id = _path2.id;
    // Calculate all the intersections
    ixs = ( _splitCache && _splitCache.intersections )?
        _splitCache.intersections : _path1.getIntersections( _path2 );
    // if we have a empty _splitCache object as an operand,
    // skip calculating boolean and cache the intersections
    if( _splitCache && !_splitCache.intersections ){
        _splitCache.intersections = ixs;
        return;
    }
    splitPath( ixs );
    splitPath( ixs, true );
    path1Id = _path1.id;
    path2Id = _path2.id;
    // Do operator specific calculations before we begin
    if( operator.name === "subtraction" ) {
        path2Clockwise = reversePath( _path2 );
    }

    var i, j, len, path, crv;
    var paths = [];
    if( _path1 instanceof CompoundPath ){
        paths = paths.concat( _path1.children );
    } else {
        paths = [ _path1 ];
    }
    if( _path2 instanceof CompoundPath ){
        paths = paths.concat( _path2.children );
    } else {
        paths.push( _path2 );
    }

    // step 1: discard invalid links according to the boolean operator
    var lastNode, firstNode, nextNode, midPoint, insidePath1, insidePath2;
    var thisId, thisWinding, contains, subtractionOp = (operator.name === 'subtraction');
    for (i = 0, len = paths.length; i < len; i++) {
        insidePath1 = insidePath2 = false;
        path = paths[i];
        thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
        thisWinding = path.clockwise;
        lastNode = path.lastSegment;
        firstNode = path.firstSegment;
        nextNode = null;
        while( nextNode !== firstNode){
            nextNode = ( nextNode )? nextNode.previous: lastNode;
            crv = nextNode.curve;
            midPoint = crv.getPoint( 0.5 );
            if( thisId !== path1Id ){
                contains = _path1.contains( midPoint );
                insidePath1 = (thisWinding === path1Clockwise || subtractionOp )? contains :
                contains && !testOnCurve( _path1, midPoint );
            }
            if( thisId !== path2Id ){
                contains = _path2.contains( midPoint );
                insidePath2 = (thisWinding === path2Clockwise )? contains :
                contains && !testOnCurve( _path2, midPoint );
            }
            if( !operator( thisId === path1Id, insidePath1, insidePath2 ) ){
                crv._INVALID = true;
                // markPoint( midPoint, '+' );
            }
        }
    }

    // Final step: Retrieve the resulting paths from the graph
    var boolResult = new CompoundPath();
    var node, nuNode, nuPath, nodeList = [], handle;
    for (i = 0, len = paths.length; i < len; i++) {
        nodeList = nodeList.concat( paths[i].segments );
    }
    for (i = 0, len = nodeList.length; i < len; i++) {
        node = nodeList[i];
        if( node.curve._INVALID || node._visited ){ continue; }
        path = node.path;
        thisId = ( path.parent instanceof CompoundPath )? path.parent.id : path.id;
        thisWinding = path.clockwise;
        nuPath = new Path();
        // nuPath.selected = true;
        firstNode = null;
        firstNode_ix = null;
        if( node.previous.curve._INVALID ) {
            node.handleIn = ( node._ixPair )?
            node._ixPair.getIntersection()._segment.handleIn : [ 0, 0 ];
        }
        while( node && !node._visited && ( node !== firstNode && node !== firstNode_ix ) ){
            node._visited = true;
            firstNode = ( firstNode )? firstNode: node;
            firstNode_ix = ( !firstNode_ix && firstNode._ixPair )?
            firstNode._ixPair.getIntersection()._segment: firstNode_ix;
            // node._ixPair is this node's intersection CurveLocation object
            // node._ixPair.getIntersection() is the other CurveLocation object this node intersects with
            nextNode = ( node._ixPair && node.curve._INVALID )? node._ixPair.getIntersection()._segment : node;
            if( node._ixPair ) {
                nextNode._visited = true;
                nuNode = new Segment( node.point, node.handleIn, nextNode.handleOut );
                nuPath.add( nuNode );
                node = nextNode;
                path = node.path;
                thisWinding = path.clockwise;
            } else {
                nuPath.add( node );
            }
            // view.draw()
            node = node.next;
        }
        nuPath.closed = true;
        boolResult.addChild( nuPath, true );
    }
    // if( operator.name === 'intersection' ){
    //     window.p = boolResult.reduce();
    // }
    // window.a = _path1;
    // window.b = _path2;
    // Delete the proxies
    // _path1.remove();
    // _path2.remove();
    // And then, we are done.
    return boolResult.reduce();
}

// Bottleneck no: 2
function testOnCurve( path, point ){
    var res = 0;
    var crv = path.getCurves();
    var i = 0;
    var bounds = path.bounds;
    if( bounds && bounds.contains( point ) ){
        for( i = 0; i < crv.length && !res; i++ ){
            var crvi = crv[i];
            if( crvi.bounds.contains( point ) && crvi.getParameterOf( point ) ){
                res = 1;
            }
        }
    }
    return res;
}

/**
 * A boolean operator is a binary operator function of the form
 * f( isPath1:boolean, isInsidePath1:Boolean, isInsidePath2:Boolean ) :Boolean
 *
 * Boolean operator determines whether a curve segment in the operands is part
 * of the boolean result, and will be called for each curve segment in the graph after
 * all the intersections between the operands are calculated and curves in the operands
 * are split at intersections.
 *
 * These functions should have a name ( "union", "subtraction" etc. below ), if we need to
 * do operator specific operations on paths inside the computeBoolean function.
 *  for example: if the name of the operator is "subtraction" then we need to reverse the second
 *                  operand. Subtraction is neither associative nor commutative.
 *
 *  The boolean operator should return a Boolean value indicating whether to keep the curve or not.
 *  return true - keep the curve
 *  return false - discard the curve
 */

 function unite( path1, path2, _cache ){
    var unionOp = function union( isPath1, isInsidePath1, isInsidePath2 ){
        return ( isInsidePath1 || isInsidePath2 )? false : true;
    };
    return computeBoolean( path1, path2, unionOp, _cache );
}

function intersect( path1, path2, _cache ){
    var intersectionOp = function intersection( isPath1, isInsidePath1, isInsidePath2 ){
        return ( !isInsidePath1 && !isInsidePath2 )? false : true;
    };
    return computeBoolean( path1, path2, intersectionOp, _cache );
}

function subtract( path1, path2, _cache ){
    var subtractionOp = function subtraction( isPath1, isInsidePath1, isInsidePath2 ){
        return ( (isPath1 && isInsidePath2) || (!isPath1 && !isInsidePath1) )? false : true;
    };
    return computeBoolean( path1, path2, subtractionOp, _cache );
}

// a.k.a. eXclusiveOR
function exclude( path1, path2 ){
    var cache = null;
    // computeBoolean( path1, path2, null, cache );
    var res1 = subtract( path1, path2, cache );
    var res2 = subtract( path2, path1, cache );
    res1 = new CompoundPath( res1.children, res2.children );
    return res1;
}

<|endoftext|>