<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Collision detection manager. **/
CLASS({
  package: 'foam.physics',
  name: 'Collider',

  properties: [
    { name: 'children', factory: function() { return []; } }
  ],

  listeners: [
    {
      name: 'tick',
      isFramed: true,
      code: function () {
        if ( this.stopped_ ) return;
        this.detectCollisions();
        this.tick();
      }
    }
  ],

  methods: [
    function start() {
      this.stopped_ = false;
      this.tick();
    },
    function stop() {
      this.stopped_ = true;
    },
    function updateChild(child) {
    },
    // TODO: this should be done much more efficiently (quad-tree, k-d tree, or similar).
    function detectCollisions() {
//      var st = Date.now();
      var cs = this.children;
      for ( var i = 0 ; i < cs.length ; i++ ) {
        var c1 = cs[i];
        this.updateChild(c1);
        for ( var j = i+1 ; j < cs.length ; j++ ) {
          var c2 = cs[j];
          if ( c1.intersects(c2) ) this.collide(c1, c2);
        }
      }
//      console.log(Date.now()-st);
    },
    function detectCollisions___() {
      /* Experimental k-d-tree-like implementation. */
      var st = Date.now();
      this.detectCollisions_(0, this.children.length-1, 'x', '');
      console.log(Date.now()-st);
    },
    function detectCollisions__(start, end) {
      var cs = this.children;
      for ( var i = start ; i <= end ; i++ ) {
        var c1 = cs[i];
        this.updateChild(c1);
        for ( var j = i+1 ; j <= end ; j++ ) {
          var c2 = cs[j];
          if ( c1.intersects(c2) ) this.collide(c1, c2);
        }
      }
    },
    function detectCollisions_(start, end, axis, prefix) {
      if ( end - start < 6 ) { this.detectCollisions__(start, end); return; }

      var cs = this.children;
      var pivot = (cs[start][axis] + cs[start+1][axis] +cs[start+Math.floor((end-start)/2)][axis] + cs[end-1][axis] + cs[end][axis])/5;
      //console.log(prefix, 'axis: ', axis, ' pivot: ', pivot, 'range: ', start, end);
      //prefix += ' ';

      var p = start-1;
      for ( var i = start ; i <= end ; i++ ) {
        var c = cs[i];
        if ( c[axis] - c.r < pivot ) {
          p++;
          var t = cs[p];
          cs[p] = c;
          cs[i] = t;
        }
      }
      if ( p !== start-1 ) {
        if ( p === end ) {
          this.detectCollisions__(start, end);
          return;
        } else {
          this.detectCollisions_(start, p, axis === 'x' ? 'y' : 'x', prefix);
        }
      }

      p = start-1;
      for ( var i = start ; i <= end ; i++ ) {
        var c = cs[i];
        if ( c[axis] + c.r > pivot ) {
          p++;
          var t = cs[p];
          cs[p] = c;
          cs[i] = t;
        }
      }
      if ( p !== start-1 ) {
        if ( p === end ) {
          this.detectCollisions__(start, end);
          return;
        } else {
          this.detectCollisions_(start, p, axis === 'x' ? 'y' : 'x', prefix);
        }
      }
    },
    /*
    function backup(c1, c2) {
      for ( var i = 0.01 ; ; i += 0.1 ) {
        var x1 = c1.x - c1.vx * i;
        var y1 = c1.y - c1.vy * i;
        var x2 = c2.x - c2.vx * i;
        var y2 = c2.y - c2.vy * i;

        if ( Movement.distance(x1-x2, y1-y2) > c1.r + c2.r || i >= 1 ) {
          c1.x = x1; c1.y = y1;
          c2.x = x2; c2.y = y2;
          return;
        }
      }
    },
    */
    function collide(c1, c2) {
      // this.backup(c1, c2);  // backup to the point of collision

      var a  = Math.atan2(c2.y-c1.y, c2.x-c1.x);
      var m1 =  c1.momentumAtAngle(a);
      var m2 = -c2.momentumAtAngle(a);
      var m  = 2 * ( m1 + m2 );

      // ensure a minimum amount of momentum to that objects don't overlap
      m = Math.max(1, m);
      var tMass = c1.mass + c2.mass;
      c1.applyMomentum(-m * c2.mass/tMass, a);
      c2.applyMomentum(m * c1.mass/tMass, a);
    },
    // add one or more components to be monitored for collisions
    function add() {
      for ( var i = 0 ; i < arguments.length ; i++ )
        this.children.push(arguments[i]);
      return this;
    },
    function findChildAt(x, y) {
      var c2 = { x: x, y: y, r: 1 };<commit_msg>More work on new collision detection algorithm.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/** Collision detection manager. **/
CLASS({
  package: 'foam.physics',
  name: 'Collider',

  properties: [
    { name: 'children', factory: function() { return []; } }
  ],

  listeners: [
    {
      name: 'tick',
      isFramed: true,
      code: function () {
        if ( this.stopped_ ) return;
        this.detectCollisions();
        this.tick();
      }
    }
  ],

  methods: [
    function start() {
      this.stopped_ = false;
      this.tick();
    },
    function stop() {
      this.stopped_ = true;
    },
    function updateChild(child) {
    },
    // TODO: this should be done much more efficiently (quad-tree, k-d tree, or similar).
    function detectCollisions() {
//      var st = Date.now();
      var cs = this.children;
      for ( var i = 0 ; i < cs.length ; i++ ) {
        var c1 = cs[i];
        this.updateChild(c1);
        for ( var j = i+1 ; j < cs.length ; j++ ) {
          var c2 = cs[j];
          if ( c1.intersects(c2) ) this.collide(c1, c2);
        }
      }
//      console.log(Date.now()-st);
    },
    function NOTdetectCollisions() {
      /* Experimental k-d-tree-like implementation. */
//      var st = Date.now();
      this.detectCollisions_(0, this.children.length-1, 'x', false, '');
      /*
      var d = Date.now()-st;
      if ( ! this.__avg__ ) this.__avg__ = d;
      this.__avg__ = this.__avg__ * 0.99 + 0.01 * d;
      console.log(Date.now()-st, this.__avg__);
      */
    },
    function detectCollisions__(start, end) {
      var cs = this.children;
      for ( var i = start ; i <= end ; i++ ) {
        var c1 = cs[i];
        this.updateChild(c1);
        for ( var j = i+1 ; j <= end ; j++ ) {
          var c2 = cs[j];
          if ( c1.intersects(c2) ) this.collide(c1, c2);
        }
      }
    },
    function choosePivot(start, end, axis) {
      var p = 0, cs = this.children, n = end-start;
      for ( var i = start ; i <= end ; i++ ) p += cs[i][axis] / n;
      return p;
    },
    function detectCollisions_(start, end, axis, oneD) {
      if ( start >= end ) return;

      var cs = this.children;
      var pivot = this.choosePivot(start, end, axis);
      var nextAxis = oneD ? axis : axis === 'x' ? 'y' : 'x' ;

      var p = start;
      for ( var i = start ; i <= end ; i++ ) {
        var c = cs[i];
        if ( c[axis] - c.r < pivot ) {
          var t = cs[p];
          cs[p] = c;
          cs[i] = t;
          p++;
        }
      }

      if ( p === start || p === end + 1 ) {
        if ( oneD ) {
          this.detectCollisions__(start, end);
        } else {
          this.detectCollisions_(start, end, nextAxis, true);
        }
      } else {
        this.detectCollisions_(start, p-1, nextAxis, oneD);
  
        for ( var i = p-1 ; i >= start ; i-- ) {
          var c = cs[i];
          if ( c[axis] + c.r > pivot ) {
            var t = cs[p];
            cs[p] = c;
            cs[i] = t;
            p--;
          }
        }
        this.detectCollisions_(p+1, end, nextAxis, oneD);
      }
    },
    function collide(c1, c2) {
      // this.backup(c1, c2);  // backup to the point of collision

      var a  = Math.atan2(c2.y-c1.y, c2.x-c1.x);
      var m1 =  c1.momentumAtAngle(a);
      var m2 = -c2.momentumAtAngle(a);
      var m  = 2 * ( m1 + m2 );

      // ensure a minimum amount of momentum to that objects don't overlap
      m = Math.max(1, m);
      var tMass = c1.mass + c2.mass;
      c1.applyMomentum(-m * c2.mass/tMass, a);
      c2.applyMomentum(m * c1.mass/tMass, a);
    },
    // add one or more components to be monitored for collisions
    function add() {
      for ( var i = 0 ; i < arguments.length ; i++ )
        this.children.push(arguments[i]);
      return this;
    },
    function findChildAt(x, y) {
      var c2 = { x: x, y: y, r: 1 };
{'fraction_non_alphanumeric': 0.15324843513921865, 'fraction_numerical': 0.017267429311461257, 'mean_word_length': 1.7720610230332037, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7361996', 'n_tokens_mistral': 3220, 'n_tokens_neox': 3147, 'n_words': 894}