text: "use strict";
  /**
   * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
   *
   * @author Alexander Rose <alexander.rose@weirdbyte.de>
   */
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.SliceRepresentationProvider = exports.SliceRepresentation = exports.SliceVisual = exports.getSliceParams = exports.SliceParams = exports.createImage = void 0;
  var tslib_1 = require("tslib");
  var param_definition_1 = require("../../mol-util/param-definition");
  var image_1 = require("../../mol-geo/geometry/image/image");
  var volume_1 = require("../../mol-model/volume");
  var representation_1 = require("./representation");
  var location_iterator_1 = require("../../mol-geo/util/location-iterator");
  var location_1 = require("../../mol-model/location");
  var loci_1 = require("../../mol-model/loci");
  var int_1 = require("../../mol-data/int");
  var util_1 = require("../../mol-geo/util");
  var color_1 = require("../../mol-util/color");
  var color_2 = require("../../mol-theme/color");
  var float_packing_1 = require("../../mol-util/float-packing");
  var util_2 = require("./util");
  function createImage(ctx, volume, theme, props, image) {
      return (0, tslib_1.__awaiter)(this, void 0, void 0, function () {
          var dim, isoValue, _a, space, data, _b, min, max, isoVal, color, _c, r, g, b, _d, width, height, x, y, z, x0, y0, z0, nx, ny, nz, corners, imageArray, groupArray, i, iy, ix, iz, val, normVal, imageTexture, groupTexture, transform;
          return (0, tslib_1.__generator)(this, function (_e) {
              dim = props.dimension.name, isoValue = props.isoValue;
              _a = volume.grid.cells, space = _a.space, data = _a.data;
              _b = volume.grid.stats, min = _b.min, max = _b.max;
              isoVal = volume_1.Volume.IsoValue.toAbsolute(isoValue, volume.grid.stats).absoluteValue;
              color = theme.color.color(location_1.NullLocation, false);
              _c = color_1.Color.toRgbNormalized(color), r = _c[0], g = _c[1], b = _c[2];
              _d = getSliceInfo(volume.grid, props), width = _d.width, height = _d.height, x = _d.x, y = _d.y, z = _d.z, x0 = _d.x0, y0 = _d.y0, z0 = _d.z0, nx = _d.nx, ny = _d.ny, nz = _d.nz;
              corners = new Float32Array(dim === 'x' ? [x, 0, 0, x, y, 0, x, 0, z, x, y, z] :
                  dim === 'y' ? [0, y, 0, x, y, 0, 0, y, z, x, y, z] :
                      [0, 0, z, 0, y, z, x, 0, z, x, y, z]);
              imageArray = new Uint8Array(width * height * 4);
              groupArray = getPackedGroupArray(volume.grid, props);
              i = 0;
              for (iy = y0; iy < ny; ++iy) {
                  for (ix = x0; ix < nx; ++ix) {
                      for (iz = z0; iz < nz; ++iz) {
                          val = space.get(data, ix, iy, iz);
                          normVal = (val - min) / (max - min);
                          imageArray[i] = r * normVal * 2 * 255;
                          imageArray[i + 1] = g * normVal * 2 * 255;
                          imageArray[i + 2] = b * normVal * 2 * 255;
                          imageArray[i + 3] = val >= isoVal ? 255 : 0;
                          i += 4;
                      }
                  }
              }
              imageTexture = { width: width, height: height, array: imageArray, flipY: true };
              groupTexture = { width: width, height: height, array: groupArray, flipY: true };
              transform = volume_1.Grid.getGridToCartesianTransform(volume.grid);
              (0, util_1.transformPositionArray)(transform, corners, 0, 4);
              return [2 /*return*/, image_1.Image.create(imageTexture, corners, groupTexture, image)];
          });
      });
  }
  exports.createImage = createImage;
  function getSliceInfo(grid, props) {
      var _a = props.dimension, dim = _a.name, index = _a.params;
      var space = grid.cells.space;
      var width, height;
      var x, y, z;
      var x0 = 0, y0 = 0, z0 = 0;
      var _b = space.dimensions, nx = _b[0], ny = _b[1], nz = _b[2];
      if (dim === 'x') {
          x = index, y = ny - 1, z = nz - 1;
          width = nz, height = ny;
          x0 = x, nx = x0 + 1;
      }
      else if (dim === 'y') {
          x = nx - 1, y = index, z = nz - 1;
          width = nz, height = nx;
          y0 = y, ny = y0 + 1;
      }
      else {
          x = nx - 1, y = ny - 1, z = index;
          width = nx, height = ny;
          z0 = z, nz = z0 + 1;
      }
      return {
          width: width,
          height: height,
          x: x,
          y: y,
          z: z,
          x0: x0,
          y0: y0,
          z0: z0,
          nx: nx,
          ny: ny,
          nz: nz
      };
  }
  function getPackedGroupArray(grid, props) {
      var space = grid.cells.space;
      var _a = getSliceInfo(grid, props), width = _a.width, height = _a.height, x0 = _a.x0, y0 = _a.y0, z0 = _a.z0, nx = _a.nx, ny = _a.ny, nz = _a.nz;
      var groupArray = new Uint8Array(width * height * 4);
      var j = 0;
      for (var iy = y0; iy < ny; ++iy) {
          for (var ix = x0; ix < nx; ++ix) {
              for (var iz = z0; iz < nz; ++iz) {
                  (0, float_packing_1.encodeFloatRGBtoArray)(space.dataOffset(ix, iy, iz), groupArray, j);
                  j += 4;
              }
          }
      }
      return groupArray;
  }
  function getGroupArray(grid, props) {
      var space = grid.cells.space;
      var _a = getSliceInfo(grid, props), width = _a.width, height = _a.height, x0 = _a.x0, y0 = _a.y0, z0 = _a.z0, nx = _a.nx, ny = _a.ny, nz = _a.nz;
      var groupArray = new Uint32Array(width * height);
      var j = 0;
      for (var iy = y0; iy < ny; ++iy) {
          for (var ix = x0; ix < nx; ++ix) {
              for (var iz = z0; iz < nz; ++iz) {
                  groupArray[j] = space.dataOffset(ix, iy, iz);
                  j += 1;
              }
          }
      }
      return groupArray;
  }
  function getLoci(volume, props) {
      // TODO cache somehow?
      var groupArray = getGroupArray(volume.grid, props);
      return volume_1.Volume.Cell.Loci(volume, int_1.SortedArray.ofUnsortedArray(groupArray));
  }
  function getSliceLoci(pickingId, volume, props, id) {
      var objectId = pickingId.objectId, groupId = pickingId.groupId;
      if (id === objectId) {
          return volume_1.Volume.Cell.Loci(volume, int_1.Interval.ofSingleton(groupId));
      }
      return loci_1.EmptyLoci;
  }
  function eachSlice(loci, volume, props, apply) {
      return (0, util_2.eachVolumeLoci)(loci, volume, undefined, apply);
  }
  //
  exports.SliceParams = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, image_1.Image.Params), { quality: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, image_1.Image.Params.quality), { isEssential: false }), dimension: param_definition_1.ParamDefinition.MappedStatic('x', {
          x: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: 0, step: 1 }),
          y: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: 0, step: 1 }),
          z: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: 0, step: 1 }),
      }, { isEssential: true }), isoValue: volume_1.Volume.IsoValueParam });
  function getSliceParams(ctx, volume) {
      var p = param_definition_1.ParamDefinition.clone(exports.SliceParams);
      var dim = volume.grid.cells.space.dimensions;
      p.dimension = param_definition_1.ParamDefinition.MappedStatic('x', {
          x: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: dim[0] - 1, step: 1 }),
          y: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: dim[1] - 1, step: 1 }),
          z: param_definition_1.ParamDefinition.Numeric(0, { min: 0, max: dim[2] - 1, step: 1 }),
      }, { isEssential: true });
      p.isoValue = volume_1.Volume.createIsoValueParam(volume_1.Volume.IsoValue.absolute(volume.grid.stats.min), volume.grid.stats);
      return p;
  }
  exports.getSliceParams = getSliceParams;
  function SliceVisual(materialId) {
      return (0, representation_1.VolumeVisual)({
          defaultProps: param_definition_1.ParamDefinition.getDefaultValues(exports.SliceParams),
          createGeometry: createImage,
          createLocationIterator: function (volume) { return (0, location_iterator_1.LocationIterator)(volume.grid.cells.data.length, 1, 1, function () { return location_1.NullLocation; }); },
          getLoci: getSliceLoci,
          eachLocation: eachSlice,
          setUpdateState: function (state, volume, newProps, currentProps, newTheme, currentTheme) {
              state.createGeometry = (newProps.dimension.name !== currentProps.dimension.name ||
                  newProps.dimension.params !== currentProps.dimension.params ||
                  !volume_1.Volume.IsoValue.areSame(newProps.isoValue, currentProps.isoValue, volume.grid.stats) ||
                  !color_2.ColorTheme.areEqual(newTheme.color, currentTheme.color));
          },
          geometryUtils: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, image_1.Image.Utils), { createRenderableState: function (props) {
                  var state = image_1.Image.Utils.createRenderableState(props);
                  updateRenderableState(state, props);
                  return state;
              }, updateRenderableState: updateRenderableState })
      }, materialId);
  }
  exports.SliceVisual = SliceVisual;
  function updateRenderableState(state, props) {
      image_1.Image.Utils.updateRenderableState(state, props);
      state.opaque = false;
      state.writeDepth = true;
  }
  function SliceRepresentation(ctx, getParams) {
      return (0, representation_1.VolumeRepresentation)('Slice', ctx, getParams, SliceVisual, getLoci);
  }
  exports.SliceRepresentation = SliceRepresentation;
  exports.SliceRepresentationProvider = (0, representation_1.VolumeRepresentationProvider)({
      name: 'slice',
      label: 'Slice',
      description: 'Slice of volume rendered as image with interpolation.',
      factory: SliceRepresentation,
      getParams: getSliceParams,
      defaultValues: param_definition_1.ParamDefinition.getDefaultValues(exports.SliceParams),
      defaultColorTheme: { name: 'uniform' },
      defaultSizeTheme: { name: 'uniform' },
      isApplicable: function (volume) { return !volume_1.Volume.isEmpty(volume); }
  });
  //# sourceMappingURL=slice.js.map