/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.vtk;
import icy.canvas.Layer;
import icy.image.colormap.IcyColorMap;
import icy.image.lut.LUT.LUTChannel;
import icy.math.Scaler;
import icy.painter.Overlay;
import icy.painter.VtkPainter;
import icy.roi.ROI;
import icy.type.DataType;
import icy.type.collection.array.Array2DUtil;
import icy.type.collection.array.ArrayUtil;
import icy.type.rectangle.Rectangle5D;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import plugins.kernel.canvas.VtkCanvas;
import vtk.vtkActor;
import vtk.vtkActor2D;
import vtk.vtkActor2DCollection;
import vtk.vtkActorCollection;
import vtk.vtkCellArray;
import vtk.vtkCollection;
import vtk.vtkColorTransferFunction;
import vtk.vtkContourFilter;
import vtk.vtkDataArray;
import vtk.vtkDoubleArray;
import vtk.vtkFloatArray;
import vtk.vtkIdTypeArray;
import vtk.vtkImageConstantPad;
import vtk.vtkImageData;
import vtk.vtkIntArray;
import vtk.vtkLongArray;
import vtk.vtkObject;
import vtk.vtkPiecewiseFunction;
import vtk.vtkPoints;
import vtk.vtkPolyData;
import vtk.vtkProp;
import vtk.vtkPropCollection;
import vtk.vtkRenderer;
import vtk.vtkShortArray;
import vtk.vtkUnsignedCharArray;
import vtk.vtkUnsignedIntArray;
import vtk.vtkUnsignedLongArray;
import vtk.vtkUnsignedShortArray;
/**
* @author Stephane
*/
public class VtkUtil
{
// VTK type
public final static int VTK_VOID = 0;
public final static int VTK_BIT = 1;
public final static int VTK_CHAR = 2;
public final static int VTK_SIGNED_CHAR = 15;
public final static int VTK_UNSIGNED_CHAR = 3;
public final static int VTK_SHORT = 4;
public final static int VTK_UNSIGNED_SHORT = 5;
public final static int VTK_INT = 6;
public final static int VTK_UNSIGNED_INT = 7;
public final static int VTK_LONG = 8;
public final static int VTK_UNSIGNED_LONG = 9;
public final static int VTK_FLOAT = 10;
public final static int VTK_DOUBLE = 11;
public final static int VTK_ID = 12;
// VTK interpolation
public final static int VTK_NEAREST_INTERPOLATION = 0;
public final static int VTK_LINEAR_INTERPOLATION = 1;
public final static int VTK_CUBIC_INTERPOLATION = 2;
// VTK bounding box
public final static int VTK_FLY_OUTER_EDGES = 0;
public final static int VTK_FLY_CLOSEST_TRIAD = 1;
public final static int VTK_FLY_FURTHEST_TRIAD = 2;
public final static int VTK_FLY_STATIC_TRIAD = 3;
public final static int VTK_FLY_STATIC_EDGES = 4;
public final static int VTK_TICKS_INSIDE = 0;
public final static int VTK_TICKS_OUTSIDE = 1;
public final static int VTK_TICKS_BOTH = 2;
public final static int VTK_GRID_LINES_ALL = 0;
public final static int VTK_GRID_LINES_CLOSEST = 1;
public final static int VTK_GRID_LINES_FURTHEST = 2;
/**
* Returns the VTK type corresponding to the specified DataType
*/
public static int getVtkType(DataType type)
{
switch (type)
{
default:
case UBYTE:
case BYTE:
return VTK_UNSIGNED_CHAR;
// FIXME: signed char not supported by VTK java wrapper ??
// case BYTE:
// return VTK_CHAR;
// return VTK_SIGNED_CHAR;
case USHORT:
return VTK_UNSIGNED_SHORT;
case SHORT:
return VTK_SHORT;
case UINT:
return VTK_UNSIGNED_INT;
case INT:
return VTK_INT;
case ULONG:
return VTK_UNSIGNED_LONG;
case LONG:
return VTK_LONG;
case FLOAT:
return VTK_FLOAT;
case DOUBLE:
return VTK_DOUBLE;
}
}
public static vtkDataArray getVtkArray(Object array, boolean signed)
{
switch (ArrayUtil.getDataType(array))
{
case BYTE:
return getUCharArray((byte[]) array);
case SHORT:
if (signed)
return getUShortArray((short[]) array);
return getShortArray((short[]) array);
case INT:
if (signed)
return getUIntArray((int[]) array);
return getIntArray((int[]) array);
case LONG:
if (signed)
return getULongArray((long[]) array);
return getLongArray((long[]) array);
case FLOAT:
return getFloatArray((float[]) array);
case DOUBLE:
return getDoubleArray((double[]) array);
default:
return null;
}
}
public static vtkUnsignedCharArray getUCharArray(byte[] array)
{
final vtkUnsignedCharArray result = new vtkUnsignedCharArray();
result.SetJavaArray(array);
return result;
}
public static vtkUnsignedShortArray getUShortArray(short[] array)
{
final vtkUnsignedShortArray result = new vtkUnsignedShortArray();
result.SetJavaArray(array);
return result;
}
public static vtkUnsignedIntArray getUIntArray(int[] array)
{
final vtkUnsignedIntArray result = new vtkUnsignedIntArray();
result.SetJavaArray(array);
return result;
}
public static vtkUnsignedLongArray getULongArray(long[] array)
{
final vtkUnsignedLongArray result = new vtkUnsignedLongArray();
result.SetJavaArray(array);
return result;
}
public static vtkShortArray getShortArray(short[] array)
{
final vtkShortArray result = new vtkShortArray();
result.SetJavaArray(array);
return result;
}
public static vtkIntArray getIntArray(int[] array)
{
final vtkIntArray result = new vtkIntArray();
result.SetJavaArray(array);
return result;
}
public static vtkLongArray getLongArray(long[] array)
{
final vtkLongArray result = new vtkLongArray();
result.SetJavaArray(array);
return result;
}
public static vtkFloatArray getFloatArray(float[] array)
{
final vtkFloatArray result = new vtkFloatArray();
result.SetJavaArray(array);
return result;
}
public static vtkDoubleArray getDoubleArray(double[] array)
{
final vtkDoubleArray result = new vtkDoubleArray();
result.SetJavaArray(array);
return result;
}
public static vtkIdTypeArray getIdTypeArray(int[] array)
{
final vtkIdTypeArray result = new vtkIdTypeArray();
final vtkIntArray iarray = getIntArray(array);
result.DeepCopy(iarray);
return result;
}
public static int[] getArray(vtkIdTypeArray array)
{
final vtkIntArray iarray = new vtkIntArray();
iarray.DeepCopy(array);
return iarray.GetJavaArray();
}
/**
* Transforms a vtkCollection to an array
*/
public static vtkObject[] vtkCollectionToArray(vtkCollection collection)
{
final vtkObject[] result = new vtkObject[collection.GetNumberOfItems()];
collection.InitTraversal();
for (int i = 0; i < result.length; i++)
result[i] = collection.GetNextItemAsObject();
return result;
}
/**
* Get vtkPoints from double[]
*/
public static vtkPoints getPoints(double[] points)
{
final vtkPoints result = new vtkPoints();
final vtkDoubleArray array = getDoubleArray(points);
array.SetNumberOfComponents(3);
result.SetData(array);
return result;
}
/**
* Get vtkPoints from double[][3]
*/
public static vtkPoints getPoints(double[][] points)
{
return getPoints(Array2DUtil.toDoubleArray1D(points));
}
/**
* Get vtkPoints from float[]
*/
public static vtkPoints getPoints(float[] points)
{
final vtkPoints result = new vtkPoints();
final vtkFloatArray array = getFloatArray(points);
array.SetNumberOfComponents(3);
result.SetData(array);
return result;
}
/**
* Get vtkPoints from float[][3]
*/
public static vtkPoints getPoints(float[][] points)
{
return getPoints(Array2DUtil.toFloatArray1D(points));
}
/**
* Get vtkPoints from int[]
*/
public static vtkPoints getPoints(int[] points)
{
final vtkPoints result = new vtkPoints();
final vtkIntArray array = getIntArray(points);
array.SetNumberOfComponents(3);
result.SetData(array);
return result;
}
/**
* Get vtkPoints from int[][3]
*/
public static vtkPoints getPoints(int[][] points)
{
return getPoints(Array2DUtil.toIntArray1D(points));
}
/**
* Get vtkCellArray from a 1D prepared cells array ( {n, i1, i2, ..., n, i1, i2,...} )
*/
public static vtkCellArray getCells(int numCell, int[] cells)
{
final vtkCellArray result = new vtkCellArray();
result.SetCells(numCell, getIdTypeArray(cells));
return result;
}
/**
* Returns the <i>vtkProp</i> from the specified <i>Layer</i> object.<br>
* Returns a 0 sized array if the specified layer is <code>null</code> or does not contains any vtkProp.
*/
public static vtkProp[] getLayerProps(Layer layer)
{
if (layer != null)
{
// add painter actor from the vtk render
final Overlay overlay = layer.getOverlay();
if (overlay instanceof VtkPainter)
return ((VtkPainter) overlay).getProps();
}
return new vtkProp[0];
}
/**
* Returns all <i>vtkProp</i> from the specified list of <i>Layer</i> object.<br>
* Returns a 0 sized array if specified layers does not contains any vtkProp.
*/
public static vtkProp[] getLayersProps(List<Layer> layers)
{
final List<vtkProp[]> layersProps = new ArrayList<vtkProp[]>();
int totalSize = 0;
for (Layer layer : layers)
{
if (layer != null)
{
// add painter actor from the vtk render
final Overlay overlay = layer.getOverlay();
if (overlay instanceof VtkPainter)
{
final vtkProp[] props = ((VtkPainter) overlay).getProps();
if (props.length > 0)
{
layersProps.add(props);
totalSize += props.length;
}
}
}
}
final vtkProp[] result = new vtkProp[totalSize];
int ind = 0;
for (vtkProp[] props : layersProps)
{
final int size = props.length;
System.arraycopy(props, 0, result, ind, size);
ind += size;
}
return result;
}
/**
* Return all actor / view prop from the specified renderer
*/
public static vtkProp[] getProps(vtkRenderer renderer)
{
if (renderer == null)
return new vtkProp[0];
final vtkPropCollection collection = renderer.GetViewProps();
final vtkProp[] result = new vtkProp[collection.GetNumberOfItems()];
collection.InitTraversal();
for (int i = 0; i < result.length; i++)
result[i] = collection.GetNextProp();
return result;
}
/**
* Return true if the renderer contains the specified actor / view prop
*/
public static boolean hasProp(vtkRenderer renderer, vtkProp actor)
{
if ((renderer == null) || (actor == null))
return false;
return renderer.HasViewProp(actor) != 0;
}
/**
* @deprecated Use {@link #hasProp(vtkRenderer, vtkProp)} instead.
*/
@Deprecated
public static boolean findProp(vtkRenderer renderer, vtkProp actor)
{
return hasProp(renderer, actor);
}
/**
* @deprecated Use {@link #hasProp(vtkRenderer, vtkProp)} instead.
*/
@Deprecated
public static boolean findActor(vtkRenderer renderer, vtkActor actor)
{
if ((renderer == null) || (actor == null))
return false;
final vtkActorCollection actors = renderer.GetActors();
actors.InitTraversal();
for (int i = 0; i < actors.GetNumberOfItems(); i++)
{
final vtkActor curActor = actors.GetNextActor();
// already present --> exit
if (curActor == actor)
return true;
// // search in sub actor
// if (findActor(curActor, actor))
// return true;
}
return false;
}
/**
* @deprecated Use {@link #hasProp(vtkRenderer, vtkProp)} instead.
*/
@Deprecated
public static boolean findActor2D(vtkRenderer renderer, vtkActor2D actor)
{
if ((renderer == null) || (actor == null))
return false;
final vtkActor2DCollection actors = renderer.GetActors2D();
actors.InitTraversal();
for (int i = 0; i < actors.GetNumberOfItems(); i++)
{
final vtkActor2D curActor = actors.GetNextActor2D();
// already present --> exit
if (curActor == actor)
return true;
// // search in sub actor
// if (findActor2D(curActor, actor))
// return true;
}
return false;
}
/**
* Add an actor (vtkProp) to the specified renderer.<br>
* If the actor is already existing in the renderer then no operation is done.
*/
public static void addProp(vtkRenderer renderer, vtkProp prop)
{
if ((renderer == null) || (prop == null))
return;
// actor not yet present in renderer ? --> add it
if (renderer.HasViewProp(prop) == 0)
renderer.AddViewProp(prop);
}
/**
* @deprecated Use {@link #addProp(vtkRenderer, vtkProp)} instead.
*/
@Deprecated
public static void addActor(vtkRenderer renderer, vtkActor actor)
{
if ((renderer == null) || (actor == null))
return;
// actor not yet present in renderer ? --> add it
if (!VtkUtil.findActor(renderer, actor))
renderer.AddActor(actor);
}
/**
* @deprecated Use {@link #addProp(vtkRenderer, vtkProp)} instead.
*/
@Deprecated
public static void addActor2D(vtkRenderer renderer, vtkActor2D actor)
{
if ((renderer == null) || (actor == null))
return;
// actor not yet present in renderer ? --> add it
if (!VtkUtil.findActor2D(renderer, actor))
renderer.AddActor2D(actor);
}
/**
* Add an array of actor (vtkProp) to the specified renderer.<br>
* If an actor is already existing in the renderer then nothing is done for this actor.
*/
public static void addProps(vtkRenderer renderer, vtkProp[] props)
{
if ((renderer == null) || (props == null))
return;
for (vtkProp prop : props)
{
// actor not yet present in renderer ? --> add it
if (renderer.HasViewProp(prop) == 0)
renderer.AddViewProp(prop);
}
}
/**
* Remove an actor from the specified renderer.
*/
public static void removeProp(vtkRenderer renderer, vtkProp actor)
{
renderer.RemoveViewProp(actor);
}
/**
* Return a 1D cells array from a 2D indexes array
*/
public static int[] prepareCells(int[][] indexes)
{
final int len = indexes.length;
int total_len = 0;
for (int i = 0; i < len; i++)
total_len += indexes[i].length + 1;
final int[] result = new int[total_len];
int offset = 0;
for (int i = 0; i < len; i++)
{
final int[] s_cells = indexes[i];
final int s_len = s_cells.length;
result[offset++] = s_len;
for (int j = 0; j < s_len; j++)
result[offset++] = s_cells[j];
}
return result;
}
/**
* Return a 1D cells array from a 1D indexes array and num vertex per cell (polygon)
*/
public static int[] prepareCells(int numVertexPerCell, int[] indexes)
{
final int num_cells = indexes.length / numVertexPerCell;
final int[] result = new int[num_cells * (numVertexPerCell + 1)];
int off_dst = 0;
int off_src = 0;
for (int i = 0; i < num_cells; i++)
{
result[off_dst++] = numVertexPerCell;
for (int j = 0; j < numVertexPerCell; j++)
result[off_dst++] = indexes[off_src + j];
off_src += numVertexPerCell;
}
return result;
}
/**
* Creates and returns a 3D binary (0/1 values) {@link vtkImageData} object corresponding to the ROI 3D boolean mask
* (C dimension is not considered) at specified T position.
*
* @param roi
* the roi we want to retrieve the vtkImageData mask
* @param sz
* the Z size to use for ROI with infinite Z dimension (if ROI has a finite Z dimension then ROI Z size is
* used).
* @param t
* the T position we want to retrieve the 3D mask data
*/
public static vtkImageData getBinaryImageData(ROI roi, int sz, int t)
{
final vtkImageData result;
final Rectangle5D bounds5d = roi.getBounds5D();
final int sizeX;
final int sizeY;
final int sizeZ;
final int x;
final int y;
final int z;
final int c;
x = (int) bounds5d.getX();
y = (int) bounds5d.getY();
sizeX = (int) (bounds5d.getMaxX() - x);
sizeY = (int) (bounds5d.getMaxY() - y);
if (bounds5d.isInfiniteZ())
{
z = 0;
sizeZ = sz;
}
else
{
z = (int) bounds5d.getZ();
sizeZ = (int) (bounds5d.getMaxZ() - z);
}
if (bounds5d.isInfiniteC())
c = 0;
else
c = (int) bounds5d.getC();
long totalSize = sizeX;
totalSize *= sizeY;
totalSize *= sizeZ;
if (totalSize > Integer.MAX_VALUE)
throw new RuntimeException("Can't allocate array (size > 2^31)");
// build java array
final int sizeXY = sizeX * sizeY;
final byte[] array = new byte[(int) totalSize];
int offset = 0;
if (bounds5d.isInfiniteZ())
{
final boolean[] mask = roi.getBooleanMask2D(x, y, sizeX, sizeY, 0, t, c, true);
for (int curZ = z; curZ < (z + sizeZ); curZ++)
{
for (int i = 0; i < sizeXY; i++)
array[offset++] = mask[i] ? (byte) 1 : (byte) 0;
}
}
else
{
for (int curZ = z; curZ < (z + sizeZ); curZ++)
{
final boolean[] mask = roi.getBooleanMask2D(x, y, sizeX, sizeY, curZ, t, c, true);
for (int i = 0; i < sizeXY; i++)
array[offset++] = mask[i] ? (byte) 1 : (byte) 0;
}
}
// create a new image data structure
result = new vtkImageData();
result.SetDimensions(sizeX, sizeY, sizeZ);
result.SetExtent(0, sizeX - 1, 0, sizeY - 1, 0, sizeZ - 1);
// pre-allocate data
result.AllocateScalars(VTK_UNSIGNED_CHAR, 1);
// set data
((vtkUnsignedCharArray) result.GetPointData().GetScalars()).SetJavaArray(array);
return result;
}
/**
* Creates and returns a {@link vtkImageData} object from the specified 1D array data.
*/
public static vtkImageData getImageData(Object data, DataType dataType, int sizeX, int sizeY, int sizeZ, int sizeC)
{
final vtkImageData result;
final vtkDataArray array;
// create a new image data structure
result = new vtkImageData();
result.SetDimensions(sizeX, sizeY, sizeZ);
result.SetExtent(0, sizeX - 1, 0, sizeY - 1, 0, sizeZ - 1);
// pre-allocate data
result.AllocateScalars(getVtkType(dataType), sizeC);
// get array structure
array = result.GetPointData().GetScalars();
switch (dataType)
{
case UBYTE:
case BYTE:
((vtkUnsignedCharArray) array).SetJavaArray((byte[]) data);
break;
case USHORT:
((vtkUnsignedShortArray) array).SetJavaArray((short[]) data);
break;
case SHORT:
((vtkShortArray) array).SetJavaArray((short[]) data);
break;
case UINT:
((vtkUnsignedIntArray) array).SetJavaArray((int[]) data);
break;
case INT:
((vtkIntArray) array).SetJavaArray((int[]) data);
break;
case FLOAT:
((vtkFloatArray) array).SetJavaArray((float[]) data);
break;
case DOUBLE:
((vtkDoubleArray) array).SetJavaArray((double[]) data);
break;
}
return result;
}
/**
* Create a 3D surface in VTK polygon format from the input VTK image.
*
* @param imageData
* the input image to construct surface from
* @param threshold
* the threshold intensity value used to build the surface
*/
public static vtkPolyData getSurfaceFromImage(vtkImageData imageData, double threshold)
{
vtkImageData out;
vtkPolyData result;
final int[] extent = imageData.GetExtent();
extent[0]--; // min X
extent[1]++; // max X
extent[2]--; // min Y
extent[3]++; // max Y
extent[4]--; // min Z
extent[5]++; // max Z
// pad on all sides to guarantee closed meshes
final vtkImageConstantPad pad = new vtkImageConstantPad();
pad.SetOutputWholeExtent(extent);
pad.SetInputData(imageData);
pad.Update();
out = pad.GetOutput();
// do not delete input image
pad.Delete();
final vtkContourFilter contourFilter = new vtkContourFilter();
contourFilter.SetInputData(out);
contourFilter.SetValue(0, threshold);
contourFilter.Update();
result = contourFilter.GetOutput();
contourFilter.GetInput().Delete();
contourFilter.Delete();
// final vtkMarchingCubes marchingCubes = new vtkMarchingCubes();
//
// marchingCubes.SetInputData(out);
// marchingCubes.SetValue(0, threshold);
// marchingCubes.Update();
//
// // get the poly data result
// result = marchingCubes.GetOutput();
// marchingCubes.GetInput().Delete();
// marchingCubes.Delete();
// if (keepLargest)
// {
// final vtkPolyDataConnectivityFilter cc = new vtkPolyDataConnectivityFilter();
//
// cc.SetInputData(result);
// cc.SetExtractionModeToLargestRegion();
// cc.Update();
//
// result = cc.GetOutput();
// cc.GetInput().Delete();
// cc.Delete();
// }
//
// if (simplifyMesh)
// {
// final vtkDecimatePro dec = new vtkDecimatePro();
//
// dec.SetInputData(result);
// dec.PreserveTopologyOn();
// dec.SetTargetReduction(0.9);
// dec.Update();
//
// result = dec.GetOutput();
// dec.GetInput().Delete();
// dec.Delete();
// }
//
// if (smoothness > 0)
// {
// final vtkSmoothPolyDataFilter smoother = new vtkSmoothPolyDataFilter();
//
// smoother.SetInputData(result);
// smoother.SetRelaxationFactor(0.3);
// smoother.FeatureEdgeSmoothingOff();
// smoother.BoundarySmoothingOn();
// smoother.SetNumberOfIterations(smoothness);
// smoother.Update();
//
// result = smoother.GetOutput();
// smoother.GetInput().Delete();
// smoother.Delete();
// }
return result;
}
/**
* Creates and returns the color map in {@link vtkColorTransferFunction} format from the
* specified {@link LUTChannel}.
*/
public static vtkColorTransferFunction getColorMap(LUTChannel lutChannel)
{
final IcyColorMap colorMap = lutChannel.getColorMap();
final Scaler scaler = lutChannel.getScaler();
// SCALAR COLOR FUNCTION
final vtkColorTransferFunction result = new vtkColorTransferFunction();
result.SetRange(scaler.getLeftIn(), scaler.getRightIn());
for (int i = 0; i < IcyColorMap.SIZE; i++)
{
result.AddRGBPoint(scaler.unscale(i), colorMap.getNormalizedRed(i), colorMap.getNormalizedGreen(i),
colorMap.getNormalizedBlue(i));
}
return result;
}
/**
* Creates and returns the opacity map in {@link vtkPiecewiseFunction} format from the specified {@link LUTChannel}.
*/
public static vtkPiecewiseFunction getOpacityMap(LUTChannel lutChannel)
{
final IcyColorMap colorMap = lutChannel.getColorMap();
final Scaler scaler = lutChannel.getScaler();
// SCALAR OPACITY FUNCTION
final vtkPiecewiseFunction result = new vtkPiecewiseFunction();
if (colorMap.isEnabled())
{
for (int i = 0; i < IcyColorMap.SIZE; i++)
result.AddPoint(scaler.unscale(i), colorMap.getNormalizedAlpha(i));
}
else
{
for (int i = 0; i < IcyColorMap.SIZE; i++)
result.AddPoint(scaler.unscale(i), 0d);
}
return result;
}
/**
* Creates and returns a binary color map in {@link vtkColorTransferFunction} format where 0 value is black and 1 is
* set to specified color.
*/
public static vtkColorTransferFunction getBinaryColorMap(Color color)
{
// SCALAR COLOR FUNCTION
final vtkColorTransferFunction result = new vtkColorTransferFunction();
result.SetRange(0, 1);
result.AddRGBPoint(0d, 0d, 0d, 0d);
result.AddRGBPoint(1d, color.getRed() / 255d, color.getGreen() / 255d, color.getBlue() / 255d);
return result;
}
/**
* Creates and returns a binary opacity map in {@link vtkPiecewiseFunction} format where 0 is 100% transparent and 1
* to the specified opacity value.
*/
public static vtkPiecewiseFunction getBinaryOpacityMap(double opacity)
{
// SCALAR OPACITY FUNCTION
final vtkPiecewiseFunction result = new vtkPiecewiseFunction();
result.AddPoint(0d, 1d);
result.AddPoint(1d, opacity);
return result;
}
/**
* Set the Color of the specified {@link vtkPolyData} object.
*
* @param polyData
* the vtkPolyData we want to change color
* @param color
* the color to set
* @param canvas
* the VtkCanvas object to lock during the color change operation for safety (can be <code>null</code> if we
* don't need to lock the VtkCanvas here)
*/
public static void setPolyDataColor(vtkPolyData polyData, Color color, VtkCanvas canvas)
{
final int numPts = polyData.GetNumberOfPoints();
vtkUnsignedCharArray colors = null;
// try to recover colors object
if (polyData.GetPointData() != null)
{
final vtkDataArray dataArray = polyData.GetPointData().GetScalars();
if (dataArray instanceof vtkUnsignedCharArray)
colors = (vtkUnsignedCharArray) dataArray;
// delete it
else if (dataArray != null)
dataArray.Delete();
}
// colors is not correctly defined ? --> reallocate
if ((colors == null) || (colors.GetNumberOfTuples() != numPts) || (colors.GetNumberOfComponents() != 3))
{
// delete first
if (colors != null)
colors.Delete();
// and reallocate
colors = new vtkUnsignedCharArray();
colors.SetNumberOfComponents(3);
colors.SetNumberOfTuples(numPts);
// set colors array
polyData.GetPointData().SetScalars(colors);
}
final int len = numPts * 3;
final byte r = (byte) color.getRed();
final byte g = (byte) color.getGreen();
final byte b = (byte) color.getBlue();
final byte[] data = new byte[len];
for (int i = 0; i < len; i += 3)
{
data[i + 0] = r;
data[i + 1] = g;
data[i + 2] = b;
}
final IcyVtkPanel vtkPanel = (canvas != null) ? canvas.getVtkPanel() : null;
if (vtkPanel != null)
{
vtkPanel.lock();
try
{
colors.SetJavaArray(data);
colors.Modified();
}
finally
{
vtkPanel.unlock();
}
}
else
{
colors.SetJavaArray(data);
colors.Modified();
}
}
/**
* Returns a cube polydata object representing the specified bounding box coordinate
*
* @see #setOutlineBounds(vtkPolyData, double, double, double, double, double, double, VtkCanvas)
*/
public static vtkPolyData getOutline(double xMin, double xMax, double yMin, double yMax, double zMin, double zMax)
{
final double points[][] = new double[8][3];
final int indexes[][] = { {0, 2, 3, 1}, {4, 5, 7, 6}, {0, 1, 5, 4}, {1, 3, 7, 5}, {0, 4, 6, 2}, {3, 2, 6, 7}};
for (int i = 0; i < 8; i++)
{
points[i][0] = ((i & 1) == 0) ? xMin : xMax;
points[i][1] = ((i & 2) == 0) ? yMin : yMax;
points[i][2] = ((i & 4) == 0) ? zMin : zMax;
}
final vtkCellArray vCells = VtkUtil.getCells(6, prepareCells(indexes));
final vtkPoints vPoints = VtkUtil.getPoints(points);
final vtkPolyData result = new vtkPolyData();
result.SetPolys(vCells);
result.SetPoints(vPoints);
return result;
}
/**
* Set the bounds of specified outline polydata object (previously created with <i>VtkUtil.getOutline(..)</i>)
*
* @param canvas
* the VtkCanvas object to lock during the color change operation for safety (can be <code>null</code> if we
* don't need to lock the VtkCanvas here)
* @return <code>false</code> if the specified polydata object is not a valid outline object
* @see #getOutline(double, double, double, double, double, double)
*/
public static boolean setOutlineBounds(vtkPolyData outline, double xMin, double xMax, double yMin, double yMax,
double zMin, double zMax, VtkCanvas canvas)
{
final vtkPoints previousPoints = outline.GetPoints();
// not valid
if ((previousPoints != null) && (previousPoints.GetNumberOfPoints() != 8))
return false;
final double newPoints[][] = new double[8][3];
for (int i = 0; i < 8; i++)
{
newPoints[i][0] = ((i & 1) == 0) ? xMin : xMax;
newPoints[i][1] = ((i & 2) == 0) ? yMin : yMax;
newPoints[i][2] = ((i & 4) == 0) ? zMin : zMax;
}
final vtkPoints points = getPoints(newPoints);
final IcyVtkPanel vtkPanel = (canvas != null) ? canvas.getVtkPanel() : null;
if (vtkPanel != null)
{
vtkPanel.lock();
try
{
// rebuild points
outline.SetPoints(points);
// changed
outline.Modified();
// delete previous points
if (previousPoints != null)
previousPoints.Delete();
}
finally
{
vtkPanel.unlock();
}
}
else
{
// rebuild points
outline.SetPoints(points);
// changed
outline.Modified();
// delete previous points
if (previousPoints != null)
previousPoints.Delete();
}
return true;
}
}