为什么两个转换不适用于 Helix 工具包对象

Why does two Transform do not work with a Helix Toolkit Object

我整理了一些代码,通过使用 WPF 滑块控件来操作两个 Helix Toolkit Torus 对象。此代码是其他一些更复杂问题的原型。

当我仅应用平移或旋转变换时,环面对象移动或旋转。然而,当我都只应用了颂歌作品中列出的最后一个时(本例中为旋转)。如果我注释掉旋转变换,翻译工作。

我尝试了 TransformGroup 方法,然后除了 Helix Tool 工具包中定义的依赖对象(例如 TorusDiameter)之外没有任何效果。

正如您从代码中看到的那样,一次只能进行一个转换,因为一次只能移动一个滑块。

我有两个问题:

(1) 为什么Transform的多应用(行)不起作用?我怎样才能让它发挥作用?

(2) 我在事件处理程序 MyTorusChanged 中放置了一个消息框。它似乎只在一开始就被解雇了。我是 WPF 的新手。 Transform 如何在不通过事件处理程序的情况下工作?

视图模型:

// April 08, 2019, Dr. I. Konuk

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using HelixToolkit.Wpf;

namespace AnimatedTorusDemo
{
    class MyTorusViewModel : ModelVisual3D
    {
        // origin of torus object
        public Point3D TorusOrigin { get; set; }
        public double translationX { get; set; }
        public double translationY { get; set; }
        public double translationZ { get; set; }

        // translation transformation parameter properties

        public static readonly DependencyProperty TranslationXProperty =
                    DependencyProperty.Register("TranslationX", typeof(double), typeof(MyTorusViewModel),
                            new UIPropertyMetadata(0.0));
        public static readonly DependencyProperty TranslationYProperty =
                    DependencyProperty.Register("TranslationY", typeof(double), typeof(MyTorusViewModel),
                            new UIPropertyMetadata(0.0));
        public static readonly DependencyProperty TranslationZProperty =
                    DependencyProperty.Register("TranslationZ", typeof(double), typeof(MyTorusViewModel),
                            new UIPropertyMetadata(0.0));

        public double TranslationX
        {
            get { return (double)GetValue(TranslationXProperty); }
            set { SetValue(TranslationXProperty, value); translationX = value; }
        }
        public double TranslationY
        {
            get { return (double)GetValue(TranslationYProperty); }
            set { SetValue(TranslationYProperty, value); translationY = value; }
        }
        public double TranslationZ
        {
            get { return (double)GetValue(TranslationZProperty); }
            set { SetValue(TranslationZProperty, value); translationZ = value; }
        }

        // MyTorusProperty
        // notice the callback function definition via Metadata

        public static DependencyProperty MyTorusProperty =
                    DependencyProperty.Register("MyTorus", typeof(TorusVisual3D), typeof(MyTorusViewModel),
                    new UIPropertyMetadata(null, MyTorusChanged));
        public TorusVisual3D MyTorus
        {
            get => (TorusVisual3D)GetValue(MyTorusProperty);
            set { SetValue(MyTorusProperty, value); }
        }

        // rotation angle property
        // Gets or sets the rotation angle (angle of torus).

        public static readonly DependencyProperty RotationAngleProperty =
                    DependencyProperty.Register("RotationAngle", typeof(double), typeof(MyTorusViewModel),
                            new UIPropertyMetadata(45.0));
        public double RotationAngle
        {
            get { return (double)GetValue(RotationAngleProperty); }
            set { SetValue(RotationAngleProperty, value); }
        }

        public static AxisAngleRotation3D axisAngleRotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0);

        public static readonly DependencyProperty TorusAxisAngleProperty =
                    DependencyProperty.Register("TorusAxisAngle", typeof(AxisAngleRotation3D), typeof(MyTorusViewModel),
                    new UIPropertyMetadata(axisAngleRotation));
        public AxisAngleRotation3D TorusAxisAngle
        {
            get { return (AxisAngleRotation3D)GetValue(TorusAxisAngleProperty);  }
            set { SetValue(TorusAxisAngleProperty, value);  }
        }

        // callback function used updating visuals (torus obejects)
        protected static void MyTorusChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((MyTorusViewModel)obj).UpdateVisuals();
        }

        // member function to update visuals
        private void UpdateVisuals()
        {
            MessageBox.Show("UpdateVisuals");

            Children.Clear();

            // each instance must have a torus object assigned for each MyTorusViewModel before

            if (MyTorus == null) return;

            MyTorus.ThetaDiv = 36;
            MyTorus.PhiDiv = 24;

            // translation

            var torusTranslate = new TranslateTransform3D(new Vector3D(translationX, translationY, translationZ));

            MyTorus.Transform = torusTranslate;

            // rotation

            var torusRotate = new RotateTransform3D();
            TorusAxisAngle = new AxisAngleRotation3D();

            TorusAxisAngle.Axis= new Vector3D(0, 1, 0);
            TorusAxisAngle.Angle = RotationAngle;

            torusRotate.Rotation = TorusAxisAngle;

            MyTorus.Transform = torusRotate;


            // transform group

            var torusTransformGroup = new Transform3DGroup();
            torusTransformGroup.Children.Add(torusTranslate);

            // MyTorus.Transform = torusTransformGroup;

            Children.Add(MyTorus);
        }

    }
}

xaml:

<Window x:Class="AnimatedTorusDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:h="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf"
        xmlns:local="clr-namespace:AnimatedTorusDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="750" Width="800">

    <Grid ShowGridLines="True">

        <Grid.RowDefinitions>
            <RowDefinition Height="4*" />
            <RowDefinition Height="0.75*" />
            <RowDefinition Height="0.75*" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>

        <h:HelixViewport3D x:Name="TorusView" ZoomExtentsWhenLoaded="True"  ShowCoordinateSystem="True" PanGesture="LeftClick" >
            <h:DefaultLights/>
        </h:HelixViewport3D>

        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >

            <Slider x:Name="translationX1Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
                    />
            <Slider x:Name="translationY1Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
                    />
            <Slider x:Name="translationZ1Slider" Value="1" Minimum="-3" Maximum="3" Width="150" Margin="10"
                    />
            <Slider x:Name="rotation1Slider" Value="45" Minimum="0" Maximum="360" Width="150" Margin="10"
                    />

        </StackPanel>

        <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >

            <Slider x:Name="translationX2Slider" Value="0" Minimum="-5.0" Maximum="5.0" Width="150" Margin="10"
                    />
            <Slider x:Name="translationY2Slider" Value="0" Minimum="-5" Maximum="5" Width="150" Margin="10"
                    />
            <Slider x:Name="translationZ2Slider" Value="-1" Minimum="-3" Maximum="3" Width="150" Margin="10"
                    />
            <Slider x:Name="rotation2Slider" Value="45" Minimum="0" Maximum="360" Width="150" Margin="10"
                    />

        </StackPanel>

        <StackPanel  Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Bottom" Opacity="0.9" >

            <Slider x:Name="torusDiameterSlider" Minimum="1" Maximum="10" Width="150" Margin="10"
                    />
            <Slider x:Name="tubeDiameterSlider" Value="1" Minimum="0.5" Maximum="5" Width="150" Margin="10"
                    />
            <Slider x:Name="thetaDivSlider" Value="36" Minimum="3" Maximum="256" Width="150" Margin="10"
                    />
            <Slider x:Name="phiDivSlider" Value="24" Minimum="3" Maximum="256" Width="150" Margin="10"/>

        </StackPanel>

    </Grid>
</Window>

主要window:

// April 08, 2019, Dr. I. Konuk

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Diagnostics;
using System.Windows.Media.Media3D;

using HelixToolkit.Wpf;

namespace AnimatedTorusDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly ModelVisual3D model;
        private MyTorusViewModel visual1;
        private MyTorusViewModel visual2;
        public MainWindow()
        {
            InitializeComponent();

            model = new ModelVisual3D();

            visual1 = new MyTorusViewModel();

            var mytorus1 = new TorusVisual3D();
            mytorus1.Fill = Brushes.Red;
            visual1.MyTorus = mytorus1;

            visual2 = new MyTorusViewModel();

            var mytorus2 = new TorusVisual3D();
            mytorus2.Fill = Brushes.Blue;
            visual2.MyTorus = mytorus2;
            mytorus2.TorusDiameter = 5;

            // bindings with sliders in code

            // Helix Toolkit dependencyproperties:

            // a) Geometry:
            BindingOperations.SetBinding(mytorus1, HelixToolkit.Wpf.TorusVisual3D.TorusDiameterProperty, 
                                        new Binding("Value") { Source = torusDiameterSlider });
            BindingOperations.SetBinding(mytorus1, HelixToolkit.Wpf.TorusVisual3D.TubeDiameterProperty, 
                                        new Binding("Value") { Source = tubeDiameterSlider });

            // b) Translation:
            // Dependency properties defined in MyTorusView Model
            BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetXProperty, 
                                        new Binding("Value") { Source = translationX1Slider });
            BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetYProperty, 
                                        new Binding("Value") { Source = translationY1Slider });
            BindingOperations.SetBinding(mytorus1.Transform, TranslateTransform3D.OffsetZProperty,
                            new Binding("Value") { Source = translationZ1Slider });

            BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetXProperty,
                                        new Binding("Value") { Source = translationX2Slider });
            BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetYProperty,
                            new Binding("Value") { Source = translationY2Slider });
            BindingOperations.SetBinding(mytorus2.Transform, TranslateTransform3D.OffsetZProperty,
                new Binding("Value") { Source = translationZ2Slider });

            // b) Rotation
            BindingOperations.SetBinding(visual1.TorusAxisAngle, AxisAngleRotation3D.AngleProperty,
                             new Binding("Value") { Source = rotation1Slider });
            BindingOperations.SetBinding(visual2.TorusAxisAngle, AxisAngleRotation3D.AngleProperty,
                             new Binding("Value") { Source = rotation2Slider });


            model.Children.Add(visual1);
            model.Children.Add(visual2);
            TorusView.Children.Add(model);

            this.DataContext = this;
        }
    }
}

当您应用旋转并将其设置为 .transform 属性 时,它会将包含平移的先前转换替换为仅包含旋转的新转换。相反,您需要做的是获取最新的变换矩阵(包括翻译)并对其应用旋转,然后重置 .transform 属性。 我对这个问题的回答回答了你问题的第一部分: 请将您的其他问题作为一个单独的问题提出(每个问题一个问题)。参考这个link原因:https://meta.stackexchange.com/questions/222735/can-i-ask-only-one-question-per-post