Home Reference Source

src/components/PolygonShape.js

import Shape from './Shape';
import { vec2 } from '../utils/gl-matrix';

const cachedVec2 = vec2.create();

export default class PolygonShape extends Shape {

  static factory() {
    return new PolygonShape();
  }

  static get propsTypes() {
    return {
      ...Shape.propsTypes,
      vertices: 'array(number)'
    };
  }

  get vertices() {
    return this._vertices;
  }

  set vertices(value) {
    if (!value) {
      throw new Error('`value` cannot be null!');
    }

    if (value instanceof Array) {
      value = new Float32Array(value);
    }

    if (!(value instanceof Float32Array)) {
      throw new Error('`value` is not type of either Array or Float32Array!');
    }

    if (value.length < 4) {
      throw new Error('`value` items count is less than 4!');
    }
    if (value.length % 2 !== 0) {
      throw new Error('`value` items count is not multiple of 2!');
    }

    this._vertices = value;
  }

  constructor() {
    super();

    this._vertices = null;
  }

  dispose() {
    super.dispose();

    this._vertices = null;
  }

  containsPoint(globalPoint, layer = null) {
    if (!globalPoint) {
      throw new Error('`globalPoint` cannot be null!');
    }
    if (globalPoint.length < 2) {
      throw new Error('`globalPoint` is not a 2 component vector!');
    }

    const { inverseTransform } = this.entity;
    const { _vertices } = this;
    if (!_vertices || !this.acceptsLayer(layer)) {
      return false;
    }

    vec2.transformMat4(cachedVec2, globalPoint, inverseTransform);
    for (var i = 0, c = _vertices.length; i < c; i += 2) {
      const vax = _vertices[i % c];
      const vay = _vertices[(i + 1) % c];
      const vbx = _vertices[(i + 2) % c];
      const vby = _vertices[(i + 3) % c];
      const bx = -(vby - vay);
      const by = vbx - vax;
      const dx = cachedVec2[0] - vax;
      const dy = cachedVec2[1] - vay;
      if (dx * bx + dy * by < 0.0) {
        return false;
      }
    }
    return true;
  }

  onPropertySerialize(name, value) {
    if (name === 'vertices') {
      if (!value) {
        return;
      }

      return [ ...value ];
    } else {
      return super.onPropertySerialize(name, value);
    }
  }

}