zoukankan      html  css  js  c++  java
  • 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了。 

  • 相关阅读:
    【纯水题】POJ 1852 Ants
    【树形DP】BZOJ 1131 Sta
    【不知道怎么分类】HDU
    【树形DP】CF 1293E Xenon's Attack on the Gangs
    【贪心算法】CF Emergency Evacuation
    【思维】UVA 11300 Spreading the Wealth
    【树形DP】NOI2003 逃学的小孩
    【树形DP】BZOJ 3829 Farmcraft
    【树形DP】JSOI BZOJ4472 salesman
    【迷宫问题】CodeForces 1292A A NEKO's Maze Game
  • 原文地址:https://www.cnblogs.com/enjoyeclipse/p/2365309.html
Copyright © 2011-2022 走看看