首页 新闻 会员 周边 捐助

如何在WPF中使用VTK进行三维重建?

0
[已解决问题] 解决于 2014-06-06 16:49

想在WPF中使用VTK对序列图片进行三维重建,不知如何关联起来,不要用WindowsFormHost控件来,能不能有直接的办法把VTK和WPF衔接起来!

溪山行旅丶的主页 溪山行旅丶 | 初学一级 | 园豆:6
提问于:2014-06-03 12:58
< >
分享
最佳答案
0

不能。

你写段用 VTK 在屏幕上绘图的代码我看看。

奖励园豆:5
Launcher | 高人七级 |园豆:45050 | 2014-06-03 13:23

这是Winform的

using System.Drawing;
using System.ServiceModel;
using System;
using System.Windows.Forms;
using Kitware.VTK;
using JXDWNav;
using LungCare.WcfServices.Service.Interface;
using System.Diagnostics;
using System.Text;
using System.IO;

namespace CameraCorrectionService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public partial class AirwayNav3DMapTestForm : Form, IAirwayNav3DMap
    {
        private const string WinstateTxt = "./winState.txt";
        private const string TempVTP = "./temp.vtp";

        private readonly int _splitContainer1Panel1Height;

        public AirwayNav3DMapTestForm()
        {
            InitializeComponent();

            _splitContainer1Panel1Height = splitContainer1.Panel1.Height;
            splitContainer1.Panel1Collapsed = true;
        }

        public vtkRenderer Renderer
        {
            get { return _renderer; }
        }

        public vtkRenderWindowInteractor RenderWindowInteractor
        {
            get { return _iren; }
        }

        private XmlPolyDataPackage _airwayOn3DMap;
        private LinePackage _cameraPackage;

        private vtkRenderer _renderer;
        private vtkRenderWindow _renwin;
        private vtkRenderWindowInteractor _iren;
        private vtkInteractorStyleTrackballCamera _interactorStyle;

        internal vtkRenderer AddTopmostRenderer(vtkRenderWindow renwin, vtkRenderer mainRenderer)
        {
            int oldNumberOfRenderer = renwin.GetNumberOfLayers();
            int newNumberOfRenderer = oldNumberOfRenderer + 1;

            mainRenderer.SetLayer(oldNumberOfRenderer - 1);

            vtkRenderer topRenderer = vtkRenderer.New();
            topRenderer.SetViewport(0, 0, 1, 1);
            topRenderer.SetLayer(oldNumberOfRenderer);
            topRenderer.InteractiveOff();

            renwin.SetNumberOfLayers(newNumberOfRenderer);
            renwin.AddRenderer(topRenderer);

            topRenderer.SetActiveCamera(mainRenderer.GetActiveCamera());

            return topRenderer;
        }

        private void Airway3DMapPackageTestForm_Load(object sender, EventArgs e)
        {
            if (File.Exists(WinstateTxt))
            {
                string[] lines = File.ReadAllLines(WinstateTxt);
                int x = int.Parse(lines[0]);
                int y = int.Parse(lines[1]);
                int w = int.Parse(lines[2]);
                int h = int.Parse(lines[3]);

                if (x > 0 && y > 0)
                {
                    Location = new Point(x, y);
                }

                if (w > 120 && h > 120)
                {
                    Width = w;
                    Height = h;
                }
            }

            LocationChanged += AirwayNavVirtualEndoscopyTestForm_LocationChanged;
            Resize += AirwayNavVirtualEndoscopyTestForm_LocationChanged;

            _renwin = vtkRenderWindow.New();

            _renderer = vtkRenderer.New();
            _renwin.AddRenderer(_renderer);
            _renwin.SetParentId(panel1.Handle);
            _renwin.SetSize(panel1.Width, panel1.Height);

            _iren = vtkRenderWindowInteractor.New();
            _iren.SetRenderWindow(_renwin);

            _interactorStyle = vtkInteractorStyleTrackballCamera.New();
            _iren.SetInteractorStyle(_interactorStyle);
            _iren.ModifiedEvt += _iren_MouseMoveEvt;

            _iren.KeyPressEvt += delegate
            {
                string keysym = _iren.GetKeySym();
                if (keysym == "Escape")
                {
                    WindowState = FormWindowState.Minimized;
                }
            };

            panel1.Resize += panel1_Resize;

            // 3D airway.
            // Set as non-topmost.
            string airwayVTPFileName = @".\data\girl.vtp";
            if (File.Exists(TempVTP))
            {
                airwayVTPFileName = TempVTP;
            }

            _airwayOn3DMap = new XmlPolyDataPackage(airwayVTPFileName, _renderer);

            vtkRenderer topmost = AddTopmostRenderer(_renwin, _renderer);
            _cameraPackage = new LinePackage(topmost);
            _cameraPackage.SetColor(1, 0, 0);

            // Parallel off.
            _renderer.GetActiveCamera().ParallelProjectionOn();

            // Gradient on.
            _renderer.GradientBackgroundOn();
            _renderer.SetBackground(0, 0, 0);
            _renderer.SetBackground2(0, 0, 1);
            _renderer.SetGradientBackground(true);

            _renderer.GetActiveCamera().OrthogonalizeViewUp();

            _renwin.Render();

            正面观();

            _orientationPackage = new OrientationPackage(
                vtpFile: @".\data\girl.vtp", 
                renwin: _renwin, 
                mainRenderer: _renderer);

            _renderer.ResetCameraClippingRange();
            _renderer.ResetCamera();
        }

        public void 正面观()
        {
            vtkCamera camera = _renderer.GetActiveCamera();
            double[] bound = _airwayOn3DMap.GetBounds;

            camera.SetFocalPoint(
                (bound[0] + bound[1]) / 2,
                (bound[2] + bound[3]) / 2,
                (bound[4] + bound[5]) / 2);

            camera.SetPosition(
                (bound[0] + bound[1]) / 2,
                1000,
                (bound[4] + bound[5]) / 2);

            camera.SetViewUp(0, 0, -1);
        }

        void panel1_Resize(object sender, EventArgs e)
        {
            _renwin.SetSize(panel1.Width, panel1.Height);

            _renderer.ResetCameraClippingRange();
            //_renderer.ResetCamera();

            _renwin.Render();
        }

        internal void FlyTo(double[] focal)
        {
            double[] directionOfProjection = _renderer.GetActiveCamera().GetDirectionOfProjection();
            double distance = _renderer.GetActiveCamera().GetDistance();
            _renderer.GetActiveCamera().SetFocalPoint(focal[0], focal[1], focal[2]);
            _renderer.GetActiveCamera().SetPosition(
                focal[0] - distance * directionOfProjection[0],
                focal[1] - distance * directionOfProjection[1],
                focal[2] - distance * directionOfProjection[2]);
        }

        private bool _isProcessing = false;
        private OrientationPackage _orientationPackage;

        public void UpdateCamera(double[] cameraposition, double[] focalposition, double[] viewUp)
        {
            if (_isProcessing)
            {
                return;
            }
            _isProcessing = true;
            //vtkCamera camera = _renderer.GetActiveCamera();

            //camera.SetPosition(cameraposition[0], cameraposition[1], cameraposition[2]);
            //camera.SetFocalPoint(focalposition[0], focalposition[1], focalposition[2]);

            //if (viewUp != null)
            //{
            //    camera.SetViewUp(viewUp[0], viewUp[1], viewUp[2]);
            //}

            _cameraPackage.SetPosition(cameraposition, focalposition);

            if (cbFly2Camera.Checked)
            {
                FlyTo(focalposition);
            }
            _renderer.ResetCameraClippingRange();
            _renwin.Render();
            _isProcessing = false;
        }

        private void AirwayNavVirtualEndoscopyTestForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Process.GetCurrentProcess().Kill();
        }

        private void AirwayNavVirtualEndoscopyTestForm_LocationChanged(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(Convert.ToString(Location.X));
            sb.AppendLine(Convert.ToString(Location.Y));
            sb.AppendLine(Convert.ToString(Width));
            sb.AppendLine(Convert.ToString(Height));

            File.WriteAllText(WinstateTxt, sb.ToString());
        }

        private void panel2_MouseLeave(object sender, EventArgs e)
        {
            if (!cb自动隐藏.Checked) { return; }
            if (!Bounds.Contains(Cursor.Position))
            {
                //panel1.Resize -= panel1_Resize;
                splitContainer1.Panel1Collapsed = true;
                //panel1.Resize += panel1_Resize;
            }
        }

        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            //splitContainer1.Panel1Collapsed = false;
        }

        private void AirwayNavVirtualEndoscopyTestForm_MouseMove(object sender, MouseEventArgs e)
        {
            //splitContainer1.Panel1Collapsed = false;
        }

        void _iren_MouseMoveEvt(vtkObject sender, vtkObjectEventArgs e)
        {
            if (!cb自动隐藏.Checked) { return; }

            int[] position = _iren.GetEventPosition();
            //Console.WriteLine(position[0] + @", " + position[1]);
            //panel1.Resize -= panel1_Resize;

            if (position[1] > Height - _splitContainer1Panel1Height)
            {
                splitContainer1.Panel1Collapsed = false;
            }
            else
            {
                splitContainer1.Panel1Collapsed = true;
            }

            //panel1.Resize += panel1_Resize;
        }

        public void Init(byte[] vtpFileBinaryData)
        {
            _airwayOn3DMap.PrintActor();

            File.WriteAllBytes(TempVTP, vtpFileBinaryData);

            _airwayOn3DMap.ChangeFile(TempVTP);

            ResetCamera();

            //File.Delete(_tempVTP);
        }

        private void ResetCamera()
        {
            _renderer.ResetCameraClippingRange();
            _renderer.ResetCamera(
                _airwayOn3DMap.GetBounds[0], _airwayOn3DMap.GetBounds[1],
                _airwayOn3DMap.GetBounds[2], _airwayOn3DMap.GetBounds[3],
                _airwayOn3DMap.GetBounds[4], _airwayOn3DMap.GetBounds[5]);
            //_renderer.ResetCameraClippingRange();
            //_renderer.ResetCamera();

            _renwin.Render();
        }

        private void btnColor_Click(object sender, EventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            if (colorDialog.ShowDialog() == DialogResult.OK)
            {
                btnColor.BackColor = colorDialog.Color;

                _airwayOn3DMap.SetColor(colorDialog.Color);
                _renwin.Render();
            }
        }

        private void tbOpacity_Scroll(object sender, EventArgs e)
        {
            _airwayOn3DMap.SetOpacity(tbOpacity.Value / 100.0);
            _renwin.Render();
        }

        public bool HeartBeat()
        {
            return true;
        }

        public bool VisibiltyOff()
        {
            this.WindowState = FormWindowState.Minimized;
            //Visible = false;
            return true;
        }

        public bool VisibiltyOn()
        {
            this.WindowState = FormWindowState.Normal;
            //Visible = true;
            return true;
        }
    }
}
溪山行旅丶 | 园豆:6 (初学一级) | 2014-06-03 13:29

@溪山行旅丶: 在 WPF 中可以用 VTK 绘制在 BMP 上。

Launcher | 园豆:45050 (高人七级) | 2014-06-03 13:39

@Launcher: 怎么获得wpf控件的句柄呢

溪山行旅丶 | 园豆:6 (初学一级) | 2014-06-03 13:48

@溪山行旅丶: 不用获得,而且也没有,WPF 只有一个 HWND 对象,使用 DirectUI 技术,所有其它控件都是采用的虚拟窗体,最后绘制在同一个 HWND 上的。你从 FrameworkElement 派生一个控件,添加一个 WriteableBitmap 类型的成员变量,然后重载 OnRender 方法,在此方法中使用 DrawingContext 的 DrawImage 将 WriteableBitmap 绘制到界面上。你的 VTK 相关的绘制都需要绘制到此 WriteableBitmap 上。而至于鼠标、键盘事件,你可能需要做些适配器来融合 WPF 的事件路由机制。

Launcher | 园豆:45050 (高人七级) | 2014-06-03 13:53

@Launcher: 受教了

溪山行旅丶 | 园豆:6 (初学一级) | 2014-06-03 14:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册