WPF HelixTookit风力发电机Demo

目录

1. 创建WPF项目WindDemo​编辑

2. NuGet安装依赖包HelixToolkit.Wpf、WiimoteLib

3. 编辑ModelView.xmal代码

4. 编辑ModelView.xmal.cs代码

5. 创建WindTurbine.cs

6. 创建WindTurbineVisual3D.cs

7. 启动调试 


1. 创建WPF项目WindDemo

2. NuGet安装依赖包HelixToolkit.Wpf、WiimoteLib

3. 编辑ModelView.xmal代码

<Window x:Class="WindDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:h="clr-namespace:HelixToolkit.Wpf;assembly=HelixToolkit.Wpf" Title="WindDemo" Height="480" Width="640">
    <Grid>
        <h:HelixViewport3D x:Name="view1" ZoomExtentsWhenLoaded="True">
            <h:DefaultLights/>
        </h:HelixViewport3D>
    </Grid>
</Window>

4. 编辑ModelView.xmal.cs代码

namespace WindDemo
{
    using System;
    using System.Diagnostics;
    using System.Windows.Media;
    using System.Windows.Media.Media3D;


    using HelixToolkit.Wpf;

    using WiimoteLib;

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        private readonly ModelVisual3D model;

        public MainWindow()
        {
            InitializeComponent();

            model = new ModelVisual3D();

            const int rows = 5;
            const int columns = 4;
            const double distance = 120;

            var turbine = new WindTurbine();
            var r = new Random();
            for (int i = 0; i < rows; i++)
            {
                double y = i * distance;
                for (int j = 0; j + (i % 2) * 0.5 <= columns - 1; j++)
                {
                    double x = (j + (i % 2) * 0.5) * distance;
                    var visual = new WindTurbineVisual3D
                    {
                        RotationAngle = r.Next(360),
                        RotationSpeed = 20,
                        WindTurbine = turbine,
                        Transform = new TranslateTransform3D(x, y, 0)
                    };
                    model.Children.Add(visual);
                }
            }

            var seasurface = new RectangleVisual3D
            {
                DivWidth = 100,
                DivLength = 100,
                Origin = new Point3D((rows - 2) * distance * 0.5, (columns) * distance * 0.5, 0),
                Width = rows * distance * 2,
                Length = columns * distance * 2
            };
            seasurface.Material = seasurface.BackMaterial = MaterialHelper.CreateMaterial(Colors.SeaGreen, 0.8);

            model.Children.Add(new GridLinesVisual3D() { Center = seasurface.Origin, Fill = Brushes.Gray, Width = seasurface.Width, Length = seasurface.Length });

            model.Children.Add(seasurface);
            view1.Children.Add(model);

            Loaded += MainWindowLoaded;
            Closed += MainWindowClosed;
        }

        private Wiimote wm;

        void MainWindowClosed(object sender, EventArgs e)
        {
            try
            {
                if (wm != null)
                    wm.Disconnect();
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex);
            }
        }

        void MainWindowLoaded(object sender, System.Windows.RoutedEventArgs e)
        {
            try
            {
                wm = new Wiimote();
                wm.WiimoteChanged += OnWiimoteChanged;
                wm.Connect();
                wm.SetReportType(InputReport.IRAccel, true);
                wm.SetLEDs(false, false, false, false);
            }
            catch
            {
                wm = null;
            }
        }

        private void OnWiimoteChanged(object sender, WiimoteChangedEventArgs e)
        {
            HeadTracking(e.WiimoteState.IRState);
        }

        // headtracking 'light'
        // computes the angles to the observer around the camera up and right directions
        // also calculates the distance between two IR points - used for scaling
        // todo: take screen distance into account
        private void HeadTracking(IRState irState)
        {
            if (irState.IRSensors[0].Found)
            {
                var p0 = irState.IRSensors[0].RawPosition;
                double mx = p0.X;
                double my = p0.Y;
                double scale = 1;

                if (irState.IRSensors[1].Found)
                {
                    var p1 = irState.IRSensors[1].RawPosition;
                    double dx = p0.X - p1.X;
                    double dy = p0.Y - p1.Y;
                    double d = Math.Sqrt(dx * dx + dy * dy);
                    mx = (p0.X + p1.X) * 0.5;
                    my = (p0.Y + p1.Y) * 0.5;
                    scale = d / 200.0;
                }
                double theta = 20.0 * (mx - 512) / 512;
                double phi = 20.0 * (my - 384) / 384;
                Dispatcher.BeginInvoke(new Action(() => SetTransform(scale, theta, phi)));
            }
            //else
            //    Dispatcher.BeginInvoke(new Action(() => SetTransform(1, 0, 0)));
        }

        private void SetTransform(double scale, double theta, double phi)
        {
            var tg = new Transform3DGroup();
            tg.Children.Add(new ScaleTransform3D(scale, scale, scale));
            var center = view1.Camera.Position + view1.Camera.LookDirection;
            var up = view1.Camera.UpDirection;
            var right = Vector3D.CrossProduct(view1.Camera.LookDirection, up);
            tg.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(up, theta), center));
            tg.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(right, phi), center));
            model.Transform = tg;
        }
    }
}

5. 创建WindTurbine.cs

namespace WindDemo
{
    public class WindTurbine
    {
        // Rotor = Blades + Hub
        public double BladeLength { get; set; }
        public double BladeRootChord { get; set; }
        public double BladeTipChord { get; set; }
        public double HubDiameter { get; set; }
        public int Blades { get; set; }

        // Nacelle
        public double NacelleDiameter { get; set; }
        public double NacelleLength { get; set; }
        public double Yaw { get; set; }

        // Tower
        public double BaseHeight { get; set; }
        public double Height { get; set; }
        public double Diameter { get; set; }
        public double ShaftAngle { get; set; }
        public double Overhang { get; set; }

        public double Pre { get; set; }

        public WindTurbine()
        {
            BladeLength = 40;
            Height = 70;
            BaseHeight = 20;
            HubDiameter = 3;
            Diameter = 4;
            Overhang = 5;
            NacelleLength = 8;
            NacelleDiameter = 2;
            BladeRootChord = 1;
            BladeTipChord = 0.2;
            Blades = 3;

            ShaftAngle = 0.5;
            Pre = -2.5;
        }
    }
}

6. 创建WindTurbineVisual3D.cs

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

namespace WindDemo
{
    public class WindTurbineVisual3D : ModelVisual3D
    {
        public static readonly DependencyProperty WindTurbineProperty =
            DependencyProperty.Register("WindTurbine", typeof(WindTurbine), typeof(WindTurbineVisual3D),
                                        new UIPropertyMetadata(null, TurbineChanged));

        public static readonly DependencyProperty RotationAngleProperty =
            DependencyProperty.Register("RotationAngle", typeof(double), typeof(WindTurbineVisual3D),
                                        new UIPropertyMetadata(0.0));

        public int Blades
        {
            get { return WindTurbine.Blades; }
            set
            {
                WindTurbine.Blades = value;
                UpdateVisuals();
            }
        }

        public double Height
        {
            get { return WindTurbine.Height; }
            set
            {
                WindTurbine.Height = value;
                UpdateVisuals();
            }
        }

        public WindTurbine WindTurbine
        {
            get { return (WindTurbine)GetValue(WindTurbineProperty); }
            set { SetValue(WindTurbineProperty, value); }
        }


        /// <summary>
        /// Gets or sets the rotation angle (angle of the rotor).
        /// </summary>
        /// <value>The rotation angle.</value>
        public double RotationAngle
        {
            get { return (double)GetValue(RotationAngleProperty); }
            set { SetValue(RotationAngleProperty, value); }
        }

        /// <summary>
        /// Gets or sets the rotation speed (rpm).
        /// </summary>
        /// <value>The rotation speed.</value>
        public double RotationSpeed
        {
            get { return (double)GetValue(RotationSpeedProperty); }
            set { SetValue(RotationSpeedProperty, value); }
        }

        public static readonly DependencyProperty RotationSpeedProperty =
            DependencyProperty.Register("RotationSpeed", typeof(double), typeof(WindTurbineVisual3D), new UIPropertyMetadata(10.0));


        protected static void TurbineChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((WindTurbineVisual3D)obj).UpdateVisuals();
        }

        private readonly Stopwatch watch = new Stopwatch();

        private readonly RenderingEventListener renderingEventListener;

        public WindTurbineVisual3D()
        {
            renderingEventListener = new RenderingEventListener(this.OnCompositionTargetRendering);
            RenderingEventManager.AddListener(renderingEventListener);
        }

        private void OnCompositionTargetRendering(object sender, RenderingEventArgs e)
        {
            double delta = watch.ElapsedMilliseconds * 0.001;
            RotationAngle += 360 * RotationSpeed / 60 * delta;
            watch.Restart();
        }

        private void UpdateVisuals()
        {
            Children.Clear();
            if (WindTurbine == null) return;

            var baseTower = new TruncatedConeVisual3D
            {
                Fill = Brushes.Yellow,
                Origin = new Point3D(0, 0, -WindTurbine.BaseHeight)
            };
            baseTower.Height = -baseTower.Origin.Z + 2;
            baseTower.BaseRadius = baseTower.TopRadius = WindTurbine.Diameter;

            var tower = new TruncatedConeVisual3D
            {
                Fill = Brushes.White,
                Origin = new Point3D(0, 0, 2),
                Height = WindTurbine.Height,
                BaseRadius = WindTurbine.Diameter
            };
            tower.TopRadius = tower.BaseRadius * (1 - WindTurbine.Height * Math.Sin(WindTurbine.ShaftAngle / 180.0 * Math.PI));

            var nacelle = new TruncatedConeVisual3D
            {
                Fill = Brushes.White,
                Origin = new Point3D(WindTurbine.Overhang, 0, tower.Origin.Z + tower.Height),
                Normal = new Vector3D(-1, 0, 0),
                TopRadius = WindTurbine.NacelleDiameter
            };
            nacelle.BaseRadius = nacelle.TopRadius * 0.7;
            nacelle.Height = WindTurbine.NacelleLength;

            Children.Add(baseTower);
            Children.Add(tower);
            Children.Add(nacelle);


            var endcap = new SphereVisual3D
            {
                Center = new Point3D(WindTurbine.Overhang - WindTurbine.NacelleLength, 0,
                                                      tower.Origin.Z + tower.Height),
                Radius = nacelle.TopRadius,
                Fill = Brushes.White
            };
            Children.Add(endcap);

            var rotor = new ModelVisual3D();

            for (int i = 0; i < WindTurbine.Blades; i++)
            {
                double angle = (double)i / WindTurbine.Blades * Math.PI * 2;

                // todo: the blade is simplified to a cone... it should be a real profile...
                var blade = new TruncatedConeVisual3D
                {
                    Origin = nacelle.Origin,
                    Normal = new Vector3D(0, Math.Cos(angle), Math.Sin(angle)),
                    Height = WindTurbine.BladeLength,
                    BaseRadius = WindTurbine.BladeRootChord,
                    TopRadius = WindTurbine.BladeTipChord,
                    Fill = Brushes.White
                };
                rotor.Children.Add(blade);
            }

            var hub = new SphereVisual3D
            {
                Fill = Brushes.White,
                Center = nacelle.Origin,
                Radius = WindTurbine.HubDiameter / 2
            };
            rotor.Children.Add(hub);
            Children.Add(rotor);

            var rotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0);
            var rotorTransform = new RotateTransform3D(null, hub.Center) { Rotation = rotation };
            rotor.Transform = rotorTransform;

            var b = new Binding("RotationAngle") { Source = this };
            BindingOperations.SetBinding(rotation, AxisAngleRotation3D.AngleProperty, b);
        }
    }
}

7. 启动调试 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值