• WPF 3D中如何选择模型的一部分并维护模型


    最近的一个项目有个需求,就是点击WPF 3D模型的某个部分并对其后续操作,例如获得这个部分的数据并展示曲线图等等(这部分暂不展开)

    先上截图。

    我选择了一个方块,将方块显示为蓝色,同时屏幕坐上显示了点击方块后的操作。

    整个流程我处理了两个问题:

    1. 如何选择模型的这一部分

    2. 如何维护你选择的这个部分 

     


    问题1:如何选择模型的这一部分

    由于WPF 3D模型中只有Viewport3D对象有MouseButtonLeftDown事件,而模型的某个部分是没有这个事件的。因此需要使用首先VisualTreeHelper.HitTest来确定具体点击的是哪个模型,同时这个模型是需要给外部用的,因此我们自定义了一个ModelVisual3DSelectedEventHandler的事件给外部调用。

     1 //自定义个一个模型选中的EventHandler 
     2 public class Visual3DEventArgs : EventArgs
     3 {
     4  public ModelVisual3D Visual3D { getset; }
     5 
     6      public Visual3DEventArgs(ModelVisual3D modelVisual3D)
     7      {
     8         this.Visual3D = modelVisual3D;
     9      }
    10 }
    11 
    12 public delegate void ModelVisual3DSelectedEventHandler(object sender, Visual3DEventArgs args);
    13 //....
    14 
    15 //声明Viewport3D的LeftButton事件
    16 ViewPort.MouseLeftButtonDown += ViewPort_MouseLeftButtonDown;
    17 
    18 //Viewport LeftButton的函数
    19 void ViewPort_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs args)
    20 {
    21     Point mousePos = args.GetPosition(ViewPort);
    22     var hitParams = new PointHitTestParameters(mousePos);
    23     VisualTreeHelper.HitTest(ViewPort, null, ResultCallback, hitParams);
    24 }
    25 
    26 //根据HitTest选中之后的处理
    27  private HitTestResultBehavior ResultCallback(HitTestResult result)
    28  {
    29             RayHitTestResult rayResult = result as RayHitTestResult;
    30             
    31             if (rayResult != null)
    32             {
    33                 var visual3D = result.VisualHit as ModelVisual3D;
    34                 if (visual3D != null)
    35                 {
    36                     if (OnModelSelected != null)
    37                     {
    38                         OnModelSelected(thisnew Visual3DEventArgs(visual3D));
    39                     }
    40 
    41                     return HitTestResultBehavior.Stop;
    42                 }
    43                 
    44             }
    45             return HitTestResultBehavior.Continue;
    46 }

    2. 问题2:如何维护你选择部分

    我刚刚在Visual3DEventArgs中已经获得了选择的模型了,这时候我就可以对它进行操作了。或许数据库中有个模型叫"block1",查找数据等等.... 但是很悲催的是, 虽然在xaml文件中ModelVisual3D是有x:name的,但是ModelVisual3D本书是没有 ModelVisual3D.Name这个属性的,即使获取了这个模型,也只能对其进行基本的渲染,根本没有办法进行逻辑操作(例如根据数据库通信等)。

    只有通过viewport3D.FindName(string name)才能获取对象!

    解决办法是:我们自己可以维护一个模型名字表(其实就是个xml文件): 

     <Sections>

    <Section>
        <Name>dg01</Name>
    </Section>
    <Section>
        <Name>dg02</Name>
    </Section>
    <Section>
        <Name>dg04</Name>
    </Section>
    </Sections>

    然后定义一个返回名字的函数:

     1 public Section GetSelSection(ModelVisual3D visual3D)
     2         {
     3             if (_context != null && _context.Sections != null && visual3D != null)
     4             {
     5                 var viewPort = _context.Model.ViewPort;
     6 
     7                 foreach (var section in _context.Sections)
     8                 {
     9                     if (viewPort.FindName(section.Name) == visual3D)
    10                     {
    11                         return section;
    12                     }
    13                 }
    14             }
    15 
    17             return null;
    18         }

    我就可以通过GetSelSection(args.Visual3D)获得这个section对象了。对了,这个Section就是刚才XML文件的映射类。和数据库操作就可以使用这个Section了。 

  • 相关阅读:
    angular中集中页面传参(我只是知识的搬运工)
    使用Cookie传递参数 ,a页面保存Cookie,b页面读取,代码如下:
    获取并处理地址栏中参数方法
    常见的css命名规范/ID命名规范/常用功能模块的命名
    angularjs 1.x 项目完整的较完整的登录验证具体代码(仅供参考)
    用angular自带的方法获取input中内容(以用户名和密码为例)的字符串长度方法
    jquery 层弹窗传值
    伯乐在线node高手的基础经验 您值得一读
    javascript 代码规范
    正确看待技术
  • 原文地址:https://www.cnblogs.com/enjoyeclipse/p/2365309.html
Copyright © 2020-2023  润新知