<commit_before>var registerComponent = require('../core/register-component').registerComponent;
var requestInterval = require('request-interval');
var THREE = require('../../lib/three');

module.exports.Component = registerComponent('raycaster', {
  init: {
    value: function () {
      this.raycaster = new THREE.Raycaster();
      this.intersectedEl = null;
      this.pollForHoverIntersections();
    }
  },

  pollForHoverIntersections: {
    value: function () {
      requestInterval(100, this.getIntersections.bind(this));
    }
  },

  getIntersections: {
    value: function () {
      var closest = this.getClosestIntersected();
      if (closest) {
        this.handleIntersection(closest);
        return;
      }
      // If we have no intersections other than the cursor itself,
      // but we still have a previously intersected element, clear it.
      if (this.intersectedEl) {
        this.clearExistingIntersection();
      }
    }
  },

  intersect: {
    value: function (objects) {
      var el = this.el;
      var raycaster = this.raycaster;
      var cursor = el.object3D;
      var parent = el.parentNode.object3D;
      var originPosition = new THREE.Vector3().setFromMatrixPosition(parent.matrixWorld);
      var cursorPosition = new THREE.Vector3().setFromMatrixPosition(cursor.matrixWorld);
      var direction = cursorPosition.sub(originPosition).normalize();
      raycaster.set(originPosition, direction);
      return raycaster.intersectObjects(objects, true);
    }
  },

  /**
   * Returns the closest intersected object.
   *
   * @returns {Object|null}
   *   The closest intersected element that is not the cursor itself
   *   nor an invisible element.
   *   If no objects are intersected, `null` is returned.
   */
  getClosestIntersected: {
    value: function () {
      var scene = this.el.sceneEl.object3D;
      var cursorEl = this.el;
      var intersectedObj;
      var intersectedObjs = this.intersect(scene.children);
      for (var i = 0; i < intersectedObjs.length; ++i) {
        intersectedObj = intersectedObjs[i];
        // If the intersected object is the cursor itself
        // or the object is further than the max distance
        if (intersectedObj.object.el === cursorEl) { return; }
        if (!intersectedObj.object.visible) { continue; }
        return intersectedObj;
      }
      return null;
    }
  },

  /**
   * Remembers the last intersected element
   */
  setExistingIntersection: {
    value: function (el, distance) {
      this.intersectedEl = el;
      this.el.emit('intersection', { el: el, distance: distance });
    }
  },

  /**
   * Emits a `mouseleave` event and clears info about the last intersection.
   */
  clearExistingIntersection: {
    value: function () {
      var intersectedEl = this.intersectedEl;
      this.el.emit('intersectioncleared', { el: intersectedEl });
      this.intersectedEl = null;
    }
  },

  handleIntersection: {
    value: function (obj) {
      var el = obj.object.el;

      // A new intersection where previously a different element was
      // and now needs a mouseleave event.
      if (this.intersectedEl !== el) {
        this.clearExistingIntersection();
      }
      this.setExistingIntersection(el, obj.distance);
    }
  }

});
<commit_msg>Fixes el.parentNode is null when removing cursor<commit_after>var registerComponent = require('../core/register-component').registerComponent;
var requestInterval = require('request-interval');
var THREE = require('../../lib/three');

module.exports.Component = registerComponent('raycaster', {
  init: {
    value: function () {
      this.raycaster = new THREE.Raycaster();
      this.intersectedEl = null;
      this.pollForHoverIntersections();
    }
  },

  remove: {
    value: function () {
      requestInterval.clear(this.pollInterval);
    }
  },

  pollForHoverIntersections: {
    value: function () {
      this.pollInterval = requestInterval(100, this.getIntersections.bind(this));
    }
  },

  getIntersections: {
    value: function () {
      var closest = this.getClosestIntersected();
      if (closest) {
        this.handleIntersection(closest);
        return;
      }
      // If we have no intersections other than the cursor itself,
      // but we still have a previously intersected element, clear it.
      if (this.intersectedEl) {
        this.clearExistingIntersection();
      }
    }
  },

  intersect: {
    value: function (objects) {
      var el = this.el;
      var raycaster = this.raycaster;
      var cursor = el.object3D;
      var parent = el.parentNode.object3D;
      var originPosition = new THREE.Vector3().setFromMatrixPosition(parent.matrixWorld);
      var cursorPosition = new THREE.Vector3().setFromMatrixPosition(cursor.matrixWorld);
      var direction = cursorPosition.sub(originPosition).normalize();
      raycaster.set(originPosition, direction);
      return raycaster.intersectObjects(objects, true);
    }
  },

  /**
   * Returns the closest intersected object.
   *
   * @returns {Object|null}
   *   The closest intersected element that is not the cursor itself
   *   nor an invisible element.
   *   If no objects are intersected, `null` is returned.
   */
  getClosestIntersected: {
    value: function () {
      var scene = this.el.sceneEl.object3D;
      var cursorEl = this.el;
      var intersectedObj;
      var intersectedObjs = this.intersect(scene.children);
      for (var i = 0; i < intersectedObjs.length; ++i) {
        intersectedObj = intersectedObjs[i];
        // If the intersected object is the cursor itself
        // or the object is further than the max distance
        if (intersectedObj.object.el === cursorEl) { return; }
        if (!intersectedObj.object.visible) { continue; }
        return intersectedObj;
      }
      return null;
    }
  },

  /**
   * Remembers the last intersected element
   */
  setExistingIntersection: {
    value: function (el, distance) {
      this.intersectedEl = el;
      this.el.emit('intersection', { el: el, distance: distance });
    }
  },

  /**
   * Emits a `mouseleave` event and clears info about the last intersection.
   */
  clearExistingIntersection: {
    value: function () {
      var intersectedEl = this.intersectedEl;
      this.el.emit('intersectioncleared', { el: intersectedEl });
      this.intersectedEl = null;
    }
  },

  handleIntersection: {
    value: function (obj) {
      var el = obj.object.el;

      // A new intersection where previously a different element was
      // and now needs a mouseleave event.
      if (this.intersectedEl !== el) {
        this.clearExistingIntersection();
      }
      this.setExistingIntersection(el, obj.distance);
    }
  }

});

{'fraction_non_alphanumeric': 0.11215370866845398, 'fraction_numerical': 0.002680965147453083, 'mean_word_length': 2.7038058466629895, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '6786414', 'n_tokens_mistral': 2012, 'n_tokens_neox': 1967, 'n_words': 485}