Files
wg_cpso/vtkControl/vtkControl.cs
2026-03-25 18:20:24 +08:00

7164 lines
313 KiB
C#

using CaeGlobals;
using CaeMesh;
using Kitware.VTK;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace vtkControl
{
// Delegates
public delegate vtkMaxActorData GetSurfaceEdgesActorDataFromElementIdDelegate
(int nodeIds, int[] elementIds, out string noEdgePartName);
public delegate vtkMaxActorData GetSurfaceEdgesActorDataFromNodeAndElementIdsDelegate
(int[] nodeIds, int[] elementIds, bool completelyInside, out string[] noEdgePartNames);
public delegate vtkMaxActorData GetGeometryActorDataDelegate
(double[] point, int elementId, int[] edgeNodeIds, int[] cellFaceNodeIds, out string noEdgePartName);
/// <summary>
/// UserControl derived implementation of vtkRenderWindow for use
/// in Windows Forms applications.
/// The client area of this UserControl is completely filled with
/// an instance of a vtkRenderWindow.
/// </summary>
[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public partial class vtkControl : UserControl
{
int countError;
// Variables
private bool _renderingOn;
private bool _userPick; // used to determine if the selection distance should be limited
private vtkRenderer _renderer;
private vtkRenderer _selectionRenderer;
private vtkRenderer _overlayRenderer;
private vtkRenderWindow _renderWindow;
private vtkRenderWindowInteractor _renderWindowInteractor;
private vtkLight _light1;
private vtkLight _light2;
private vtkLight _light3;
// Symbols resolution
private int _arrowTipResolution = 21;
private int _arrowShaftResolution = 15;
// Widgets
private vtkOrientationMarkerWidget _coorSys;
private vtkMaxScaleWidget _scaleWidget;
private vtkLookupTable _lookupTable;
private vtkMaxScalarBarWidget _scalarBarWidget;
private vtkMaxColorBarWidget _colorBarWidget;
private vtkMaxStatusBlockWidget _statusBlockWidget;
private vtkInteractorStyleControl _style;
private bool _drawCoorSys;
private bool _drawStatusBlock;
private vtkEdgesVisibility _edgesVisibility;
//
private vtkMaxColorSpectrum _colorSpectrum;
//
private Dictionary<string, vtkMaxTextWithArrowWidget> _arrowWidgets;
private vtkMaxTextWidget _probeWidget;
//
private Dictionary<string, vtkMaxActor> _actors;
private List<vtkMaxActor> _selectedActors;
private Dictionary<string, vtkMaxActor> _overlayActors;
private Dictionary<string, vtkMaxActor[]> _animationActors;
private vtkMaxAnimationFrameData _animationFrameData;
private bool _animationAcceleration;
private Color _primaryHighlightColor;
private Color _secondaryHighlightColor;
private double _maxSymbolSize;
private bool _drawSymbolEdges;
//
private bool _animating;
private bool _mouseIn;
//
OrderedDictionary<vtkTransform, int> _transforms;
// Section
private SectionViewData _sectionViewData;
// Selection
private vtkSelectItem _selectItem;
private vtkSelectBy _selectBy;
private vtkPropPicker _propPicker;
private vtkPointPicker _pointPicker;
private vtkCellPicker _cellPicker;
private vtkRenderedAreaPicker _areaPicker;
//
private vtkMaxActor _mouseSelectionActorCurrent;
private HashSet<int> _mouseSelectionAllIds;
private int[] _mouseSelectionCurrentIds;
//
private HashSet<string> _selectableActorsFilter;
//
private object myLock = new object();
// Camera path
private bool _drawCameraPath = false;
private List<double[]> _positions;
private List<double[]> _focalPoints;
// Properties
public bool RenderingOn
{
get { return _renderingOn; }
set
{
if (value != _renderingOn)
{
_renderingOn = value;
if (_renderingOn)
{
RenderScene();
AdjustCameraDistanceAndClipping(); // Update the scale widget after render
}
}
}
}
public bool UserPick { get { return _userPick; } set { _userPick = value; } }
public vtkEdgesVisibility EdgesVisibility
{
get { return _edgesVisibility; }
set
{
if (_edgesVisibility != value)
{
_edgesVisibility = value;
ApplyEdgesVisibilityAndBackfaceCulling();
}
}
}
public vtkSelectBy SelectBy
{
get { return _selectBy; }
set
{
if (_selectBy != value)
{
_selectBy = value;
//
switch (_selectBy)
{
// General
case vtkSelectBy.Off:
_style.RubberBandEnabled = false;
break;
case vtkSelectBy.Default:
// Mesh based
case vtkSelectBy.Node:
case vtkSelectBy.Element:
case vtkSelectBy.Part:
// Geometry
case vtkSelectBy.Geometry:
case vtkSelectBy.GeometryPart:
_style.RubberBandEnabled = true;
break;
// Mesh based
case vtkSelectBy.Id:
case vtkSelectBy.Edge:
case vtkSelectBy.Surface:
case vtkSelectBy.EdgeAngle:
case vtkSelectBy.SurfaceAngle:
// Geometry
case vtkSelectBy.GeometryVertex:
case vtkSelectBy.GeometryEdge:
case vtkSelectBy.GeometrySurface:
case vtkSelectBy.GeometryEdgeAngle:
case vtkSelectBy.GeometrySurfaceAngle:
// Query
case vtkSelectBy.QueryNode:
case vtkSelectBy.QueryElement:
case vtkSelectBy.QueryEdge:
case vtkSelectBy.QuerySurface:
case vtkSelectBy.QueryPart:
_style.RubberBandEnabled = false;
break;
// Widget
case vtkSelectBy.Widget:
_style.RubberBandEnabled = false;
break;
default:
throw new NotSupportedException();
}
ClearCurrentMouseSelection();
}
}
}
public vtkSelectItem SelectItem { get { return _selectItem; } set { if (_selectItem != value) { _selectItem = value; } } }
// Setters
public void SetSelectBy(vtkSelectBy selectBy)
{
SelectBy = selectBy;
}
public void SetAnimationAcceleration(bool animationAcceleration)
{
_animationAcceleration = animationAcceleration;
}
public void SetSelectableActorsFilter(string[] selectableActors)
{
if (selectableActors != null) _selectableActorsFilter = new HashSet<string>(selectableActors);
else _selectableActorsFilter = null;
}
// Getters
public bool IsRubberBandActive
{
get
{
vtkInteractorStyleControl style = (vtkInteractorStyleControl)(_renderWindowInteractor.GetInteractorStyle());
return style.IsRubberBandActive;
}
}
// Callbacks
public Func<string, string> Controller_GetAnnotationText;
public Func<int[], vtkMaxActorData> Controller_GetNodeActorData;
public Func<int[], int[], vtkMaxActorData> Controller_GetCellActorData;
public Func<int, int[], vtkMaxActorData> Controller_GetCellFaceActorData;
public Func<int, int[], vtkMaxActorData> Controller_GetEdgeActorData;
public GetSurfaceEdgesActorDataFromElementIdDelegate Controller_GetSurfaceEdgesActorDataFromElementId;
public GetSurfaceEdgesActorDataFromNodeAndElementIdsDelegate Controller_GetSurfaceEdgesActorDataFromNodeAndElementIds;
public Func<int[], vtkMaxActorData> Controller_GetPartActorData;
public GetGeometryActorDataDelegate Controller_GetGeometryActorData;
public Func<double[], int, int[], int[], vtkMaxActorData> Controller_GetGeometryVertexActorData;
//
public Action<MouseEventArgs, Keys, string[]> Controller_ActorsPicked;
public Action<MouseEventArgs, Keys, string, Rectangle> Form_WidgetPicked;
public Action Form_ShowColorBarSettings;
public Action Form_ShowLegendSettings;
public Action Form_ShowStatusBlockSettings;
public Action Form_EndEditArrowWidget;
// Events
public event Action<double[], double[], double[][], bool, vtkSelectOperation, string[]> OnMouseLeftButtonUpSelection;
// Constructors
public vtkControl()
{
InitializeComponent();
//
Globals.Initialize();
//
Controller_GetNodeActorData = null;
Controller_GetCellActorData = null;
//
_renderingOn = true;
_drawCoorSys = true;
_drawStatusBlock = true;
_edgesVisibility = vtkEdgesVisibility.ElementEdges;
_colorSpectrum = new vtkMaxColorSpectrum();
//
_actors = new Dictionary<string, vtkMaxActor>();
_selectedActors = new List<vtkMaxActor>();
_overlayActors = new Dictionary<string, vtkMaxActor>();
_animationActors = new Dictionary<string, vtkMaxActor[]>();
_animationFrameData = null;
_primaryHighlightColor = Color.Red;
_secondaryHighlightColor = Color.Violet;
_drawSymbolEdges = true;
//
_animating = false;
//
_transforms = new OrderedDictionary<vtkTransform, int>("Transformations");
//
_sectionViewData = new SectionViewData();
//
//SelectBy = vtkSelectBy.Default;
_selectItem = vtkSelectItem.None;
//
_propPicker = vtkPropPicker.New();
_propPicker.PickFromListOn();
_propPicker.InitializePickList();
//
_pointPicker = vtkPointPicker.New();
_pointPicker.SetTolerance(0.01);
//
_cellPicker = vtkCellPicker.New();
_cellPicker.SetTolerance(0.01);
//
_areaPicker = vtkRenderedAreaPicker.New();
_mouseSelectionActorCurrent = null;
_mouseSelectionCurrentIds = null;
_mouseSelectionAllIds = new HashSet<int>();
//
_selectableActorsFilter = null;
}
// Event handlers
private void vtkControl_Resize(object sender, EventArgs e)
{
if (_renderWindow != null) _renderWindow.Modified(); // this has to be here in order for the vtkMAx widgets to work on maximize/minimize
//if (_renderWindowInteractor != null) _renderWindowInteractor.Render();
if (_coorSys != null) SetCoorSysVisibility(_drawCoorSys);
if (_renderer != null)
{
SetAllCaptionPositions();
//float scale = vtkTextActor.GetFontScale(_renderer);
//Console.WriteLine(scale.ToString());
//int[] size = _renderer.GetSize();
//foreach (var actor in _actors)
//{
// if (actor is vtkScalarBarActor)
// {
// vtkScalarBarActor sb = (vtkScalarBarActor)actor;
// int height = 300;
// int border = 20;
// sb.SetDisplayPosition(border, size[1] - border - height);
// }
//}
}
}
private void vtkControl_Load(object sender, EventArgs e)
{
InitializeControl();
}
private void vtkControl_EnabledChanged(object sender, EventArgs e)
{
if (Enabled) SetAllCaptionPositions();
}
//
void _renderWindowInteractor_ModifiedEvt(vtkObject sender, vtkObjectEventArgs e)
{
if (_style.GetState() == vtkInteractorStyleControl.VTKIS_ROTATE && _probeWidget != null &&
_probeWidget.GetVisibility() == 1)
{
_probeWidget.VisibilityOff();
}
}
//
void style_EnterEvt(vtkObject sender, vtkObjectEventArgs e)
{
if (!_mouseIn) _mouseIn = true;
}
void style_LeaveEvt(vtkObject sender, vtkObjectEventArgs e)
{
if (_mouseIn) _mouseIn = false;
_renderWindow.SetCurrentCursor(0); // Default
}
//
private void colorBarWidget_DoubleClicked(object sender, MouseEventArgs e)
{
Form_ShowColorBarSettings?.Invoke();
}
private void scalarBarWidget_DoubleClicked(object sender, MouseEventArgs e)
{
Form_ShowLegendSettings?.Invoke();
}
private void statusBlockWidget_DoubleClicked(object sender, MouseEventArgs e)
{
Form_ShowStatusBlockSettings?.Invoke();
}
private void arrowWidget_DoubleClicked(object sender, MouseEventArgs e)
{
if (sender is vtkMaxTextWithArrowWidget aw)
{
Form_WidgetPicked(e, Keys.None, aw.GetName(), aw.GetRectangle());
}
}
// Mouse Events - Style
public void Pick(int x1, int y1, bool rubberBandSelection, int x2, int y2)
{
// Test only method
MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1, x1, y1, 0);
style_PointPickedOnLeftUpEvt(e, rubberBandSelection, x2, y2);
}
private void style_PointPickedOnMouseMoveEvt(int x1, int y1, bool rubberBandSelection, int x2, int y2)
{
try
{
// Off
if (_probeWidget == null || _selectBy == vtkSelectBy.Off) return;
else if (_selectBy == vtkSelectBy.Widget) return;
// Default selection of parts
else if (_selectBy == vtkSelectBy.Default)
{
// Area selection
if (rubberBandSelection)
{
string[] pickedActorNames = null;
PickByArea(x1, y1, x2, y2, false, out pickedActorNames);
//
MouseEventArgs e = new MouseEventArgs(MouseButtons.Left, 1, x1, y1, 0);
//
Controller_ActorsPicked?.Invoke(e, ModifierKeys, pickedActorNames.ToArray());
}
}
//
else if (rubberBandSelection)
{
ClearCurrentMouseSelection();
PickByArea(x1, y1, x2, y2, true, out string[] pickedActorNAmes);
}
else
{
vtkActor pickedActor = null;
//
ClearCurrentMouseSelection();
//
switch (_selectBy)
{
//case vtkSelectBy.Default:
case vtkSelectBy.Id:
break;
case vtkSelectBy.Node:
PickByNode(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.Element:
PickByCell(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.Edge:
PickByEdge(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.Surface:
PickBySurface(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.EdgeAngle:
PickByEdgeAngle(out pickedActor, x1, y1);
break;
case vtkSelectBy.SurfaceAngle:
PickBySurfaceAngle(out pickedActor, x1, y1);
break;
case vtkSelectBy.Part:
PickByActor(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.Geometry:
PickByGeometry(out pickedActor, x1, y1);
break;
case vtkSelectBy.GeometryVertex:
PickByGeometryVertex(out pickedActor, x1, y1);
break;
case vtkSelectBy.GeometryEdge:
PickByEdge(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.GeometrySurface:
PickBySurface(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.GeometryEdgeAngle:
PickByGeometryEdgeAngle(out pickedActor, x1, y1);
break;
case vtkSelectBy.GeometrySurfaceAngle:
PickBySurface(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.GeometryPart:
PickByActor(out pickedActor, x1, y1, false);
break;
case vtkSelectBy.QueryNode:
PickByNode(out pickedActor, x1, y1, true);
break;
case vtkSelectBy.QueryElement:
PickByCell(out pickedActor, x1, y1, true);
break;
case vtkSelectBy.QueryEdge:
PickByEdge(out pickedActor, x1, y1, true);
break;
case vtkSelectBy.QuerySurface:
PickBySurface(out pickedActor, x1, y1, true);
break;
case vtkSelectBy.QueryPart:
PickByActor(out pickedActor, x1, y1, true);
break;
default:
throw new NotSupportedException();
}
//
if (pickedActor == null) ClearCurrentMouseSelection();
}
}
catch { }
}
private void style_PointPickedOnLeftUpEvt(MouseEventArgs mea, bool rubberBandSelection, int x2, int y2)
{
string[] pickedActorNames = null;
// Off
if (_selectBy == vtkSelectBy.Off) return;
else if (_selectBy == vtkSelectBy.Widget)
{
if (mea.Clicks == 1) Form_EndEditArrowWidget?.Invoke();
}
// Default selection of parts during normal use
else if (_selectBy == vtkSelectBy.Default)
{
// Point selection
if (!rubberBandSelection)
{
vtkActor pickedActor;
GetPickPoint(out pickedActor, mea.Location.X, mea.Location.Y);
pickedActorNames = new string[] { GetActorName(pickedActor) };
}
// Area selection
else
{
PickByArea(mea.Location.X, mea.Location.Y, x2, y2, false, out pickedActorNames);
}
//
Controller_ActorsPicked?.Invoke(mea, ModifierKeys, pickedActorNames.ToArray());
}
else
{
vtkSelectOperation selectOperation;
if (Control.ModifierKeys == (Keys.Shift | Keys.Control)) selectOperation = vtkSelectOperation.Intersect;
else if (Control.ModifierKeys == Keys.Shift) selectOperation = vtkSelectOperation.Add;
else if (Control.ModifierKeys == Keys.Control) selectOperation = vtkSelectOperation.Subtract;
else selectOperation = vtkSelectOperation.None;
//
vtkActor pickedActor = null;
bool completelyInside = mea.Location.X > x2;
// Point selection
if (!rubberBandSelection)
{
double[] pickedPoint = GetPickPoint(out pickedActor, mea.Location.X, mea.Location.Y);
double[] direction = _renderer.GetActiveCamera().GetDirectionOfProjection();
pickedActorNames = new string[] { GetActorName(pickedActor) };
OnMouseLeftButtonUpSelection?.Invoke(pickedPoint, direction, null, completelyInside,
selectOperation, pickedActorNames);
}
// Area selection
else
{
PickByArea(mea.Location.X, mea.Location.Y, x2, y2, false, out pickedActorNames);
vtkPlanes planes = _areaPicker.GetFrustum();
vtkPlane plane;
double[] origin;
double[] normal;
double[][] planeParameters = new double[planes.GetNumberOfPlanes()][];
//
for (int i = 0; i < planes.GetNumberOfPlanes(); i++)
{
plane = planes.GetPlane(i);
origin = plane.GetOrigin();
normal = plane.GetNormal();
planeParameters[i] = new double[] { origin[0], origin[1], origin[2], normal[0], normal[1], normal[2] };
}
//
OnMouseLeftButtonUpSelection?.Invoke(null, null, planeParameters, completelyInside,
selectOperation, pickedActorNames);
}
}
}
private void style_RightButtonPressEvent(object sender, MouseEventArgs e)
{
// Off
if (_selectBy == vtkSelectBy.Off) return;
else if (_selectBy == vtkSelectBy.Widget) return;
//
if (sender != null && sender is vtkMaxTextWithArrowWidget widget)
{
Form_WidgetPicked(e, Keys.None, widget.GetName(), widget.GetRectangle());
}
else
{
vtkActor pickedActor;
GetPickPoint(out pickedActor, e.Location.X, e.Location.Y);
//
if (pickedActor != null)
{
Controller_ActorsPicked?.Invoke(e, ModifierKeys, new string[] { GetActorName(pickedActor) });
}
}
}
private void style_ZoomChangedEvent()
{
SetAllCaptionPositions();
}
#region Selection #########################################################################################################
// On mouse move selection
private void PickByNode(out vtkActor pickedActor, int x, int y, bool showLabel)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
int globalPointId = GetNodeIdOnCellFaceClosestToPoint(pickedPoint);
_mouseSelectionCurrentIds = new int[] { globalPointId };
//
vtkMaxActorData data = Controller_GetNodeActorData(_mouseSelectionCurrentIds);
_mouseSelectionActorCurrent = new vtkMaxActor(data, true, true);
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if (showLabel)
{
// Probe widget
_renderer.SetWorldPoint(pickedPoint[0], pickedPoint[1], pickedPoint[2], 1.0);
_renderer.WorldToDisplay();
double[] display = _renderer.GetDisplayPoint();
double w = x + 20d;
double h = y + 10d;
//
_probeWidget.SetPosition(w, h);
_probeWidget.SetText(Controller_GetAnnotationText(globalPointId.ToString()));
//
if (_probeWidget.GetVisibility() == 0) _probeWidget.VisibilityOn();
}
}
private void PickByCell(out vtkActor pickedActor, int x, int y, bool showLabel)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCell cell;
vtkCellLocator cellLocator;
string actorName = GetActorName(pickedActor);
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
//
_mouseSelectionCurrentIds = new int[] { globalCellId };
//
vtkMaxActorData actorData = Controller_GetCellActorData(_mouseSelectionCurrentIds, null);
//
vtkMaxActor actor = new vtkMaxActor(actorData, true, false);
actor.GeometryMapper.GetInput().GetPointData().RemoveArray(Globals.ScalarArrayName);
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if (actor.ElementEdges != null)
{
AddActorEdges(_mouseSelectionActorCurrent, false, vtkRendererLayer.Selection);
_selectedActors.Remove(_mouseSelectionActorCurrent);
}
//
if (showLabel)
{
// Probe widget
double w = x + 20;
double h = y + 10;
//
_probeWidget.SetPosition(w, h);
_probeWidget.SetText(Controller_GetAnnotationText(globalCellId.ToString()));
//
if (_probeWidget.GetVisibility() == 0) _probeWidget.VisibilityOn();
}
}
private void PickByEdge(out vtkActor pickedActor, int x, int y, bool showLabel)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCell cell;
vtkCellLocator cellLocator;
int globalPointId = GetNodeIdOnCellFaceClosestToPoint(pickedPoint);
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
vtkMaxActorData cellFaceData = Controller_GetCellFaceActorData(globalCellId, globalCellFaceNodeIds); // works on undeformed mesh
//
int[] nodeIds;
double[][] nodeCoor;
int[] edgeCell;
int edgeCellType;
GetClosestEdgeCell(pickedPoint, cellFaceData, out nodeIds, out nodeCoor, out edgeCell, out edgeCellType);
//
vtkMaxActorData actorData = Controller_GetEdgeActorData(globalCellId, nodeIds);
//
if (actorData != null)
{
vtkMaxActor actor = new vtkMaxActor(actorData);
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if (showLabel)
{
// Probe widget
_renderer.SetWorldPoint(pickedPoint[0], pickedPoint[1], pickedPoint[2], 1.0);
_renderer.WorldToDisplay();
double[] display = _renderer.GetDisplayPoint();
//
double w = x + 20d;
double h = y + 10d;
//
_probeWidget.SetPosition(w, h);
_probeWidget.SetText(Controller_GetAnnotationText(actorData.Name));
//
if (_probeWidget.GetVisibility() == 0) _probeWidget.VisibilityOn();
}
}
}
private void PickByEdgeAngle(out vtkActor pickedActor, int x, int y)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCell cell;
vtkCellLocator cellLocator;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
// Works on deformed mesh
vtkMaxActorData cellFaceData = Controller_GetCellFaceActorData(globalCellId, globalCellFaceNodeIds);
//
double[][] nodeCoor;
int[] edgeCell;
int edgeCellType;
GetClosestEdgeCell(pickedPoint, cellFaceData, out _, out nodeCoor, out edgeCell, out edgeCellType);
//
vtkPoints p = vtkPoints.New();
for (int i = 0; i < nodeCoor.Length; i++)
{
p.InsertNextPoint(nodeCoor[i][0], nodeCoor[i][1], nodeCoor[i][2]);
}
vtkUnstructuredGrid grid = vtkUnstructuredGrid.New();
grid.SetPoints(p);
//
vtkIdList pointIds = vtkIdList.New();
for (int i = 0; i < edgeCell.Length; i++) // renumber
{
pointIds.InsertNextId(edgeCell[i]);
}
grid.InsertNextCell(edgeCellType, pointIds);
grid.Update(); // must create a new grid, not only grid from cell . is not drawn for some zoom values ???
//
vtkMaxActor actor = new vtkMaxActor(grid);
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
}
private void GetClosestEdgeCell(double[] pickedPoint, vtkMaxActorData cellFaceData, out int[] nodeIds,
out double[][] nodeCoor, out int[] edgeCell, out int edgeCellType)
{
nodeIds = null;
nodeCoor = null;
edgeCell = null;
edgeCellType = -1;
if (cellFaceData == null) return;
//
double[][] allNodeCoor = cellFaceData.Geometry.Nodes.Coor;
int[] allNodeIds = cellFaceData.Geometry.Nodes.Ids;
//
int[][] cellEdges = GetVisualizationCellEdges(cellFaceData.Geometry.Nodes.Ids.Length);
//
double[] d = new double[cellEdges.Length];
for (int i = 0; i < cellEdges.Length; i++)
{
if (cellEdges[i].Length == 2) // linear edge
{
d[i] = PointToLineSegmentDistance(pickedPoint, allNodeCoor[cellEdges[i][0]], allNodeCoor[cellEdges[i][1]]);
}
else if (cellEdges[i].Length == 3) // parabolic edge
{
d[i] = Math.Min(PointToLineSegmentDistance(pickedPoint, allNodeCoor[cellEdges[i][0]], allNodeCoor[cellEdges[i][1]]),
PointToLineSegmentDistance(pickedPoint, allNodeCoor[cellEdges[i][1]], allNodeCoor[cellEdges[i][2]]));
}
}
//
double min = d[0];
int minId = 0;
for (int i = 1; i < d.Length; i++)
{
if (d[i] < min)
{
min = d[i];
minId = i;
}
}
//
int numOfNodes = cellEdges[minId].Length;
nodeIds = new int[numOfNodes];
nodeCoor = new double[numOfNodes][];
for (int i = 0; i < nodeIds.Length; i++)
{
nodeIds[i] = allNodeIds[cellEdges[minId][i]];
nodeCoor[i] = allNodeCoor[cellEdges[minId][i]];
}
if (numOfNodes == 2)
{
edgeCell = new int[] { 0, 1 };
edgeCellType = (int)vtkCellType.VTK_LINE;
}
else if (numOfNodes == 3)
{
edgeCell = new int[] { 0, 2, 1 };
edgeCellType = (int)vtkCellType.VTK_QUADRATIC_EDGE;
}
else throw new NotSupportedException();
// Swap edge node ids and coor so that first node is the closest
double[] firstCoor = allNodeCoor[cellEdges[minId].First()];
double[] lastCoor = allNodeCoor[cellEdges[minId].Last()];
//
double d1 = Math.Pow(pickedPoint[0] - firstCoor[0], 2) +
Math.Pow(pickedPoint[1] - firstCoor[1], 2) +
Math.Pow(pickedPoint[2] - firstCoor[2], 2);
//
double d2 = Math.Pow(pickedPoint[0] - lastCoor[0], 2) +
Math.Pow(pickedPoint[1] - lastCoor[1], 2) +
Math.Pow(pickedPoint[2] - lastCoor[2], 2);
//
bool swap = d2 < d1;
int tmpId;
double[] tmpCoor;
//
if (swap)
{
tmpId = nodeIds[0];
nodeIds[0] = nodeIds[numOfNodes - 1];
nodeIds[numOfNodes - 1] = tmpId;
//
tmpCoor = nodeCoor[0];
nodeCoor[0] = nodeCoor[numOfNodes - 1];
nodeCoor[numOfNodes - 1] = tmpCoor;
}
}
public int[][] GetVisualizationCellEdges(int numOfNodes)
{
// lookup - leave here for future searches
int[] nodeIds = Enumerable.Range(0, numOfNodes).ToArray();
if (nodeIds.Length == 3)
{
return new int[][] { new int[] { nodeIds[0], nodeIds[1] },
new int[] { nodeIds[1], nodeIds[2] },
new int[] { nodeIds[2], nodeIds[0] } };
}
else if (nodeIds.Length == 4)
{
return new int[][] { new int[] { nodeIds[0], nodeIds[1] },
new int[] { nodeIds[1], nodeIds[2] },
new int[] { nodeIds[2], nodeIds[3] },
new int[] { nodeIds[3], nodeIds[0] } };
}
else if (nodeIds.Length == 6)
{
return new int[][] { new int[] { nodeIds[0], nodeIds[3], nodeIds[1] },
new int[] { nodeIds[1], nodeIds[4], nodeIds[2] },
new int[] { nodeIds[2], nodeIds[5], nodeIds[0] } };
}
else if (nodeIds.Length == 8)
{
return new int[][] { new int[] { nodeIds[0], nodeIds[4], nodeIds[1] },
new int[] { nodeIds[1], nodeIds[5], nodeIds[2] },
new int[] { nodeIds[2], nodeIds[6], nodeIds[3] },
new int[] { nodeIds[3], nodeIds[7], nodeIds[0] } };
}
else throw new NotSupportedException();
}
private double PointToLineSegmentDistance(double[] p, double[] l1, double[] l2)
{
double[] n = new double[] { l2[0] - l1[0], l2[1] - l1[1], l2[2] - l1[2] };
double d = Math.Sqrt(Math.Pow(n[0], 2) + Math.Pow(n[1], 2) + Math.Pow(n[2], 2));
if (d <= 0) return 0;
// normalize
n[0] /= d;
n[1] /= d;
n[2] /= d;
double[] a = new double[] { p[0] - l1[0], p[1] - l1[1], p[2] - l1[2] };
double aProj = a[0] * n[0] + a[1] * n[1] + a[2] * n[2];
if (aProj <= 0)
{
d = Math.Sqrt(Math.Pow(a[0], 2) + Math.Pow(a[1], 2) + Math.Pow(a[2], 2));
return d;
}
else if (aProj >= d)
{
double[] b = new double[] { l2[0] - p[0], l2[1] - p[1], l2[2] - p[2] };
d = Math.Sqrt(Math.Pow(b[0], 2) + Math.Pow(b[1], 2) + Math.Pow(b[2], 2));
return d;
}
else
{
double[] c = new double[] { a[0] - aProj * n[0], a[1] - aProj * n[1], a[2] - aProj * n[2] };
d = Math.Sqrt(Math.Pow(c[0], 2) + Math.Pow(c[1], 2) + Math.Pow(c[2], 2));
return d;
}
}
private void PickBySurface(out vtkActor pickedActor, int x, int y, bool showLabel)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCellLocator cellLocator;
vtkCell cell;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
//
string noEdgePartName;
vtkMaxActor actor = null;
vtkMaxActorData actorData = Controller_GetSurfaceEdgesActorDataFromElementId(globalCellId, globalCellFaceNodeIds,
out noEdgePartName);
if (actorData != null)
{
actorData.CanHaveElementEdges = true;
actor = new vtkMaxActor(actorData);
}
else if (noEdgePartName != null)
{
actor = GetHighlightActorFromActorName(noEdgePartName);
}
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if (showLabel)
{
// Probe widget
_renderer.SetWorldPoint(pickedPoint[0], pickedPoint[1], pickedPoint[2], 1.0);
_renderer.WorldToDisplay();
//
double w = x + 20d;
double h = y + 10d;
//
_probeWidget.SetPosition(w, h);
_probeWidget.SetText(Controller_GetAnnotationText(actorData.Name));
//
if (_probeWidget.GetVisibility() == 0) _probeWidget.VisibilityOn();
}
}
private void PickBySurfaceAngle(out vtkActor pickedActor, int x, int y)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
vtkCell cell;
vtkCellLocator cellLocator;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
vtkMaxActorData data = Controller_GetCellFaceActorData(globalCellId, globalCellFaceNodeIds); // works on undeformed mesh
vtkMaxActor actor = new vtkMaxActor(data);
_mouseSelectionActorCurrent = actor;
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
if (actor.ElementEdges != null)
{
AddActorEdges(_mouseSelectionActorCurrent, false, vtkRendererLayer.Selection);
_selectedActors.Remove(_mouseSelectionActorCurrent);
}
}
private void PickByActor(out vtkActor pickedActor, int x, int y, bool showLabel)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCellLocator cellLocator;
vtkCell cell;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
//
string actorName = GetActorName(pickedActor);
vtkMaxActor actor = GetHighlightActorFromActorName(actorName);
//
if (actor != null)
{
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if (actor.ElementEdges != null)
{
AddActorEdges(_mouseSelectionActorCurrent, false, vtkRendererLayer.Selection);
_selectedActors.Remove(_mouseSelectionActorCurrent);
}
//
if (showLabel)
{
// Probe widget
_renderer.SetWorldPoint(pickedPoint[0], pickedPoint[1], pickedPoint[2], 1.0);
_renderer.WorldToDisplay();
//
double w = x + 20d;
double h = y + 10d;
//
_probeWidget.SetPosition(w, h);
_probeWidget.SetText(Controller_GetAnnotationText(actorName));
//
if (_probeWidget.GetVisibility() == 0) _probeWidget.VisibilityOn();
}
}
}
private void PickByGeometry(out vtkActor pickedActor, int x, int y)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
//
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCellLocator cellLocator;
vtkCell cell;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellEdgeNodeIds = GetEdgeNodeIds(pickedPoint, globalCellId, cell, cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
//double distance = GetSelectionPrecision();
//
string noEdgePartName;
vtkMaxActorData actorData = Controller_GetGeometryActorData(pickedPoint,
globalCellId,
globalCellEdgeNodeIds,
globalCellFaceNodeIds,
out noEdgePartName);
//
if (actorData != null)
{
if (actorData.Geometry.Nodes.Coor.Length == 1)
{
// Nodal actor data
_mouseSelectionActorCurrent = new vtkMaxActor(actorData, false, true);
}
else
{
// Edge or surface actor data
actorData.CanHaveElementEdges = true;
_mouseSelectionActorCurrent = new vtkMaxActor(actorData);
}
}
else if (noEdgePartName != null)
{
_mouseSelectionActorCurrent = GetHighlightActorFromActorName(noEdgePartName);
}
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
}
private void PickByGeometryVertex(out vtkActor pickedActor, int x, int y)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
//
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCellLocator cellLocator;
vtkCell cell;
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellEdgeNodeIds = GetEdgeNodeIds(pickedPoint, globalCellId, cell, cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
//double distance = GetSelectionPrecision();
//
vtkMaxActorData actorData = Controller_GetGeometryVertexActorData(pickedPoint,
globalCellId,
globalCellEdgeNodeIds,
globalCellFaceNodeIds);
if (actorData != null)
{
_mouseSelectionActorCurrent = new vtkMaxActor(actorData, false, true);
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
}
}
private void PickByGeometryEdgeAngle(out vtkActor pickedActor, int x, int y)
{
double[] pickedPoint = GetPickPoint(out pickedActor, x, y);
if (pickedPoint == null)
{
if (_probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
return;
}
//
vtkCell cell;
vtkCellLocator cellLocator;
int globalPointId = GetNodeIdOnCellFaceClosestToPoint(pickedPoint);
int globalCellId = GetGlobalCellIdClosestTo3DPoint(ref pickedPoint, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
// Works on deformed mesh
vtkMaxActorData cellFaceData = Controller_GetCellFaceActorData(globalCellId, globalCellFaceNodeIds);
//
int[] nodeIds;
GetClosestEdgeCell(pickedPoint, cellFaceData, out nodeIds, out _, out _, out _);
//
vtkMaxActorData edgeData = Controller_GetEdgeActorData(globalCellId, nodeIds);
//
if (edgeData != null)
{
vtkMaxActor actor = new vtkMaxActor(edgeData);
_mouseSelectionActorCurrent = actor;
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
}
}
//
private void PickByArea(int x1, int y1, int x2, int y2, bool highlight, out string[] pickedActorNames)
{
_areaPicker.AreaPick(x1, y1, x2, y2, _renderer);
vtkPlanes planes = _areaPicker.GetFrustum();
//
List<string> selectedActorNames = new List<string>();
HashSet<int> selectedPointGlobalIds = new HashSet<int>();
HashSet<int> selectedCellGlobalIds = new HashSet<int>();
vtkActor pickedActor;
vtkProp3DCollection pickedActors = _areaPicker.GetProp3Ds();
//
pickedActors.InitTraversal();
pickedActor = (vtkActor)pickedActors.GetNextProp3D();
//
vtkCellLocator locator;
vtkExtractSelectedFrustum extractor;
//
while (pickedActor != null)
{
string pickedActorName = GetActorName(pickedActor);
vtkMaxActor maxActor;
//
if (pickedActorName == null ||
!(_actors.TryGetValue(pickedActorName, out maxActor) && maxActor.FrustumCellLocator != null))
{
// Actor has no locator
}
else
{
// Actors
selectedActorNames.Add(pickedActorName);
//
locator = maxActor.FrustumCellLocator;
// Points
extractor = vtkExtractSelectedFrustum.New(); // must be inside the loop
extractor.SetFieldType((int)vtkSelectionField.POINT);
extractor.SetContainingCells(0);
extractor.SetInput(0, locator.GetDataSet());
extractor.SetFrustum(planes);
extractor.Update();
//
vtkUnstructuredGrid selected = vtkUnstructuredGrid.New();
selected.ShallowCopy(extractor.GetOutput());
//
vtkDataArray globalPointIds = selected.GetPointData().GetGlobalIds();
if (globalPointIds == null) // skip actor
{
pickedActor = (vtkActor)pickedActors.GetNextProp3D();
continue;
}
else
{
if (highlight)
{
for (int i = 0; i < globalPointIds.GetNumberOfTuples(); i++)
{
selectedPointGlobalIds.Add((int)globalPointIds.GetTuple1(i));
}
}
}
// Cells
extractor.SetFieldType((int)vtkSelectionField.CELL);
extractor.Update();
//
selected = vtkUnstructuredGrid.New();
selected.ShallowCopy(extractor.GetOutput());
//
vtkDataArray globalCellIds = selected.GetCellData().GetGlobalIds();
if (globalCellIds == null) // skip actor
{
pickedActor = (vtkActor)pickedActors.GetNextProp3D();
continue;
}
else
{
if (highlight)
{
for (int i = 0; i < globalCellIds.GetNumberOfTuples(); i++)
{
selectedCellGlobalIds.Add((int)globalCellIds.GetTuple1(i));
}
}
}
}
pickedActor = (vtkActor)pickedActors.GetNextProp3D();
}
//
pickedActorNames = selectedActorNames.ToArray();
//
// Graphics
bool completelyInside = x1 > x2;
if (highlight)
{
int[] pointIds = new int[selectedPointGlobalIds.Count];
selectedPointGlobalIds.CopyTo(pointIds);
//
vtkMaxActorData data = null;
if (_selectBy == vtkSelectBy.Node)
{
if (pointIds.Length <= 0) return;
//
data = Controller_GetNodeActorData(pointIds);
//
_mouseSelectionCurrentIds = pointIds;
_mouseSelectionActorCurrent = new vtkMaxActor(data, true, true);
}
else if (_selectBy == vtkSelectBy.Element)
{
if (selectedCellGlobalIds.Count <= 0) return;
//
int[] cellIds = new int[selectedCellGlobalIds.Count];
selectedCellGlobalIds.CopyTo(cellIds);
//
if (_selectItem == vtkSelectItem.Element && _selectBy == vtkSelectBy.Node)
data = Controller_GetCellActorData(cellIds, null);
else data = Controller_GetCellActorData(cellIds, pointIds);
//
_mouseSelectionCurrentIds = data.Geometry.Cells.Ids;
_mouseSelectionActorCurrent = new vtkMaxActor(data, true, false);
}
else if (_selectBy == vtkSelectBy.Part || _selectBy == vtkSelectBy.GeometryPart)
{
_mouseSelectionActorCurrent = GetAppendedActor(pickedActorNames, GetHighlightActorFromActorName);
//
if (_mouseSelectionActorCurrent == null) return;
}
else if (_selectBy == vtkSelectBy.Geometry)
{
int[] cellIds = new int[selectedCellGlobalIds.Count];
selectedCellGlobalIds.CopyTo(cellIds);
//
string[] noEdgePartNames;
vtkMaxActorData actorData = Controller_GetSurfaceEdgesActorDataFromNodeAndElementIds(pointIds, cellIds,
completelyInside,
out noEdgePartNames);
actorData.CanHaveElementEdges = true;
// Append actors
vtkMaxActor actor = new vtkMaxActor(actorData);
if (noEdgePartNames != null && noEdgePartNames.Length > 0)
{
vtkMaxActor noEdgeActor = GetAppendedActor(noEdgePartNames, GetHighlightActorFromActorName);
actor = GetAppendedActor(actor, noEdgeActor);
}
_mouseSelectionActorCurrent = actor;
}
else throw new NotSupportedException();
//
AddActorGeometry(_mouseSelectionActorCurrent, vtkRendererLayer.Selection);
_mouseSelectionActorCurrent.Geometry.SetProperty(Globals.CurrentMouseSelectionProperty);
//
if ((_selectBy == vtkSelectBy.Element || _selectBy == vtkSelectBy.Part)
&& _mouseSelectionActorCurrent.ElementEdges != null)
{
AddActorEdges(_mouseSelectionActorCurrent, false, vtkRendererLayer.Selection);
_selectedActors.Remove(_mouseSelectionActorCurrent);
}
}
}
private void PickAreaHardware(int x1, int y1, int x2, int y2)
{
vtkHardwareSelector selector = vtkHardwareSelector.New();
selector.SetFieldAssociation((int)vtkFieldAssociations.FIELD_ASSOCIATION_CELLS);
selector.SetRenderer(_renderer);
selector.SetArea((uint)x1, (uint)y1, (uint)x2, (uint)y2);
//static_cast<unsigned int>(this.Renderer.GetPickX1()),
//static_cast<unsigned int>(this.Renderer.GetPickY1()),
//static_cast<unsigned int>(this.Renderer.GetPickX2()),
//static_cast<unsigned int>(this.Renderer.GetPickY2()));
// Make the actual pick and pass the result to the convenience function
// defined earlier
_renderer.Render();
vtkSelection result = selector.Select();
uint numNodes = result.GetNumberOfNodes();
vtkSelectionNode node;
vtkDataSetAttributes fd1;
vtkIdTypeArray fd1_array;
for (uint i = 0; i < numNodes; i++)
{
node = result.GetNode(i);
//vtkIdTypeArray selIds = (vtkIdTypeArray)node.GetSelectionList();
fd1 = node.GetSelectionData();
if (fd1.GetNumberOfArrays() != 1) return;
if (fd1.GetArray(0).GetDataType() != 12) return; // 12 ... VTK_ID_TYPE
fd1_array = (vtkIdTypeArray)fd1.GetArray(0);
long fd1_N = fd1_array.GetNumberOfTuples();
List<long> fd1_list = new List<long>();
for (int j = 0; j < fd1_N; j++) fd1_list.Add(fd1_array.GetValue(j));
}
}
private double[] GetPickPoint(out vtkActor pickedActor, int x, int y)
{
pickedActor = null;
if (_style.IsPositionOverWidget(x, y)) return null;
//
double[] p = null;
int cellId = -1;
vtkCell cell;
vtkCellLocator locator;
// Make all actors visible
foreach (var entry in _actors)
{
//if (entry.Value.Pickable)
{
if (_selectableActorsFilter != null)
{
// Change the visibility of geometry only to enable reset
if (_selectableActorsFilter.Contains(entry.Value.Name)) entry.Value.Geometry.VisibilityOn();
else entry.Value.Geometry.VisibilityOff();
}
// Set opacity for all visible actors to 1
if (entry.Value.GeometryProperty.GetOpacity() != 1) entry.Value.GeometryProperty.SetOpacity(1);
}
}
// Pick actor by hardware rendering - render the scene before Pick
//_overlayRenderer.Render();
//_propPicker.Pick(x, y, 0, _overlayRenderer);
//pickedActor = _propPicker.GetActor();
//
_renderer.Render();
_propPicker.Pick(x, y, 0, _renderer);
pickedActor = _propPicker.GetActor();
// First pick
if (pickedActor != null)
{
p = _propPicker.GetPickPosition(); // this function sometimes gives strange values
cellId = GetGlobalCellIdClosestTo3DPoint(ref p, out _, out _);
}
// Try some more picks
if (cellId == -1)
{
int numOfLoops = 0;
int stepSize = 5;
//
for (int i = 1; i <= numOfLoops; i++) // try in a cross shape
{
_propPicker.Pick(x + i * stepSize, y, 0, _renderer);
pickedActor = _propPicker.GetActor();
if (pickedActor != null)
{
p = _propPicker.GetPickPosition(); // this function sometimes gives strange values
cellId = GetGlobalCellIdClosestTo3DPoint(ref p, out _, out _);
if (cellId != -1) break;
}
//
_propPicker.Pick(x - i * stepSize, y, 0, _renderer);
pickedActor = _propPicker.GetActor();
if (pickedActor != null)
{
p = _propPicker.GetPickPosition(); // this function sometimes gives strange values
cellId = GetGlobalCellIdClosestTo3DPoint(ref p, out _, out _);
if (cellId != -1) break;
}
//
_propPicker.Pick(x, y + i * stepSize, 0, _renderer);
pickedActor = _propPicker.GetActor();
if (pickedActor != null)
{
p = _propPicker.GetPickPosition(); // this function sometimes gives strange values
cellId = GetGlobalCellIdClosestTo3DPoint(ref p, out _, out _);
if (cellId != -1) break;
}
//
_propPicker.Pick(x, y - i * stepSize, 0, _renderer);
pickedActor = _propPicker.GetActor();
if (pickedActor != null)
{
p = _propPicker.GetPickPosition(); // this function sometimes gives strange values
cellId = GetGlobalCellIdClosestTo3DPoint(ref p, out _, out _);
if (cellId != -1) break;
}
}
}
// Reset the actor visibility
foreach (var entry in _actors)
{
//if (entry.Value.Pickable)
{
entry.Value.UpdateColor();
ApplyEdgeVisibilityAndBackfaceCullingToActor(entry.Value.Geometry, entry.Value.GeometryProperty,
vtkRendererLayer.Base);
}
}
//
if (cellId == -1)
{
p = null;
pickedActor = null;
}
//
return p;
}
// Item selection - Point
private int GetGlobalCellIdClosestTo3DPoint(ref double[] point, out vtkCell cell, out vtkCellLocator cellLocator)
{
// a 3D point is saved in history and used for regenerate
cell = null;
cellLocator = null;
//
IntPtr x = Marshal.AllocHGlobal(3 * 8);
Marshal.Copy(point, 0, x, 3);
//
IntPtr closestPoint = Marshal.AllocHGlobal(3 * 8);
//
int globalCellId = -1;
double minDistance = double.MaxValue;
long localCellId = -1;
int subId = -1;
double distance2 = -1;
double[] pointOut = new double[3];
vtkCellLocator locator;
//
foreach (var entry in _actors)
{
// Set filtered actors
if (_selectableActorsFilter != null)
{
if (_selectableActorsFilter.Contains(entry.Value.Name)) entry.Value.Geometry.VisibilityOn();
else entry.Value.Geometry.VisibilityOff();
}
// Skip invisible actors
if (entry.Value.Geometry.GetVisibility() != 0)
{
locator = entry.Value.CellLocator;
if (locator != null)
{
locator.FindClosestPoint(x, closestPoint, ref localCellId, ref subId, ref distance2);
// Error: distance2 can be -1 if something in locator is not properly defined
if (distance2 >= 0 && distance2 < minDistance)
{
minDistance = distance2;
cellLocator = locator;
cell = locator.GetDataSet().GetCell(localCellId);
globalCellId = (int)locator.GetDataSet().GetCellData().GetGlobalIds().GetTuple1(localCellId);
//
Marshal.Copy(closestPoint, pointOut, 0, 3);
}
}
}
// Reset visibility
ApplyEdgeVisibilityAndBackfaceCullingToActor(entry.Value.Geometry, entry.Value.GeometryProperty,
vtkRendererLayer.Base);
if (minDistance == 0) break;
}
//
Marshal.FreeHGlobal(x);
Marshal.FreeHGlobal(closestPoint);
//
double maxErrorDistance2;
if (_renderingOn) // user mouse interaction
maxErrorDistance2 = Math.Pow(GetSelectionPrecision(), 2);
else // regeneration - the distance to the closest item if items changed
maxErrorDistance2 = double.MaxValue;
//
if (!_userPick) maxErrorDistance2 = double.MaxValue; // must be in a separate if
//
if (minDistance > maxErrorDistance2) return -1;
else
{
point = pointOut;
return globalCellId;
}
}
private int[] GetEdgeNodeIds(double[] point, int globalCellId, vtkCell cell, vtkCellLocator cellLocator)
{
// Cell face
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
vtkMaxActorData cellFaceData = Controller_GetCellFaceActorData(globalCellId, globalCellFaceNodeIds); // works on undeformed mesh
// Closest edge cell
int[] nodeIds;
GetClosestEdgeCell(point, cellFaceData, out nodeIds, out _, out _, out _);
//
return nodeIds;
}
private int[] GetCellFaceNodeIds(vtkCell cell, vtkCellLocator cellLocator)
{
vtkDataArray globalIds = cellLocator.GetDataSet().GetPointData().GetGlobalIds();
//
int[] faceGlobalNodeIds = new int[cell.GetPointIds().GetNumberOfIds()];
for (int i = 0; i < faceGlobalNodeIds.Length; i++)
{
faceGlobalNodeIds[i] = (int)globalIds.GetTuple1(cell.GetPointId(i));
}
//
return faceGlobalNodeIds;
}
private int GetNodeIdOnCellFaceClosestToPoint(double[] point)
{
vtkCell cell;
vtkCellLocator cellLocator;
GetGlobalCellIdClosestTo3DPoint(ref point, out cell, out cellLocator);
int[] globalCellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
double[][] coor = GetCellFaceNodeCoor(cell);
double distance;
double minDistance = double.MaxValue;
int minId = -1;
for (int i = 0; i < coor.Length; i++)
{
distance = Math.Pow(coor[i][0] - point[0], 2) + Math.Pow(coor[i][1] - point[1], 2) +
Math.Pow(coor[i][2] - point[2], 2);
if (distance < minDistance)
{
minDistance = distance;
minId = i;
}
}
int globalPointId = globalCellFaceNodeIds[minId];
return globalPointId;
}
private double[][] GetCellFaceNodeCoor(vtkCell cell)
{
vtkPoints points = cell.GetPoints();
double[][] coor = new double[points.GetNumberOfPoints()][];
for (int i = 0; i < coor.Length; i++)
{
coor[i] = points.GetPoint(i);
}
return coor;
}
public void GetGeometryPickProperties(double[] point, out int elementId, out int[] edgeNodeIds, out int[] cellFaceNodeIds)
{
// Turn rendering off in order to
vtkCellLocator cellLocator;
vtkCell cell;
elementId = GetGlobalCellIdClosestTo3DPoint(ref point, out cell, out cellLocator);
edgeNodeIds = GetEdgeNodeIds(point, elementId, cell, cellLocator);
cellFaceNodeIds = GetCellFaceNodeIds(cell, cellLocator);
}
public double GetSelectionPrecision()
{
return vtkInteractorStyleControl.DisplayToWorldScale(_renderer, 7);
}
// Item selection - Frustum
public void GetPointAndCellIdsInsideFrustum(double[][] planeParameters, out int[] pointIds, out int[] cellIds)
{
vtkDataArray normals = vtkDoubleArray.New();
normals.SetNumberOfComponents(3);
vtkPoints points = vtkPoints.New();
//
for (int i = 0; i < planeParameters.Length; i++)
{
normals.InsertNextTuple3(planeParameters[i][3], planeParameters[i][4], planeParameters[i][5]);
points.InsertNextPoint(planeParameters[i][0], planeParameters[i][1], planeParameters[i][2]);
}
//
vtkPlanes planes = vtkPlanes.New();
planes.SetPoints(points);
planes.SetNormals(normals);
//
pointIds = new int[0];
cellIds = new int[0];
//
vtkExtractSelectedFrustum extractor;
vtkDataArray globalPointIdsDataArray;
vtkDataArray globalCellIdsDataArray;
HashSet<int> globalPointIds = new HashSet<int>();
HashSet<int> globalCellIds = new HashSet<int>();
vtkCellLocator locator;
//
foreach (var entry in _actors)
{
// Set filtered actors
if (_selectableActorsFilter != null)
{
if (_selectableActorsFilter.Contains(entry.Value.Name)) entry.Value.Geometry.VisibilityOn();
else entry.Value.Geometry.VisibilityOff();
}
// Skip invisible actors
if (entry.Value.Geometry.GetVisibility() != 0)
{
locator = entry.Value.FrustumCellLocator;
if (locator != null)
{
// Inside points
extractor = vtkExtractSelectedFrustum.New(); // must be inside the loop
extractor.SetFieldType((int)vtkSelectionField.POINT);
extractor.SetContainingCells(0);
extractor.SetInput(0, locator.GetDataSet());
extractor.SetFrustum(planes);
extractor.Update();
//
globalPointIdsDataArray = (extractor.GetOutput() as vtkUnstructuredGrid).GetPointData().GetGlobalIds();
if (globalPointIdsDataArray != null)
{
for (int i = 0; i < globalPointIdsDataArray.GetNumberOfTuples(); i++)
{
globalPointIds.Add((int)globalPointIdsDataArray.GetTuple1(i));
}
}
// Inside and border cells
extractor.SetFieldType((int)vtkSelectionField.CELL);
extractor.Update();
//
globalCellIdsDataArray = (extractor.GetOutput() as vtkUnstructuredGrid).GetCellData().GetGlobalIds();
if (globalCellIdsDataArray != null)
{
for (int i = 0; i < globalCellIdsDataArray.GetNumberOfTuples(); i++)
{
globalCellIds.Add((int)globalCellIdsDataArray.GetTuple1(i));
}
}
}
}
// Reset visibility
ApplyEdgeVisibilityAndBackfaceCullingToActor(entry.Value.Geometry, entry.Value.GeometryProperty,
vtkRendererLayer.Base);
}
//
pointIds = globalPointIds.ToArray();
cellIds = globalCellIds.ToArray();
}
#endregion #################################################################################################################
// Private methods
private void InitializeControl()
{
// Render window
_renderWindow.PointSmoothingOn();
_renderWindow.LineSmoothingOn();
//_renderWindow.PolygonSmoothingOn();
_renderWindow.SetMultiSamples(2);
// Camera lights are defined in camera coordinate system where:
// camera is located at (0, 0, 1), the camera is looking at (0, 0, 0), and up is (0, 1, 0).
_light1 = vtkLight.New();
_light1.SetPosition(-1, 1, 1);
_light1.SetFocalPoint(0, 0, 0);
_light1.SetColor(1, 1, 1);
_light1.SetIntensity(0.4);
_light1.SetLightTypeToCameraLight();
_renderer.AddLight(_light1);
_overlayRenderer.AddLight(_light1);
_selectionRenderer.AddLight(_light1);
//
_light2 = vtkLight.New();
_light2.SetPosition(1, 1, 1);
_light2.SetFocalPoint(0, 0, 0);
_light2.SetColor(1, 1, 1);
_light2.SetIntensity(0.4);
_light2.SetLightTypeToCameraLight();
_renderer.AddLight(_light2);
_overlayRenderer.AddLight(_light2);
_selectionRenderer.AddLight(_light2);
//
_light3 = vtkLight.New();
_light3.SetPosition(0, -1, 0);
_light3.SetFocalPoint(0, 0, 0);
_light3.SetColor(1, 1, 1);
_light3.SetIntensity(0.4);
_light3.SetLightTypeToCameraLight();
_renderer.AddLight(_light3);
_overlayRenderer.AddLight(_light3);
_selectionRenderer.AddLight(_light3);
// Coordinate system
vtkAxesActor axes = vtkAxesActor.New();
axes.GetXAxisTipProperty().SetColor(0.706, 0.016, 0.150);
axes.GetXAxisShaftProperty().SetColor(0.706, 0.016, 0.150);
axes.GetYAxisTipProperty().SetColor(0.130, 0.806, 0.150);
axes.GetYAxisShaftProperty().SetColor(0.130, 0.806, 0.150);
axes.GetZAxisTipProperty().SetColor(0.230, 0.299, 0.754);
axes.GetZAxisShaftProperty().SetColor(0.230, 0.299, 0.754);
//
vtkTextProperty tp = CreateNewTextProperty();
axes.GetXAxisCaptionActor2D().SetCaptionTextProperty(tp);
axes.GetYAxisCaptionActor2D().SetCaptionTextProperty(tp);
axes.GetZAxisCaptionActor2D().SetCaptionTextProperty(tp);
axes.SetShaftTypeToLine();
//
_coorSys = vtkOrientationMarkerWidget.New();
_coorSys.SetOutlineColor(0.9300, 0.5700, 0.1300);
_coorSys.SetOrientationMarker(axes);
_coorSys.SetInteractor(_renderWindowInteractor);
_coorSys.KeyPressActivationOff(); // char i or I turns off the widget otherwise
SetCoorSysVisibility(_drawCoorSys);
_coorSys.InteractiveOff(); // must be after enabled ???
// Interactor style
_style = vtkInteractorStyleControl.New();
_style.AutoAdjustCameraClippingRangeOn();
_style.SetDefaultRenderer(_renderer);
_style.SetCurrentRenderer(_renderer);
_style.SetOverlayRenderer(_overlayRenderer);
_style.SetSelectionRenderer(_selectionRenderer);
_style.GetPickPoint = this.GetPickPoint;
//
_style.PointPickedOnMouseMoveEvt += style_PointPickedOnMouseMoveEvt;
_style.PointPickedOnLeftUpEvt += style_PointPickedOnLeftUpEvt;
_style.ClearCurrentMouseSelection += ClearCurrentMouseSelection;
_style.RightButtonPressEvent += style_RightButtonPressEvent;
_style.ZoomChangedEvent += style_ZoomChangedEvent;
_style.KeyPressEvt += style_KeyPressEvt;
_style.LeaveEvt += style_LeaveEvt;
_style.EnterEvt += style_EnterEvt;
_renderWindowInteractor.SetInteractorStyle(_style);
_style.Reset();
_renderWindowInteractor.ModifiedEvt += _renderWindowInteractor_ModifiedEvt;
// Background
_renderer.SetBackground(0.4, 0.4, 0.4); // bottom
_renderer.SetBackground2(0.8, 0.8, 0.8); // top
_renderer.SetGradientBackground(true);
// Camera
vtkCamera camera = _renderer.GetActiveCamera();
camera.SetParallelProjection(1);
// Offset lines from polygons
vtkPolyDataMapper.SetResolveCoincidentTopologyToPolygonOffset();
// Scale bar
_scaleWidget = new vtkMaxScaleWidget();
_scaleWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
_scaleWidget.SetWidth(400);
_scaleWidget.SetHorizontallyRelativePosition(320, 0);
_scaleWidget.SetBorderColor(0, 0, 0);
_scaleWidget.SetTextProperty(CreateNewTextProperty());
_scaleWidget.SetPadding(5);
_scaleWidget.GetBackgroundProperty().SetColor(1, 1, 1);
_scaleWidget.VisibilityOn();
_scaleWidget.BackgroundVisibilityOff();
_scaleWidget.BorderVisibilityOff();
// Scalar bar
InitializeScalarBar();
// Color bar
_colorBarWidget = new vtkMaxColorBarWidget();
_colorBarWidget.SetInteractor(_renderer, _renderWindowInteractor);
_colorBarWidget.SetTextProperty(CreateNewTextProperty());
_colorBarWidget.SetPadding(15);
_colorBarWidget.VisibilityOn();
_colorBarWidget.BackgroundVisibilityOn();
_colorBarWidget.BorderVisibilityOn();
_colorBarWidget.SetBackgroundColor(1, 1, 1);
_colorBarWidget.MouseDoubleClick += colorBarWidget_DoubleClicked;
// Status block
_statusBlockWidget = new vtkMaxStatusBlockWidget();
//_statusBlock.SetRenderer(_selectionRenderer);
_statusBlockWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
_statusBlockWidget.SetTextProperty(CreateNewTextProperty());
_statusBlockWidget.SetPadding(5);
_statusBlockWidget.GetBackgroundProperty().SetColor(1, 1, 1);
_statusBlockWidget.BackgroundVisibilityOff();
_statusBlockWidget.VisibilityOff();
_statusBlockWidget.MouseDoubleClick += statusBlockWidget_DoubleClicked;
// Probe widget
_probeWidget = new vtkMaxTextWidget();
_probeWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
_probeWidget.SetBorderColor(0, 0, 0);
_probeWidget.SetTextProperty(CreateNewTextProperty());
_probeWidget.SetPadding(5);
_probeWidget.GetBackgroundProperty().SetColor(1, 1, 1);
_probeWidget.VisibilityOff();
// Arrow widgets
_arrowWidgets = new Dictionary<string, vtkMaxTextWithArrowWidget>();
// Add the actors to the scene
//Hexahedron();
//Actor2D();
//Timer timer = new Timer();
//timer.Tick += Timer_Tick;
//timer.Interval = 10 * 1000;
//timer.Enabled = true;
}
private void InitializeScalarBar()
{
// Lookup table
_lookupTable = vtkLookupTable.New();
// Scalar bar
_scalarBarWidget = new vtkMaxScalarBarWidget();
_scalarBarWidget.SetInteractor(_renderer, _renderWindowInteractor);
//_vtkMaxScalarBar.SetRenderer(_selectionRenderer);
_scalarBarWidget.SetTextProperty(CreateNewTextProperty());
_scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), 0, 1);
_scalarBarWidget.SetLabelFormat("E3");
_scalarBarWidget.SetPadding(15);
_scalarBarWidget.VisibilityOn();
_scalarBarWidget.BackgroundVisibilityOn();
_scalarBarWidget.BorderVisibilityOn();
_scalarBarWidget.SetBackgroundColor(1, 1, 1);
//
_scalarBarWidget.MouseDoubleClick += scalarBarWidget_DoubleClicked;
}
private void Timer_Tick(object sender, EventArgs e)
{
((Timer)sender).Enabled = false;
AddDiskAnimation();
}
private void style_KeyPressEvt(vtkObject sender, vtkObjectEventArgs e)
{
if (_scalarBarWidget.GetVisibility() == 1) _scalarBarWidget.OnRenderWindowModified();
}
private vtkTextProperty CreateNewTextProperty()
{
vtkTextProperty textProperty = vtkTextProperty.New();
textProperty.SetColor(0, 0, 0);
textProperty.SetFontFamilyToArial();
//textProperty.SetFontFamilyAsString("Arial Nova");
textProperty.SetFontSize(16);
textProperty.SetLineOffset(-Math.Round(textProperty.GetFontSize() / 7.0));
textProperty.SetLineSpacing(1.5);
return textProperty;
}
private vtkActor GetActorEdgesFromGrid(vtkUnstructuredGrid uGridEdges)
{
if (uGridEdges.GetNumberOfCells() <= 0) return null;
// extract visualization surface of the unstructured grid
vtkUnstructuredGridGeometryFilter filter = vtkUnstructuredGridGeometryFilter.New();
filter.SetInput(uGridEdges);
filter.Update();
// extract edges of the visualization surface
vtkExtractEdges extractEdges = vtkExtractEdges.New();
extractEdges.SetInput(filter.GetOutput());
extractEdges.Update();
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInput(extractEdges.GetOutput());
vtkProperty prop = vtkProperty.New();
//prop.SetRepresentationToWireframe();
prop.SetColor(0, 0, 0);
prop.SetLighting(false);
vtkActor edges = vtkActor.New();
edges.SetMapper(mapper);
edges.SetProperty(prop);
edges.PickableOff();
return edges;
}
// Formatting
private void ApplySelectionFormattingToActor(vtkMaxActor actor)
{
if (actor == null || actor.GeometryMapper == null) return;
// Get actor cell type
vtkCellTypes types = vtkCellTypes.New();
actor.GeometryMapper.GetInput().GetCellTypes(types);
int num = types.GetNumberOfTypes();
byte cellType;
bool onlyEdges = true;
bool onlyNodes = true;
for (int i = 0; i < num; i++)
{
cellType = types.GetCellType(i);
if (cellType != (int)vtkCellType.VTK_LINE && cellType != (int)vtkCellType.VTK_QUADRATIC_EDGE)
{
onlyEdges = false;
//break;
}
if (cellType != (int)vtkCellType.VTK_VERTEX)
{
onlyNodes = false;
//break;
}
}
//
double k;
double ambient;
double diffuse;
if (onlyNodes || onlyEdges)
{
k = 1;
ambient = 1;
diffuse = 1;
}
else
{
k = 0.7;
ambient = 0.6;
diffuse = 0.6;
}
// If the point size was already set, do not change it
// If (actor.GeometryProperty.GetPointSize() <= 1)
actor.GeometryProperty.SetPointSize(actor.GeometryProperty.GetPointSize() + 2);
//
Color highlightColor;
if (actor.UseSecondaryHighlightColor) highlightColor = _secondaryHighlightColor;
else highlightColor = _primaryHighlightColor;
//
actor.GeometryProperty.SetColor(highlightColor.R / 255d * k,
highlightColor.G / 255d * k,
highlightColor.B / 255d * k);
actor.GeometryProperty.SetAmbient(ambient); // color background - even away from light
actor.GeometryProperty.SetDiffuse(diffuse); // color from the lights
actor.GeometryProperty.SetLineWidth(2.2f);
actor.GeometryProperty.SetOpacity(1);
//property.BackfaceCullingOn();
actor.Geometry.PickableOff();
}
private void ApplySelectionFormattingToCaptionActor(vtkMaxCaptionActor actor)
{
Color highlightColor;
if (actor.UseSecondaryHighlightColor) highlightColor = _secondaryHighlightColor;
else highlightColor = _primaryHighlightColor;
//
vtkTextProperty tp;
if (actor.CaptionActor is vtkCaptionActor2D ca2D)
{
tp = ca2D.GetCaptionTextProperty();
tp.SetColor(highlightColor.R / 255d, highlightColor.G / 255d, highlightColor.B / 255d);
//tp.BoldOn();
ca2D.SetCaptionTextProperty(tp);
}
}
private void ApplySymbolFormattingToActor(vtkMaxActor actor)
{
actor.BackfaceCulling = true;
actor.Ambient = 0.6;
actor.Diffuse = 0.6;
}
//
private void PrepareActorLookupTable(double scalarRangeMin, double scalarRangeMax)
{
double min = scalarRangeMin;
double max = scalarRangeMax;
bool addMinColor = false;
bool addMaxColor = false;
//
vtkColorTransferFunction ctf = GetColorTransferFunction();
// Determine the need for min/max color
if (_colorSpectrum.MinMaxType == vtkColorSpectrumMinMaxType.Manual)
{
min = Math.Min(scalarRangeMin, _colorSpectrum.MinUserValue);
max = Math.Max(scalarRangeMax, _colorSpectrum.MaxUserValue);
//
if (_colorSpectrum.MinUserValue > min && max != min)
{
addMinColor = true;
min = _colorSpectrum.MinUserValue;
}
if (_colorSpectrum.MaxUserValue < max && max != min)
{
addMaxColor = true;
max = _colorSpectrum.MaxUserValue;
}
}
//
double[] color;
double delta;
_lookupTable = vtkLookupTable.New(); // this is a fix for a _lookupTable.DeepCopy later on
//
if (addMinColor || addMaxColor)
{
int numOfAllColors = _colorSpectrum.NumberOfColors;
delta = (max - min) / _colorSpectrum.NumberOfColors;
//
if (addMinColor)
{
numOfAllColors++;
min -= delta;
}
if (addMaxColor)
{
numOfAllColors++;
max += delta;
}
//
_lookupTable.SetTableRange(min, max);
_lookupTable.SetNumberOfColors(numOfAllColors);
// Below range color
int count = 0;
if (addMinColor)
{
_lookupTable.SetTableValue(count++, _colorSpectrum.MinColor.R / 255.0,
_colorSpectrum.MinColor.G / 255.0,
_colorSpectrum.MinColor.B / 255.0, 1.0); //R,G,B,A
}
// Between range color
double rangeDelta = 1.0 / (_colorSpectrum.NumberOfColors - 1);
for (int i = 0; i < _colorSpectrum.NumberOfColors; i++)
{
color = ctf.GetColor(i * rangeDelta);
_lookupTable.SetTableValue(count++, color[0], color[1], color[2], 1.0); //R,G,B,A
}
// Above range color
if (addMaxColor)
{
_lookupTable.SetTableValue(count++, _colorSpectrum.MaxColor.R / 255.0,
_colorSpectrum.MaxColor.G / 255.0,
_colorSpectrum.MaxColor.B / 255.0, 1.0); //R,G,B,A
}
}
else
{
_lookupTable.SetTableRange(min, max);
_lookupTable.SetNumberOfColors(_colorSpectrum.NumberOfColors);
delta = 1.0 / (_lookupTable.GetNumberOfColors() - 1);
for (int i = 0; i < _lookupTable.GetNumberOfColors(); i++)
{
color = ctf.GetColor(i * delta);
_lookupTable.SetTableValue(i, color[0], color[1], color[2], 1.0); //R,G,B,A
}
}
}
private vtkColorTransferFunction GetColorTransferFunction()
{
vtkColorTransferFunction ctf = vtkColorTransferFunction.New();
List<double[]> rgbPoints = new List<double[]>();
//
// https://colorbrewer2.org/
//
if (_colorSpectrum.Type == vtkColorSpectrumType.CoolWarm)
{
// Cool-Warm
//http://aplotnikov.com/2016/simple-visualization-of-unstructured-grid-quality/
//http://www.kennethmoreland.com/color-maps/
ctf.SetColorSpaceToDiverging();
//rgbPoints.Add(new double[] { 0, 0.230, 0.299, 0.754 });
//rgbPoints.Add(new double[] { 1, 0.706, 0.016, 0.150 });
rgbPoints.Add(new double[] { 0, 0.038, 0.124, 0.693 });
rgbPoints.Add(new double[] { 1, 0.632, 0.0, 0.0 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Rainbow)
{
double b = 0.0;
ctf.SetColorSpaceToHSV();
rgbPoints.Add(new double[] { 0.000, b, b, 1 });
rgbPoints.Add(new double[] { 0.250, b, 1, 1 });
rgbPoints.Add(new double[] { 0.500, b, 1, b });
rgbPoints.Add(new double[] { 0.750, 1, 1, b });
rgbPoints.Add(new double[] { 1.000, 1, b, b });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.RainbowDesaturated)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0.278, 0.278, 0.788 });
rgbPoints.Add(new double[] { 0.143, 0.02, 0.02, 0.396 });
rgbPoints.Add(new double[] { 0.286, 0, 0.871, 0.918 });
rgbPoints.Add(new double[] { 0.429, 0, 0.604, 0.2 });
rgbPoints.Add(new double[] { 0.571, 1, 0.875, 0 });
rgbPoints.Add(new double[] { 0.714, 1, 0.329, 0 });
rgbPoints.Add(new double[] { 0.857, 0.451, 0.02, 0.02 });
rgbPoints.Add(new double[] { 1, 0.878, 0.302, 0.302 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Warm)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0.549, 0.176, 0.016 });
rgbPoints.Add(new double[] { 0.143, 0.8, 0.298, 0.008 });
rgbPoints.Add(new double[] { 0.286, 0.925, 0.439, 0.078 });
rgbPoints.Add(new double[] { 0.429, 0.996, 0.6, 0.161 });
rgbPoints.Add(new double[] { 0.571, 0.996, 0.769, 0.31 });
rgbPoints.Add(new double[] { 0.714, 0.996, 0.89, 0.569 });
rgbPoints.Add(new double[] { 0.857, 1, 0.969, 0.737 });
rgbPoints.Add(new double[] { 1, 1, 1, 0.898 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Cool)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0.031, 0.271, 0.58 });
rgbPoints.Add(new double[] { 0.143, 0.129, 0.443, 0.71 });
rgbPoints.Add(new double[] { 0.286, 0.259, 0.573, 0.776 });
rgbPoints.Add(new double[] { 0.429, 0.42, 0.682, 0.839 });
rgbPoints.Add(new double[] { 0.571, 0.62, 0.792, 0.882 });
rgbPoints.Add(new double[] { 0.714, 0.776, 0.859, 0.937 });
rgbPoints.Add(new double[] { 0.857, 0.871, 0.922, 0.969 });
rgbPoints.Add(new double[] { 1, 0.969, 0.984, 1 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Cividis)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0, 0.125, 0.297 });
rgbPoints.Add(new double[] { 0.125, 0.023, 0.211, 0.43 });
rgbPoints.Add(new double[] { 0.25, 0.254, 0.301, 0.418 });
rgbPoints.Add(new double[] { 0.375, 0.375, 0.391, 0.43 });
rgbPoints.Add(new double[] { 0.5, 0.484, 0.48, 0.469 });
rgbPoints.Add(new double[] { 0.625, 0.609, 0.578, 0.465 });
rgbPoints.Add(new double[] { 0.75, 0.738, 0.684, 0.43 });
rgbPoints.Add(new double[] { 0.875, 0.875, 0.793, 0.363 });
rgbPoints.Add(new double[] { 1, 0.996, 0.91, 0.27 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Viridis)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0.267, 0.005, 0.329 });
rgbPoints.Add(new double[] { 0.143, 0.275, 0.197, 0.497 });
rgbPoints.Add(new double[] { 0.286, 0.213, 0.359, 0.552 });
rgbPoints.Add(new double[] { 0.429, 0.153, 0.498, 0.558 });
rgbPoints.Add(new double[] { 0.571, 0.122, 0.632, 0.531 });
rgbPoints.Add(new double[] { 0.714, 0.29, 0.759, 0.428 });
rgbPoints.Add(new double[] { 0.857, 0.622, 0.854, 0.226 });
rgbPoints.Add(new double[] { 1, 0.993, 0.906, 0.144 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Plasma)
{
ctf.SetColorSpaceToRGB();
rgbPoints.Add(new double[] { 0, 0.05, 0.03, 0.528 });
rgbPoints.Add(new double[] { 0.143, 0.328, 0.007, 0.64 });
rgbPoints.Add(new double[] { 0.286, 0.545, 0.038, 0.647 });
rgbPoints.Add(new double[] { 0.429, 0.725, 0.197, 0.538 });
rgbPoints.Add(new double[] { 0.571, 0.859, 0.359, 0.408 });
rgbPoints.Add(new double[] { 0.714, 0.956, 0.534, 0.285 });
rgbPoints.Add(new double[] { 0.857, 0.995, 0.738, 0.167 });
rgbPoints.Add(new double[] { 1, 0.94, 0.975, 0.131 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.BlackBody)
{
ctf.SetColorSpaceToLab();
rgbPoints.Add(new double[] { 0, 0, 0, 0 });
rgbPoints.Add(new double[] { 0.143, 0.257, 0.089, 0.069 });
rgbPoints.Add(new double[] { 0.286, 0.502, 0.123, 0.107 });
rgbPoints.Add(new double[] { 0.429, 0.735, 0.198, 0.124 });
rgbPoints.Add(new double[] { 0.571, 0.877, 0.395, 0.038 });
rgbPoints.Add(new double[] { 0.714, 0.911, 0.632, 0.1 });
rgbPoints.Add(new double[] { 0.857, 0.907, 0.855, 0.189 });
rgbPoints.Add(new double[] { 1, 1, 1, 1 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Inferno)
{
ctf.SetColorSpaceToLab();
rgbPoints.Add(new double[] { 0, 0.001, 0, 0.014 });
rgbPoints.Add(new double[] { 0.143, 0.159, 0.044, 0.329 });
rgbPoints.Add(new double[] { 0.286, 0.397, 0.083, 0.433 });
rgbPoints.Add(new double[] { 0.429, 0.623, 0.165, 0.388 });
rgbPoints.Add(new double[] { 0.571, 0.831, 0.283, 0.259 });
rgbPoints.Add(new double[] { 0.714, 0.962, 0.49, 0.084 });
rgbPoints.Add(new double[] { 0.857, 0.982, 0.756, 0.153 });
rgbPoints.Add(new double[] { 1, 0.988, 0.998, 0.645 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Kindlmann)
{
ctf.SetColorSpaceToLab();
rgbPoints.Add(new double[] { 0, 0, 0, 0 });
rgbPoints.Add(new double[] { 0.143, 0.14, 0.022, 0.46 });
rgbPoints.Add(new double[] { 0.286, 0.028, 0.243, 0.587 });
rgbPoints.Add(new double[] { 0.429, 0.021, 0.449, 0.382 });
rgbPoints.Add(new double[] { 0.571, 0.031, 0.625, 0.083 });
rgbPoints.Add(new double[] { 0.714, 0.44, 0.767, 0.037 });
rgbPoints.Add(new double[] { 0.857, 0.98, 0.815, 0.572 });
rgbPoints.Add(new double[] { 1, 1, 1, 1 });
}
else if (_colorSpectrum.Type == vtkColorSpectrumType.Grayscale)
{
ctf.SetColorSpaceToLab();
//rgbPoints.Add(new double[] { 0, 0, 0, 0 });
rgbPoints.Add(new double[] { 0, 0.2, 0.2, 0.2 });
rgbPoints.Add(new double[] { 1, 1.0, 1.0, 1.0 });
}
//
double n = 0;
double k = 1;
double x = _colorSpectrum.ColorBrightness;
if (_colorSpectrum.ReverseColors)
{
n = 1;
k = -1;
}
//
foreach (var rgbPoint in rgbPoints)
ctf.AddRGBPoint(k * rgbPoint[0] + n, rgbPoint[1] + x * (1 - rgbPoint[1]),
rgbPoint[2] + x * (1 - rgbPoint[2]),
rgbPoint[3] + x * (1 - rgbPoint[3]));
//
return ctf;
}
//
private void ApplyEdgesVisibilityAndBackfaceCulling()
{
// Visibility functions must use vtkMaxActor.Visible property to determine visibility
// Base layer
foreach (var entry in _actors)
{
ApplyEdgeVisibilityAndBackfaceCullingToActor(entry.Value.Geometry, entry.Value.GeometryProperty,
vtkRendererLayer.Base);
if (entry.Value.ElementEdges != null) ApplyEdgeVisibilityAndBackfaceCullingToActorEdges(entry.Value, entry.Key);
if (entry.Value.ModelEdges != null) ApplyEdgeVisibilityAndBackfaceCullingToModelEdges(entry.Value, entry.Key);
}
// Selection
foreach (var selectedActor in _selectedActors)
{
ApplyEdgeVisibilityAndBackfaceCullingToActor(selectedActor.Geometry, selectedActor.GeometryProperty,
vtkRendererLayer.Selection);
if (selectedActor.ElementEdges != null) ApplyEdgeVisibilityAndBackfaceCullingToActorEdges(selectedActor, null);
}
// Overlay
foreach (var entry in _overlayActors)
{
if (entry.Value.Geometry != null) // null is for Caption actor
ApplyEdgeVisibilityAndBackfaceCullingToActor(entry.Value.Geometry, entry.Value.Geometry.GetProperty(),
vtkRendererLayer.Overlay);
}
//
RenderScene();
}
private void ApplyEdgeVisibilityAndBackfaceCullingToActor(vtkActor actor, vtkProperty actorProperty, vtkRendererLayer layer)
{
// Visibility functions must use vtkMaxActor.Visible property to determine visibility
//
// Skip formatting for the overlay layer
if (layer == vtkRendererLayer.Overlay) return;
//
if (_edgesVisibility == vtkEdgesVisibility.ElementEdges) actorProperty.SetInterpolationToFlat();
else actorProperty.SetInterpolationToPhong();
//
if (_edgesVisibility == vtkEdgesVisibility.Wireframe && layer == vtkRendererLayer.Base)
{
actor.VisibilityOff();
}
else
{
actorProperty.SetRepresentationToSurface();
//
vtkMaxActor maxActor = null;
if (layer == vtkRendererLayer.Base)
{
string actorName = GetActorName(actor);
maxActor = _actors[actorName];
}
else if (layer == vtkRendererLayer.Selection)
{
maxActor = GetSelectedMaxActor(actor);
}
//
if (maxActor != null)
{
if (maxActor.VtkMaxActorVisible) actor.VisibilityOn();
else actor.VisibilityOff();
//
if (maxActor.BackfaceCulling) actorProperty.BackfaceCullingOn();
else actorProperty.BackfaceCullingOff();
//
if (maxActor.ActorRepresentation == vtkMaxActorRepresentation.SolidAsShell && _sectionViewData.Active)
actorProperty.BackfaceCullingOff();
}
}
}
private void ApplyEdgeVisibilityAndBackfaceCullingToActorEdges(vtkMaxActor actor, string actorName)
{
// Visibility functions must use vtkMaxActor.Visible property to determine visibility
//
// Turn off edges for hidden actors
if (actorName != null && _actors.ContainsKey(actorName) && !_actors[actorName].VtkMaxActorVisible)
{
actor.ElementEdges.VisibilityOff();
}
else
{
// For visible actors
if (_edgesVisibility == vtkEdgesVisibility.ElementEdges)
{
actor.ElementEdges.VisibilityOn();
}
else
{
actor.ElementEdges.VisibilityOff();
}
}
actor.ElementEdgesProperty.BackfaceCullingOn();
}
private void ApplyEdgeVisibilityAndBackfaceCullingToModelEdges(vtkMaxActor actor, string actorName)
{
// visibility functions must use vtkMaxActor.Visible property to determine visibility
// turn off edges for hidden actors
if (actorName != null && _actors.ContainsKey(actorName) && !_actors[actorName].VtkMaxActorVisible)
{
actor.ModelEdges.VisibilityOff();
}
else
{
if (_edgesVisibility == vtkEdgesVisibility.ModelEdges || _edgesVisibility == vtkEdgesVisibility.Wireframe)
{
actor.ModelEdges.VisibilityOn();
}
//else if (_edgesVisibility == vtkEdgesVisibility.ElementEdges && !_actors[actorName].BackfaceCulling)
//{
// modelEdges.VisibilityOn();
//}
else
{
actor.ModelEdges.VisibilityOff();
}
actor.ModelEdgesProperty.BackfaceCullingOn();
}
}
private void ApplyVisibilityToActorNodes()
{
// Base layer
foreach (var entry in _actors)
{
if (entry.Value.Nodes == null) continue;
// Visibility functions must use vtkMaxActor.Visible property to determine visibility
//
// Turn off nodes for hidden actors
if (entry.Key != null && _actors.ContainsKey(entry.Key) && !_actors[entry.Key].VtkMaxActorVisible)
{
entry.Value.Nodes.VisibilityOff();
}
else
{
// For visible actors
entry.Value.Nodes.VisibilityOn();
}
}
}
// Public methods
#region Views #############################################################################################################
public void SetFrontBackView(bool animate, bool front)
{
if (_animating) return;
_animating = animate;
int delta = 1;
if (!front) delta = -1;
if (_drawCameraPath) ClearOverlay();
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
double[] fPos = camera.GetFocalPoint();
camera.SetPosition(fPos[0], fPos[1], fPos[2] + delta);
camera.SetViewUp(0, 1, 0);
ResetCamera();
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
public void SetTopBottomView(bool animate, bool top)
{
if (_animating) return;
_animating = animate;
int delta = 1;
if (!top) delta = -1;
if (_drawCameraPath) ClearOverlay();
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
double[] fPos = camera.GetFocalPoint();
camera.SetPosition(fPos[0], fPos[1] + delta, fPos[2]);
camera.SetViewUp(0, 0, -delta);
ResetCamera();
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
public void SetLeftRightView(bool animate, bool left)
{
if (_animating) return;
_animating = animate;
int delta = -1;
if (!left) delta = 1;
if (_drawCameraPath) ClearOverlay();
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
double[] fPos = camera.GetFocalPoint();
camera.SetPosition(fPos[0] + delta, fPos[1], fPos[2]);
camera.SetViewUp(0, 1, 0);
ResetCamera();
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
public void SetVerticalView(bool animate, bool updateView)
{
if (updateView)
{
if (_animating) return;
_animating = animate;
}
if (_drawCameraPath) ClearOverlay();
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
double[] zRange = camera.GetClippingRange();
double aspect = (double)Width / Height;
vtkMatrix4x4 m = camera.GetCompositeProjectionTransformMatrix(aspect, zRange[0], zRange[1]);
double[] x = new double[2]; // 2d projection of the X axis
double[] y = new double[2]; // 2d projection of the Y axis
double[] z = new double[2]; // 2d projection of the Z axis
x[0] = m.GetElement(0, 0);
x[1] = m.GetElement(1, 0);
y[0] = m.GetElement(0, 1);
y[1] = m.GetElement(1, 1);
z[0] = m.GetElement(0, 2);
z[1] = m.GetElement(1, 2);
// normalize
double d;
d = Math.Sqrt(Math.Pow(x[0], 2) + Math.Pow(x[1], 2));
if (d != 0) x[1] /= d;
x[0] = Math.Abs(x[1]);
d = Math.Sqrt(Math.Pow(y[0], 2) + Math.Pow(y[1], 2));
if (d != 0) y[1] /= d;
y[0] = Math.Abs(y[1]);
d = Math.Sqrt(Math.Pow(z[0], 2) + Math.Pow(z[1], 2));
if (d != 0) z[1] /= d;
z[0] = Math.Abs(z[1]);
if (Math.Max(Math.Max(x[0], y[0]), Math.Max(y[0], z[0])) == x[0])
camera.SetViewUp(Math.Sign(x[1]), 0, 0);
else if (Math.Max(Math.Max(x[0], y[0]), Math.Max(y[0], z[0])) == y[0])
camera.SetViewUp(0, Math.Sign(y[1]), 0);
else if (Math.Max(Math.Max(x[0], y[0]), Math.Max(y[0], z[0])) == z[0])
camera.SetViewUp(0, 0, Math.Sign(z[1]));
ResetCamera();
if (updateView)
{
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
}
public void SetNormalView(bool animate)
{
if (_animating) return;
_animating = animate;
//
if (_drawCameraPath) ClearOverlay();
//
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
//
double[] direction = camera.GetViewPlaneNormal();
double[] abs = new double[] { Math.Abs(direction[0]), Math.Abs(direction[1]), Math.Abs(direction[2]) };
int[] ids = new int[] { 0, 1, 2 };
Array.Sort(abs, ids);
int maxId = ids[2];
//
double[] delta = new double[3];
delta[maxId] = Math.Abs(direction[maxId]) == 1 ? -Math.Sign(direction[maxId]) : Math.Sign(direction[maxId]);
//
double[] fPoint = camera.GetFocalPoint();
camera.SetPosition(fPoint[0] + delta[0], fPoint[1] + delta[1], fPoint[2] + delta[2]);
//
SetVerticalView(false, false);
//
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
public void SetIsometricView(bool animate, bool positive)
{
if (_animating) return;
_animating = animate;
int delta = 1;
if (!positive) delta = -1;
if (_drawCameraPath) ClearOverlay();
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
SetVerticalView(false, false);
double[] fPos = camera.GetFocalPoint();
int q = GetClosestIsoDirectionQuadrant(camera.GetViewPlaneNormal());
if (q == 1) camera.SetPosition(fPos[0] + delta, fPos[1] + delta, fPos[2] + delta);
else if (q == 2) camera.SetPosition(fPos[0] - delta, fPos[1] + delta, fPos[2] + delta);
else if (q == 3) camera.SetPosition(fPos[0] - delta, fPos[1] - delta, fPos[2] + delta);
else if (q == 4) camera.SetPosition(fPos[0] + delta, fPos[1] - delta, fPos[2] + delta);
else if (q == 5) camera.SetPosition(fPos[0] + delta, fPos[1] + delta, fPos[2] - delta);
else if (q == 6) camera.SetPosition(fPos[0] - delta, fPos[1] + delta, fPos[2] - delta);
else if (q == 7) camera.SetPosition(fPos[0] - delta, fPos[1] - delta, fPos[2] - delta);
else if (q == 8) camera.SetPosition(fPos[0] + delta, fPos[1] - delta, fPos[2] - delta);
camera.OrthogonalizeViewUp(); // not needed ?
double[] up = camera.GetViewUp();
int maxID = -1;
double max = -double.MaxValue;
for (int i = 0; i < up.Length; i++)
{
if (Math.Abs(up[i]) > max)
{
max = Math.Abs(up[i]);
maxID = i;
}
}
if (maxID == 0) camera.SetViewUp(Math.Sign(up[0]), 0, 0);
else if (maxID == 1) camera.SetViewUp(0, Math.Sign(up[1]), 0);
else camera.SetViewUp(0, 0, Math.Sign(up[2]));
ResetCamera();
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
public void SetZoomFactor(double factor)
{
vtkCamera camera = _renderer.GetActiveCamera();
camera.SetParallelScale(factor);
}
public void AnimateZoomToFactor(double factor, int timeMs)
{
if (_animating) return;
_animating = true;
//
if (_drawCameraPath) ClearOverlay();
//
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
//
SetZoomFactor(factor);
//
AnimateCamera(cameraStart, camera, camera, timeMs);
}
public void SetZoomToFit(bool animate)
{
if (_animating) return;
_animating = animate;
//
if (_drawCameraPath) ClearOverlay();
//
vtkCamera camera = _renderer.GetActiveCamera();
vtkCamera cameraStart = vtkCamera.New();
cameraStart.DeepCopy(camera);
//
ResetCamera();
//_renderWindowInteractor.Modified(); // this updates the vtkMax annotation objects
if (animate) AnimateCamera(cameraStart, camera, camera);
else RenderScene();
}
//
private void ResetCamera()
{
double delta1;
double delta2 = double.MaxValue;
double[] b1 = _renderer.ComputeVisiblePropBounds();
double[] b2;
//
//if (_overlayActors.Count > 0)
{
while (true)
{
////double[] b2 = _overlayRenderer.ComputeVisiblePropBounds();
////double[] b3 = new double[] { Math.Min(b1[0], b2[0]), Math.Max(b1[1], b2[1]),
//// Math.Min(b1[2], b2[2]), Math.Max(b1[3], b2[3]),
//// Math.Min(b1[4], b2[4]), Math.Max(b1[5], b2[5])};
////
////_renderer.ResetCamera(b3[0], b3[1], b3[2], b3[3], b3[4], b3[5]);
////
////bool left, right, bottom, top;
////left = b2[0] < b1[0];
////right = b2[1] > b1[1];
////bottom = b2[2] < b1[2];
////top = b2[4] > b1[4];
////
//int wFactor = 0;
//int hFactor = 0;
////
////if (left) wFactor++;
////if (right) wFactor++;
////if (bottom) hFactor++;
////if (top) hFactor++;
////
//// Simple solution
//wFactor = 2;
//hFactor = 2;
////
//double w = Width - wFactor * _maxSymbolSize;
//double h = Height - hFactor * _maxSymbolSize;
//double zoomW = Width / w;
//double zoomH = Height / h;
////
//double mid;
//double l;
//// Width
//mid = (b1[0] + b1[1]) / 2;
//l = b1[1] - b1[0];
////if (wFactor == 1)
////{
//// if (left) mid += l * (1 - zoomW) / 2;
//// if (right) mid -= l * (1 - zoomW) / 2;
////}
//l *= zoomW;
//b1[0] = mid - l / 2;
//b1[1] = mid + l / 2;
//// Height
//mid = (b1[2] + b1[3]) / 2;
//l = b1[3] - b1[2];
////if (hFactor == 1)
////{
//// if (bottom) mid += l * (1 - zoomH) / 2;
//// if (top) mid -= l * (1 - zoomH) / 2;
////}
//l *= zoomH;
//b1[2] = mid - l / 2;
//b1[3] = mid + l / 2;
////
//_renderer.ResetCamera(b1[0], b1[1], b1[2], b1[3], b1[4], b1[5]);
//
_renderer.ResetCamera();
b2 = _renderer.ComputeVisiblePropBounds();
delta1 = Math.Abs(b1[0] - b2[0]);
if (Math.Abs(delta1 - delta2) < 1E-6) break;
else
{
b1 = b2.ToArray();
delta2 = delta1;
}
}
}
//else _renderer.ResetCamera();
//
_style.ResetClippingRange();
//
SetAllCaptionPositions();
}
//
private int GetClosestIsoDirectionQuadrant(double[] camera)
{
double[] quadrant = new double[3];
double[] angles = new double[4];
// I
quadrant[0] = 1;
quadrant[1] = 1;
quadrant[2] = 1;
angles[0] = GetAngle(camera, quadrant);
// II
quadrant[0] = -1;
quadrant[1] = 1;
quadrant[2] = 1;
angles[1] = GetAngle(camera, quadrant);
// III
quadrant[0] = -1;
quadrant[1] = -1;
quadrant[2] = 1;
angles[2] = GetAngle(camera, quadrant);
// IV
quadrant[0] = 1;
quadrant[1] = -1;
quadrant[2] = 1;
angles[3] = GetAngle(camera, quadrant);
// find min angle
int minId = -1;
double min = double.MaxValue;
for (int i = 0; i < angles.Length; i++)
{
if (angles[i] < min)
{
min = angles[i];
minId = i + 1;
}
}
if (minId == 1)
{
if (camera[0] >= 0 && camera[1] >= 0 && camera[2] >= 0) return 1;
else return 7;
}
else if (minId == 2)
{
if (camera[0] <= 0 && camera[1] >= 0 && camera[2] >= 0) return 2;
else return 8;
}
else if (minId == 3)
{
if (camera[0] <= 0 && camera[1] <= 0 && camera[2] >= 0) return 3;
else return 5;
}
else //if (minId == 4)
{
if (camera[0] >= 0 && camera[1] <= 0 && camera[2] >= 0) return 4;
else return 6;
}
}
public double[] GetViewPlaneNormal()
{
vtkCamera camera = _renderer.GetActiveCamera();
//double[] fPos = camera.GetFocalPoint();
double[] vpn = camera.GetViewPlaneNormal();
return vpn;
}
public double GetAngle(double[] v1, double[] v2)
{
double angle = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
double abs1 = Math.Sqrt(Math.Pow(v1[0], 2) + Math.Pow(v1[1], 2) + Math.Pow(v1[2], 2));
double abs2 = Math.Sqrt(Math.Pow(v2[0], 2) + Math.Pow(v2[1], 2) + Math.Pow(v2[2], 2));
if (abs1 == 0 || abs2 == 0) return 0;
else return Math.Acos(Math.Min(1, Math.Abs(angle / (abs1 * abs2))));
}
public double[] Subtract(double[] v1, double[] v2)
{
double[] v = new double[3];
v[0] = v1[0] - v2[0];
v[1] = v1[1] - v2[1];
v[2] = v1[2] - v2[2];
return v;
}
//
public void AnimateCamera_(vtkCamera cameraStart, vtkCamera cameraEnd, vtkCamera camera)
{
vtkCameraInterpolator interpolator = vtkCameraInterpolator.New();
interpolator.SetInterpolationTypeToSpline();
interpolator.AddCamera(0, cameraStart);
interpolator.AddCamera(1, cameraEnd);
//double zEnd = camera.GetParallelScale();
//interpolator.InterpolateCamera(0.5, camera);
//double zStart = cameraStart.GetParallelScale();
//double zMid = camera.GetParallelScale();
double[] v1 = cameraStart.GetDirectionOfProjection();
double[] v2 = cameraEnd.GetDirectionOfProjection();
double angle = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
if (angle < -0.99)
{
cameraStart.OrthogonalizeViewUp();
cameraEnd.OrthogonalizeViewUp();
double[] up1 = cameraStart.GetViewUp();
double[] up2 = cameraEnd.GetViewUp();
double[] up3 = new double[3];
up3[0] = (up1[0] + up2[0]) / 2;
up3[1] = (up1[1] + up2[1]) / 2;
up3[2] = (up1[2] + up2[2]) / 2;
if (up3[0] == 0 && up3[1] == 0 && up3[2] == 0)
{
up3[0] = v1[0];
up3[1] = v1[1];
up3[2] = v1[2];
}
double[] v3 = new double[3];
v3[0] = v1[1] * up1[2] - v1[2] * up1[1];
v3[1] = -(v1[0] * up1[2] - v1[2] * up1[0]);
v3[2] = v1[0] * up1[1] - v1[1] * up1[0];
double[] focal = cameraStart.GetFocalPoint();
double distance = Math.Max(cameraStart.GetDistance(), cameraEnd.GetDistance());
cameraStart.SetPosition(focal[0] + v3[0] * distance, focal[1] + v3[1] * distance, focal[2] + v3[2] * distance);
cameraStart.SetViewUp(up3[0], up3[1], up3[2]);
cameraStart.OrthogonalizeViewUp();
interpolator.AddCamera(0.5, cameraStart);
}
DateTime start = DateTime.Now;
int delta = 200; //ms
double currentDelta = 0;
while (currentDelta < delta)
{
currentDelta = (DateTime.Now - start).TotalMilliseconds;
interpolator.InterpolateCamera(currentDelta / delta, camera);
camera.OrthogonalizeViewUp();
_style.AdjustCameraDistanceAndClipping();
System.Threading.Thread.Sleep(1);
RenderScene();
Application.DoEvents();
}
interpolator.InterpolateCamera(1, camera);
RenderScene();
}
public void AnimateCameraQuat(vtkCamera cameraStart, vtkCamera cameraEnd, vtkCamera camera)
{
vtkMatrix4x4 mCamStart = cameraStart.GetViewTransformMatrix();
double[][] rStart = new double[3][];
for (int i = 0; i < 3; i++)
{
rStart[i] = new double[3];
for (int j = 0; j < 3; j++)
{
rStart[i][j] = mCamStart.GetElement(i, j);
}
}
double[] tStart = new double[3];
for (int i = 0; i < 3; i++)
{
tStart[i] = mCamStart.GetElement(i, 3);
}
double[] fpStart = cameraStart.GetFocalPoint();
double zStart = cameraStart.GetParallelScale();
double[] q1 = QuaternionHelper.QuaternionFromMatrix3x3(rStart);
vtkMatrix4x4 mCamEnd = cameraEnd.GetViewTransformMatrix();
double[][] rEnd = new double[3][];
for (int i = 0; i < 3; i++)
{
rEnd[i] = new double[3];
for (int j = 0; j < 3; j++)
{
rEnd[i][j] = mCamEnd.GetElement(i, j);
}
}
double[] tEnd = new double[3];
for (int i = 0; i < 3; i++)
{
tEnd[i] = mCamEnd.GetElement(i, 3);
}
double[] fpEnd = cameraEnd.GetFocalPoint();
double zEnd = cameraEnd.GetParallelScale();
double[] q2 = QuaternionHelper.QuaternionFromMatrix3x3(rEnd);
double[] q;
double[][] rOut;
double[][] rOutT;
double[] transform;
double[] fp;
double[] pos = new double[3];
double[] up = new double[3];
double z;
double t;
DateTime start = DateTime.Now;
int delta = 500; //ms
double currentDelta;
do
{
//http://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix
//
// | |
// M = | R T |
// | |
// | 0 0 0 1 |
//
// camera position C:
// C = -R(transpose)*T
//
currentDelta = (DateTime.Now - start).TotalMilliseconds;
t = currentDelta / delta;
if (t > 1) t = 1;
q = QuaternionHelper.QuaternionSlerp(q1, q2, t);
transform = QuaternionHelper.VectorLerp(tStart, tEnd, t);
fp = QuaternionHelper.VectorLerp(fpStart, fpEnd, t);
z = zStart + (t) * (zEnd - zStart);
rOut = QuaternionHelper.Matrix3x3FromQuaternion(q);
rOutT = QuaternionHelper.TransponseMatrix3x3(rOut);
pos[0] = -(rOutT[0][0] * transform[0] + rOutT[0][1] * transform[1] + rOutT[0][2] * transform[2]);
pos[1] = -(rOutT[1][0] * transform[0] + rOutT[1][1] * transform[1] + rOutT[1][2] * transform[2]);
pos[2] = -(rOutT[2][0] * transform[0] + rOutT[2][1] * transform[1] + rOutT[2][2] * transform[2]);
up[0] = rOutT[0][1];
up[1] = rOutT[1][1];
up[2] = rOutT[2][1];
camera.SetPosition(pos[0], pos[1], pos[2]);
camera.SetFocalPoint(fp[0], fp[1], fp[2]);
camera.SetViewUp(up[0], up[1], up[2]);
camera.SetParallelScale(z);
camera.OrthogonalizeViewUp();
_style.AdjustCameraDistanceAndClipping();
System.Threading.Thread.Sleep(5);
RenderScene();
Application.DoEvents();
} while (currentDelta < delta);
_animating = false;
}
public void AnimateCamera(vtkCamera cameraStart, vtkCamera cameraEnd, vtkCamera camera, int timeMs = 500)
{
// The idea is to use quaternions to interpolate the camera orientation while maintaining the
// focal point (end camera position) in the center of the screen. Then use projections to pan
// the cmara in 2D display coordinates from the start to end positions
((vtkInteractorStyleControl)_renderWindowInteractor.GetInteractorStyle()).Animating = true;
IntPtr pq1 = new IntPtr();
IntPtr pq2 = new IntPtr();
IntPtr pq = new IntPtr();
try
{
// Get camera end data
vtkMatrix4x4 mCamEnd = cameraEnd.GetViewTransformMatrix();
double[][] rEnd = new double[3][];
for (int i = 0; i < 3; i++)
{
rEnd[i] = new double[3];
for (int j = 0; j < 3; j++)
{
rEnd[i][j] = mCamEnd.GetElement(i, j);
if (double.IsNaN(rEnd[i][j])) throw new NotSupportedException();
}
}
double[] tEnd = new double[3];
for (int i = 0; i < 3; i++)
{
tEnd[i] = mCamEnd.GetElement(i, 3);
}
double[] fpEnd = cameraEnd.GetFocalPoint();
double zEnd = cameraEnd.GetParallelScale();
double[] q2 = QuaternionHelper.QuaternionFromMatrix3x3(rEnd);
pq2 = QuaternionHelper.IntPtrFromQuaternion(q2);
// Get display (XY) projection of the final focal point (model center) for both cameras
double[] fpEndXY = vtkInteractorStyleControl.WorldToDisplay(_renderer, fpEnd);
_renderer.SetActiveCamera(cameraStart);
double[] fpStartXY = vtkInteractorStyleControl.WorldToDisplay(_renderer, fpEnd);
// Project both XY points into 3D
double[] fpEndworld;
double[] fpStartWorld;
fpEndworld = vtkInteractorStyleControl.DisplayToWorld(_renderer, fpEndXY);
fpStartWorld = vtkInteractorStyleControl.DisplayToWorld(_renderer, fpStartXY);
// Assign the end camera back to the renderer
_renderer.SetActiveCamera(camera);
// Compute the delta of the 3D projected points
double[] fpDelta = new double[] { fpStartWorld[0] - fpEndworld[0],
fpStartWorld[1] - fpEndworld[1],
fpStartWorld[2] - fpEndworld[2]};
// Pan the start camera to look at the model center
double[] cPos = cameraStart.GetPosition();
double[] fPos = cameraStart.GetFocalPoint();
cameraStart.SetPosition(cPos[0] + fpDelta[0], cPos[1] + fpDelta[1], cPos[2] + fpDelta[2]);
cameraStart.SetFocalPoint(fPos[0] + fpDelta[0], fPos[1] + fpDelta[1], fPos[2] + fpDelta[2]);
// Get camera start data
vtkMatrix4x4 mCamStart = cameraStart.GetViewTransformMatrix();
double[][] rStart = new double[3][];
for (int i = 0; i < 3; i++)
{
rStart[i] = new double[3];
for (int j = 0; j < 3; j++)
{
rStart[i][j] = mCamStart.GetElement(i, j);
if (double.IsNaN(rStart[i][j])) throw new NotSupportedException();
}
}
double[] tStart = new double[3];
for (int i = 0; i < 3; i++)
{
tStart[i] = mCamStart.GetElement(i, 3);
}
double[] fpStart = cameraStart.GetFocalPoint();
double zStart = cameraStart.GetParallelScale();
double[] q1 = QuaternionHelper.QuaternionFromMatrix3x3(rStart);
pq1 = QuaternionHelper.IntPtrFromQuaternion(q1);
//
double[] q;
double[][] rOut;
double[][] rOutT;
double[] transform;
double[] fp;
double[] pos = new double[3];
double[] up = new double[3];
double[] fpXY;
double z;
double t;
//
vtkQuaternionInterpolator qi = vtkQuaternionInterpolator.New();
qi.SetInterpolationTypeToLinear();
qi.AddQuaternion(0, pq1);
qi.AddQuaternion(1, pq2);
pq = Marshal.AllocHGlobal(Marshal.SizeOf(q1[0]) * q1.Length);
//
DateTime start = DateTime.Now;
int delta = timeMs;
double currentDelta = 0;
//
_positions = new List<double[]>();
_focalPoints = new List<double[]>();
// Do interpolation
do
{
//
//http://math.stackexchange.com/questions/82602/how-to-find-camera-position-and-rotation-from-a-4x4-matrix
//
// | |
// M = | R T |
// | |
// | 0 0 0 1 |
//
// camera position C:
// C = -R(transpose)*T
//
currentDelta = (DateTime.Now - start).TotalMilliseconds;
t = currentDelta / delta;
if (t > 1) t = 1;
//
if (Math.Abs(q1[0] - q2[0]) + Math.Abs(q1[1] - q2[1]) + Math.Abs(q1[2] - q2[2]) + Math.Abs(q1[3] - q2[3]) < 0.00001)
q = q1;
else
{
qi.InterpolateQuaternion(t, pq);
q = QuaternionHelper.QuaternionFromIntPtr(pq);
}
//
transform = QuaternionHelper.VectorLerp(tStart, tEnd, t);
//fp = QuaternionHelper.VectorLerp(fpStart, fpEnd, t);
fp = fpEnd;
z = zStart + (t) * (zEnd - zStart);
rOut = QuaternionHelper.Matrix3x3FromQuaternion(q);
rOutT = QuaternionHelper.TransponseMatrix3x3(rOut);
//
pos[0] = -(rOutT[0][0] * transform[0] + rOutT[0][1] * transform[1] + rOutT[0][2] * transform[2]);
pos[1] = -(rOutT[1][0] * transform[0] + rOutT[1][1] * transform[1] + rOutT[1][2] * transform[2]);
pos[2] = -(rOutT[2][0] * transform[0] + rOutT[2][1] * transform[1] + rOutT[2][2] * transform[2]);
//
up[0] = rOutT[0][1];
up[1] = rOutT[1][1];
up[2] = rOutT[2][1];
// Update camera to get correct projections
camera.SetPosition(pos[0], pos[1], pos[2]);
camera.SetFocalPoint(fp[0], fp[1], fp[2]);
camera.SetParallelScale(z);
// Pan the camera in the 2D display coordinates
fpXY = QuaternionHelper.VectorLerp(fpStartXY, fpEndXY, t);
fpEndworld = vtkInteractorStyleControl.DisplayToWorld(_renderer, fpEndXY);
fpStartWorld = vtkInteractorStyleControl.DisplayToWorld(_renderer, fpXY);
// Compute the delta of the 3D projected points
fpDelta = new double[] { fpEndworld[0] - fpStartWorld[0],
fpEndworld[1] - fpStartWorld[1],
fpEndworld[2] - fpStartWorld[2]};
// Pan the camera to look at the model center
camera.SetPosition(pos[0] + fpDelta[0], pos[1] + fpDelta[1], pos[2] + fpDelta[2]);
camera.SetFocalPoint(fp[0] + fpDelta[0], fp[1] + fpDelta[1], fp[2] + fpDelta[2]);
//
camera.SetViewUp(up[0], up[1], up[2]);
camera.OrthogonalizeViewUp();
_style.AdjustCameraDistanceAndClipping();
//System.Threading.Thread.Sleep(5);
_renderWindowInteractor.Modified(); // this updates the vtkMax annotation objects
RenderScene();
//
if (_drawCameraPath)
{
_positions.Add(pos.ToArray());
_focalPoints.Add(fp.ToArray());
}
//
Application.DoEvents();
}
while (currentDelta < delta);
}
finally
{
// Free the unmanaged memory.
Marshal.FreeHGlobal(pq1);
Marshal.FreeHGlobal(pq2);
Marshal.FreeHGlobal(pq);
_animating = false;
//
((vtkInteractorStyleControl)_renderWindowInteractor.GetInteractorStyle()).Animating = false;
//
if (_drawCameraPath) DrawCameraPath();
}
}
private void DrawCameraPath()
{
ClearOverlay();
//
vtkMaxActorData data = new vtkMaxActorData();
data.Name = "positions" + Globals.NameSeparator + "nodes";
data.NodeSize = 3;
data.Color = Color.Red;
data.Layer = vtkRendererLayer.Overlay;
data.Geometry.Nodes.Coor = _positions.ToArray();
AddPoints(data);
data = new vtkMaxActorData();
data.Name = "focalPoints" + Globals.NameSeparator + "nodes";
data.NodeSize = 3;
data.Color = Color.Black;
data.Layer = vtkRendererLayer.Overlay;
data.Geometry.Nodes.Coor = _focalPoints.ToArray();
AddPoints(data);
}
//
public void AdjustCameraDistanceAndClipping()
{
_style.AdjustCameraDistanceAndClipping();
}
public void AdjustCameraDistanceAndClippingRedraw()
{
_style.AdjustCameraDistanceAndClipping();
RenderScene();
}
public void UpdateScalarsAndRedraw()
{
// Update scalar field
UpdateScalarFormatting();
//
RenderScene();
}
public void UpdateScalarsAndCameraAndRedraw()
{
// Update scalar field
UpdateScalarFormatting();
//
_style.AdjustCameraDistanceAndClipping();
//
RenderScene();
}
//
public void Rotate(double azimuthAngle, double elevationAngle, double rollAngle)
{
_style.Rotate(azimuthAngle, elevationAngle, rollAngle);
}
#endregion ################################################################################################################
#region Add geometry ######################################################################################################
private bool AreAnyActorsVisible()
{
if (_actors != null && _actors.Count > 0)
{
foreach (var entry in _actors)
{
if (entry.Value.VtkMaxActorVisible) return true;
}
}
return false;
}
public vtkMaxActor AddPoints(vtkMaxActorData data)
{
vtkMaxActor actor = new vtkMaxActor(data, false, true);
AddActorGeometry(actor, data.Layer);
//
if (!AreAnyActorsVisible()) AdjustCameraDistanceAndClippingRedraw();
//
return actor;
}
public vtkMaxActor AddCells(vtkMaxActorData data)
{
// Create actor
vtkMaxActor actor = new vtkMaxActor(data);
//
AddActor(actor);
//
if (!AreAnyActorsVisible()) AdjustCameraDistanceAndClippingRedraw();
//
return actor;
}
//
public void AddSphereActor(vtkMaxActorData data, double symbolSize)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0],
data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Source object
vtkSphereSource sphereSource = vtkSphereSource.New();
sphereSource.SetRadius(0.2);
sphereSource.SetPhiResolution(13);
sphereSource.SetThetaResolution(13);
sphereSource.Update();
// Compute normals
vtkPolyDataNormals normals = vtkPolyDataNormals.New();
normals.SetInput(sphereSource.GetOutput());
normals.Update();
// Set normals
sphereSource.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(sphereSource.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(1.0);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "sphere";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddCoordinateAxis(vtkMaxActorData data, double symbolSize)
{
double relativeSize = 1;
//
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[0][0], data.Geometry.Nodes.Coor[0][1],
data.Geometry.Nodes.Coor[0][2]);
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3);
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[0][0], data.Geometry.Nodes.Normals[0][1],
data.Geometry.Nodes.Normals[0][2]);
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize * relativeSize);
distanceToCamera.SetRenderer(_renderer);
// Line
vtkLineSource line = vtkLineSource.New();
line.SetPoint1(0, 0, 0);
line.SetPoint2(1 * relativeSize, 0, 0);
// Cone
vtkConeSource cone = vtkConeSource.New();
cone.SetCenter(0.9 * relativeSize, 0, 0);
cone.SetHeight(0.2 * relativeSize);
cone.SetRadius(0.08 * relativeSize);
cone.SetResolution(31);
// Append
vtkAppendPolyData appendFilter = vtkAppendPolyData.New();
appendFilter.AddInput(line.GetOutput());
appendFilter.AddInput(cone.GetOutput());
// Compute normals
vtkPolyDataNormals appendNormals = vtkPolyDataNormals.New();
appendNormals.SetInput(appendFilter.GetOutput());
appendNormals.Update();
// Transform
vtkTransform transform = vtkTransform.New();
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(appendFilter.GetOutput());
transformFilter.SetTransform(transform);
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(1.0);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "axis";
//
data.LineWidth = 2;
vtkMaxActor actor = new vtkMaxActor(data, mapper);
actor.Color = data.Color;
actor.GeometryProperty.SetRepresentationToSurface();
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddCaptionActor(string name, string caption, Color color, double[] position,
double[] offsetVector, double fontScaleFactor, vtkRendererLayer layer)
{
// Create an actor for the text
vtkCaptionActor2D captionActor = vtkCaptionActor2D.New();
// Text
vtkTextProperty tp = CreateNewTextProperty();
captionActor.SetCaption(caption);
tp.SetFontSize((int)(tp.GetFontSize() * fontScaleFactor));
//tp.SetJustificationToLeft();
//tp.SetVerticalJustificationToCentered();
captionActor.SetCaptionTextProperty(tp);
captionActor.GetTextActor().SetTextScaleModeToNone();
//
captionActor.GetPositionCoordinate().SetValue(position[0], position[1], position[2]);
captionActor.GetPositionCoordinate().SetCoordinateSystemToWorld();
//
captionActor.LeaderOff();
captionActor.BorderOff();
//captionActor.SetWidth(0.01);
//
vtkActor tmpActor = GetActorTmp(position);
// Actor
vtkMaxCaptionActor actor = new vtkMaxCaptionActor(name, color, captionActor, tmpActor);
actor.Position = position;
if (offsetVector != null && offsetVector.Length == 3) actor.OffsetVector = offsetVector;
// Add
AddActorCaption(actor, layer);
//
SetAllCaptionPositions();
}
private vtkActor GetActorTmp(double[] position)
{
vtkPoints points = vtkPoints.New();
points.InsertNextPoint(position[0], position[1], position[2]);
vtkCellArray lineIndices = vtkCellArray.New();
lineIndices.InsertNextCell(2);
lineIndices.InsertCellPoint(0);
lineIndices.InsertCellPoint(0);
vtkPolyData pointsPolyData = vtkPolyData.New();
pointsPolyData.SetPoints(points);
pointsPolyData.SetLines(lineIndices);
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInput(pointsPolyData);
mapper.Update();
vtkActor actorTmp = vtkActor.New();
actorTmp.SetMapper(mapper);
return actorTmp;
}
private void SetAllCaptionPositions()
{
double size = vtkInteractorStyleControl.DisplayToWorldScale(_renderer, 1);
//
foreach (var entry in _actors)
{
if (entry.Value is vtkMaxCaptionActor ca) SetCaptionOffsetPositions(ca, size);
}
foreach (var entry in _overlayActors)
{
if (entry.Value is vtkMaxCaptionActor ca) SetCaptionOffsetPositions(ca, size);
}
foreach (var entry in _selectedActors)
{
if (entry is vtkMaxCaptionActor ca) SetCaptionOffsetPositions(ca, size);
}
}
private void SetCaptionOffsetPositions(vtkMaxCaptionActor vtkMaxCaptionActor, double size)
{
double[] position = vtkMaxCaptionActor.Position;
double[] offset = vtkMaxCaptionActor.OffsetVector;
//
if (offset != null && offset.Length == 3)
{
double[] pos = new double[3]; // make a copy
pos[0] = position[0] + size * offset[0];
pos[1] = position[1] + size * offset[1];
pos[2] = position[2] + size * offset[2];
//
vtkMaxCaptionActor.CaptionActor.GetPositionCoordinate().SetValue(pos[0], pos[1], pos[2]);
}
}
public void AddOrientedDisplacementConstraintActor(vtkMaxActorData data, double symbolSize)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
//
double[][] points = data.Geometry.Nodes.Coor;
double[][] normals = data.Geometry.Nodes.Normals;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < points.GetLength(0); i++)
{
if (points[i] != null && points[i].Length == 3)
pointData.InsertNextPoint(points[i][0], points[i][1], points[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3);
for (int i = 0; i < normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(normals[i][0], normals[i][1], normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Cone
//vtkTubeFilter cone = CreateConeSource(-0.5, 0, 0, 21);
vtkConeSource cone = vtkConeSource.New();
cone.SetCenter(-0.5, 0, 0);
cone.SetResolution(31);
// Compute normals
vtkPolyDataNormals coneNormals = vtkPolyDataNormals.New();
coneNormals.SetInput(cone.GetOutput());
coneNormals.Update();
// Set normals
//cone.GetOutput().GetPointData().SetNormals(coneNormals.GetOutput().GetPointData().GetNormals());
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(cone.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(0.3);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "cones";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
actor.GeometryProperty.SetRepresentationToSurface();
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddOrientedRotationalConstraintActor(vtkMaxActorData data, double symbolSize)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
//
double[][] points = data.Geometry.Nodes.Coor;
double[][] normals = data.Geometry.Nodes.Normals;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < points.GetLength(0); i++)
{
pointData.InsertNextPoint(points[i][0], points[i][1], points[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3);
for (int i = 0; i < normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(normals[i][0], normals[i][1], normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Cube
vtkCubeSource cubeSource = vtkCubeSource.New();
cubeSource.SetCenter(-1.55, 0.0, 0.0);
cubeSource.SetXLength(0.4);
cubeSource.SetYLength(0.9);
cubeSource.SetZLength(0.9);
// Line
vtkLineSource line = vtkLineSource.New();
line.SetPoint1(0, 0, 0);
line.SetPoint2(-1.3, 0, 0);
// Append
vtkAppendPolyData appendFilter = vtkAppendPolyData.New();
appendFilter.AddInput(cubeSource.GetOutput());
appendFilter.AddInput(line.GetOutput());
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(appendFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(0.3);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "cylinder";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
actor.GeometryProperty.SetInterpolationToFlat();
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddOrientedArrowsActor(vtkMaxActorData data, double symbolSize, bool invert, double relativeSize = 1)
{
data.Geometry.RemoveZeroLengthNormals();
//
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0], data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3); //3d normals (ie x,y,z)
for (int i = 0; i < data.Geometry.Nodes.Normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[i][0], data.Geometry.Nodes.Normals[i][1],
data.Geometry.Nodes.Normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize * relativeSize);
distanceToCamera.SetRenderer(_renderer);
// Arrow
vtkArrowSource arrow = vtkArrowSource.New();
arrow.SetTipResolution(_arrowTipResolution);
arrow.SetTipLength(0.3 / relativeSize);
arrow.SetTipRadius(0.1 / relativeSize);
arrow.SetShaftResolution(_arrowShaftResolution);
arrow.SetShaftRadius(0.03 / relativeSize);
// Compute normals
vtkPolyDataNormals normals = vtkPolyDataNormals.New();
normals.SetInput(arrow.GetOutput());
normals.Update();
// Set normals
//arrow.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
// Transform
vtkTransform transform = vtkTransform.New();
transform.Identity();
if (invert) transform.Translate(-1.05, 0, 0);
else transform.Translate(0.05, 0, 0);
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(arrow.GetOutput());
transformFilter.SetTransform(transform);
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(1.0);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "arrow";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
actor.Color = data.Color;// Color.Blue;
actor.GeometryProperty.SetRepresentationToSurface();
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddOrientedDoubleArrowsActor(vtkMaxActorData data, double symbolSize)
{
data.Geometry.RemoveZeroLengthNormals();
//
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Double arrow for moment loads
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0], data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3); //3d normals (ie x,y,z)
for (int i = 0; i < data.Geometry.Nodes.Normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[i][0], data.Geometry.Nodes.Normals[i][1],
data.Geometry.Nodes.Normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Arrow
vtkArrowSource arrow = vtkArrowSource.New();
arrow.SetTipResolution(_arrowTipResolution);
arrow.SetTipLength(0.3);
arrow.SetTipRadius(0.1);
arrow.SetShaftResolution(_arrowShaftResolution);
arrow.SetShaftRadius(0.03);
// Cone
vtkConeSource cone = vtkConeSource.New();
cone.SetResolution(21);
cone.SetHeight(0.3);
cone.SetRadius(0.1);
cone.SetCenter(0.65, 0, 0);
// Append
vtkAppendPolyData appendFilter = vtkAppendPolyData.New();
appendFilter.AddInput(arrow.GetOutput());
appendFilter.AddInput(cone.GetOutput());
// Compute normals
vtkPolyDataNormals normals = vtkPolyDataNormals.New();
normals.SetInput(appendFilter.GetOutput());
normals.Update();
// Set normals
//appendFilter.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
// Transform
vtkTransform transform = vtkTransform.New();
transform.Identity();
transform.Translate(0.05, 0, 0);
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(appendFilter.GetOutput());
transformFilter.SetTransform(transform);
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(1.0);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "doubleArrow";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddOrientedSpringActor(vtkMaxActorData data, double symbolSize, bool invert)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0], data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3); //3d normals (ie x,y,z)
for (int i = 0; i < data.Geometry.Nodes.Normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[i][0], data.Geometry.Nodes.Normals[i][1],
data.Geometry.Nodes.Normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Source for the glyph filter
vtkPolyData lineData;
vtkPolyData spring = CreateSpringSource(0.2, 1, 8, 10, out lineData);
// Transform
vtkTransform transform = vtkTransform.New();
transform.Identity();
//if (invert) transform.Translate(-1.05, 0, 0);
//else transform.Translate(0.05, 0, 0);
transform.Translate(-1.05, 0, 0);
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(spring);
transformFilter.SetTransform(transform);
transformFilter.Update();
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(1.0);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "spring";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
actor.GeometryProperty.SetRepresentationToSurface();
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
private vtkPolyData CreateSpringSource(double diameter, double height, int numOfTurns, int radialResolution,
out vtkPolyData lineData)
{
// Points
double r = diameter / 2;
double delta;
double phi = 0;
double phiDelta = Math.PI / radialResolution;
double linPart = diameter;
double hDelta = (height - 2 * linPart) / (numOfTurns * radialResolution);
int linResolution = 3;
int numOfPoints = numOfTurns * radialResolution + 1 + 2 * 2 * linResolution;
int count = 0;
//
double[][] points = new double[numOfPoints][];
// Start
delta = linPart / linResolution;
for (int i = 0; i < linResolution; i++) points[count++] = new double[] { delta * i, 0, 0 };
delta = r / linResolution;
for (int i = 0; i < linResolution; i++) points[count++] = new double[] { linPart, delta * i, 0 };
// Helix
for (int i = 0; i <= numOfTurns * radialResolution; i++)
{
points[count++] = new double[] { linPart + hDelta * i, r * Math.Cos(phi), r * Math.Sin(phi) };
phi += phiDelta;
}
// End
delta = r / linResolution;
for (int i = 0; i < linResolution; i++) points[count++] = new double[] { height - linPart, r - delta * (i + 1), 0, 0 };
delta = linPart / linResolution;
for (int i = 0; i < linResolution; i++) points[count++] = new double[] { height - linPart + delta * (i + 1), 0, 0 };
//
points = SmoothLinePoints(points, 3);
//
vtkPoints vtkPoints = vtkPoints.New();
foreach (var point in points) vtkPoints.InsertNextPoint(point[0], point[1], point[2]);
// Polyline
vtkPolyLine polyLine = vtkPolyLine.New();
polyLine.GetPointIds().SetNumberOfIds(numOfPoints);
for (int i = 0; i < numOfPoints; i++) polyLine.GetPointIds().SetId(i, i);
// Create a cell array to store the lines in and add the lines to it
vtkCellArray cells = vtkCellArray.New();
cells.InsertNextCell(polyLine);
// Poly data
lineData = vtkPolyData.New();
lineData.SetPoints(vtkPoints);
lineData.SetLines(cells);
// Create tube filter
vtkTubeFilter tubeFilter = vtkTubeFilter.New();
tubeFilter.SetInput(lineData);
tubeFilter.SetRadius(0.03);
tubeFilter.SetNumberOfSides(10);
tubeFilter.CappingOn();
tubeFilter.UseDefaultNormalOff();
tubeFilter.Update();
// For vtkPolyDataSilhouette
vtkTriangleFilter triangleFilter = vtkTriangleFilter.New();
triangleFilter.SetInput(tubeFilter.GetOutput());
triangleFilter.Update();
//
return triangleFilter.GetOutput();
}
private double[][] SmoothLinePoints(double[][] points, int numOfPoints)
{
int half = numOfPoints / 2;
int evenNumOfPoints = half * 2 + 1;
double[][] smooth = new double[points.Length][];
double[] newPoint;
//
for (int i = 0; i < points.Length; i++)
{
if (i < half || i >= points.Length - half)
{
smooth[i] = points[i];
}
else
{
newPoint = new double[3];
for (int j = -half; j <= half; j++)
{
newPoint[0] += points[i + j][0];
newPoint[1] += points[i + j][1];
newPoint[2] += points[i + j][2];
}
newPoint[0] /= evenNumOfPoints;
newPoint[1] /= evenNumOfPoints;
newPoint[2] /= evenNumOfPoints;
//
smooth[i] = newPoint;
}
}
//
return smooth;
}
private vtkTubeFilter CreateConeSource(double sx, double sy, double sz, int resolution)
{
// Points
int numOfPoints = 2;
//
vtkPoints points = vtkPoints.New();
// Start
points.InsertNextPoint(sx - 0.5, sy , sz );
points.InsertNextPoint(sx + 0.5, sy , sz );
// Polyline
vtkPolyLine polyLine = vtkPolyLine.New();
polyLine.GetPointIds().SetNumberOfIds(numOfPoints);
for (int i = 0; i < numOfPoints; i++) polyLine.GetPointIds().SetId(i, i);
// Create a cell array to store the lines in and add the lines to it
vtkCellArray cells = vtkCellArray.New();
cells.InsertNextCell(polyLine);
// Diameter
vtkFloatArray scalars = vtkFloatArray.New();
scalars.InsertNextTuple1(0.5);
scalars.InsertNextTuple1(0.01);
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(points);
polyData.SetLines(cells);
polyData.GetPointData().SetScalars(scalars);
// Create tube filter
vtkTubeFilter tubeFilter = vtkTubeFilter.New();
tubeFilter.SetInput(polyData);
tubeFilter.SetNumberOfSides(resolution);
tubeFilter.SetVaryRadiusToVaryRadiusByAbsoluteScalar();
tubeFilter.CappingOn();
tubeFilter.Update();
// Compute normals
vtkPolyDataNormals normals = vtkPolyDataNormals.New();
normals.SetInput(tubeFilter.GetOutput());
normals.ComputeCellNormalsOff();
normals.Update();
// Set normals
tubeFilter.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
//
return tubeFilter;
}
public void AddOrientedThermoActor(vtkMaxActorData data, double symbolSize, bool invert)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0], data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3); //3d normals (ie x,y,z)
for (int i = 0; i < data.Geometry.Nodes.Normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[i][0], data.Geometry.Nodes.Normals[i][1],
data.Geometry.Nodes.Normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Sphere
double rs = 0.2;
double rc = 0.1;
vtkSphereSource sphereSource = vtkSphereSource.New();
sphereSource.SetRadius(rs);
sphereSource.SetPhiResolution(11);
sphereSource.SetThetaResolution(11);
sphereSource.SetCenter(rs, 0, 0);
// Cylinder
vtkCylinderSource cylinderSource = vtkCylinderSource.New();
cylinderSource.SetRadius(rc);
cylinderSource.SetHeight(1 - rs);
cylinderSource.SetResolution(7);
cylinderSource.SetCenter(0, 0.5 + rs, 0);
//Transform
vtkTransform transform = vtkTransform.New();
transform.Identity();
transform.RotateZ(-90);
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(cylinderSource.GetOutput());
transformFilter.SetTransform(transform);
// Append
vtkAppendPolyData append = vtkAppendPolyData.New();
append.AddInput(sphereSource.GetOutput());
append.AddInput(transformFilter.GetOutput());
// Compute normals
vtkPolyDataNormals normals = vtkPolyDataNormals.New();
normals.SetInput(append.GetOutput());
normals.Update();
// Set normals
append.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
// Transform
transform = vtkTransform.New();
transform.Identity();
if (invert) transform.Translate(-1.05, 0, 0);
else transform.Translate(0.05, 0, 0);
// Transform filter
transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(append.GetOutput());
transformFilter.SetTransform(transform);
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(0.5);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "thermo";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
public void AddOrientedFluxActor(vtkMaxActorData data, double symbolSize, bool center, bool invert)
{
if (symbolSize > _maxSymbolSize) _maxSymbolSize = symbolSize;
// Points
vtkPoints pointData = vtkPoints.New();
for (int i = 0; i < data.Geometry.Nodes.Coor.GetLength(0); i++)
{
pointData.InsertNextPoint(data.Geometry.Nodes.Coor[i][0], data.Geometry.Nodes.Coor[i][1],
data.Geometry.Nodes.Coor[i][2]);
}
// Normals
vtkDoubleArray pointNormalsArray = vtkDoubleArray.New();
pointNormalsArray.SetNumberOfComponents(3); //3d normals (ie x,y,z)
for (int i = 0; i < data.Geometry.Nodes.Normals.GetLength(0); i++)
{
pointNormalsArray.InsertNextTuple3(data.Geometry.Nodes.Normals[i][0], data.Geometry.Nodes.Normals[i][1],
data.Geometry.Nodes.Normals[i][2]);
}
// Poly data
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(pointData);
polyData.GetPointData().SetNormals(pointNormalsArray);
// Calculate the distance to the camera of each point.
vtkDistanceToCamera distanceToCamera = vtkDistanceToCamera.New();
distanceToCamera.SetInput(polyData);
distanceToCamera.SetScreenSize(symbolSize);
distanceToCamera.SetRenderer(_renderer);
// Sphere
double rs = 0.2;
vtkSphereSource sphereSource = vtkSphereSource.New();
sphereSource.SetRadius(rs);
sphereSource.SetPhiResolution(9);
sphereSource.SetThetaResolution(11);
if (center) rs = 0;
sphereSource.SetCenter(rs, 0, 0);
// Compute normals
//vtkPolyDataNormals normals = vtkPolyDataNormals.New();
//normals.SetInput(sphereSource.GetOutput());
//normals.Update();
//// Set normals
//sphereSource.GetOutput().GetPointData().SetNormals(normals.GetOutput().GetPointData().GetNormals());
// Transform
vtkTransform transform = vtkTransform.New();
transform.Identity();
if (invert) transform.Translate(-1.05, 0, 0);
else transform.Translate(0.05, 0, 0);
// Transform filter
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(sphereSource.GetOutput());
transformFilter.SetTransform(transform);
// Glyph
vtkGlyph3D glyph = vtkGlyph3D.New();
glyph.SetSourceConnection(transformFilter.GetOutputPort());
glyph.SetInputConnection(distanceToCamera.GetOutputPort());
glyph.SetVectorModeToUseNormal();
// Scale
glyph.ScalingOn();
glyph.SetScaleModeToScaleByScalar();
glyph.SetInputArrayToProcess(0, 0, 0, "vtkDataObject::FIELD_ASSOCIATION_POINTS", "DistanceToCamera");
glyph.SetScaleFactor(0.5);
glyph.OrientOn();
glyph.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(0, glyph.GetOutputPort());
mapper.ScalarVisibilityOff();
// Actor
data.Name += Globals.NameSeparator + "flux";
vtkMaxActor actor = new vtkMaxActor(data, mapper);
// Add
ApplySymbolFormattingToActor(actor);
AddActorGeometry(actor, data.Layer);
//
if (_drawSymbolEdges) AddSymbolEdges(data, glyph.GetOutputPort());
}
private void AddSymbolEdges(vtkMaxActorData data, vtkAlgorithmOutput output)
{
// Compute the silhouette
vtkPolyDataSilhouette silhouette = vtkPolyDataSilhouette.New();
silhouette.SetInputConnection(0, output);
silhouette.SetCamera(_renderer.GetActiveCamera());
silhouette.SetEnableFeatureAngle(1);
silhouette.SetFeatureAngle(60);
silhouette.Update();
// Mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(silhouette.GetOutputPort());
// Actor
data.Name += Globals.NameSeparator + "silhouette";
bool pickable = data.Pickable;
data.Pickable = false;
vtkMaxActor actor = new vtkMaxActor(data, mapper);
data.Pickable = pickable;
// Backface color is used for annotateWithColor
if (data.BackfaceColor != Color.Empty) actor.Color = data.BackfaceColor;
//
actor.GeometryProperty.SetLineWidth(1.5f);
//
double k = 0.2;
actor.Color = Color.FromArgb((int)(actor.Color.R + (255 - actor.Color.R) * k),
(int)(actor.Color.G + (255 - actor.Color.G) * k),
(int)(actor.Color.B + (255 - actor.Color.B) * k));
// Add
AddActorGeometry(actor, data.Layer);
}
//
public void AddActor(vtkMaxActor actor)
{
AddActor(actor, actor.Layer);
}
private void AddActor(vtkMaxActor actor, vtkRendererLayer layer)
{
// Add actor
AddActorGeometry(actor, layer);
// Add actorElementEdges
if (actor.ElementEdges != null) AddActorEdges(actor, false, layer);
// Add modelEdges
if (actor.ModelEdges != null) AddActorEdges(actor, true, layer);
// Add nodes
if (actor.Nodes != null) AddActorNodes(actor, layer);
}
private void AddActorGeometry(vtkMaxActor actor, vtkRendererLayer layer)
{
// Add actor
if (layer == vtkRendererLayer.Base)
{
if (actor.Name == null) actor.Name = (_actors.Count + 1).ToString();
_actors.Add(actor.Name, actor);
_renderer.AddActor(actor.Geometry);
//
if (actor.Geometry.GetPickable() == 1)
{
if (actor.CellLocator != null) _cellPicker.AddLocator(actor.CellLocator);
_propPicker.AddPickList(actor.Geometry);
}
}
else if (layer == vtkRendererLayer.Overlay)
{
if (actor.Name == null) actor.Name = (_overlayActors.Count + 1).ToString();
_overlayActors.Add(actor.Name, actor);
_overlayRenderer.AddActor(actor.Geometry);
//
if (actor.Geometry.GetPickable() == 1)
{
if (actor.CellLocator != null) _cellPicker.AddLocator(actor.CellLocator);
_propPicker.AddPickList(actor.Geometry);
}
else actor.Geometry.PickableOff();
}
else if (layer == vtkRendererLayer.Selection)
{
if (actor.Name == null) actor.Name = (_selectedActors.Count + 1).ToString();
_selectedActors.Add(actor);
if (actor.DrawOnGeometry) _renderer.AddActor(actor.Geometry);
else _selectionRenderer.AddActor(actor.Geometry);
//
actor.Geometry.PickableOff();
ApplySelectionFormattingToActor(actor);
}
//
ApplyEdgeVisibilityAndBackfaceCullingToActor(actor.Geometry, actor.GeometryProperty, layer);
}
private void AddActorCaption(vtkMaxCaptionActor actor, vtkRendererLayer layer)
{
// Add actor
if (layer == vtkRendererLayer.Base)
{
if (actor.Name == null) actor.Name = (_actors.Count + 1).ToString();
_actors.Add(actor.Name, actor);
_renderer.AddActor2D(actor.CaptionActor);
_renderer.AddActor(actor.TmpActor);
}
else if (layer == vtkRendererLayer.Overlay)
{
if (actor.Name == null) actor.Name = (_overlayActors.Count + 1).ToString();
_overlayActors.Add(actor.Name, actor);
_overlayRenderer.AddActor2D(actor.CaptionActor);
_overlayRenderer.AddActor(actor.TmpActor);
}
else if (layer == vtkRendererLayer.Selection)
{
if (actor.Name == null) actor.Name = (_selectedActors.Count + 1).ToString();
_selectedActors.Add(actor);
// Caption 2d actors are added to overlay renderer since no text is rendered in selectionRenderer !!!
_selectionRenderer.AddActor2D(actor.CaptionActor);
_selectionRenderer.AddActor(actor.TmpActor);
ApplySelectionFormattingToCaptionActor(actor);
}
}
private void AddActorEdges(vtkMaxActor actor, bool isModelEdge, vtkRendererLayer layer)
{
if (layer == vtkRendererLayer.Base)
{
if (actor.Name == null) actor.Name = (_actors.Count + 1).ToString();
//
if (_actors.ContainsKey(actor.Name))
{
if (isModelEdge && _actors[actor.Name].ModelEdges != actor.ModelEdges)
throw new Exception("Animation changes exception.");
if (!isModelEdge && _actors[actor.Name].ElementEdges != actor.ElementEdges)
throw new Exception("Animation changes exception.");
}
else
{
_actors.Add(actor.Name, actor);
}
//
if (isModelEdge) _renderer.AddActor(actor.ModelEdges);
else _renderer.AddActor(actor.ElementEdges);
}
else if (layer == vtkRendererLayer.Overlay)
{
_overlayActors.Add(actor.Name, actor);
//
if (isModelEdge) _overlayRenderer.AddActor(actor.ModelEdges);
else _overlayRenderer.AddActor(actor.ElementEdges);
}
else if (layer == vtkRendererLayer.Selection)
{
// Wireframe selection
if (!_selectedActors.Contains(actor)) _selectedActors.Add(actor);
//
vtkActor edgeActor;
if (isModelEdge) edgeActor = actor.ModelEdges;
else edgeActor = actor.ElementEdges;
//
if (actor.DrawOnGeometry) _renderer.AddActor(edgeActor);
else _selectionRenderer.AddActor(edgeActor);
}
//if (isModelEdge) ApplyEdgesFormattingToActor(actor.ModelEdges);
//else ApplyEdgesFormattingToActor(actor.ElementEdges);
if (isModelEdge) ApplyEdgeVisibilityAndBackfaceCullingToModelEdges(actor, actor.Name);
else ApplyEdgeVisibilityAndBackfaceCullingToActorEdges(actor, actor.Name);
}
private void AddActorNodes(vtkMaxActor actor, vtkRendererLayer layer)
{
if (layer == vtkRendererLayer.Base)
{
if (actor.Name == null) actor.Name = (_actors.Count + 1).ToString();
//
if (_actors.ContainsKey(actor.Name))
{
if (_actors[actor.Name].Nodes != actor.Nodes) throw new Exception("Animation changes exception.");
}
else
{
_actors.Add(actor.Name, actor);
}
//
_renderer.AddActor(actor.Nodes);
}
//else if (layer == vtkRendererLayer.Overlay)
//{
// _overlayActors.Add(actor.Name, actor.Geometry);
// //
// if (isModelEdge) _overlayRenderer.AddActor(actor.ModelEdges);
// else _overlayRenderer.AddActor(actor.ElementEdges);
//}
//else if (layer == vtkRendererLayer.Selection)
//{
// // Wireframe selection
// if (!_selectedActors.Contains(actor)) _selectedActors.Add(actor);
// //
// vtkActor edgeActor;
// if (isModelEdge) edgeActor = actor.ModelEdges;
// else edgeActor = actor.ElementEdges;
// //
// if (actor.DrawOnGeometry) _renderer.AddActor(edgeActor);
// else _selectionRenderer.AddActor(edgeActor);
//}
////if (isModelEdge) ApplyEdgesFormattingToActor(actor.ModelEdges);
////else ApplyEdgesFormattingToActor(actor.ElementEdges);
//if (isModelEdge) ApplyEdgeVisibilityAndBackfaceCullingToModelEdges(actor, actor.Name);
//else ApplyEdgeVisibilityAndBackfaceCullingToActorEdges(actor, actor.Name);
}
#endregion ################################################################################################################
#region Highlight geometry ################################################################################################
public void HighlightActor(string actorName)
{
string sectionViewActorName = GetSectionViewActorName(actorName);
HighlightAllActorsByName(actorName);
if (_sectionViewData.Active) HighlightAllActorsByName(sectionViewActorName);
}
private void HighlightAllActorsByName(string actorName)
{
vtkMaxActor highlightActor = GetHighlightActorFromActorName(actorName);
//
if (highlightActor != null)
{
highlightActor.GeometryProperty.SetOpacity(1);
AddActorGeometry(highlightActor, vtkRendererLayer.Selection);
RenderScene();
}
}
private vtkMaxActor GetHighlightActorFromActorName(string actorName)
{
vtkMaxActor highlightActor = GetCopyOfModelEdgesActor(actorName);
if (highlightActor != null && highlightActor.Geometry.GetMapper().GetInput().GetNumberOfPoints() == 0)
{
// Silhouette
vtkMaxActor actor = _actors[actorName];
vtkPolyDataSilhouette silhouette = vtkPolyDataSilhouette.New();
silhouette.SetInput(actor.GeometryMapper.GetInput());
silhouette.SetCamera(_renderer.GetActiveCamera());
//silhouette.SetDirectionToCameraOrigin(); // not working
silhouette.SetDirectionToCameraVector();
silhouette.SetBorderEdges(1); // free edges
silhouette.SetEnableFeatureAngle(1);
silhouette.SetFeatureAngle(30);
//
vtkDataSetMapper dsMapper = vtkDataSetMapper.New();
dsMapper.SetInput(silhouette.GetOutput());
//
highlightActor = new vtkMaxActor();
highlightActor.GeometryMapper = dsMapper;
highlightActor.Geometry.PickableOff();
}
//
return highlightActor;
}
private vtkMaxActor GetCopyOfEdgesActor(string actorName)
{
vtkMaxActor actor = null;
if (_actors.ContainsKey(actorName))
{
vtkMaxActor actorToHighLight = _actors[actorName];
//
vtkPolyData data = vtkPolyData.New();
data.DeepCopy(actorToHighLight.ElementEdges.GetMapper().GetInput());
//
vtkDataSetMapper mapper = vtkDataSetMapper.New();
mapper.SetInput(data);
//
actor = new vtkMaxActor();
actor.GeometryMapper = mapper;
actor.Geometry.PickableOff();
}
return actor;
}
private vtkMaxActor GetCopyOfModelEdgesActor(string actorName)
{
vtkMaxActor actor = null;
if (_actors.ContainsKey(actorName))
{
vtkMaxActor actorToHighLight = _actors[actorName];
//
vtkPolyData data = vtkPolyData.New();
data.DeepCopy(actorToHighLight.ModelEdges.GetMapper().GetInput());
//
vtkDataSetMapper mapper = vtkDataSetMapper.New();
mapper.SetInput(data);
//
actor = new vtkMaxActor();
actor.GeometryMapper = mapper;
actor.Geometry.PickableOff();
}
return actor;
}
private vtkMaxActor GetAppendedActor(string[] actorNames, Func<string, vtkMaxActor> GetActor)
{
if (actorNames == null || actorNames.Length == 0) return null;
//
if (actorNames.Length == 1) return GetActor(actorNames[0]);
//
bool added = false;
vtkMaxActor appendedActor;
vtkAppendPolyData appendFilter = vtkAppendPolyData.New();
//
foreach (var actorName in actorNames)
{
appendedActor = GetActor(actorName);
if (appendedActor != null)
{
appendFilter.AddInput(appendedActor.GeometryMapper.GetInput());
added = true;
}
}
//
if (added)
{
vtkDataSetMapper mapper = vtkDataSetMapper.New();
mapper.SetInput(appendFilter.GetOutput());
//
appendedActor = new vtkMaxActor();
appendedActor.GeometryMapper = mapper;
appendedActor.Geometry.PickableOff();
//
return appendedActor;
}
else return null;
}
private vtkMaxActor GetAppendedActor(vtkMaxActor actor1, vtkMaxActor actor2)
{
vtkAppendPolyData appendFilter = vtkAppendPolyData.New();
appendFilter.AddInput(actor1.GeometryMapper.GetInput());
appendFilter.AddInput(actor2.GeometryMapper.GetInput());
//
vtkDataSetMapper mapper = vtkDataSetMapper.New();
mapper.SetInput(appendFilter.GetOutput());
//
vtkMaxActor appendedActor = new vtkMaxActor();
appendedActor.GeometryMapper = mapper;
appendedActor.Geometry.PickableOff();
//
return appendedActor;
}
#endregion ################################################################################################################
#region Hide/Show geometry ################################################################################################
public void HideActors(string[] actorNames, bool updateColorContours)
{
HideShowActors(actorNames, updateColorContours, false);
}
public void ShowActors(string[] actorNames, bool updateColorContours)
{
HideShowActors(actorNames, updateColorContours, true);
}
private void HideShowActors(string[] actorNames, bool updateColorContours, bool visible)
{
string[] tmp;
string[] splitter = new string[] { "_animation-frame-", "_undeformed" };
HashSet<string> actorNamesHash = new HashSet<string>(actorNames);
foreach (var entry in _actors)
{
// Check for animated actors
tmp = entry.Key.Split(splitter, StringSplitOptions.None);
if (tmp.Length == 2)
{
// Name splitting also takes care of section view actors since they have the same base name
if (actorNamesHash.Contains(tmp[0]))
{
entry.Value.VtkMaxActorVisible = visible;
// Animated actors
_animationFrameData.ActorVisible[tmp[0]] = visible;
}
}
// Non animated actors
else
{
if (actorNamesHash.Contains(entry.Key)) HideShowActor(entry.Value, visible);
}
}
// Overlay actors
vtkMaxActor actor;
foreach (var name in actorNames)
{
if (_overlayActors.TryGetValue(name, out actor)) actor.VtkMaxActorVisible = true;
}
//
if (updateColorContours) UpdateScalarFormatting();
//
ApplyEdgesVisibilityAndBackfaceCulling();
ApplyVisibilityToActorNodes();
_style.AdjustCameraDistanceAndClipping();
}
private void HideShowActor(vtkMaxActor actor, bool visible)
{
// Use vtkMaxActor Visibility setting
actor.VtkMaxActorVisible = visible;
// Section view
if (_sectionViewData.Active && actor.SectionViewActor != null)
actor.SectionViewActor.VtkMaxActorVisible = visible;
// Transformed copies
foreach (var copy in actor.Copies) HideShowActor(copy, visible);
}
#endregion ################################################################################################################
#region Section view ######################################################################################################
public void CreateSectionView(double[] point, double[] normal, bool lightenColors, Color sectionColor)
{
lock (myLock)
{
if (!_sectionViewData.Active)
{
_sectionViewData.Active = true;
// Set section cut plane
_sectionViewData.Plane = vtkPlane.New();
_sectionViewData.Plane.SetOrigin(point[0], point[1], point[2]);
_sectionViewData.Plane.SetNormal(normal[0], normal[1], normal[2]);
_sectionViewData.LightenColors = lightenColors;
_sectionViewData.SectionColor = sectionColor;
//
foreach (var entry in _actors)
{
if (entry.Value.SectionViewPossible) entry.Value.AddClippingPlane(_sectionViewData.Plane);
}
// Add new section cut actors
vtkMaxActor sectionViewActor;
foreach (var actor in _actors.Values.ToArray()) // must be copied to array
{
if (actor.SectionViewPossible)
{
sectionViewActor = GetSectionViewActor(actor);
//
if (sectionViewActor != null)
{
UpdateSectionViewActorColor(sectionViewActor);
//
AddActor(sectionViewActor, vtkRendererLayer.Base);
actor.SectionViewActor = sectionViewActor;
}
}
}
//
UpdateScalarFormatting();
//
RenderScene();
}
}
}
public void UpdateSectionView(double[] point, double[] normal, bool lightenColors, Color sectionColor)
{
lock (myLock)
{
if (_sectionViewData.Active)
{
// Remove previous section cut actors
ClearSectionViewActors();
// Modify section cut plane
_sectionViewData.Plane.SetOrigin(point[0], point[1], point[2]);
_sectionViewData.Plane.SetNormal(normal[0], normal[1], normal[2]);
_sectionViewData.LightenColors = lightenColors;
_sectionViewData.SectionColor = sectionColor;
// Add new section cut actors
vtkMaxActor sectionViewActor;
foreach (var actor in _actors.Values.ToArray())
{
if (actor.SectionViewPossible)
{
sectionViewActor = GetSectionViewActor(actor);
//
if (sectionViewActor != null)
{
UpdateSectionViewActorColor(sectionViewActor);
//
AddActor(sectionViewActor, vtkRendererLayer.Base);
actor.SectionViewActor = sectionViewActor;
}
//GetSectionViewActorProperties(sectionViewActor, point);
}
}
//
UpdateScalarFormatting();
//
RenderScene();
}
}
}
public void RemoveSectionView()
{
lock (myLock)
{
if (_sectionViewData.Active)
{
foreach (var entry in _actors) entry.Value.RemoveAllClippingPlanes();
// Remove previous section cut actors
ClearSectionViewActors();
//
_sectionViewData.Reset();
//
UpdateScalarFormatting();
//
RenderScene();
}
}
}
//
private void ClearSectionViewActors()
{
vtkMaxActor sectionVewActor;
foreach (var entry in _actors.ToArray())
{
sectionVewActor = entry.Value.SectionViewActor;
if (sectionVewActor != null)
{
_renderer.RemoveActor(sectionVewActor.Geometry);
if (sectionVewActor.ElementEdges != null) _renderer.RemoveActor(sectionVewActor.ElementEdges);
if (sectionVewActor.ModelEdges != null) _renderer.RemoveActor(sectionVewActor.ModelEdges);
//
_actors.Remove(sectionVewActor.Name);
entry.Value.SectionViewActor = null;
}
}
}
private vtkMaxActor GetSectionViewActor(vtkMaxActor actor)
{
try
{
if (actor.ActorRepresentation == vtkMaxActorRepresentation.Solid ||
actor.ActorRepresentation == vtkMaxActorRepresentation.Shell)
{
return GetSectionViewActorFromSolid(actor);
}
else if (actor.ActorRepresentation == vtkMaxActorRepresentation.SolidAsShell)
{
return GetSectionViewActorFromSolidAsShell(actor);
}
else
return null;
}
catch
{
return null;
}
}
private void GetSectionViewActorProperties(vtkMaxActor actor, double[] point)
{
vtkCell cell;
vtkPoints points;
vtkDataSet dataSet = actor.GeometryMapper.GetInput();
long numPoints = dataSet.GetNumberOfPoints();
long numCells = dataSet.GetNumberOfCells();
//
Dictionary<int, FeNode> nodes = new Dictionary<int, FeNode>();
for (int i = 0; i < numPoints; i++)
{
nodes.Add(i, new FeNode(i, dataSet.GetPoint(i)));
}
int[] nodeIds;
Dictionary<int, FeElement> elements = new Dictionary<int, FeElement>();
for (int i = 0; i < numCells; i++)
{
cell = dataSet.GetCell(i);
if (cell.GetCellType() == (int)vtkCellType.VTK_TRIANGLE)
{
vtkTriangle triangle = (vtkTriangle)cell;
nodeIds = new int[] { (int)triangle.GetPointId(0), (int)triangle.GetPointId(1), (int)triangle.GetPointId(2) };
elements.Add(i, new LinearTriangleElement(i, nodeIds));
}
}
FeMesh mesh = new FeMesh(nodes, elements, MeshRepresentation.Geometry, ImportOptions.DetectEdges);
//
double sumA = -1;
double sumL = -1;
double[] faceCenter = new double[3];
if (mesh.Parts.Count == 1)
{
VisualizationData vis = mesh.Parts.First().Value.Visualization;
if (vis.FaceCount == 1)
{
sumA = vis.FaceAreas[0];
sumL = 0;
for (int i = 0; i < vis.FaceEdgeIds[0].Length; i++) sumL += vis.EdgeLengths[i];
}
//
double A;
double[] elementFaceCenter;
foreach (var entry in elements)
{
mesh.GetElementFaceCenterAndNormal(entry.Value, FeFaceName.S2, out elementFaceCenter, out _, out _);
A = entry.Value.GetArea(FeFaceName.S2, nodes);
//
faceCenter[0] += elementFaceCenter[0] * A;
faceCenter[1] += elementFaceCenter[1] * A;
faceCenter[2] += elementFaceCenter[2] * A;
}
faceCenter[0] /= sumA;
faceCenter[1] /= sumA;
faceCenter[2] /= sumA;
}
//
string data = string.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}{8}", point[0], point[1], point[2],
sumA, sumL, faceCenter[0], faceCenter[1], faceCenter[2],
Environment.NewLine);
File.AppendAllText(@"C:\Temp\CrossSectionData.txt", data);
}
private vtkMaxActor GetSectionViewActorFromSolid(vtkMaxActor actor)
{
vtkMaxActor sectionViewActor = new vtkMaxActor(actor);
sectionViewActor.Name = GetSectionViewActorName(actor.Name);
sectionViewActor.BackfaceCulling = false;
// Get the unstructured grid
vtkUnstructuredGrid grid = vtkUnstructuredGrid.New();
grid.DeepCopy(actor.FrustumCellLocator.GetDataSet());
// Create a cutter
vtkCutter cutter = vtkCutter.New();
cutter.SetCutFunction(_sectionViewData.Plane);
cutter.SetInput(grid);
cutter.GenerateCutScalarsOff();
cutter.Update();
// GEOMETRY ##########################################################################
// Create poly data for the geometry actor
vtkGeometryFilter geometryFilter = vtkGeometryFilter.New();
geometryFilter.SetInput(cutter.GetOutput());
geometryFilter.Update();
vtkPolyData polyData = geometryFilter.GetOutput();
// Create the mapper for the geometry actor
vtkPolyDataMapper polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(polyData);
// Create actor
sectionViewActor.Geometry = vtkActor.New();
sectionViewActor.GeometryMapper = polyMapper;
sectionViewActor.GeometryProperty.DeepCopy(actor.GeometryProperty);
sectionViewActor.Geometry.PickableOff();
sectionViewActor.Geometry.SetVisibility(actor.Geometry.GetVisibility());
// EDGES #############################################################################
// The best function would be:
// - vtkExtractEdges
// but vtkExtractEdges produces internal edges for quadratic cells
// The solution:
// - extract the faces of all cells and cut the faces to get cell edges in the plane
// - to make it faster first find the cells on the plane
vtkExtractGeometry extract = vtkExtractGeometry.New();
extract.SetImplicitFunction(_sectionViewData.Plane);
extract.ExtractBoundaryCellsOn();
extract.ExtractOnlyBoundaryCellsOn();
extract.SetInput(grid);
extract.Update();
//
vtkCell cell;
vtkCell cellFace;
vtkUnstructuredGrid cellGrid = vtkUnstructuredGrid.New();
cellGrid.SetPoints(extract.GetOutput().GetPoints());
//
for (int i = 0; i < extract.GetOutput().GetNumberOfCells(); i++)
{
cell = extract.GetOutput().GetCell(i);
for (int j = 0; j < cell.GetNumberOfFaces(); j++)
{
cellFace = cell.GetFace(j);
cellGrid.InsertNextCell(cellFace.GetCellType(), cellFace.GetPointIds());
}
}
cellGrid.Update();
// Sometimes when cutting with a parallel plane, no section is found
// The solution:
// - move the cutting plane to find some edges
// - project the edges back to the plane to prevent them from hiding behind the section cut surface
vtkPlane cutPlane = vtkPlane.New();
double[] origin = _sectionViewData.Plane.GetOrigin();
double[] normal = _sectionViewData.Plane.GetNormal();
cutPlane.SetOrigin(origin[0], origin[1], origin[2]);
cutPlane.SetNormal(normal[0], normal[1], normal[2]);
//
cutter = vtkCutter.New();
cutter.SetCutFunction(cutPlane);
cutter.SetInput(cellGrid);
cutter.GenerateCutScalarsOff();
cutter.Update();
//
int count = 0;
int step = 0;
double delta = 0.01;
double[] b = GetBoundingBoxSize();
double[] v = new double[] { b[0] * delta * normal[0], b[1] * delta * normal[1], b[2] * delta * normal[2] };
//
if (cellGrid.GetNumberOfCells() > 0 && cutter.GetOutput().GetNumberOfCells() == 0)
{
// Try to move the cut plane forward and backward
while (count++ <= 4)
{
if (cutter.GetOutput().GetNumberOfCells() == 0)
{
step = (int)Math.Pow(-1, count) * (count + 1) / 2;
cutPlane.SetOrigin(origin[0] + step * v[0], origin[1] + step * v[1], origin[2] + step * v[2]);
cutter.Update();
}
else
{
// The section was found - move the points back to the plane
vtkPoints points = cutter.GetOutput().GetPoints();
double[] coor;
for (int i = 0; i < points.GetNumberOfPoints(); i++)
{
coor = points.GetPoint(i);
coor[0] -= step * v[0];
coor[1] -= step * v[1];
coor[2] -= step * v[2];
points.SetPoint(i, coor[0], coor[1], coor[2]);
}
break;
}
}
}
// Create the mapper for the element edges actor
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(cutter.GetOutput());
// Create actor
sectionViewActor.ElementEdges = vtkActor.New();
sectionViewActor.ElementEdges.SetMapper(polyMapper);
sectionViewActor.ElementEdgesProperty.DeepCopy(actor.ElementEdgesProperty);
sectionViewActor.ElementEdges.PickableOff();
sectionViewActor.ElementEdges.SetVisibility(actor.ElementEdges.GetVisibility());
sectionViewActor.ElementEdges.GetMapper().GetInput().GetPointData().RemoveArray(Globals.ScalarArrayName);
// MODEL EDGES #######################################################################
vtkFeatureEdges featureEdges = vtkFeatureEdges.New();
featureEdges.SetInput(polyData);
featureEdges.BoundaryEdgesOn();
featureEdges.FeatureEdgesOff();
featureEdges.ManifoldEdgesOff();
featureEdges.NonManifoldEdgesOff();
featureEdges.SetColoring(0);
featureEdges.Update();
// Create the mapper for the model edges actor
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(featureEdges.GetOutput());
// Create actor
sectionViewActor.ModelEdges = vtkActor.New();
sectionViewActor.ModelEdges.SetMapper(polyMapper);
sectionViewActor.ModelEdgesProperty.DeepCopy(actor.ModelEdgesProperty);
sectionViewActor.ModelEdges.PickableOff();
sectionViewActor.ModelEdges.SetVisibility(actor.ModelEdges.GetVisibility());
sectionViewActor.ModelEdges.GetMapper().GetInput().GetPointData().RemoveArray(Globals.ScalarArrayName);
//
return sectionViewActor;
}
private vtkMaxActor GetSectionViewActorFromSolidAsShell(vtkMaxActor actor)
{
vtkMaxActor sectionViewActor = new vtkMaxActor(actor);
sectionViewActor.Name = GetSectionViewActorName(actor.Name);
sectionViewActor.BackfaceCulling = false;
// Get the unstructured grid
vtkUnstructuredGrid grid = vtkUnstructuredGrid.New();
grid.DeepCopy(actor.FrustumCellLocator.GetDataSet());
// Create a cutter
vtkCutter cutter = vtkCutter.New();
cutter.SetCutFunction(_sectionViewData.Plane);
//cutter.SetInput(grid);
cutter.SetInput(actor.GeometryMapper.GetInput());
cutter.Update();
vtkStripper cutStrips = vtkStripper.New();
cutStrips.SetInput(cutter.GetOutput());
cutStrips.Update();
vtkPolyData polyData;
vtkPolyDataMapper polyMapper;
///////////////////////////////////////////////////////////////////////////////////////
polyData = vtkPolyData.New();
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(polyData);
sectionViewActor.Geometry = vtkActor.New();
sectionViewActor.GeometryMapper = polyMapper;
polyData = cutStrips.GetOutput();
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(polyData);
sectionViewActor.ElementEdges = vtkActor.New();
sectionViewActor.ElementEdges.SetMapper(polyMapper);
sectionViewActor.ElementEdgesProperty.DeepCopy(actor.ElementEdgesProperty);
sectionViewActor.ElementEdges.PickableOff();
sectionViewActor.ElementEdges.SetVisibility(actor.ElementEdges.GetVisibility());
sectionViewActor.ModelEdges = vtkActor.New();
sectionViewActor.ModelEdges.SetMapper(polyMapper);
sectionViewActor.ModelEdgesProperty.DeepCopy(actor.ModelEdgesProperty);
sectionViewActor.ModelEdges.PickableOff();
sectionViewActor.ModelEdges.SetVisibility(actor.ModelEdges.GetVisibility());
return sectionViewActor;
///////////////////////////////////////////////////////////////////////////////////////
if (cutter.GetOutput().GetNumberOfPoints() == 0) return null;
//System.Diagnostics.Debug.WriteLine("Cutter num. of points: " + cutter.GetOutput().GetNumberOfPoints());
//System.Diagnostics.Debug.WriteLine("Cutter num. of cells: " + cutter.GetOutput().GetNumberOfCells());
// GEOMETRY
//System.Diagnostics.Debug.WriteLine("CutStrips num. of points: " + cutStrips.GetOutput().GetNumberOfPoints());
//System.Diagnostics.Debug.WriteLine("CutStrips num. of cells: " + cutStrips.GetOutput().GetNumberOfCells());
// Normal
double[] n = _sectionViewData.Plane.GetNormal();
// Axis = n X z(0,0,1)
double[] axis = new double[] { n[1], -n[0], 0 };
// Angle
double l2 = Math.Pow(n[0], 2) + Math.Pow(n[1], 2) + Math.Pow(n[2], 2);
double phi = Math.Acos(n[2] / Math.Sqrt(l2));
vtkTransform transform = vtkTransform.New();
transform.RotateWXYZ(phi, axis[0], axis[1], axis[2]);
n[0] = Math.Abs(n[0]);
n[1] = Math.Abs(n[1]);
n[2] = Math.Abs(n[2]);
if (cutStrips.GetOutput().GetNumberOfCells() > 1
&& cutStrips.GetOutput().GetCell(0) is vtkPolyLine
&& n[2] == Math.Max(Math.Max(n[0], n[1]), n[2])
//&& false
)
{
polyData = cutStrips.GetOutput();
vtkPolyLine line0 = vtkPolyLine.New();
vtkPolyLine line1 = vtkPolyLine.New();
line0.DeepCopy(polyData.GetCell(0));
line1.DeepCopy(polyData.GetCell(1));
// Define a polygonal hole with a clockwise polygon
vtkPolygon polygon0 = vtkPolygon.New();
vtkPolygon polygon1 = vtkPolygon.New();
double[] coor;
long id;
for (int i = 0; i < line0.GetNumberOfPoints(); i++)
//for (int i = (int)line0.GetNumberOfPoints() - 1; i >= 0 ; i--)
{
id = line0.GetPointId(i);
polygon0.GetPointIds().InsertNextId(id);
coor = line0.GetPoints().GetPoint(i);
polygon0.GetPoints().InsertNextPoint(coor[0], coor[1], coor[2]);
}
for (int i = 0; i < line1.GetNumberOfPoints(); i++)
//for (int i = (int)line1.GetNumberOfPoints() - 1; i >= 0 ; i--)
{
id = line1.GetPointId(i);
polygon1.GetPointIds().InsertNextId(id);
coor = line1.GetPoints().GetPoint(i);
polygon1.GetPoints().InsertNextPoint(coor[0], coor[1], coor[2]);
}
double[] bounds0 = polygon0.GetBounds();
double[] bounds1 = polygon1.GetBounds();
vtkDelaunay3D test = vtkDelaunay3D.New();
// Create a cell array to store the polygon in
vtkCellArray polygonArray = vtkCellArray.New();
//polygonArray.InsertNextCell(polygon0);
//polygonArray.InsertNextCell(polygon1);
vtkPolyData allPoints = vtkPolyData.New();
allPoints.SetPoints(cutStrips.GetOutput().GetPoints());
// Create a poly data to store the boundary. The points must be the
// same as the points we will triangulate.
vtkPolyData boundary = vtkPolyData.New(); // this is the boundary
boundary.SetPoints(allPoints.GetPoints());
boundary.SetPolys(polygonArray);
// Triangulate the grid points
vtkDelaunay2D delaunay = vtkDelaunay2D.New();
delaunay.SetTransform(transform);
delaunay.SetInput(0, allPoints);
delaunay.SetInput(1, boundary);
delaunay.Update();
polyData = delaunay.GetOutput();
//polyData = boundary;
//if (polyData.GetNumberOfPoints() == 0)
// return null;
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(polyData);
//polyMapper.SetInputConnection(delaunay.GetOutputPort());
}
else
{
polyData = vtkPolyData.New();
polyData.SetPoints(cutStrips.GetOutput().GetPoints());
polyData.SetPolys(cutStrips.GetOutput().GetLines());
vtkTriangleFilter cutTriangles = vtkTriangleFilter.New();
cutTriangles.SetInput(polyData);
cutTriangles.Update();
polyData = cutTriangles.GetOutput();
// Create the mapper for the geometry actor
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(polyData);
//polyMapper.SetInputConnection(cutTriangles.GetOutputPort());
}
if (polyData.GetNumberOfPoints() == 0) return null;
// Create Actor
sectionViewActor.Geometry = vtkActor.New();
sectionViewActor.GeometryMapper = polyMapper;
sectionViewActor.GeometryProperty.DeepCopy(actor.GeometryProperty);
sectionViewActor.Geometry.PickableOff();
sectionViewActor.Geometry.SetVisibility(actor.Geometry.GetVisibility());
////////////////////////////////////////////////////////////////////////////////////////
//vtkClipClosedSurface clipClosed = vtkClipClosedSurface.New();
////////////////////////////////////////////////////////////////////////////////////////
// EDGES
//System.Diagnostics.Debug.WriteLine("Num. of points: " + polyData.GetNumberOfPoints());
//System.Diagnostics.Debug.WriteLine("Num. of cells: " + polyData.GetNumberOfCells());
vtkExtractEdges extractEdges = vtkExtractEdges.New();
extractEdges.SetInput(polyData);
extractEdges.Update();
// Create the mapper for the geometry actor
polyMapper = vtkPolyDataMapper.New();
polyMapper.SetInput(extractEdges.GetOutput());
sectionViewActor.ElementEdges = vtkActor.New();
sectionViewActor.ElementEdges.SetMapper(polyMapper);
sectionViewActor.ElementEdgesProperty.DeepCopy(actor.ElementEdgesProperty);
sectionViewActor.ElementEdges.PickableOff();
sectionViewActor.ElementEdges.SetVisibility(actor.ElementEdges.GetVisibility());
// MODEL EDGES
vtkFeatureEdges featureEdges = vtkFeatureEdges.New();
featureEdges.SetInput(polyData);
featureEdges.BoundaryEdgesOn();
featureEdges.FeatureEdgesOff();
featureEdges.ManifoldEdgesOff();
featureEdges.NonManifoldEdgesOff();
featureEdges.SetColoring(0);
featureEdges.Update();
// Create the mapper for the geometry actor
polyMapper = vtkPolyDataMapper.New();
//polyMapper.SetInput(featureEdges.GetOutput());
polyMapper.SetInput(cutStrips.GetOutput());
sectionViewActor.ModelEdges = vtkActor.New();
sectionViewActor.ModelEdges.SetMapper(polyMapper);
sectionViewActor.ModelEdgesProperty.DeepCopy(actor.ModelEdgesProperty);
sectionViewActor.ModelEdges.PickableOff();
sectionViewActor.ModelEdges.SetVisibility(actor.ModelEdges.GetVisibility());
return sectionViewActor;
}
//
private string GetSectionViewActorName(string actorName)
{
string name = actorName + Globals.NameSeparator + Globals.SectionViewSuffix + Globals.NameSeparator;
name = _actors.GetNextNumberedKey(name);
return name;
}
#endregion ################################################################################################################
#region Exploded view #####################################################################################################
public void PreviewExplodedView(Dictionary<string, double[]> partOffsets, bool animate, int timeMs)
{
vtkMaxActor actor;
double[] offsetFinal;
double[] offsetStart;
//
Dictionary<string, double[]> partOffsetsAnimation = new Dictionary<string, double[]>();
foreach (var partOffset in partOffsets)
{
offsetFinal = partOffset.Value;
if (_actors.TryGetValue(partOffset.Key, out actor))
{
offsetStart = actor.Geometry.GetPosition();
partOffsetsAnimation.Add(partOffset.Key, new double[] { offsetFinal[0] - offsetStart[0],
offsetFinal[1] - offsetStart[1],
offsetFinal[2] - offsetStart[2]});
}
}
//
DateTime start = DateTime.Now;
int delta = timeMs; //ms
double currentDelta;
double t;
double tPrev = 0;
Vec3D position = new Vec3D();
do
{
currentDelta = (DateTime.Now - start).TotalMilliseconds;
t = currentDelta / delta;
if (t > 1 || !animate) t = 1;
//t = 0.5 - 0.5 * Math.Cos(t * Math.PI);
t = 0.5 + 0.5 * Math.Atan(t * 6 - 3) / Math.Atan(3);
//
foreach (var partOffset in partOffsetsAnimation)
{
position.Coor = partOffset.Value;
position *= (t - tPrev);
actor = _actors[partOffset.Key];
position += new Vec3D(actor.Geometry.GetPosition());
//
actor.Geometry.SetPosition(position.X, position.Y, position.Z);
actor.ModelEdges.SetPosition(position.X, position.Y, position.Z);
actor.ElementEdges.SetPosition(position.X, position.Y, position.Z);
}
tPrev = t;
//
AdjustCameraDistanceAndClipping();
//
RenderScene();
//
Application.DoEvents();
}
while (t < 1);
}
public void RemovePreviewedExplodedView(string[] partNames)
{
vtkMaxActor actor;
double[] offset = new double[] { 0, 0, 0 };
//
foreach (var partName in partNames)
{
if (_actors.TryGetValue(partName, out actor))
{
actor.Geometry.SetPosition(offset[0], offset[1], offset[2]);
actor.ModelEdges.SetPosition(offset[0], offset[1], offset[2]);
actor.ElementEdges.SetPosition(offset[0], offset[1], offset[2]);
}
}
//
RenderScene();
}
#endregion ################################################################################################################
#region Transformations ###################################################################################################
public void AddSymmetry(int symmetryPlane, double[] symmetryPoint)
{
vtkTransform transform = vtkTransform.New();
transform.Translate(symmetryPoint[0], symmetryPoint[1], symmetryPoint[2]);
if (symmetryPlane == 0) transform.Scale(-1.0, 1.0, 1.0);
else if (symmetryPlane == 1) transform.Scale(1.0, -1.0, 1.0);
else if (symmetryPlane == 2) transform.Scale(1.0, 1.0, -1.0);
else throw new NotSupportedException();
transform.Translate(-symmetryPoint[0], -symmetryPoint[1], -symmetryPoint[2]);
//
_transforms.Add(transform, 2); // must be 2 for 1 loop
}
public void AddLinearPattern(double[] displacement, int numOfItems)
{
vtkTransform transform = vtkTransform.New();
transform.Translate(displacement[0], displacement[1], displacement[2]);
_transforms.Add(transform, numOfItems);
}
public void AddCircularPattern(double[] axisPoint, double[] axisNormal, double angle, int numOfItems)
{
vtkTransform transform = vtkTransform.New();
transform.Translate(axisPoint[0], axisPoint[1], axisPoint[2]);
transform.RotateWXYZ(angle, axisNormal[0], axisNormal[1], axisNormal[2]);
transform.Translate(-axisPoint[0], -axisPoint[1], -axisPoint[2]);
//
_transforms.Add(transform, numOfItems);
}
public void ApplyTransforms()
{
foreach (var transform in _transforms) TransformAllMaxActors(transform.Key, transform.Value);
//
UpdateScalarFormatting();
//
RenderScene();
}
public void RemoveTransformedActors()
{
bool copyExists = true;
while (copyExists)
{
copyExists = false;
foreach (vtkMaxActor actor in _actors.Values.ToArray())
{
if (actor.Copies != null && actor.Copies.Count > 0)
{
foreach (var copy in actor.Copies) RemoveActorWithCopies(copy);
actor.Copies.Clear();
//
copyExists = true;
}
}
}
}
private void RemoveActorWithCopies(vtkMaxActor actor)
{
// Transformed copies
foreach (var copy in actor.Copies) RemoveActorWithCopies(copy);
//
actor.Copies.Clear();
//
_actors.Remove(actor.Name);
//
_renderer.RemoveActor(actor.Geometry);
_renderer.RemoveActor(actor.ElementEdges);
_renderer.RemoveActor(actor.ModelEdges);
}
public void HideTransformedActors()
{
foreach (var entry in _actors)
{
if (entry.Value.Copies != null)
{
foreach (var actorCopy in entry.Value.Copies) HideShowActor(actorCopy, false);
}
}
ApplyEdgesVisibilityAndBackfaceCulling();
ApplyVisibilityToActorNodes();
//_style.AdjustCameraDistanceAndClipping();
}
public void ShowTransformedActors()
{
foreach (var entry in _actors)
{
if (entry.Value.Copies != null)
{
foreach (var actorCopy in entry.Value.Copies) HideShowActor(actorCopy, entry.Value.VtkMaxActorVisible);
}
}
ApplyEdgesVisibilityAndBackfaceCulling();
ApplyVisibilityToActorNodes();
//_style.AdjustCameraDistanceAndClipping();
}
//
public void TransformAllMaxActors(vtkTransform transform, int numOfItems)
{
vtkMaxActor baseActor;
vtkMaxActor transformedActor;
foreach (var actor in _actors.Values.ToArray())
{
baseActor = actor;
//
for (int i = 0; i < numOfItems - 1; i++)
{
transformedActor = new vtkMaxActor(baseActor);
transformedActor.Name = GetTransformedActorName(transformedActor.Name);
//
baseActor.Copies.Add(transformedActor);
//
TransformMaxActor(transformedActor, transform);
//
AddActor(transformedActor, vtkRendererLayer.Base);
//
baseActor = transformedActor;
}
}
}
private void TransformMaxActor(vtkMaxActor vtkMaxActor, vtkTransform transform)
{
TransformActor(vtkMaxActor.Geometry, transform);
if (vtkMaxActor.ElementEdges != null) TransformActor(vtkMaxActor.ElementEdges, transform);
if (vtkMaxActor.ModelEdges != null) TransformActor(vtkMaxActor.ModelEdges, transform);
// Transform locator to enable section view
if (vtkMaxActor.FrustumCellLocator != null)
{
vtkTransformFilter transformFilter = vtkTransformFilter.New();
transformFilter.SetInput(vtkMaxActor.FrustumCellLocator.GetDataSet());
transformFilter.SetTransform(transform);
transformFilter.Update();
//
vtkMaxActor.FrustumCellLocator.SetDataSet(transformFilter.GetOutput());
}
}
private void TransformActor(vtkActor actor, vtkTransform transform)
{
vtkPolyData polyData = (vtkPolyData)actor.GetMapper().GetInput();
//
vtkTransformPolyDataFilter transformFilter = vtkTransformPolyDataFilter.New();
transformFilter.SetInput(polyData);
transformFilter.SetTransform(transform);
transformFilter.Update();
//
double[] scale = transform.GetScale();
if (scale[0] < 0 || scale[1] < 0 || scale[2] < 0)
{
vtkReverseSense reverseSense = vtkReverseSense.New();
reverseSense.SetInputConnection(transformFilter.GetOutputPort());
reverseSense.ReverseNormalsOff();
reverseSense.ReverseCellsOn();
reverseSense.Update();
//
actor.GetMapper().SetInputConnection(reverseSense.GetOutputPort());
}
else
{
actor.GetMapper().SetInputConnection(transformFilter.GetOutputPort());
}
//
actor.PickableOff();
}
//
private string GetTransformedActorName(string actorName)
{
string name = actorName + Globals.NameSeparator + Globals.TransformationSuffix;
name = _actors.GetNextNumberedKey(name);
return name;
}
#endregion ################################################################################################################
#region Settings ###########################################################################################################
public void SetCoorSysVisibility(bool visibility)
{
if (_coorSys == null) return;
//
_drawCoorSys = visibility;
if (_drawCoorSys)
{
_coorSys.SetViewport(1 - 200f / Width, 0, 1, 200f / Height);
_coorSys.SetEnabled(1);
}
else _coorSys.SetEnabled(0);
}
// Scale bar
public void SetScaleWidgetVisibility(bool visibility)
{
if (visibility) _scaleWidget.VisibilityOn();
else _scaleWidget.VisibilityOff();
}
public void SetScaleWidgetUnit(string unit)
{
_scaleWidget.SetUnit(unit);
//
RenderScene();
}
// Scalar bar
public void InitializeResultWidgetPositions()
{
_scalarBarWidget.SetTopLeftPosition(20, 20);
_statusBlockWidget.SetTopLeftPosition(Width - _statusBlockWidget.GetWidth() - 20, 20);
}
public void SetScalarBarColorSpectrum(vtkMaxColorSpectrum colorSpectrum)
{
_colorSpectrum.DeepCopy(colorSpectrum);
//
_scalarBarWidget.SetNumberOfColors(_colorSpectrum.NumberOfColors); // for the scalar bar
_scalarBarWidget.MinColor = colorSpectrum.MinColor;
_scalarBarWidget.MaxColor = colorSpectrum.MaxColor;
}
public void SetScalarBarNumberFormat(string numberFormat)
{
_scalarBarWidget.SetLabelFormat(numberFormat);
}
public void SetScalarBarText(string fieldName, string componentName, string unitAbbreviation, string complexComponent,
string minMaxType)
{
_scalarBarWidget.SetText(fieldName, componentName, unitAbbreviation, complexComponent, minMaxType);
//
UpdateScalarFormatting();
}
public void DrawScalarBarBackground(bool drawBackground)
{
_scalarBarWidget.SetBackgroundColor(1, 1, 1);
if (drawBackground) _scalarBarWidget.BackgroundVisibilityOn();
else _scalarBarWidget.BackgroundVisibilityOff();
}
public void DrawScalarBarBorder(bool drawBorder)
{
if (drawBorder) _scalarBarWidget.BorderVisibilityOn();
else _scalarBarWidget.BorderVisibilityOff();
}
private string GetUnitAbbreviation()
{
if (_scalarBarWidget.GetVisibility() == 0) return "";
//
string unitAbbreviation = _scalarBarWidget.UnitAbbreviation;
if (unitAbbreviation == "/") unitAbbreviation = "";
else unitAbbreviation = " " + unitAbbreviation;
return unitAbbreviation;
}
// Color bar
public void InitializeColorBarWidgetPosition()
{
_colorBarWidget.SetTopLeftPosition(20, 20);
}
public void SetColorBarColorsAndLabels(Color[] colors, string[] labels)
{
_colorBarWidget.SetColorsAndLabels(colors, labels);
_colorBarWidget.VisibilityOn();
}
public void AddColorBarColorsAndLabels(Color[] colors, string[] labels)
{
_colorBarWidget.AddColorsAndLabels(colors, labels);
_colorBarWidget.VisibilityOn();
}
public void DrawColorBarBackground(bool drawBackground)
{
if (_colorBarWidget.GetVisibility() == 1)
{
_colorBarWidget.SetBackgroundColor(1, 1, 1);
if (drawBackground) _colorBarWidget.BackgroundVisibilityOn();
else _colorBarWidget.BackgroundVisibilityOff();
}
}
public void DrawColorBarBorder(bool drawBorder)
{
if (_colorBarWidget.GetVisibility() == 1)
{
if (drawBorder) _colorBarWidget.BorderVisibilityOn();
else _colorBarWidget.BorderVisibilityOff();
}
}
public void HideColorBar()
{
_colorBarWidget.VisibilityOff();
_colorBarWidget.ClearColorsAndLabels();
//
RenderScene();
}
// Status bar
public void SetStatusBlockVisibility(bool visibility)
{
_drawStatusBlock = visibility;
}
public void DrawStatusBlockBackground(bool drawBackground)
{
_statusBlockWidget.SetBackgroundColor(1, 1, 1);
if (drawBackground) _statusBlockWidget.BackgroundVisibilityOn();
else _statusBlockWidget.BackgroundVisibilityOff();
}
public void DrawStatusBlockBorder(bool drawBorder)
{
if (drawBorder) _statusBlockWidget.BorderVisibilityOn();
else _statusBlockWidget.BorderVisibilityOff();
}
public void SetStatusBlock(string name, DateTime dateTime, float analysisTimeOrFrequency, string unit,
string deformationVariable, float scaleFactor, vtkMaxFieldDataType fieldType, int stepNumber,
int incrementNumber)
{
if (_statusBlockWidget == null) return;
_statusBlockWidget.Name = name;
_statusBlockWidget.AnalysisTime = analysisTimeOrFrequency;
_statusBlockWidget.AnalysisTimeUnit = unit;
_statusBlockWidget.DateTime = dateTime;
_statusBlockWidget.DeformationVariable = deformationVariable;
_statusBlockWidget.DeformationScaleFactor = scaleFactor;
_statusBlockWidget.FieldType = fieldType;
_statusBlockWidget.AnimationScaleFactor = -1;
_statusBlockWidget.StepNumber = stepNumber;
_statusBlockWidget.IncrementNumber = incrementNumber;
if (_drawStatusBlock) _statusBlockWidget.VisibilityOn();
else _statusBlockWidget.VisibilityOff();
}
// General
public void SetBackground(bool gradient, Color topColor, Color bottomColor, bool redraw)
{
if (_renderer != null)
{
_renderer.SetGradientBackground(gradient);
_renderer.SetBackground2(topColor.R / 255.0, topColor.G / 255.0, topColor.B / 255.0);
_renderer.SetBackground(bottomColor.R / 255.0, bottomColor.G / 255.0, bottomColor.B / 255.0);
if (redraw) RenderScene();
}
}
public void SetLighting(double ambient, double diffuse, bool redraw)
{
foreach (var entry in _actors)
{
entry.Value.Ambient = ambient; // calls update color
entry.Value.Diffuse = diffuse; // calls update color
}
if (redraw) RenderScene();
}
public void SetSmoothing(bool pointSmoothing, bool lineSmoothing, bool redraw)
{
if (_renderWindow != null)
{
if (pointSmoothing != (_renderWindow.GetPointSmoothing() == 1) ||
lineSmoothing != (_renderWindow.GetLineSmoothing() == 1))
{
_renderWindow.Dispose();
_renderWindowInteractor.Dispose();
_renderWindow = vtkRenderWindow.New();
_renderWindow.SetParentId(this.Handle);
_renderWindow.SetNumberOfLayers(3);
_renderWindow.AddRenderer(_renderer);
_renderWindow.AddRenderer(_overlayRenderer);
_renderWindow.AddRenderer(_selectionRenderer);
SyncRenderWindowSize();
_renderWindowInteractor = vtkRenderWindowInteractor.New();
_renderWindowInteractor.SetInteractorStyle(_style);
_style.Reset();
_renderWindow.SetInteractor(_renderWindowInteractor);
_coorSys.SetInteractor(_renderWindowInteractor);
//_scaleBarWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
//_scalarBarWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
//_statusBlockWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
//_minValueWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
//_maxValueWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
//_probeWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
if (_drawCoorSys) _coorSys.EnabledOn();
else _coorSys.EnabledOff();
if (pointSmoothing) _renderWindow.PointSmoothingOn();
else _renderWindow.PointSmoothingOff();
if (lineSmoothing) _renderWindow.LineSmoothingOn();
else _renderWindow.LineSmoothingOff();
}
}
if (redraw) RenderScene();
}
// Highlight
public void SetHighlightColor(Color primaryHighlightColor, Color secondaryHighlightColor)
{
_primaryHighlightColor = primaryHighlightColor;
_secondaryHighlightColor = secondaryHighlightColor;
//
Color highlightColor;
foreach (var actor in _selectedActors)
{
if (actor.UseSecondaryHighlightColor) highlightColor = secondaryHighlightColor;
else highlightColor = primaryHighlightColor;
//
ApplySelectionFormattingToActor(actor);
}
RenderScene();
}
public void SetMouseHighlightColor(Color mouseHighlightColor)
{
Globals.CurrentMouseHighlightColor = mouseHighlightColor;
Globals.Initialize();
}
// Symbols
public void SetDrawSymbolEdges(bool drawSymbolEdges)
{
_drawSymbolEdges = drawSymbolEdges;
}
#endregion #################################################################################################################
#region Scalar fields ######################################################################################################
public void AddScalarFieldOnCells(vtkMaxActorData data, bool update)
{
// Create actor
vtkMaxActor actor = new vtkMaxActor(data);
// Add actor
AddActorGeometry(actor, vtkRendererLayer.Base);
// Add actorEdges
if (data.CanHaveElementEdges && actor.ElementEdges != null) AddActorEdges(actor, false, vtkRendererLayer.Base);
// Add modelEdges
if (actor.ModelEdges != null) AddActorEdges(actor, true, data.Layer);
//
if (update) UpdateScalarsAndCameraAndRedraw();
}
//
public bool AddAnimatedScalarFieldOnCells(vtkMaxActorData data)
{
if (_animationAcceleration) return AddAnimatedScalarFieldOnCellsAllActors(data);
else return AddAnimatedScalarFieldOnCellsAddRemoveActors(data);
}
public bool AddAnimatedScalarFieldOnCellsAddRemoveActors(vtkMaxActorData data)
{
//countError = 0;
int n = data.Geometry.NodesAnimation.Length;
// Create actor
vtkMaxActor actor;
vtkMaxActor baseActor = new vtkMaxActor(data);
// Add actor
AddActorGeometry(baseActor, data.Layer);
_animationFrameData.MemMb += n * baseActor.GeometryMapper.GetInput().GetActualMemorySize() / 1024.0;
// Add actorElementEdges
if (data.CanHaveElementEdges && baseActor.ElementEdges != null)
{
AddActorEdges(baseActor, false, data.Layer);
_animationFrameData.MemMb += n * baseActor.ElementEdges.GetMapper().GetInput().GetActualMemorySize() / 1024.0;
}
// Add modelEdges
if (baseActor.ModelEdges != null)
{
AddActorEdges(baseActor, true, data.Layer);
_animationFrameData.MemMb += n * baseActor.ModelEdges.GetMapper().GetInput().GetActualMemorySize() / 1024.0;
}
string name;
vtkMaxActor[] actors = new vtkMaxActor[n];
for (int i = 0; i < n; i++)
{
name = data.Name + "_animation-frame-" + i;
// Create actor
actor = new vtkMaxActor(baseActor);
actor.SetAnimationFrame(data, i);
actor.Name = name;
// Add actor
actors[i] = actor;
}
//
_animationActors.Add(baseActor.Name, actors);
//
AdjustCameraDistanceAndClippingRedraw();
//
return true;
}
public bool AddAnimatedScalarFieldOnCellsAllActors(vtkMaxActorData data)
{
string name;
Dictionary<int, string> animatedActorNames = new Dictionary<int, string>();
vtkMaxActor actor;
vtkMaxActor baseActor = new vtkMaxActor(data);
//
int n = data.Geometry.NodesAnimation.Length;
for (int i = 0; i < n; i++)
{
// Animated actor names
name = data.Name + "_animation-frame-" + i;
animatedActorNames.Add(i, name);
// Create actor
actor = new vtkMaxActor(baseActor);
actor.Name = name;
actor.SetAnimationFrame(data, i);
// Add actor
AddActorGeometry(actor, vtkRendererLayer.Base);
_animationFrameData.MemMb += actor.GeometryMapper.GetInput().GetActualMemorySize() / 1024.0;
// Add actorEdges
if (data.CanHaveElementEdges && actor.ElementEdges != null)
{
AddActorEdges(actor, false, vtkRendererLayer.Base);
_animationFrameData.MemMb += actor.ElementEdges.GetMapper().GetInput().GetActualMemorySize() / 1024.0;
}
// Add modelEdges
if (actor.ModelEdges != null)
{
AddActorEdges(actor, true, data.Layer);
_animationFrameData.MemMb += actor.ModelEdges.GetMapper().GetInput().GetActualMemorySize() / 1024.0;
}
int memLimit = 1000;
if (_animationFrameData.MemMb > memLimit)
{
if (MessageBoxes.ShowWarningQuestionOKCancel("The size of the problem requires more than " + memLimit + " MB of RAM." +
"This might cause the application to close down unexpectedly. Continue?")
== DialogResult.OK)
{
_animationFrameData.MemMb = -1000000; // prevet the message box from reappearing
}
else return false;
}
}
//
_animationFrameData.ActorVisible.Add(data.Name, true);
_animationFrameData.AnimatedActorNames.Add(animatedActorNames);
//
AdjustCameraDistanceAndClippingRedraw();
//
return true;
}
//
private void UpdateScalarFormatting()
{
vtkMaxActor actor;
vtkMapper mapper;
vtkPointData pointData;
// Legend
_scalarBarWidget.VisibilityOff();
//
vtkMaxTextWithArrowWidget minValueWidget;
vtkMaxTextWithArrowWidget maxValueWidget;
_arrowWidgets.TryGetValue(Globals.MinAnnotationName, out minValueWidget);
_arrowWidgets.TryGetValue(Globals.MaxAnnotationName, out maxValueWidget);
//
if (minValueWidget != null && minValueWidget.GetVisibility() == 0) minValueWidget = null;
if (maxValueWidget != null && maxValueWidget.GetVisibility() == 0) maxValueWidget = null;
//
if (minValueWidget != null) minValueWidget.VisibilityOff();
if (maxValueWidget != null) maxValueWidget.VisibilityOff();
//
vtkMaxExtreemeNode minNode = null;
vtkMaxExtreemeNode maxNode = null;
// Find min and max value on actors
foreach (var entry in _actors)
{
actor = entry.Value;
if (entry.Value == null) throw new ArgumentNullException("_actors.Actor", "The actor does not exist.");
mapper = actor.GeometryMapper;
pointData = mapper.GetInput().GetPointData();
// if the part does not have scalar data
if (actor.MinNode == null || actor.MaxNode == null) continue;
//
if (actor.ColorContours)
{
if (pointData.GetAttribute(0) == null || pointData.GetAttribute(0).GetName() != Globals.ScalarArrayName)
pointData.SetActiveScalars(Globals.ScalarArrayName);
if (mapper.GetInterpolateScalarsBeforeMapping() != 1)
mapper.SetInterpolateScalarsBeforeMapping(1); // discrete colors - smooth colors
}
else
{
if (pointData.GetAttribute(0) != null && pointData.GetAttribute(0).GetName() != "none")
pointData.SetActiveScalars("none");
if (mapper.GetInterpolateScalarsBeforeMapping() != 0)
mapper.SetInterpolateScalarsBeforeMapping(0); // discrete colors must be turned off
actor.UpdateColor();
}
//
if (!actor.VtkMaxActorVisible || !actor.ColorContours) continue;
//
if (minNode == null || maxNode == null) // the first time through
{
minNode = actor.MinNode;
maxNode = actor.MaxNode;
}
else
{
if (actor.MinNode != null && !float.IsNaN(actor.MinNode.Value) && actor.MinNode.Value < minNode.Value)
minNode = actor.MinNode;
if (actor.MaxNode != null && !float.IsNaN(actor.MaxNode.Value) && actor.MaxNode.Value > maxNode.Value)
maxNode = actor.MaxNode;
}
}
if (minNode == null || maxNode == null) return;
// Scalar bar and min/max values of actor scalar range
if (_colorSpectrum.MinMaxType == vtkColorSpectrumMinMaxType.Automatic)
{
if (_animationFrameData != null && _animationFrameData.UseAllFrameData) // animation from all frames
{
double[] animationRange = _animationFrameData.AllFramesScalarRange;
_scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), animationRange[0], animationRange[1]);
PrepareActorLookupTable(animationRange[0], animationRange[1]);
}
else // min max from current frame
{
_scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), minNode.Value, maxNode.Value);
PrepareActorLookupTable(minNode.Value, maxNode.Value);
}
}
else // Manual and min max from current frame
{
_scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), minNode.Value, maxNode.Value,
_colorSpectrum.MinUserValue, _colorSpectrum.MaxUserValue);
PrepareActorLookupTable(minNode.Value, maxNode.Value);
}
// Edit actors mapper
double[] actorRange = _lookupTable.GetTableRange();
vtkLookupTable lookup = vtkLookupTable.New();
lookup.DeepCopy(_lookupTable);
// Set NAN color as white
lookup.SetNanColor(1, 1, 1, 1);
//
foreach (var entry in _actors)
{
actor = entry.Value;
mapper = actor.GeometryMapper;
pointData = mapper.GetInput().GetPointData();
if (actor.ColorContours && actor.VtkMaxActorVisible && pointData.GetScalars() != null
&& !_animationFrameData.InitializedActorNames.Contains(entry.Value.Name)) // animation speedup
{
mapper.SetScalarRange(actorRange[0], actorRange[1]);
mapper.SetLookupTable(lookup);
}
}
// Scalar bar
_scalarBarWidget.VisibilityOn();
// Min Max widgets
string format;
//
double[] coor;
bool minVisible = minValueWidget != null;
bool maxVisible = maxValueWidget != null;
//
if (minVisible)
{
format = minValueWidget.GetNumberFormat();
coor = minNode.Coor;
if (coor != null)
{
minValueWidget.VisibilityOn();
minValueWidget.SetText("Min: " + minNode.Value.ToString(format) + GetUnitAbbreviation() + Environment.NewLine +
"Node id: " + minNode.Id);
minValueWidget.SetAnchorPoint(coor[0], coor[1], coor[2]);
}
else minValueWidget.VisibilityOff();
}
//
if (maxVisible)
{
format = maxValueWidget.GetNumberFormat();
coor = maxNode.Coor;
if (coor != null)
{
maxValueWidget.VisibilityOn();
maxValueWidget.SetText("Max: " + maxNode.Value.ToString(format) + GetUnitAbbreviation() + Environment.NewLine +
"Node id: " + maxNode.Id);
maxValueWidget.SetAnchorPoint(coor[0], coor[1], coor[2]);
}
else maxValueWidget.VisibilityOff();
}
}
public void UpdateActorScalarField(string actorName, float[] values, NodesExchangeData extremeNodes,
float[] frustumCellLocatorValues, bool update)
{
if (System.Diagnostics.Debugger.IsAttached && false)
{
Test(actorName, values, extremeNodes, frustumCellLocatorValues);
return;
}
// Add scalars
if (values != null)
{
vtkFloatArray scalars = vtkFloatArray.New();
scalars.SetName(Globals.ScalarArrayName);
scalars.SetNumberOfValues(values.Length);
for (int i = 0; i < values.Length; i++) scalars.SetValue(i, values[i]);
//
vtkFloatArray frustumScalars = vtkFloatArray.New();
frustumScalars.SetName(Globals.ScalarArrayName);
frustumScalars.SetNumberOfValues(frustumCellLocatorValues.Length);
for (int i = 0; i < frustumCellLocatorValues.Length; i++) frustumScalars.SetValue(i, frustumCellLocatorValues[i]);
//
UpdateActorScalarField(actorName, scalars, frustumScalars, extremeNodes);
}
else
{
RemoveActorScalarField(actorName);
}
//
if (update) UpdateScalarsAndRedraw();
}
private void UpdateActorScalarField(string actorName, vtkFloatArray scalars, vtkFloatArray frustumScalars,
NodesExchangeData extremeNodes)
{
vtkMaxActor actor = _actors[actorName];
// Transformed copies
foreach (var copy in actor.Copies) UpdateActorScalarField(copy.Name, scalars, frustumScalars, extremeNodes);
// Set scalars
actor.GeometryMapper.GetInput().GetPointData().SetScalars(scalars);
actor.MinNode = new vtkMaxExtreemeNode(extremeNodes.Ids[0], extremeNodes.Coor[0], extremeNodes.Values[0]);
actor.MaxNode = new vtkMaxExtreemeNode(extremeNodes.Ids[1], extremeNodes.Coor[1], extremeNodes.Values[1]);
// Set frustum scalars
actor.FrustumCellLocator.GetDataSet().GetPointData().SetScalars(frustumScalars);
}
private void RemoveActorScalarField(string actorName)
{
if (_actors.TryGetValue(actorName, out vtkMaxActor actor))
{
// Transformed copies
foreach (var copy in actor.Copies) RemoveActorScalarField(copy.Name);
// Remove scalars
//actor.GeometryMapper.GetInput().GetPointData().GetScalars().RemoveLastTuple();
actor.GeometryMapper.GetInput().GetPointData().RemoveArray(Globals.ScalarArrayName);
actor.MinNode = null;
actor.MaxNode = null;
// Remove frustum scalars
actor.FrustumCellLocator.GetDataSet().GetPointData().RemoveArray(Globals.ScalarArrayName);
//
vtkMapper mapper = actor.GeometryMapper;
if (mapper.GetInterpolateScalarsBeforeMapping() != 0) mapper.SetInterpolateScalarsBeforeMapping(0);
}
}
private void Test(string actorName, float[] values, CaeGlobals.NodesExchangeData extremeNodes,
float[] frustumCellLocatorValues)
{
// Add scalars
if (values != null)
{
vtkFloatArray scalars = vtkFloatArray.New();
scalars.SetName(Globals.ScalarArrayName);
scalars.SetNumberOfValues(values.Length);
for (int i = 0; i < values.Length; i++)
{
scalars.SetValue(i, values[i]);
}
vtkFloatArray frustumScalars = vtkFloatArray.New();
frustumScalars.SetName(Globals.ScalarArrayName);
frustumScalars.SetNumberOfValues(frustumCellLocatorValues.Length);
for (int i = 0; i < frustumCellLocatorValues.Length; i++)
{
frustumScalars.SetValue(i, frustumCellLocatorValues[i]);
}
if (_actors.ContainsKey(actorName)) // added for testing
{
// Set scalars
_actors[actorName].GeometryPointData.SetScalars(scalars);
//
_actors[actorName].MinNode = new vtkMaxExtreemeNode(extremeNodes.Ids[0], extremeNodes.Coor[0], extremeNodes.Values[0]);
_actors[actorName].MaxNode = new vtkMaxExtreemeNode(extremeNodes.Ids[1], extremeNodes.Coor[1], extremeNodes.Values[1]);
//Set frustum scalars
_actors[actorName].FrustumPointData.SetScalars(frustumScalars);
//up to here 185000++
}
//UpdateScalarFormatting();
if (true)
{
vtkMaxActor actor;
//vtkMapper mapper;
vtkPointData pointData;
vtkMaxExtreemeNode minNode = null;
vtkMaxExtreemeNode maxNode = null;
// Find min and max value on actors
foreach (var entry in _actors)
{
actor = entry.Value;
if (entry.Value == null) throw new ArgumentNullException("_actors.Actor", "The actor does not exist.");
//mapper = actor.GeometryMapper;
pointData = actor.GeometryPointData;
// if the part does not have scalar data
if (actor.MinNode == null || actor.MaxNode == null) continue;
if (actor.ColorContours)
{
if (pointData.GetAttribute(0) == null || pointData.GetAttribute(0).GetName() != Globals.ScalarArrayName)
pointData.SetActiveScalars(Globals.ScalarArrayName);
//if (mapper.GetInterpolateScalarsBeforeMapping() != 1)
// mapper.SetInterpolateScalarsBeforeMapping(1); // discrete colors
}
else
{
if (pointData.GetAttribute(0) != null && pointData.GetAttribute(0).GetName() != "none")
pointData.SetActiveScalars("none");
//if (mapper.GetInterpolateScalarsBeforeMapping() != 0)
// mapper.SetInterpolateScalarsBeforeMapping(0); // discrete colors must be turned off
actor.GeometryProperty.SetColor(actor.Color.R / 255d, actor.Color.G / 255d, actor.Color.B / 255d);
}
if (!actor.VtkMaxActorVisible || !actor.ColorContours) continue;
if (minNode == null || maxNode == null) // the first time through
{
minNode = actor.MinNode;
maxNode = actor.MaxNode;
}
else
{
if (actor.MinNode != null && actor.MinNode.Value < minNode.Value) minNode = actor.MinNode;
if (actor.MaxNode != null && actor.MaxNode.Value > maxNode.Value) maxNode = actor.MaxNode;
}
}
// Working to here
//if (minNode == null || maxNode == null) return;
//// Scalar bar and min/max values of actor scalar range
//if (_colorSpectrum.MinMaxType == vtkColorSpectrumMinMaxType.Automatic)
//{
// if (_animationFrameData != null && _animationFrameData.UseAllFrameData) // animation from all frames
// {
// double[] animationRange = _animationFrameData.AllFramesScalarRange;
// _scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), animationRange[0], animationRange[1]);
// PrepareActorLookupTable(animationRange[0], animationRange[1]);
// }
// else // min max from current frame
// {
// _scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), minNode.Value, maxNode.Value);
// PrepareActorLookupTable(minNode.Value, maxNode.Value);
// }
//}
//else // Manual and min max from current frame
//{
// _scalarBarWidget.CreateLookupTable(GetColorTransferFunction(), minNode.Value, maxNode.Value, _colorSpectrum.MinUserValue, _colorSpectrum.MaxUserValue);
// PrepareActorLookupTable(minNode.Value, maxNode.Value);
//}
}
RenderScene();
countError++;
if (countError % 1000 == 0) System.Diagnostics.Debug.WriteLine("Count: " + countError);
}
}
public void UpdateActorsColorContoursVisibility(string[] actorNames, bool colorContours)
{
foreach (var name in actorNames) UpdateActorColorContoursVisibility(name, colorContours);
//
UpdateScalarFormatting();
//
RenderScene();
}
private void UpdateActorColorContoursVisibility(string actorName, bool colorContours)
{
vtkMaxActor actor = _actors[actorName];
actor.ColorContours = colorContours;
// Transformed copies
foreach (var copy in actor.Copies) UpdateActorColorContoursVisibility(copy.Name, colorContours);
// Section view
if (actor.SectionViewActor != null) actor.SectionViewActor.ColorContours = colorContours;
}
#endregion #################################################################################################################
#region Animation ##########################################################################################################
public void SetAnimationFrameData(float[] time, int[] stepId, int[] stepIncrementId, float[] scale,
double[] allFramesScalarRange, vtkMaxAnimationType animationType)
{
_animationFrameData.Time = time;
_animationFrameData.StepId = stepId;
_animationFrameData.StepIncrementId = stepIncrementId;
_animationFrameData.ScaleFactor = scale;
_animationFrameData.AllFramesScalarRange = allFramesScalarRange;
_animationFrameData.AnimationType = animationType;
}
//
public void SetAnimationFrame(int frameNumber, bool scalarRangeFromAllFrames)
{
if (_animationAcceleration) SetAnimationFrameAllActors(frameNumber, scalarRangeFromAllFrames);
else SetAnimationFrameAddRemoveActors(frameNumber, scalarRangeFromAllFrames);
}
private void SetAnimationFrameAddRemoveActors(int frameNumber, bool scalarRangeFromAllFrames)
{
_animationFrameData.UseAllFrameData = scalarRangeFromAllFrames;
//
if (_statusBlockWidget != null && _animationFrameData != null)
{
_statusBlockWidget.StepNumber = _animationFrameData.StepId[frameNumber];
_statusBlockWidget.IncrementNumber = _animationFrameData.StepIncrementId[frameNumber];
_statusBlockWidget.AnalysisTime = _animationFrameData.Time[frameNumber];
_statusBlockWidget.AnimationScaleFactor = _animationFrameData.ScaleFactor[frameNumber];
_statusBlockWidget.AnimationType = _animationFrameData.AnimationType;
}
//
List<string> visibleActors = new List<string>();
vtkMaxActor actor;
bool applySectionView = false;
SectionViewData sectionViewData = null;
if (_sectionViewData.Active)
{
sectionViewData = _sectionViewData.DeepCopy();
applySectionView = true;
RemoveSectionView();
}
//
RemoveTransformedActors();
//
bool visible;
foreach (var entry in _animationActors)
{
// Find actor
if (_actors.TryGetValue(entry.Key, out actor))
{
visible = actor.VtkMaxActorVisible;
// Remove actor
RemoveActorWithCopies(actor);
_actors.Remove(entry.Key); // must be here to remove the actor - it has a different key than name
//
if (visible)
{
// Get animation actor
actor = entry.Value[frameNumber];
// Add actor
_actors.Add(entry.Key, actor);
_renderer.AddActor(actor.Geometry);
_renderer.AddActor(actor.ElementEdges);
_renderer.AddActor(actor.ModelEdges);
// Add actor name
visibleActors.Add(actor.Name);
}
}
}
//
ApplyTransforms();
//
if (applySectionView) CreateSectionView(sectionViewData.Plane.GetOrigin(), sectionViewData.Plane.GetNormal(),
sectionViewData.LightenColors, sectionViewData.SectionColor);
//
UpdateScalarFormatting();
//
_animationFrameData.InitializedActorNames.UnionWith(visibleActors); // add visible actors to initialized actors
//
ApplyEdgesVisibilityAndBackfaceCulling(); // calls invalidate
_style.AdjustCameraDistanceAndClipping();
//
//countError++;
//if (countError % 10 == 0) System.Diagnostics.Debug.WriteLine("Count: " + countError);
}
//
private void SetAnimationFrameAllActors(int frameNumber, bool scalarRangeFromAllFrames)
{
_animationFrameData.UseAllFrameData = scalarRangeFromAllFrames;
//
if (_statusBlockWidget != null && _animationFrameData != null)
{
_statusBlockWidget.StepNumber = _animationFrameData.StepId[frameNumber];
_statusBlockWidget.IncrementNumber = _animationFrameData.StepIncrementId[frameNumber];
_statusBlockWidget.AnalysisTime = _animationFrameData.Time[frameNumber];
_statusBlockWidget.AnimationScaleFactor = _animationFrameData.ScaleFactor[frameNumber];
_statusBlockWidget.AnimationType = _animationFrameData.AnimationType;
}
//
bool visible;
vtkMaxActor maxActor;
List<string> visibleActors = new List<string>();
string[] tmp;
string[] splitter = new string[] { "_animation-frame-" };
foreach (var listEntry in _animationFrameData.AnimatedActorNames)
{
foreach (var entry in listEntry)
{
tmp = entry.Value.Split(splitter, StringSplitOptions.None);
if (_animationFrameData.ActorVisible[tmp[0]])
{
if (_actors.TryGetValue(entry.Value, out maxActor))
{
visible = entry.Key == frameNumber;
//
HideShowActor(maxActor, visible);
if (visible) visibleActors.Add(entry.Value);
}
}
}
}
//
UpdateScalarFormatting();
//
_animationFrameData.InitializedActorNames.UnionWith(visibleActors); // add visible actors to initialized actors
//
ApplyEdgesVisibilityAndBackfaceCulling(); // calls invalidate
_style.AdjustCameraDistanceAndClipping();
}
//
public void SaveAnimationAsAVI(string fileName, int[] firstLastFrame, int step, int fps, bool scalarRangeFromAllFrames,
bool swing, bool encoderOptions)
{
if (step < 1) step = 1;
//
if (System.IO.File.Exists(fileName))
{
if (CaeGlobals.Tools.IsFileLocked(fileName))
{
MessageBoxes.ShowWarning("The selected file cannot be replaced.");
return;
}
}
//
vtkWindowToImageFilter windowToImage = vtkWindowToImageFilter.New();
windowToImage.SetInput(_renderWindow);
windowToImage.SetInputBufferTypeToRGB();
//
vtkAVIWriter avw = vtkAVIWriter.New();
avw.SetInputConnection(windowToImage.GetOutputPort());
avw.SetFileName(fileName);
avw.SetQuality(2);
avw.SetRate(fps);
//
if (encoderOptions) avw.PromptCompressionOptionsOn();
//avw.SetCompressorFourCC("MSVC"); //DIVX, XVID, and H264
//
vtkObject.GlobalWarningDisplayOff(); // if the video compression window is closed an error occurs
avw.Start();
vtkObject.GlobalWarningDisplayOn();
//
for (int i = firstLastFrame[0]; i <= firstLastFrame[1]; i += step)
{
SetAnimationFrame(i, scalarRangeFromAllFrames);
windowToImage.Modified();
avw.Write();
}
if (swing)
{
for (int i = firstLastFrame[1]; i >= firstLastFrame[0]; i -= step)
{
SetAnimationFrame(i, scalarRangeFromAllFrames);
windowToImage.Modified();
avw.Write();
}
}
avw.End();
}
public void SaveAnimationAsImages(string fileName, int[] firstLastFrame, int step, bool scalarRangeFromAllFrames, bool swing)
{
if (step < 1) step = 1;
int count = 0;
for (int i = firstLastFrame[0]; i <= firstLastFrame[1]; i += step) count++;
if (swing) for (int i = firstLastFrame[1]; i >= firstLastFrame[0]; i -= step) count++;
// create file names
string[] fileNames = new string[count];
int numOfPlaces = (int)Math.Log10(count) + 1;
string path = System.IO.Path.GetDirectoryName(fileName);
fileName = System.IO.Path.GetFileName(fileName);
for (int i = 0; i < fileNames.Length; i++)
{
fileNames[i] = System.IO.Path.Combine(path, (i + 1).ToString().PadLeft(numOfPlaces, '0') + "_" + fileName);
if (System.IO.File.Exists(fileNames[i]))
{
if (CaeGlobals.Tools.IsFileLocked(fileNames[i]))
{
MessageBoxes.ShowError("The file '" + fileNames[i] + "' cannot be replaced.");
return;
}
}
}
vtkWindowToImageFilter windowToImage = vtkWindowToImageFilter.New();
windowToImage.SetInput(_renderWindow);
windowToImage.SetInputBufferTypeToRGB();
vtkPNGWriter pngWriter = vtkPNGWriter.New();
pngWriter.SetInputConnection(windowToImage.GetOutputPort());
count = 0;
for (int i = firstLastFrame[0]; i <= firstLastFrame[1]; i += step)
{
SetAnimationFrame(i, scalarRangeFromAllFrames);
windowToImage.Modified();
pngWriter.SetFileName(fileNames[count++]);
pngWriter.Write();
}
if (swing)
{
for (int i = firstLastFrame[1]; i >= firstLastFrame[0]; i -= step)
{
SetAnimationFrame(i, scalarRangeFromAllFrames);
windowToImage.Modified();
pngWriter.SetFileName(fileNames[count++]);
pngWriter.Write();
}
}
}
public void RenderToPNG(string fileName)
{
vtkWindowToImageFilter windowToImage = vtkWindowToImageFilter.New();
windowToImage.SetInput(_renderWindow);
windowToImage.SetInputBufferTypeToRGB();
//
vtkPNGWriter pngWriter = vtkPNGWriter.New();
pngWriter.SetInputConnection(windowToImage.GetOutputPort());
//
pngWriter.SetFileName(fileName);
pngWriter.Write();
}
#endregion #################################################################################################################
#region Clear ##############################################################################################################
public void Clear()
{
if (_sectionViewData.Active) RemoveSectionView();
_transforms.Clear();
//
foreach (var entry in _actors)
{
if (entry.Value is vtkMaxCaptionActor ca)
{
_renderer.RemoveActor2D(ca.CaptionActor);
_renderer.RemoveActor(ca.TmpActor);
}
_renderer.RemoveActor(entry.Value.Geometry);
_renderer.RemoveActor(entry.Value.ElementEdges);
_renderer.RemoveActor(entry.Value.ModelEdges);
_renderer.RemoveActor(entry.Value.Nodes);
}
//_renderer.RemoveAllViewProps(); this removes all other actors for min/max values ...
_actors.Clear();
_cellPicker.RemoveAllLocators();
_propPicker.InitializePickList();
_animationActors.Clear();
_animationFrameData = new vtkMaxAnimationFrameData();
//
if (_scalarBarWidget != null) _scalarBarWidget.VisibilityOff();
if (_colorBarWidget != null) HideColorBar();
if (_statusBlockWidget != null) _statusBlockWidget.VisibilityOff();
if (_style != null) _style.Reset();
// Widgets
HideAllArrowWidgets();
//
ClearSelection();
ClearOverlay();
RemoveSectionView();
}
public void ClearButKeepParts()
{
vtkMaxActor actor;
List<string> actorsToRemove = new List<string>();
//
foreach (var entry in _actors)
{
actor = entry.Value;
if (!actor.IsAPart)
{
actorsToRemove.Add(actor.Name);
// Remove from renderer
_renderer.RemoveActor(actor.Geometry);
_renderer.RemoveActor(actor.ElementEdges);
_renderer.RemoveActor(actor.ModelEdges);
_renderer.RemoveActor(entry.Value.Nodes);
// Remove cell locator and picker
if (actor.Geometry.GetPickable() == 1)
{
if (actor.CellLocator != null) _cellPicker.RemoveLocator(actor.CellLocator);
_propPicker.DeletePickList(actor.Geometry);
}
}
}
// Remove actors
foreach (string name in actorsToRemove) _actors.Remove(name);
//
ClearSelection();
ClearOverlay();
}
public void ClearSelection(bool clearAllMouseSelection = true)
{
if (clearAllMouseSelection)
{
if (_mouseSelectionAllIds.Count > 0) _mouseSelectionAllIds.Clear();
_mouseSelectionCurrentIds = null;
}
//
ClearCurrentMouseSelection(false);
// Actors
foreach (var entry in _actors)
{
entry.Value.UpdateColor();
}
// Actors and edges - leave mouse
foreach (vtkMaxActor actor in _selectedActors)
{
if (actor is vtkMaxCaptionActor ca)
{
_selectionRenderer.RemoveActor2D(ca.CaptionActor);
_selectionRenderer.RemoveActor(ca.TmpActor);
}
else
{
_renderer.RemoveActor(actor.Geometry); // some selections are drawn on the base layer
_renderer.RemoveActor(actor.ElementEdges);
//
_selectionRenderer.RemoveActor(actor.Geometry);
_selectionRenderer.RemoveActor(actor.ElementEdges);
}
}
_selectedActors.Clear();
//
RenderScene();
}
public void ClearCurrentMouseSelection()
{
ClearCurrentMouseSelection(true);
}
public void ClearCurrentMouseSelection(bool render)
{
if (_mouseSelectionActorCurrent != null)
{
_selectionRenderer.RemoveActor(_mouseSelectionActorCurrent.Geometry);
_selectionRenderer.RemoveActor(_mouseSelectionActorCurrent.ElementEdges);
_selectedActors.Remove(_mouseSelectionActorCurrent);
_mouseSelectionActorCurrent = null;
}
//
_mouseSelectionCurrentIds = null;
//
if (_probeWidget != null && _probeWidget.GetVisibility() == 1) _probeWidget.VisibilityOff();
if (render) RenderScene();
}
public void ClearOverlay()
{
_maxSymbolSize = 0;
foreach (var entry in _overlayActors)
{
if (entry.Value is vtkMaxCaptionActor ca)
{
_overlayRenderer.RemoveActor2D(ca.CaptionActor);
_overlayRenderer.RemoveActor(ca.TmpActor);
}
else _overlayRenderer.RemoveActor(entry.Value.Geometry);
}
_overlayActors.Clear();
RenderScene();
}
// Add by Luke 2025-11-25
public Dictionary<string, vtkMaxActor> OverlayActors => _overlayActors;
#endregion #################################################################################################################
#region Widgets ############################################################################################################
public void ResetScaleBarPosition()
{
_scaleWidget.SetHorizontallyRelativePosition((Width - _scaleWidget.GetWidth()) / 2, 0);
}
public void AddArrowWidget(string name, string text, string numberFormat, double[] anchorPoint,
bool drawBackground, bool drawBorder, bool visible)
{
vtkMaxTextWithArrowWidget arrowWidget;
// Create annotation
if (!_arrowWidgets.TryGetValue(name, out arrowWidget))
{
arrowWidget = new vtkMaxTextWithArrowWidget(name);
arrowWidget.SetInteractor(_selectionRenderer, _renderWindowInteractor);
arrowWidget.SetBorderColor(0, 0, 0);
arrowWidget.SetTextProperty(CreateNewTextProperty());
arrowWidget.SetPadding(5);
arrowWidget.GetBackgroundProperty().SetColor(1, 1, 1);
// Set text, number format and anchor before arrange
arrowWidget.SetNumberFormat(numberFormat);
// Event
arrowWidget.MouseDoubleClick += arrowWidget_DoubleClicked;
// Add
_arrowWidgets.Add(name, arrowWidget);
// Arrange
ArrangeVisibleArrowWidgets();
}
// Edit annotation
else
{
arrowWidget.SetNumberFormat(numberFormat);
}
//
if (visible) arrowWidget.VisibilityOn();
else arrowWidget.VisibilityOff();
//
if (drawBackground) arrowWidget.BackgroundVisibilityOn();
else arrowWidget.BackgroundVisibilityOff();
if (drawBorder) arrowWidget.BorderVisibilityOn();
else arrowWidget.BorderVisibilityOff();
// Update the contents and visibility of the min/max annotations - due to visibility must be here
if (visible && (name == Globals.MinAnnotationName || name == Globals.MaxAnnotationName)) UpdateScalarFormatting();
else
{
arrowWidget.SetText(text);
arrowWidget.SetAnchorPoint(anchorPoint[0], anchorPoint[1], anchorPoint[2]);
}
//
RenderScene();
}
private void ArrangeVisibleArrowWidgets()
{
// Count visible
int count = 0;
foreach (var entry in _arrowWidgets)
{
if (entry.Value.GetVisibility() == 1) count++;
}
CaeMesh.BoundingBox[] boxes = new CaeMesh.BoundingBox[count];
CaeMesh.BoundingBox[] fixedBoxes = new CaeMesh.BoundingBox[count];
// Get bounding boxes
count = 0;
foreach (var entry in _arrowWidgets)
{
if (entry.Value.GetVisibility() == 1)
{
boxes[count] = entry.Value.GetBoundingBox();
fixedBoxes[count] = entry.Value.GetAnchorPointBox();
count++;
}
}
// Compute BB offsets
int explodedType = 4; // z = 0
double scaleFactor = 1;
double[][] offsets = CaeMesh.BoundingBox.GetExplodedBBOffsets(explodedType, scaleFactor, boxes, fixedBoxes);
// Modify position
count = 0;
foreach (var entry in _arrowWidgets)
{
if (entry.Value.GetVisibility() == 1)
{
entry.Value.OffsetPosition(offsets[count][0], offsets[count][1]);
count++;
}
}
}
public void RemoveAllArrowWidgets()
{
foreach (var entry in _arrowWidgets) entry.Value.RemoveInteractor();
//
_arrowWidgets.Clear();
}
public void RemoveArrowWidgets(string[] widgetNames)
{
vtkMaxTextWithArrowWidget widget;
foreach (var name in widgetNames)
{
if (_arrowWidgets.TryGetValue(name, out widget))
{
widget.RemoveInteractor();
_arrowWidgets.Remove(name);
}
}
//
RenderScene();
}
public void HideAllArrowWidgets()
{
foreach (var entry in _arrowWidgets) entry.Value.VisibilityOff();
}
#endregion #################################################################################################################
public void SwitchLights()
{
_renderer.RemoveAllLights();
//
_renderer.AddLight(_light1);
_light1.SetSwitch((_light1.GetSwitch() + 1) % 2);
//
_renderer.AddLight(_light2);
_light2.SetSwitch((_light2.GetSwitch() + 1) % 2);
//
vtkLight light3 = vtkLight.New();
light3.SetPosition(0, -1, 0);
light3.SetFocalPoint(0, 0, 0);
light3.SetColor(1, 1, 1);
light3.SetIntensity(0.5);
light3.SetSpecularColor(0, 0, 0);
light3.SetLightTypeToCameraLight();
_renderer.AddLight(light3);
//
RenderScene();
}
public void InterpolateMeshData(PartExchangeData source, ref PartExchangeData input)
{
vtkMaxActorData vtkSourceData = new vtkMaxActorData();
vtkSourceData.Geometry = source;
vtkMaxActor vtkSourceActor = new vtkMaxActor(vtkSourceData);
//
vtkMaxActorData vtkInputData = new vtkMaxActorData();
vtkInputData.Geometry = input;
vtkMaxActor vtkInputActor = new vtkMaxActor(vtkInputData);
//
vtkProbeFilter probeFilter = new vtkProbeFilter();
probeFilter.SetSource(vtkSourceActor.Geometry.GetMapper().GetInput());
probeFilter.SetInput(vtkInputActor.Geometry.GetMapper().GetInput());
probeFilter.Update();
//
vtkDataArray scalars = probeFilter.GetOutput().GetPointData().GetScalars(Globals.ScalarArrayName);
input.Nodes.Values = new float[scalars.GetNumberOfTuples()];
for (int i = 0; i < scalars.GetNumberOfTuples(); i++)
{
input.Nodes.Values[i] = (float)scalars.GetTuple1(i);
}
}
public bool ContainsActor(string actorName)
{
return _actors.ContainsKey(actorName);
}
private string GetActorName(vtkActor actor)
{
if (actor == null) return null;
//
foreach (var entry in _actors)
{
if (entry.Value.Geometry == actor || entry.Value.ElementEdges == actor ||entry.Value.ModelEdges == actor)
return entry.Key;
}
//
return null;
}
private vtkMaxActor GetSelectedMaxActor(vtkActor actor)
{
if (actor == null) return null;
//
foreach (var selectionActor in _selectedActors)
{
if (selectionActor.Geometry == actor || selectionActor.ElementEdges == actor || selectionActor.ModelEdges == actor)
return selectionActor;
}
//
return null;
}
private vtkMaxActor GetMaxActor(vtkActor actor)
{
if (actor == null) return null;
//
foreach (var entry in _actors)
{
if (entry.Value.Geometry == actor || entry.Value.ElementEdges == actor || entry.Value.ModelEdges == actor)
return entry.Value;
}
//
return null;
}
public void UpdateActor(string oldName, string newName, Color newColor)
{
if (!_actors.ContainsKey(oldName)) return;
//
vtkMaxActor actor = _actors[oldName];
actor.Name = newName;
//
UpdateActorColor(actor, newColor);
//
_actors.Remove(oldName);
_actors.Add(newName, actor);
//
ApplyEdgesVisibilityAndBackfaceCulling();
//
RenderScene();
}
public void UpdateActorColor(vtkMaxActor actor, Color newColor)
{
actor.Color = newColor;
// Transformed copies
foreach (var copy in actor.Copies) UpdateActorColor(copy, newColor);
// Section view
if (_sectionViewData.Active && actor.SectionViewActor != null)
{
actor.SectionViewActor.Color = newColor; // set to default
UpdateSectionViewActorColor(actor.SectionViewActor); // update
}
}
private void UpdateSectionViewActorColor(vtkMaxActor sectionViewActor)
{
if (sectionViewActor != null)
{
if (_sectionViewData.LightenColors)
sectionViewActor.Color = sectionViewActor.Color.Lighten();
else if (_sectionViewData.SectionColor != null &&
_sectionViewData.SectionColor != Color.Empty)
{
sectionViewActor.Color = _sectionViewData.SectionColor;
}
}
}
public double[] GetBoundingBox()
{
// xMin, xMax, yMin, yMax, zMin, zMax
return _renderer.ComputeVisiblePropBounds();
}
public double[] GetBoundingBoxSize()
{
// xMin, xMax, yMin, yMax, zMin, zMax
double[] b = _renderer.ComputeVisiblePropBounds();
return new double[] { b[1] - b[0], b[3] - b[2], b[5] - b[4] };
}
public double GetBoundingBoxDiagonal()
{
double[] b = GetBoundingBoxSize();
return Math.Sqrt(Math.Pow(b[0], 2) + Math.Pow(b[1], 2) + Math.Pow(b[2], 2));
}
// Render
private void RenderScene()
{
if (_renderingOn)
{
this.Invalidate();
//Application.DoEvents();
}
}
// Tools
public void CropPartWithCylinder(string partName, double r, string fileName)
{
vtkMaxActor actor = _actors[partName];
actor.CropWithCylinder(r, fileName);
}
public void CropPartWithCube(string partName, double a, string fileName)
{
vtkMaxActor actor = _actors[partName];
actor.CropWithCube(a, fileName);
}
public void SmoothPart(string partName, double a, string fileName)
{
vtkMaxActor actor = _actors[partName];
actor.Smooth(a, fileName);
}
// Test
public void Export(string fileName)
{
foreach (var entry in _actors)
{
if (entry.Key == "Solid_part-1")
{
vtkPolyDataWriter writer = new vtkPolyDataWriter();
writer.SetInput(entry.Value.GeometryMapper.GetInput());
fileName = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".vtk");
writer.SetFileName(fileName);
writer.Write();
}
}
return;
_renderWindow.RemoveRenderer(_selectionRenderer);
_renderWindow.RemoveRenderer(_overlayRenderer);
vtkOBJExporter exporter = vtkOBJExporter.New();
//vtkX3DExporter exporter = vtkX3DExporter.New();
//vtkVRMLExporter exporter = vtkVRMLExporter.New();
exporter.SetRenderWindow(_renderWindow);
exporter.DebugOn();
//exporter.SetFileName(Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".vrml"));
exporter.SetFilePrefix(Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) + ".out"));
//string outName = exporter.GetFilePrefix();
exporter.Update();
exporter.Write();
_renderWindow.AddRenderer(_selectionRenderer);
_renderWindow.AddRenderer(_overlayRenderer);
}
public void AddTetrahedronFaces(double[][] nodes, int[][] tetrahedrons, Color color, int faceId, vtkRendererLayer layer)
{
// Create the points
vtkPoints points = vtkPoints.New();
points.SetNumberOfPoints(nodes.GetLength(0));
for (int i = 0; i < nodes.GetLength(0); i++)
{
points.SetPoint(i, nodes[i][0], nodes[i][1], nodes[i][2]);
}
// Node Ids from face ids
int[] nodeIds;
switch (faceId)
{
case 1:
nodeIds = new int[] { 0, 2, 1 };
break;
case 2:
nodeIds = new int[] { 0, 1, 3 };
break;
case 3:
nodeIds = new int[] { 1, 2, 3 };
break;
case 4:
nodeIds = new int[] { 2, 0, 3 };
break;
default:
throw new NotImplementedException();
}
// Elements to cells
vtkCellArray cells = vtkCellArray.New();
for (int i = 0; i < tetrahedrons.GetLength(0); i++)
{
cells.InsertNextCell(3);
cells.InsertCellPoint(tetrahedrons[i][nodeIds[0]]);
cells.InsertCellPoint(tetrahedrons[i][nodeIds[1]]);
cells.InsertCellPoint(tetrahedrons[i][nodeIds[2]]);
}
// Unstructured grid
vtkUnstructuredGrid uGrid = vtkUnstructuredGrid.New();
uGrid.SetPoints(points);
uGrid.SetCells((int)vtkCellType.VTK_TRIANGLE, cells);
uGrid.Update();
// Edges
vtkExtractEdges extractEdges = vtkExtractEdges.New();
extractEdges.SetInput(uGrid);
extractEdges.Update();
// Visualize mesh
vtkDataSetMapper mapperGrid = vtkDataSetMapper.New();
mapperGrid.SetInput(uGrid);
vtkMaxActor actorGrid = new vtkMaxActor();
actorGrid.GeometryMapper = mapperGrid;
actorGrid.GeometryProperty.SetColor(color.R / 255d, color.G / 255d, color.B / 255d);
actorGrid.GeometryProperty.SetAmbient(0.5);
actorGrid.GeometryProperty.BackfaceCullingOn();
AddActorGeometry(actorGrid, layer);
RenderScene();
}
public void AddTest()
{
double[,] p = new double[,] {
{ 0.0, 0.0, 0.0 },
{ 1.0, 0.0, 0.0 },
{ 1.0, 1.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0 },
{ 1.0, 0.0, 1.0 },
{ 1.0, 1.0, 1.0 },
{ 0.0, 1.0, 1.0 },
{ 0.0, 1.0, 2.0 }
};
// Create the points
vtkPoints points = vtkPoints.New();
points.SetNumberOfPoints(p.GetLength(0));
for (int i = 0; i < p.GetLength(0); i++)
{
points.SetPoint(i, p[i, 0], p[i, 1], p[i, 2]);
}
// Elements to cells
//vtkCellArray cells = vtkCellArray.New();
//for (int i = 0; i < tetrahedrons.GetLength(0); i++)
//{
// cells.InsertNextCell(4);
// cells.InsertCellPoint(tetrahedrons[i][0]);
// cells.InsertCellPoint(tetrahedrons[i][1]);
// cells.InsertCellPoint(tetrahedrons[i][2]);
// cells.InsertCellPoint(tetrahedrons[i][3]);
//}
// Create a hexahedron from the points
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
// Unstructured grid
vtkUnstructuredGrid uGrid = vtkUnstructuredGrid.New();
uGrid.SetPoints(points);
vtkIdList list = vtkIdList.New();
for (int i = 0; i < 1; i++)
{
list.SetNumberOfIds(8);
for (int j = 0; j < 8; j++)
{
list.SetId(j, j);
}
uGrid.InsertNextCell((int)vtkCellType.VTK_HEXAHEDRON, list);
list.SetNumberOfIds(4);
list.SetId(0, 4);
list.SetId(1, 6);
list.SetId(2, 7);
list.SetId(3, 8);
uGrid.InsertNextCell((int)vtkCellType.VTK_TETRA, list);
}
watch.Stop();
//uGrid.InsertNextCell(hex.GetCellType(), hex.GetPointIds());
uGrid.Update();
// Visualize mesh
vtkDataSetMapper mapperGrid = vtkDataSetMapper.New();
mapperGrid.SetInput(uGrid);
vtkMaxActor actorGrid = new vtkMaxActor();
actorGrid.GeometryMapper = mapperGrid;
actorGrid.GeometryProperty.SetColor(1, 0.5, 0.5);
// Visualize edges
// Extract edges
vtkExtractEdges extractEdges = vtkExtractEdges.New();
extractEdges.SetInput(uGrid);
extractEdges.Update();
vtkPolyDataMapper mapperEdges = vtkPolyDataMapper.New();
mapperEdges.SetInputConnection(extractEdges.GetOutputPort());
vtkMaxActor actorEdges = new vtkMaxActor();
actorEdges.GeometryMapper = mapperEdges;
actorEdges.GeometryProperty.SetColor(0, 0, 0);
actorEdges.GeometryProperty.SetLineWidth(1);
actorEdges.Geometry.PickableOff();
AddActorGeometry(actorGrid, vtkRendererLayer.Base);
RenderScene();
}
private void Hexahedron()
{
// Setup the coordinates of eight points
// (faces must be in counter clockwise order as viewed from the outside)
double[,] p = new double[,] {
{ 0.0, 0.0, 2.0 },
{ 1.0, 0.0, 2.0 },
{ 1.0, 1.0, 2.0 },
{ 0.0, 1.0, 2.0 },
{ 0.0, 0.0, 3.0 },
{ 1.0, 0.0, 3.0 },
{ 1.0, 1.0, 3.0 },
{ 0.0, 1.0, 3.0 }
};
// Create the points
vtkPoints points = vtkPoints.New();
for (int i = 0; i < 8; i++)
points.InsertNextPoint(p[i, 0], p[i, 1], p[i, 2]);
// Create a hexahedron from the points
vtkHexahedron hex = vtkHexahedron.New();
for (int i = 0; i < 8; i++)
hex.GetPointIds().SetId(i, i);
// Add the hexahedron to a cell array
vtkCellArray hexes = vtkCellArray.New();
hexes.InsertNextCell(hex);
// Add the points and hexahedron to an unstructured grid
vtkUnstructuredGrid uGrid = vtkUnstructuredGrid.New();
uGrid.SetPoints(points);
uGrid.InsertNextCell(hex.GetCellType(), hex.GetPointIds());
// Edges
vtkExtractEdges extractEdges = vtkExtractEdges.New();
extractEdges.SetInput(uGrid);
extractEdges.Update();
// Visualize
vtkDataSetMapper mapper = vtkDataSetMapper.New();
mapper.SetInput(uGrid);
vtkActor actor = vtkActor.New();
actor.SetMapper(mapper);
actor.GetProperty().BackfaceCullingOn();
// Visualize edges
vtkPolyDataMapper mapperEdges = vtkPolyDataMapper.New();
mapperEdges.SetInputConnection(extractEdges.GetOutputPort());
vtkPolyDataMapper.SetResolveCoincidentTopologyToPolygonOffset();
vtkActor actorEdges = vtkActor.New();
actorEdges.SetMapper(mapperEdges);
actorEdges.GetProperty().SetColor(0, 0, 0);
actorEdges.GetProperty().SetLineWidth(1);
_renderer.AddActor(actor);
_renderer.AddActor(actorEdges);
// fit all in
//double[] bounds = m_Renderer.ComputeVisiblePropBounds();
IntPtr test = System.Runtime.InteropServices.Marshal.AllocHGlobal(6 * 8);
_renderer.ComputeVisiblePropBounds(test);
_renderer.ResetCamera(test);
RenderScene();
}
public void AddSphere()
{
// source object
vtkSphereSource SphereSource = vtkSphereSource.New();
SphereSource.SetRadius(100);
//SphereSource.SetEndTheta(180);
//SphereSource.SetEndPhi(180);
SphereSource.SetPhiResolution(50);
SphereSource.SetThetaResolution(50);
SphereSource.Update();
// mapper
vtkPolyDataMapper sphereMapper = vtkPolyDataMapper.New();
sphereMapper.SetInputConnection(SphereSource.GetOutputPort());
// actor
vtkActor sphereActor = vtkActor.New();
sphereActor.GetProperty().SetColor(1, 0, 0);
sphereActor.SetMapper(sphereMapper);
//sphereActor.GetProperty().SetInterpolationToFlat();
//sphereActor.GetProperty().SetInterpolationToGouraud();
sphereActor.GetProperty().SetInterpolationToPhong();
sphereActor.GetProperty().SetAmbient(0.5);
sphereActor.GetProperty().SetDiffuse(0.5);
sphereActor.GetProperty().SetSpecular(0.6);
sphereActor.GetProperty().SetSpecularColor(1, 1, 1);
sphereActor.GetProperty().SetSpecularPower(100);
// add actor to the renderer
_renderer.AddActor(sphereActor);
//_selectedActors.Add(sphereActor);
// ensure all actors are visible (in this example not necessarily needed,
// but in case more than one actor needs to be shown it might be a good idea)
_renderer.ResetCamera();
RenderScene();
}
private void Actor2D()
{
// Create the geometry of a point (the coordinate)
vtkPoints points = vtkPoints.New();
//points.InsertNextPoint(rotationCenter[0], rotationCenter[1], rotationCenter[2]);
points.InsertNextPoint(100, 100, 0);
points.InsertNextPoint(200, 200, 0);
points.InsertNextPoint(200, 10, 200);
vtkPolyData pointsPolyData = vtkPolyData.New();
pointsPolyData.SetPoints(points);
vtkVertexGlyphFilter glyphFilter = vtkVertexGlyphFilter.New();
glyphFilter.SetInputConnection(pointsPolyData.GetProducerPort());
glyphFilter.Update();
// Visualize
vtkPolyDataMapper2D mapper = vtkPolyDataMapper2D.New();
mapper.SetInputConnection(glyphFilter.GetOutputPort());
mapper.Update();
vtkActor2D actor = vtkActor2D.New();
actor.SetMapper(mapper);
actor.GetProperty().SetColor(1, 0, 0);
actor.GetProperty().SetPointSize(5);
_renderer.AddViewProp(actor);
_renderer.ResetCamera();
}
private void AddGlyphDemo()
{
vtkPoints points = vtkPoints.New();
points.InsertNextPoint(77.5, 65, 0);
points.InsertNextPoint(78.5, 65, 0);
points.InsertNextPoint(79.5, 65, 0);
vtkPolyData polyData = vtkPolyData.New();
polyData.SetPoints(points);
// Create anything you want here, we will use a polygon for the demo.
vtkRegularPolygonSource polygonSource = vtkRegularPolygonSource.New(); //default is 6 sides
vtkGlyph2D glyph2D = vtkGlyph2D.New();
glyph2D.SetSourceConnection(polygonSource.GetOutputPort());
glyph2D.SetInput(polyData);
glyph2D.Update();
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInputConnection(glyph2D.GetOutputPort());
mapper.Update();
// Create a subclass of vtkActor: a vtkFollower that remains facing the camera
vtkFollower follower = vtkFollower.New();
follower.SetMapper(mapper);
follower.GetProperty().SetColor(1, 0, 0); // red
vtkActor actor = vtkActor.New();
actor.SetMapper(mapper);
_renderer.AddActor(actor);
_renderer.AddActor(follower);
follower.SetCamera(_renderer.GetActiveCamera());
RenderScene();
}
private void AddCaptionWidget()
{
// Create the widget and its representation
vtkCaptionRepresentation captionRepresentation = vtkCaptionRepresentation.New();
captionRepresentation.GetCaptionActor2D().SetCaption("Test caption");
captionRepresentation.GetCaptionActor2D().GetTextActor().GetTextProperty().SetFontSize(16);
double[] pos = new double[] { 66, 66, 20 };
IntPtr posPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(4 * 8);
Marshal.Copy(pos, 0, posPtr, 2);
captionRepresentation.SetAnchorPosition(posPtr);
Marshal.FreeHGlobal(posPtr);
//vtkPointHandleRepresentation3D anchorRepresentation = captionRepresentation.GetAnchorRepresentation();
vtkPropCollection coll = null;
captionRepresentation.GetVolumes(coll);
vtkCaptionWidget captionWidget = vtkCaptionWidget.New();
captionWidget.SetInteractor(_renderWindowInteractor);
captionWidget.SetRepresentation(captionRepresentation);
captionWidget.SetCurrentRenderer(_selectionRenderer);
captionWidget.SetDefaultRenderer(_selectionRenderer);
// Add the actors to the scene
captionWidget.On();
}
private void AddDiskAnimation()
{
//vtkCamera camera = vtkCamera.New();
//camera.Elevation(-45);
//_renderer.SetActiveCamera(camera);
//# Creating disk mesh
vtkDiskSource disk = vtkDiskSource.New();
disk.SetInnerRadius(0.1);
disk.SetOuterRadius(2.0);
disk.SetRadialResolution(800);
disk.SetCircumferentialResolution(800);
disk.Update();
vtkPolyData polyData = disk.GetOutput();
Console.WriteLine(polyData.GetNumberOfPoints() + " nodes");
Console.WriteLine(polyData.GetNumberOfCells() + " elements");
//# Setup actor and mapper
vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
mapper.SetInput(polyData);
vtkActor actor = vtkActor.New();
actor.SetMapper(mapper);
_renderer.AddActor(actor);
int n = 36;
double[] nodePos;
polyData = disk.GetOutput();
vtkPoints[] vtkPointsList = new vtkPoints[n];
Console.WriteLine("Calculate...");
for (int i = 0; i < n; i++)
{
vtkPointsList[i] = vtkPoints.New();
vtkPointsList[i].DeepCopy(polyData.GetPoints());
for (int j = 0; j < polyData.GetNumberOfPoints(); j++)
{
nodePos = vtkPointsList[i].GetPoint(j);
vtkPointsList[i].SetPoint(j, nodePos[0], nodePos[1], 0.3 * Math.Sin(nodePos[0] * 2 + 360 / (n - 1) * i * Math.PI / 180));
}
polyData.SetPoints(vtkPointsList[i]);
_renderWindow.Render();
Application.DoEvents();
}
Console.WriteLine("Done. Animate.");
System.Threading.Thread.Sleep(2000);
//# First animation without color
DateTime start_time = DateTime.Now;
//for (int j = 0; j < 10; j++)
//{
// for (int i = 0; i < n; i++)
// {
// polyData.SetPoints(vtkPointsList[i]);
// _renderWindow.Render();
// //Application.DoEvents();
// //RenderScene();
// }
//}
double fps = 10 * n / (DateTime.Now - start_time).TotalSeconds;
Console.WriteLine(fps + " FPS");
MessageBoxes.ShowInfo(fps + " FPS");
Console.WriteLine("Done. Animate actor array.");
_renderer.RemoveActor(actor);
vtkActor[] actors = new vtkActor[n];
for (int i = 0; i < n; i++)
{
disk = vtkDiskSource.New();
disk.SetInnerRadius(0.1);
disk.SetOuterRadius(2.0);
disk.SetRadialResolution(800);
disk.SetCircumferentialResolution(800);
disk.Update();
polyData = disk.GetOutput();
polyData.SetPoints(vtkPointsList[i]);
mapper = vtkPolyDataMapper.New();
mapper.SetInput(polyData);
actors[i] = vtkActor.New();
actors[i].SetMapper(mapper);
_renderer.AddActor(actors[i]);
_renderWindow.Render();
Application.DoEvents();
actors[i].VisibilityOff();
}
start_time = DateTime.Now;
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < n; i++)
{
//for (int k = 0; k < n; k++)
//{
// actors[k].VisibilityOff();
//}
actors[(i + n - 1) % n].VisibilityOff();
actors[i].VisibilityOn();
_renderWindow.Render();
}
}
fps = 10 * n / (DateTime.Now - start_time).TotalSeconds;
Console.WriteLine(fps + " FPS");
MessageBoxes.ShowInfo(fps + " FPS");
}
}
}