using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using Kitware.VTK; namespace vtkControl { public delegate double[] GetPickPointDelegate(out vtkActor pickedActor, int x, int y); class vtkInteractorStyleControl : vtkInteractorStyleTrackballCamera { // Enum private enum EventIds { NoEvent = 0, AnyEvent, DeleteEvent, StartEvent, EndEvent, RenderEvent, ProgressEvent, PickEvent, StartPickEvent, EndPickEvent, AbortCheckEvent, ExitEvent, LeftButtonPressEvent, LeftButtonReleaseEvent, MiddleButtonPressEvent, MiddleButtonReleaseEvent, RightButtonPressEvent, RightButtonReleaseEvent, EnterEvent, LeaveEvent, KeyPressEvent, KeyReleaseEvent, CharEvent, ExposeEvent, ConfigureEvent, TimerEvent, MouseMoveEvent, MouseWheelForwardEvent, MouseWheelBackwardEvent, ResetCameraEvent, ResetCameraClippingRangeEvent, ModifiedEvent, WindowLevelEvent, StartWindowLevelEvent, EndWindowLevelEvent, ResetWindowLevelEvent, SetOutputEvent, ErrorEvent, WarningEvent, StartInteractionEvent, //mainly used InteractionEvent, EndInteractionEvent, EnableEvent, DisableEvent, CreateTimerEvent, DestroyTimerEvent, PlacePointEvent, PlaceWidgetEvent, CursorChangedEvent, ExecuteInformationEvent, RenderWindowMessageEvent, WrongTagEvent, StartAnimationCueEvent, // used AnimationCueTickEvent, EndAnimationCueEvent, VolumeMapperRenderProgressEvent, VolumeMapperComputeGradientsEndEvent, VolumeMapperComputeGradientsProgressEvent, VolumeMapperComputeGradientsStartEvent, WidgetModifiedEvent, WidgetValueChangedEvent, WidgetActivateEvent, UserEvent = 1000 } // Variables public const int VTKIS_START = 0; public const int VTKIS_NONE = 0; public const int VTKIS_ROTATE = 1; public const int VTKIS_PAN = 2; public const int VTKIS_SPIN = 3; public const int VTKIS_DOLLY = 4; public const int VTKIS_ZOOM = 5; public const int VTKIS_USCALE = 6; public const int VTKIS_TIMER = 7; public const int VTKIS_FORWARDFLY = 8; public const int VTKIS_REVERSEFLY = 9; public const int VTKIS_SELECTION = 10; public const int VTKIS_ANIM_OFF = 0; public const int VTKIS_ANIM_ON = 1; // private double _motionFactor; private double[] _rotationCenterWorld; private double[] _rotationCenterDisplay; private int[] _clickPos; private double[] _clickPosWorld; private vtkProp _centerAnnotationActor; private bool _rubberBandEnabled; private bool _animating; private System.Windows.Threading.DispatcherTimer _selectionTimer; private int _x; private int _y; // Double click protected int _lastX; protected int _lastY; protected int _numOfClicks; protected DateTime _lastClickTime; private TimeSpan _doubleClickTimeSpan = new TimeSpan(0, 0, 0, 0, SystemInformation.DoubleClickTime); private int _doubleClickDisp = 5; // protected bool _leftMouseButtonPressed; protected bool _rubberBandSelection; protected bool _selectionCanceled; protected vtkRenderer _selectionRenderer; protected vtkRenderer _overlayRenderer; protected vtkPolyDataMapper2D _selectionBackgroundMapper; protected vtkActor2D _selectionBackgroundActor; protected vtkActor2D _selectionBorderActor; // protected List _widgets; protected List _reversedWidgets; // Properties public new const string MRFullTypeName = "Kitware.VTK.vtkInteractorStyleControl"; public bool RubberBandEnabled { get { return _rubberBandEnabled; } set { _rubberBandEnabled = value; } } public bool Animating { get { return _animating; } set { _animating = value; } } // Getters public bool IsRubberBandActive { get { return _rubberBandSelection; } } // Callbacks public GetPickPointDelegate GetPickPoint; // Events public event Action PointPickedOnMouseMoveEvt; public event Action PointPickedOnLeftUpEvt; public event Action ClearCurrentMouseSelection; public event Action RightButtonPressEvent; public event Action ZoomChangedEvent; // Constructors public vtkInteractorStyleControl() { _motionFactor = 10.0; _rotationCenterWorld = null; _animating = false; _selectionTimer = new System.Windows.Threading.DispatcherTimer(); _selectionTimer.Interval = new TimeSpan(0, 0, 0, 0, 200); _selectionTimer.Tick += _selectionTimer_Tick; // _lastX = int.MinValue; _lastY = int.MinValue; _lastClickTime = DateTime.Now; // _rubberBandEnabled = true; _widgets = new List(); _reversedWidgets = new List(); // this.LeftButtonPressEvt += vtkInteractorStyleControl_LeftButtonPressEvt; this.LeftButtonReleaseEvt += vtkInteractorStyleControl_LeftButtonReleaseEvt; this.MiddleButtonPressEvt += vtkInteractorStyleControl_MiddleButtonPressEvt; this.MiddleButtonReleaseEvt += vtkInteractorStyleControl_MiddleButtonReleaseEvt; this.RightButtonPressEvt += vtkInteractorStyleControl_RightButtonPressEvt; this.RightButtonReleaseEvt += vtkInteractorStyleControl_RightButtonReleaseEvt; this.MouseMoveEvt += vtkInteractorStyleControl_MouseMoveEvt; this.MouseWheelForwardEvt += vtkInteractorStyleControl_MouseWheelForwardEvt; this.MouseWheelBackwardEvt += vtkInteractorStyleControl_MouseWheelBackwardEvt; this.KeyPressEvt += VtkInteractorStyleControl_KeyPressEvt; } new public static vtkInteractorStyleControl New() { return new vtkInteractorStyleControl(); } // Event handlers void vtkInteractorStyleControl_LeftButtonPressEvt(vtkObject sender, vtkObjectEventArgs e) { vtkRenderWindowInteractor rwi = this.GetInteractor(); // int x = rwi.GetEventPosition()[0]; int y = rwi.GetEventPosition()[1]; // _numOfClicks = 1; // Double click if (DateTime.Now - _lastClickTime < _doubleClickTimeSpan && Math.Abs(x - _lastX) < _doubleClickDisp && Math.Abs(y - _lastY) < _doubleClickDisp) _numOfClicks = 2; // Set global variable _clickPos = new int[] { x, y }; // World click pos vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; _clickPosWorld = DisplayToWorld(renderer, new double[] { x, y }); // Widgets vtkMaxBorderWidget borderWidget = null; MouseEventArgs mea = new MouseEventArgs(MouseButtons.Left, _numOfClicks, x, y, 0); foreach (vtkMaxBorderWidget widget in _reversedWidgets) { if (widget.LeftButtonPress(mea)) { borderWidget = widget; break; // do not return here to set _lastX, lastY, _lastClickTime } } // if (borderWidget == null) { _leftMouseButtonPressed = true; _rubberBandSelection = false; _selectionCanceled = false; // Area selection vtkPoints backgroundPoints = _selectionBackgroundMapper.GetInput().GetPoints(); backgroundPoints.SetPoint(0, _clickPos[0], _clickPos[1], 0.0); backgroundPoints.SetPoint(1, _clickPos[0], _clickPos[1], 0.0); backgroundPoints.SetPoint(2, _clickPos[0], _clickPos[1], 0.0); backgroundPoints.SetPoint(3, _clickPos[0], _clickPos[1], 0.0); backgroundPoints.Modified(); } // _lastX = x; _lastY = y; _lastClickTime = DateTime.Now; } void vtkInteractorStyleControl_LeftButtonReleaseEvt(vtkObject sender, vtkObjectEventArgs e) { vtkRenderWindowInteractor rwi = this.GetInteractor(); // int x = rwi.GetEventPosition()[0]; int y = rwi.GetEventPosition()[1]; // Widgets if (!_rubberBandSelection) { foreach (vtkMaxBorderWidget widget in _reversedWidgets) { if (widget.LeftButtonRelease(x, y)) return; } } if (!_selectionCanceled) { int[] mousePos = rwi.GetEventPosition(); // if (PointPickedOnLeftUpEvt != null) { if (_clickPos == null) { } else { MouseEventArgs mea = new MouseEventArgs(MouseButtons.Left, _numOfClicks, mousePos[0], mousePos[1], 0); PointPickedOnLeftUpEvt(mea, _rubberBandSelection, _clickPos[0], _clickPos[1]); } } } // _clickPos = null; _clickPosWorld = null; _leftMouseButtonPressed = false; _rubberBandSelection = false; // _selectionBackgroundActor.VisibilityOff(); _selectionBorderActor.VisibilityOff(); // rwi.Render(); } // void vtkInteractorStyleControl_MiddleButtonPressEvt(vtkObject sender, vtkObjectEventArgs e) { // Cancel rubber band CancelRubberBandSelection(); // base.OnLeftButtonDown(); // vtkRenderWindowInteractor rwi = this.GetInteractor(); // int x = rwi.GetEventPosition()[0]; int y = rwi.GetEventPosition()[1]; this.FindPokedRenderer(x, y); // vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // _clickPos = rwi.GetEventPosition(); // set global variable // UpdateRotationCenterDisplay(); // AddAnnotationForCenter3D(rwi, renderer); // Widgets - middle pressed foreach (vtkMaxBorderWidget widget in _widgets) { widget.MiddleButtonPress(x, y); } // rwi.Render(); } void vtkInteractorStyleControl_MiddleButtonReleaseEvt(vtkObject sender, vtkObjectEventArgs e) { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // Remove first in order not to affect the bounds of the model RemoveAnnotationForCenter(renderer); // vtkRenderWindowInteractor rwi = this.GetInteractor(); int[] currClickPos = rwi.GetEventPosition(); // if (_clickPos != null && Math.Abs(_clickPos[0] - currClickPos[0]) + Math.Abs(_clickPos[0] - currClickPos[0]) < 2) { // Only click happened if (GetPickPoint != null) { //vtkPropPicker picker = vtkPropPicker.New(); //renderer.Render(); // to redraw the first - BASE - layer of geometry again //picker.Pick(currClickPos[0], currClickPos[1], 0, renderer); //_rotationCenterWorld = picker.GetPickPosition(); vtkActor actor; double[] pickPoint = GetPickPoint(out actor, currClickPos[0], currClickPos[1]); if (pickPoint != null) _rotationCenterWorld = pickPoint; // if (actor == null) // picker.GetActor() == null { // The click was not a hit // Use the center of the bounding box double[] bounds = renderer.ComputeVisiblePropBounds(); _rotationCenterWorld[0] = (bounds[1] + bounds[0]) / 2; _rotationCenterWorld[1] = (bounds[3] + bounds[2]) / 2; _rotationCenterWorld[2] = (bounds[5] + bounds[4]) / 2; } else { // The click was a hit vtkCamera camera = renderer.GetActiveCamera(); double[] center = camera.GetFocalPoint(); PanCamera(camera, center, _rotationCenterWorld); AdjustCameraDistance(renderer, camera); } } } // Adjust the clipping range and lights if (this.GetAutoAdjustCameraClippingRange() == 1) ResetClippingRange(); if (rwi.GetLightFollowCamera() == 1) renderer.UpdateLightsGeometryToFollowCamera(); // Widgets - middle released foreach (vtkMaxBorderWidget widget in _widgets) { widget.MiddleButtonRelease(currClickPos[0], currClickPos[1]); } // rwi.Modified(); // _clickPos = null; _clickPosWorld = null; // base.OnLeftButtonUp(); // left button is rotation by default } // void vtkInteractorStyleControl_RightButtonPressEvt(vtkObject sender, vtkObjectEventArgs e) { vtkRenderWindowInteractor rwi = this.GetInteractor(); int x = rwi.GetEventPosition()[0]; int y = rwi.GetEventPosition()[1]; // this.FindPokedRenderer(x, y); // vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer != null) { int[] clickPos = rwi.GetEventPosition(); // Widgets - right pressed vtkMaxBorderWidget clickedWidget = null; MouseEventArgs mea = new MouseEventArgs(MouseButtons.Right, 1, x, y, 0); // foreach (vtkMaxBorderWidget widget in _widgets) { if (widget.RightButtonPress(x, y)) { clickedWidget = widget; break; } } // RightButtonPressEvent?.Invoke(clickedWidget, mea); } } void vtkInteractorStyleControl_RightButtonReleaseEvt(vtkObject sender, vtkObjectEventArgs e) { } // void vtkInteractorStyleControl_MouseMoveEvt(vtkObject sender, vtkObjectEventArgs e) { _x = this.GetInteractor().GetEventPosition()[0]; _y = this.GetInteractor().GetEventPosition()[1]; // Widgets - Move foreach (vtkMaxBorderWidget widget in _widgets) { if (widget.MouseMove(_x, _y)) { this.GetInteractor().Render(); return; } } // switch (this.GetState()) { case VTKIS_NONE: //if (_selection) { _selectionTimer.Stop(); _selectionTimer.Start(); // if (_rubberBandEnabled) { if (!_rubberBandSelection && _leftMouseButtonPressed && _clickPos != null && Math.Abs(_x - _clickPos[0]) > 1 && Math.Abs(_y - _clickPos[1]) > 1) { _rubberBandSelection = true; } if (_rubberBandSelection) DrawRubberBandSelection(_x, _y); } } break; case VTKIS_ROTATE: this.FindPokedRenderer(_x, _y); this.Rotate(); this.InvokeEvent((uint)EventIds.InteractionEvent, IntPtr.Zero); break; case VTKIS_PAN: this.FindPokedRenderer(_x, _y); this.Pan(); this.InvokeEvent((uint)EventIds.InteractionEvent, IntPtr.Zero); break; } } // void vtkInteractorStyleControl_MouseWheelForwardEvt(vtkObject sender, vtkObjectEventArgs e) { if (this.GetState() == VTKIS_NONE) { int[] clickPos = this.GetInteractor().GetEventPosition(); this.FindPokedRenderer(clickPos[0], clickPos[1]); vtkRenderer renderer = this.GetCurrentRenderer(); double[] worldPos = DisplayToWorld(renderer, new double[] { clickPos[0], clickPos[1] }); vtkCamera camera = renderer.GetActiveCamera(); double factor = Math.Pow(1.1, this._motionFactor * 0.2 * this.GetMouseWheelMotionFactor()); //factor = 1; camera.SetParallelScale(camera.GetParallelScale() * factor); double[] worldPosAfter = DisplayToWorld(renderer, new double[] { clickPos[0], clickPos[1] }); PanCamera(camera, worldPosAfter, worldPos); // Rubber band if (_rubberBandSelection) DrawRubberBandSelection(_x, _y); // Widgets - mouse wheel scrolled foreach (vtkMaxBorderWidget widget in _widgets) { widget.MouseWheelScrolled(); } if (ZoomChangedEvent != null) ZoomChangedEvent(); this.GetInteractor().Modified(); this.GetInteractor().Render(); } } void vtkInteractorStyleControl_MouseWheelBackwardEvt(vtkObject sender, vtkObjectEventArgs e) { if (this.GetState() == VTKIS_NONE) { int[] clickPos = this.GetInteractor().GetEventPosition(); this.FindPokedRenderer(clickPos[0], clickPos[1]); vtkRenderer renderer = this.GetCurrentRenderer(); double[] worldPos = DisplayToWorld(renderer, new double[] { clickPos[0], clickPos[1] }); vtkCamera camera = renderer.GetActiveCamera(); double factor = Math.Pow(1.1, this._motionFactor * 0.2 * this.GetMouseWheelMotionFactor()); //factor = 1.00; camera.SetParallelScale(camera.GetParallelScale() / factor); double[] worldPosAfter = DisplayToWorld(renderer, new double[] { clickPos[0], clickPos[1] }); PanCamera(camera, worldPosAfter, worldPos); // Rubber band if (_rubberBandSelection) DrawRubberBandSelection(_x, _y); // Widgets - mouse wheel scrolled foreach (vtkMaxBorderWidget widget in _widgets) { widget.MouseWheelScrolled(); } if (ZoomChangedEvent != null) ZoomChangedEvent(); this.GetInteractor().Modified(); this.GetInteractor().Render(); } } // private void VtkInteractorStyleControl_KeyPressEvt(vtkObject sender, vtkObjectEventArgs e) { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // vtkRenderWindowInteractor rwi = this.GetInteractor(); sbyte key = rwi.GetKeyCode(); // Arrow keys for rotation if (key >= 37 && key <= 40) { CancelRubberBandSelection(); // UpdateRotationCenterDisplay(); rwi.Modified(); // double delta = 5; if (key == 37) Rotate(+delta, 0); // left else if (key == 39) Rotate(-delta, 0); // right else if (key == 38) Rotate(0, -delta); // up else if (key == 40) Rotate(0, +delta); // down // rwi.Modified(); rwi.Render(); } // Escape key else if (key == 27) { CancelRubberBandSelection(); } } // Public setters public void SetSelectionRenderer(vtkRenderer renderer) { _selectionRenderer = renderer; InitializeRubberBandSelection(); } public void SetOverlayRenderer(vtkRenderer renderer) { _overlayRenderer = renderer; } // Methods void _selectionTimer_Tick(object sender, EventArgs e) { _selectionTimer.Stop(); this.FindPokedRenderer(_x, _y); this.Select(_x, _y); } public bool IsPositionOverWidget(int x, int y) { foreach (vtkMaxBorderWidget widget in _widgets) { if (widget.MouseOver(x, y)) return true; } return false; } // public void AddVtkMaxWidget(vtkMaxBorderWidget widget) { _widgets.Add(widget); _reversedWidgets.Insert(0, widget); } public void RemoveVtkMaxWidget(vtkMaxBorderWidget widget) { _widgets.Remove(widget); _reversedWidgets.Remove(widget); } public void Reset() { _rotationCenterWorld = null; } private void UpdateRotationCenterDisplay() { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; if (_rotationCenterWorld == null) { // for the first time use the center of the bounding box double[] bounds = renderer.ComputeVisiblePropBounds(); _rotationCenterWorld = new double[3]; _rotationCenterWorld[0] = (bounds[1] + bounds[0]) / 2; _rotationCenterWorld[1] = (bounds[3] + bounds[2]) / 2; _rotationCenterWorld[2] = (bounds[5] + bounds[4]) / 2; } // must update since zoom can also change _rotationCenterDisplay = WorldToDisplay(renderer, _rotationCenterWorld); } public static double[] WorldToDisplay(vtkRenderer renderer, double[] worldPos) { IntPtr posOutPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(2 * 8); ComputeWorldToDisplay(renderer, worldPos[0], worldPos[1], worldPos[2], posOutPtr); double[] displayPos = new double[2]; System.Runtime.InteropServices.Marshal.Copy(posOutPtr, displayPos, 0, 2); return displayPos; } public static double[] DisplayToWorld(vtkRenderer renderer, double[] displayPos) { IntPtr posOutPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(4 * 8); ComputeDisplayToWorld(renderer, displayPos[0], displayPos[1], 0, posOutPtr); double[] worldPos = new double[3]; System.Runtime.InteropServices.Marshal.Copy(posOutPtr, worldPos, 0, 3); return worldPos; } public static double DisplayToWorldScale(vtkRenderer renderer, int size = 1) { int delta = 1 * size; int x = 0; int y = 0; double[] p1 = vtkInteractorStyleControl.DisplayToWorld(renderer, new double[] { x, y }); double[] p2 = vtkInteractorStyleControl.DisplayToWorld(renderer, new double[] { x + delta, y }); return Math.Sqrt(Math.Pow(p1[0] - p2[0], 2) + Math.Pow(p1[1] - p2[1], 2) + Math.Pow(p1[2] - p2[2], 2)); } public override void Pan() { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // vtkRenderWindowInteractor rwi = this.GetInteractor(); int[] clickPos = rwi.GetEventPosition(); // double[] newPickPoint; double[] oldPickPoint; // newPickPoint = DisplayToWorld(renderer, new double[] { clickPos[0], clickPos[1] }); oldPickPoint = DisplayToWorld(renderer, new double[] { rwi.GetLastEventPosition()[0], rwi.GetLastEventPosition()[1] }); // vtkCamera camera = renderer.GetActiveCamera(); PanCamera(camera, newPickPoint, oldPickPoint); // if (rwi.GetLightFollowCamera() == 1) renderer.UpdateLightsGeometryToFollowCamera(); // Widgets - Pan int dx; int dy; foreach (vtkMaxBorderWidget widget in _widgets) { // compute the delta dx = clickPos[0] - rwi.GetLastEventPosition()[0]; dy = clickPos[1] - rwi.GetLastEventPosition()[1]; // widget.MousePan(dx, dy); } rwi.Render(); } private void PanCamera(vtkCamera camera, double[] posStart, double[] posEnd) { double[] motionVector = new double[3]; motionVector[0] = posEnd[0] - posStart[0]; motionVector[1] = posEnd[1] - posStart[1]; motionVector[2] = posEnd[2] - posStart[2]; // double[] cPos = camera.GetPosition(); double[] fPos = camera.GetFocalPoint(); // //System.Diagnostics.Debug.WriteLine(string.Format("cPos1 x: {0}, y: {1}, z: {2}", cPos[0], cPos[1], cPos[2])); // camera.SetPosition(cPos[0] + motionVector[0], cPos[1] + motionVector[1], cPos[2] + motionVector[2]); camera.SetFocalPoint(fPos[0] + motionVector[0], fPos[1] + motionVector[1], fPos[2] + motionVector[2]); // AdjustCameraDistanceAndClipping(); } // public override void Rotate() { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // vtkRenderWindowInteractor rwi = this.GetInteractor(); int[] clickPos = rwi.GetEventPosition(); // Compute the angle int dx = clickPos[0] - rwi.GetLastEventPosition()[0]; int dy = clickPos[1] - rwi.GetLastEventPosition()[1]; // double delta_elevation = -20.0 / 500; double delta_azimuth = -20.0 / 500; // double rxf = dx * delta_azimuth * this._motionFactor; double ryf = dy * delta_elevation * this._motionFactor; // Rotate(rxf, ryf); } public void Rotate(double azimuthAngle, double elevationAngle, double rollAngle = 0) { vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // vtkCamera camera = renderer.GetActiveCamera(); vtkRenderWindowInteractor rwi = this.GetInteractor(); // if (azimuthAngle != 0) camera.Azimuth(azimuthAngle); if (elevationAngle != 0) camera.Elevation(elevationAngle); if (rollAngle != 0) camera.Roll(rollAngle); camera.OrthogonalizeViewUp(); // Move the cameras focal point back to the display position of the first click - the opposite direction! double[] wpa = DisplayToWorld(renderer, _rotationCenterDisplay); double[] n = camera.GetViewPlaneNormal(); // Compute a plane through rotationWorldCenter and project the rotationDisplayCenter on it double[] v = new double[3]; // vector from rotationWorldCenter to DisplayToWorld point double[] rotCenter = _rotationCenterWorld; if (rotCenter == null) rotCenter = new double[3]; v[0] = wpa[0] - rotCenter[0]; v[1] = wpa[1] - rotCenter[1]; v[2] = wpa[2] - rotCenter[2]; double d = n[0] * v[0] + n[1] * v[1] + n[2] * v[2]; // distance of DisplayToWorld point from plane wpa[0] -= n[0] * d; wpa[1] -= n[1] * d; wpa[2] -= n[2] * d; // PanCamera(camera, wpa, rotCenter); // calls AdjustCameraDistanceAndClipping() // Adjust the lights if (rwi.GetLightFollowCamera() == 1) renderer.UpdateLightsGeometryToFollowCamera(); // Widgets - Rotate foreach (vtkMaxBorderWidget widget in _widgets) { widget.MouseRotate(azimuthAngle, elevationAngle); } rwi.Modified(); rwi.Render(); } // private void Select(int x, int y) { if (PointPickedOnMouseMoveEvt != null) { vtkRenderer renderer = this.GetCurrentRenderer(); if (_clickPos != null && _clickPosWorld != null && renderer != null) { int[] clickPos = _clickPos; if (_rubberBandSelection) { double[] clickPosD = WorldToDisplay(renderer, _clickPosWorld); clickPos[0] = (int)clickPosD[0]; clickPos[1] = (int)clickPosD[1]; } PointPickedOnMouseMoveEvt(x, y, _rubberBandSelection, clickPos[0], clickPos[1]); } else PointPickedOnMouseMoveEvt(x, y, _rubberBandSelection, 0, 0); } } private void DrawRubberBandSelection(int x, int y) { if (_clickPosWorld == null) return; // vtkRenderer renderer = this.GetCurrentRenderer(); if (renderer == null) return; // double[] clickPos = WorldToDisplay(renderer, _clickPosWorld); // _selectionBackgroundActor.VisibilityOn(); _selectionBorderActor.VisibilityOn(); // Border if (clickPos[0] > x) { _selectionBorderActor.GetProperty().SetColor(0.3, 1.0, 0.3); _selectionBackgroundActor.GetProperty().SetColor(0.2, 1, 0.5); //_selectionBorderActor.GetProperty().SetLineStipplePattern(65280); } else { _selectionBorderActor.GetProperty().SetColor(0.3, 0.3, 1.0); _selectionBackgroundActor.GetProperty().SetColor(0.2, 0.5, 1); //_selectionBorderActor.GetProperty().SetLineStipplePattern(0xffff); } // vtkRenderWindowInteractor rwi = this.GetInteractor(); vtkPoints backgroundPoints = _selectionBackgroundMapper.GetInput().GetPoints(); // int id1 = 1; int id2 = 2; int id3 = 3; // Switch ids 1 and 3 if II or IV quadrant if ((x < clickPos[0] && y > clickPos[1]) || (x > clickPos[0] && y < clickPos[1])) { id1 = 3; id3 = 1; } // backgroundPoints.SetPoint(0, clickPos[0], clickPos[1], 0.0); backgroundPoints.SetPoint(id1, x, clickPos[1], 0.0); backgroundPoints.SetPoint(id2, x, y, 0.0); backgroundPoints.SetPoint(id3, clickPos[0], y, 0.0); backgroundPoints.Modified(); // rwi.Render(); } private void CancelRubberBandSelection() { if (_rubberBandSelection) { _selectionCanceled = true; _clickPos = null; _clickPosWorld = null; _rubberBandSelection = false; // _selectionBackgroundActor.VisibilityOff(); _selectionBorderActor.VisibilityOff(); // ClearCurrentMouseSelection?.Invoke(); // this.GetInteractor().Render(); } } // private void AddAnnotationForCenter3D(vtkRenderWindowInteractor interactor, vtkRenderer renderer) { if (_centerAnnotationActor != null) RemoveAnnotationForCenter(renderer); // int[] size = renderer.GetSize(); double minSize = Math.Min(size[0], size[1]); vtkCamera camera = renderer.GetActiveCamera(); double scale = camera.GetParallelScale(); double dMin = 30 / minSize * scale; double dMax = 100 / minSize * scale; // vtkPoints points = vtkPoints.New(); points.InsertNextPoint(_rotationCenterWorld[0] + dMin, _rotationCenterWorld[1], _rotationCenterWorld[2]); points.InsertNextPoint(_rotationCenterWorld[0] + dMax, _rotationCenterWorld[1], _rotationCenterWorld[2]); // points.InsertNextPoint(_rotationCenterWorld[0] - dMin, _rotationCenterWorld[1], _rotationCenterWorld[2]); points.InsertNextPoint(_rotationCenterWorld[0] - dMax, _rotationCenterWorld[1], _rotationCenterWorld[2]); // points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1] + dMin, _rotationCenterWorld[2]); points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1] + dMax, _rotationCenterWorld[2]); // points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1] - dMin, _rotationCenterWorld[2]); points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1] - dMax, _rotationCenterWorld[2]); // points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1], _rotationCenterWorld[2] + dMax * 1.3); points.InsertNextPoint(_rotationCenterWorld[0], _rotationCenterWorld[1], _rotationCenterWorld[2] - dMax * 0.7); // vtkCellArray lineIndices = vtkCellArray.New(); for (int i = 0; i < 5; i++) { lineIndices.InsertNextCell(2); lineIndices.InsertCellPoint(2 * i); lineIndices.InsertCellPoint(2 * i + 1); } // vtkPolyData pointsPolyData = vtkPolyData.New(); pointsPolyData.SetPoints(points); pointsPolyData.SetLines(lineIndices); // Visualize vtkPolyDataMapper mapper = vtkPolyDataMapper.New(); mapper.SetInput(pointsPolyData); mapper.Update(); // vtkActor actor = vtkActor.New(); actor.SetMapper(mapper); actor.GetProperty().SetColor(1, 0.7, 0); //actor.GetProperty().SetLineWidth(1); renderer.AddActor(actor); _centerAnnotationActor = actor; } private void RemoveAnnotationForCenter(vtkRenderer renderer) { if (_centerAnnotationActor != null) { renderer.RemoveActor(_centerAnnotationActor); _centerAnnotationActor.Dispose(); _centerAnnotationActor = null; } } public void AdjustCameraDistanceAndClipping() { vtkRenderer renderer = this.GetCurrentRenderer(); vtkCamera camera = renderer.GetActiveCamera(); // AdjustCameraDistance(renderer, camera); ResetClippingRange(); // Widgets - Modified foreach (vtkMaxBorderWidget widget in _widgets) { widget.CameraModified(); } } private void AdjustCameraDistance(vtkRenderer renderer, vtkCamera camera) { // Camera should not be to close or to far double[] b1 = renderer.ComputeVisiblePropBounds(); double[] b2 = _selectionRenderer.ComputeVisiblePropBounds(); double[] b3 = _overlayRenderer.ComputeVisiblePropBounds(); // double[] b = new double[] { Math.Min(b1[0], Math.Min(b2[0], b3[0])), Math.Max(b1[1], Math.Max(b2[1], b3[1])), Math.Min(b1[2], Math.Min(b2[2], b3[2])), Math.Max(b1[3], Math.Max(b2[3], b3[3])), Math.Min(b1[4], Math.Min(b2[4], b3[4])), Math.Max(b1[5], Math.Max(b2[5], b3[5]))}; // double r = 0.5 * Math.Sqrt(Math.Pow(b[0] - b[1], 2) + Math.Pow(b[2] - b[3], 2) + Math.Pow(b[4] - b[5], 2)); // radius r *= 1.05; double[] center = new double[] { (b[0] + b[1]) / 2, (b[2] + b[3]) / 2, (b[4] + b[5]) / 2 }; // double[] pos = camera.GetPosition(); // double[] delta = new double[3]; // vector from camera position to the geometry center // delta[0] = center[0] - pos[0]; delta[1] = center[1] - pos[1]; delta[2] = center[2] - pos[2]; // double[] normal = camera.GetDirectionOfProjection(); double d = normal[0] * delta[0] + normal[1] * delta[1] + normal[2] * delta[2]; // distance to geometry center double k = d - r; // double[] motionVector = new double[3]; motionVector[0] = k * normal[0]; motionVector[1] = k * normal[1]; motionVector[2] = k * normal[2]; // //System.Diagnostics.Debug.WriteLine(string.Format("pos4 x: {0}, y: {1}, z: {2}", pos[0], pos[1], pos[2])); // double[] newPos = new double[3]; newPos[0] = pos[0] + motionVector[0]; newPos[1] = pos[1] + motionVector[1]; newPos[2] = pos[2] + motionVector[2]; camera.SetPosition(newPos[0], newPos[1], newPos[2]); // //System.Diagnostics.Debug.WriteLine(string.Format("pos5 x: {0}, y: {1}, z: {2}", newPos[0], newPos[1], newPos[2])); // //double[] focalPos = camera.GetFocalPoint(); //newPos[0] = focalPos[0] + motionVector[0]; //newPos[1] = focalPos[1] + motionVector[1]; //newPos[2] = focalPos[2] + motionVector[2]; newPos[0] += normal[0]; newPos[1] += normal[1]; newPos[2] += normal[2]; // camera.SetFocalPoint(newPos[0], newPos[1], newPos[2]); } private void AdjustCameraDistance__(vtkRenderer renderer, vtkCamera camera) { double[] b = renderer.ComputeVisiblePropBounds(); double l = 0.01 * Math.Sqrt(Math.Pow(b[0] - b[1], 2) + Math.Pow(b[2] - b[3], 2) + Math.Pow(b[4] - b[5], 2)); double[] pos = camera.GetPosition(); double[] direction = camera.GetViewPlaneNormal(); double[] point = null; if (direction[0] > 0 && direction[1] > 0 && direction[2] > 0) point = new double[] { b[1], b[3], b[5] }; else if (direction[0] <= 0 && direction[1] > 0 && direction[2] > 0) point = new double[] { b[0], b[3], b[5] }; else if (direction[0] <= 0 && direction[1] <= 0 && direction[2] > 0) point = new double[] { b[0], b[2], b[5] }; else if (direction[0] > 0 && direction[1] <= 0 && direction[2] > 0) point = new double[] { b[1], b[2], b[5] }; else if (direction[0] > 0 && direction[1] > 0 && direction[2] <= 0) point = new double[] { b[1], b[3], b[4] }; else if (direction[0] <= 0 && direction[1] > 0 && direction[2] <= 0) point = new double[] { b[0], b[3], b[4] }; else if (direction[0] <= 0 && direction[1] <= 0 && direction[2] <= 0) point = new double[] { b[0], b[2], b[4] }; else if (direction[0] > 0 && direction[1] <= 0 && direction[2] <= 0) point = new double[] { b[1], b[2], b[4] }; else throw new Exception(); double[] relDir = new double[] { point[0] - pos[0], point[1] - pos[1], point[2] - pos[2] }; // positive value means the camera distance double d = -(direction[0] * relDir[0] + direction[1] * relDir[1] + direction[2] * relDir[2]); d -= l; double[] newPos = new double[3]; newPos[0] = pos[0] - d * direction[0]; newPos[1] = pos[1] - d * direction[1]; newPos[2] = pos[2] - d * direction[2]; camera.SetPosition(newPos[0], newPos[1], newPos[2]); } private void AdjustCameraDistance_(vtkRenderer renderer, vtkCamera camera) { double[] b = renderer.ComputeVisiblePropBounds(); double[] center = new double[] { (b[0] + b[1]) / 2, (b[2] + b[3]) / 2, (b[4] + b[5]) / 2 }; double R = Math.Sqrt(Math.Pow(b[0] - b[1], 2) + Math.Pow(b[2] - b[3], 2) + Math.Pow(b[4] - b[5], 2)) / 2; double[] pos = camera.GetPosition(); double[] direction = camera.GetViewPlaneNormal(); double[] point = new double[] { center[0] + R * direction[0], center[1] + R * direction[1], center[2] + R * direction[2] }; double[] relDir = new double[] { point[0] - pos[0], point[1] - pos[1], point[2] - pos[2] }; // positive value means the camera will move forward double d = -(direction[0] * relDir[0] + direction[1] * relDir[1] + direction[2] * relDir[2]); d -= R * 0.01; camera.SetDistance(d + 10); double[] newPos = new double[3]; newPos[0] = pos[0] - d * direction[0]; newPos[1] = pos[1] - d * direction[1]; newPos[2] = pos[2] - d * direction[2]; camera.SetPosition(newPos[0], newPos[1], newPos[2]); //System.Diagnostics.Debug.WriteLine(string.Format("newPos x: {0}, y: {1}, z: {1}", newPos[0], newPos[1], newPos[2])); } public void ResetClippingRange() { double min, max, minSel, maxSel, minOver, maxOver; min = max = minSel = maxSel = minOver = maxOver = 0; // GetCurrentRenderer().ResetCameraClippingRange(); GetCurrentRenderer().GetActiveCamera().GetClippingRange(ref min, ref max); // _selectionRenderer.ResetCameraClippingRange(); _selectionRenderer.GetActiveCamera().GetClippingRange(ref minSel, ref maxSel); // _overlayRenderer.ResetCameraClippingRange(); _overlayRenderer.GetActiveCamera().GetClippingRange(ref minOver, ref maxOver); // Near and far settng for the Z-buffer GetCurrentRenderer().GetActiveCamera().SetClippingRange(Math.Min(min, Math.Min(minSel, minOver)), Math.Max(max, Math.Max(maxSel, maxOver))); //System.Diagnostics.Debug.WriteLine("Near: " + Math.Min(min, Math.Min(minSel, minOver)) + " " + // "Far: " + Math.Max(max, Math.Max(maxSel, maxOver))); } private void InitializeRubberBandSelection() { vtkPoints backgroundPoints = vtkPoints.New(); backgroundPoints.SetNumberOfPoints(4); backgroundPoints.SetPoint(0, 0.0, 0.0, 0.0); backgroundPoints.SetPoint(1, 10.5, 0.0, 0.0); backgroundPoints.SetPoint(2, 10.5, 10.5, 0.0); backgroundPoints.SetPoint(3, 0.0, 10.5, 0.0); vtkCellArray backgroundPolygon = vtkCellArray.New(); backgroundPolygon.InsertNextCell(4); backgroundPolygon.InsertCellPoint(0); backgroundPolygon.InsertCellPoint(1); backgroundPolygon.InsertCellPoint(2); backgroundPolygon.InsertCellPoint(3); vtkPolyData backgroundPolyData = vtkPolyData.New(); backgroundPolyData.SetPoints(backgroundPoints); backgroundPolyData.SetPolys(backgroundPolygon); _selectionBackgroundMapper = vtkPolyDataMapper2D.New(); _selectionBackgroundMapper.SetInput(backgroundPolyData); _selectionBackgroundActor = vtkActor2D.New(); _selectionBackgroundActor.SetMapper(_selectionBackgroundMapper); _selectionBackgroundActor.GetProperty().SetOpacity(0.2); _selectionBackgroundActor.VisibilityOff(); _selectionBackgroundActor.GetProperty().SetColor(0.2, 0.5, 1); _selectionRenderer.AddActor(_selectionBackgroundActor); vtkCellArray borderPolygon = vtkCellArray.New(); borderPolygon.InsertNextCell(5); borderPolygon.InsertCellPoint(0); borderPolygon.InsertCellPoint(1); borderPolygon.InsertCellPoint(2); borderPolygon.InsertCellPoint(3); borderPolygon.InsertCellPoint(0); vtkPolyData borderPolyData = vtkPolyData.New(); borderPolyData.SetPoints(backgroundPoints); borderPolyData.SetLines(borderPolygon); vtkPolyDataMapper2D borderMapper = vtkPolyDataMapper2D.New(); borderMapper.SetInput(borderPolyData); _selectionBorderActor = vtkActor2D.New(); _selectionBorderActor.SetMapper(borderMapper); _selectionBorderActor.GetProperty().SetColor(0.3, 0.3, 1.0); _selectionBorderActor.VisibilityOff(); _selectionRenderer.AddActor(_selectionBorderActor); } private void DrawSphereOnLeft(vtkObject sender, vtkObjectEventArgs e) { vtkInteractorStyleControl interactor = (vtkInteractorStyleControl)sender; vtkRenderer renderer = interactor.GetInteractor().GetRenderWindow().GetRenderers().GetFirstRenderer(); int[] clickPos = interactor.GetInteractor().GetEventPosition(); // Pick from this location. vtkPropPicker picker = vtkPropPicker.New(); //vtkRendererCollection renderers = interactor.GetInteractor().GetRenderWindow().GetRenderers(); //interactor.GetInteractor().GetRenderWindow().RemoveRenderer(renderers.GetNextItem()); renderer.Render(); // to redraw the first layer of geometry picker.Pick(clickPos[0], clickPos[1], 0, renderer); double[] pos = picker.GetPickPosition(); Console.WriteLine("Pick position (world coordinates) is: " + pos[0].ToString() + " " + pos[1].ToString() + " " + pos[2].ToString()); //Console.WriteLine("Picked actor: " + picker.GetActor().ToString()); //Create a sphere vtkSphereSource sphereSource = vtkSphereSource.New(); sphereSource.SetCenter(pos[0], pos[1], pos[2]); sphereSource.SetRadius(1); //Create a mapper and actor vtkPolyDataMapper mapper = vtkPolyDataMapper.New(); mapper.SetInputConnection(sphereSource.GetOutputPort()); vtkActor actor = vtkActor.New(); actor.SetMapper(mapper); actor.PickableOff(); //this.GetInteractor().GetRenderWindow().GetRenderers().GetDefaultRenderer().AddActor(actor); renderer.AddActor(actor); // Forward events interactor.OnLeftButtonUp(); this.GetInteractor().Render(); } } }