"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.makeSwcSurface = makeSwcSurface;
exports.parseSwc = parseSwc;

var THREE = _interopRequireWildcard(require("three"));

var _BufferGeometryUtils = require("three/examples/jsm/utils/BufferGeometryUtils");

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

/* eslint-disable prefer-template */
// From https://github.com/JaneliaSciComp/SharkViewer/blob/master/src/viewer/util.js
function parseSwc(swcFile) {
  // split by lines
  var swcAr = swcFile.split("\n");
  var swcJSON = {};
  var float = "-?\\d*(?:\\.\\d+)?";
  var pattern = new RegExp("^[ \\t]*(" + ["\\d+", // index
  "\\d+", // type
  float, // x
  float, // y
  float, // z
  float, // radius
  "-1|\\d+" // parent
  ].join(")[ \\t]+(") + ")[ \\t]*$", "m");
  swcAr.forEach(function (e) {
    // if line is good, put into json
    var match = e.match(pattern);

    if (match) {
      var id = parseInt(match[1], 10);
      swcJSON[id] = {
        id: id,
        type: parseInt(match[2], 10),
        x: parseFloat(match[3]),
        y: parseFloat(match[4]),
        z: parseFloat(match[5]),
        radius: parseFloat(match[6]),
        parent: parseInt(match[7], 10)
      };
    }
  }); // return json

  return swcJSON;
}
/* eslint-enable prefer-template */


function makeSwcSurface(swcJson, colorStr) {
  var geometries = [];
  Object.values(swcJson).forEach(function (v) {
    if (v.parent !== -1) {
      var par = v.parent;
      var p0 = new THREE.Vector3(swcJson[par].x, swcJson[par].y, swcJson[par].z);
      var p1 = new THREE.Vector3(v.x, v.y, v.z);
      var pos = new THREE.Vector3();
      pos.addVectors(p0, p1).divideScalar(2);
      var height = p0.distanceTo(p1);
      var y = new THREE.Vector3();
      y.subVectors(p0, p1).normalize();
      var x = new THREE.Vector3(1, 0, 0);
      var xOnY = new THREE.Vector3(x.x, x.y, x.z);
      xOnY.projectOnVector(y);
      x.sub(xOnY).normalize();
      var z = new THREE.Vector3();
      z.crossVectors(x, y).normalize();
      var m = new THREE.Matrix4();
      m.makeBasis(x, y, z);
      var radialSegments = 5;
      var geometry = new THREE.CylinderGeometry(swcJson[par].radius, v.radius, height, radialSegments);
      geometry.applyMatrix4(m);
      geometry.translate(pos.x, pos.y, pos.z);
      geometries.push(geometry);
    }
  });

  if (geometries.length > 0) {
    // Keeping all the segments of the SWC as separate geometries reduces Three.js
    // rendering performance.  Merging them into one geometry makes a big difference.
    var mergedGeometry = _BufferGeometryUtils.BufferGeometryUtils.mergeBufferGeometries(geometries);

    var surfaceMaterial = new THREE.MeshLambertMaterial();

    if (colorStr) {
      surfaceMaterial.color.set(colorStr);
    }

    var surface = new THREE.Mesh(mergedGeometry, surfaceMaterial);
    return surface;
  }

  return null;
}