0

大家好,这是我在这里的第一个问题。所以请随时给我CC :)

关于该项目。我想在不触及 Z 轴(0,0,0 0,1,0 1,0,0 1,1,0)的情况下从平面多边形平面进行非仿射变换。我需要通过定位它的 4 个角点来做到这一点。我通过使用 Charles Petzold ( http://www.charlespetzold.com/blog/2007/08/250638.html ) 的“2D 非仿射变换”实现了这一点。

到目前为止一切都很好。也没有消失的飞机。

因为我需要画笔/纹理来扩展平面的边缘。我决定添加三角形,直到我有 5x5 的平面网格。(通过选择第一个平面的角点(它是中间的那个),整个几何图形仍然可以变换。)

可悲的是,我还不允许发布图片。

https://i.imgur.com/oG3gKRD.png

浅蓝色的矩形是具有可选角的矩形,紫色是其余的(对于图片我包含另一个平面(与大平面没有连接,只是为了表明没有疯狂的变换效果)只有值相差 1(无论哪个角)

https://i.imgur.com/wSkywVk.png

据我所知,这不是相机的问题。改变很多东西的值,比如相机/近和远平面距离。如果我将网格缩小到 3x3 平面,这种定位总是会导致不可见的几何图形(它不是唯一的位置,其中有一些,但我看不到连接)我有同样的问题,仅在其他职位上。对象仍然存在,只是不可见(我仍然可以选择角点,它会立即再次可见)

有谁知道会导致什么?或者有人知道我如何调试这样的“错误”吗?

也许它是一般增长可变形平面的错误方法?如果有人有想法,请告诉我!

设置两个平面的几何图形(两个自定义类“scalingCanvas”和“CenterOnPoint”,您可以使用具有正常定位的普通画布)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:HtMatrix">
    <Style TargetType="local:HtProjektor">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:HtProjektor">
                    <Grid Background="DarkOrange">
                        <Viewport3D Name="viewport3d"  Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}" >

                            <ModelVisual3D>
                                <ModelVisual3D.Content>
                                    <Model3DGroup>


                                        <GeometryModel3D>
                                            <GeometryModel3D.Geometry>


                                                <MeshGeometry3D x:Name="mesh"
                                                                Positions="0 0 0, 0 1 0, 1 0 0, 1 1 0,
                                                                0 1 0, 0 2 0, 1 1 0, 1 2 0,
                                                                0 -1 0, 0 0 0, 1 -1 0, 1 0 0,
                                                                1 1 0, 1 2 0, 2 1 0, 2 2 0,
                                                                1 0 0, 1 1 0, 2 0 0, 2 1 0,
                                                                1 -1 0, 1 0 0, 2 -1 0, 2 0 0,
                                                                -1 0 0, -1 1 0, 0 0 0, 0 1 0,
                                                                -1 1 0, -1 2 0, 0 1 0, 0 2 0,
                                                                -1 -1 0, -1 0 0, 0 -1 0, 0 0 0,

                                                                -2 2 0, -2 3 0, -1 2 0, -1 3 0,
                                                                -1 2 0, -1 3 0, 0 2 0, 0 3 0,
                                                                0 2 0, 0 3 0, 1 2 0, 1 3 0,
                                                                1 2 0, 1 3 0, 2 2 0, 2 3 0,
                                                                2 2 0, 2 3 0, 3 2 0, 3 3 0

                                                               -2 1 0, -2 2 0, -1 1 0, -1 2 0, 
                                                                2 1 0, 2 2 0, 3 1 0, 3 2 0,
                                                                -2 0 0, -2 1 0, -1 0 0, -1 1 0,
                                                                2 0 0, 2 1 0, 3 0 0, 3 1 0
                                                                -2 -1 0, -2 0 0, -1 -1 0, -1 0 0,                                                                
                                                                2 -1 0, 2 0 0, 3 -1 0, 3 0 0,

                                                                -2 -2 0, -2 -1 0, -1 -2 0, -1 -1 0,
                                                                -1 -2 0, -1 -1 0, 0 -2 0, 0 -1 0,
                                                                0 -2 0, 0 -1 0, 1 -2 0, 1 -1 0,
                                                                1 -2 0, 1 -1 0, 2 -2 0, 2 -1 0,
                                                                2 -2 0, 2 -1 0, 3 -2 0, 3 -1 0

                                                                "



                                                                TextureCoordinates="0 0, 0 1, 1 0, 1 1,
                                                                0 1, 0 2, 1 1, 1 2,
                                                                0 -1, 0 0, 1 -1, 1 0,
                                                                1 1, 1 2, 2 1, 2 2,
                                                                1 0, 1 1, 2 0, 2 1,
                                                                1 -1, 1 0, 2 -1, 2 0,
                                                                -1 0, -1 1, 0 0, 0 1,
                                                                -1 1, -1 2, 0 1, 0 2,
                                                                -1 -1, -1 0, 0 -1, 0 0,

                                                                -2 2, -2 3, -1 2, -1 3,
                                                                -1 2, -1 3, 0 2, 0 3,
                                                                0 2, 0 3, 1 2, 1 3,
                                                                1 2, 1 3, 2 2, 2 3,
                                                                2 2, 2 3, 3 2, 3 3

                                                                -2 1, -2 2, -1 1, -1 2, 
                                                                2 1, 2 2, 3 1, 3 2,
                                                                -2 0, -2 1, -1 0, -1 1,
                                                                2 0, 2 1, 3 0, 3 1,
                                                                -2 -1, -2 0, -1 -1, -1 0,
                                                                2 -1, 2 0, 3 -1, 3 0

                                                                -2 -2, -2 -1, -1 -2, -1 -1,
                                                                -1 -2, -1 -1, 0 -2, 0 -1,
                                                                0 -2, 0 -1, 1 -2, 1 -1,
                                                                1 -2, 1 -1, 2 -2, 2 -1,
                                                                2 -2, 2 -1, 3 -2, 3 -1
                                                                "

                                                                TriangleIndices="0 2 1, 1 2 3,
                                                                4 6 5, 5 6 7,
                                                                8 10 9, 9 10 11,
                                                                12 14 13, 13 14 15,
                                                                16 18 17, 17 18 19,
                                                                20 22 21, 21 22 23,
                                                                24 26 25, 25 26 27,
                                                                28 30 29, 29 30 31,
                                                                32 34 33, 33 34 35,

                                                                36 38 37, 37 38 39,
                                                                40 42 41, 41 42 43,
                                                                44 46 45, 45 46 47,
                                                                48 50 49, 49 50 51,
                                                                52 54 53, 53 54 55

                                                                56 58 57, 57 58 59,
                                                                60 62 61, 61 62 63,
                                                                64 66 65, 65 66 67,
                                                                68 70 69, 69 70 71,
                                                                72 74 73, 73 74 75,
                                                                76 78 77, 77 78 79,

                                                                80 82 81, 81 82 83,
                                                                84 86 85, 85 86 87,
                                                                88 90 89, 89 90 91,
                                                                92 94 93, 93 94 95,
                                                                96 98 97, 97 98 99

                                                                " />

                                            </GeometryModel3D.Geometry>


                                            <GeometryModel3D.Material>
                                                <DiffuseMaterial>
                                                    <DiffuseMaterial.Brush>
                                                        <VisualBrush>
                                                            <VisualBrush.Visual>



                                                                <local:ScalingCanvas  Background="Gray" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}">

                                                                    <Grid Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}" ClipToBounds="True">


                                                                        <local:ScalingCanvas Width="{Binding RelativeSource={RelativeSource TemplatedParent}}" Height="{Binding RelativeSource={RelativeSource TemplatedParent}}" Background="PaleVioletRed" Opacity="0.5">
                                                                            <local:ScalingCanvas.RenderTransform>
                                                                                <ScaleTransform ScaleX="{Binding ScaleX, RelativeSource={RelativeSource TemplatedParent}}" ScaleY="{Binding ScaleY, RelativeSource={RelativeSource TemplatedParent}}"/>
                                                                            </local:ScalingCanvas.RenderTransform>
                                                                            <Rectangle Height="768" Width="1024"/>

                                                                            <Rectangle local:ScalingCanvas.Top="200" local:ScalingCanvas.Left="200"  Fill="Aqua" Width="100" Height="100" />
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="100,100" Fill="Blue" Width="100" Height="100" Opacity="0.7"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="0,0" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="1024,0" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="0,768" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="1024,768" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="500, 0" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="600, 768" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="500, 868" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="500, -100" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="0,350" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="1000,384" Fill="Black" Height="100" Width="100"/>
                                                                            <Rectangle local:CenterOnPoint.CenterPoint="512,384" Fill="YellowGreen" Height="153.6" Width="204.8" Opacity="0.5"/>

                                                                            <Image local:CenterOnPoint.CenterPoint="512,384" Source="IMG_4831.JPG" Width="100" Height="150" Stretch="Fill" />

                                                                        </local:ScalingCanvas>

                                                                    </Grid>

                                                                </local:ScalingCanvas>

                                                            </VisualBrush.Visual>
                                                        </VisualBrush>

                                                    </DiffuseMaterial.Brush>
                                                </DiffuseMaterial>
                                            </GeometryModel3D.Material>



                                            <GeometryModel3D.Transform >
                                                <Transform3DGroup>
                                                    <MatrixTransform3D x:Name="xform" />

                                                </Transform3DGroup>

                                            </GeometryModel3D.Transform>

                                        </GeometryModel3D>


                                    <GeometryModel3D>
                                        <GeometryModel3D.Geometry>


                                            <MeshGeometry3D x:Name="mesh1"
                                                            Positions="0 0 0, 0 1 0, 1 0 0, 1 1 0"
                                                            TextureCoordinates="0 0, 0 1, 1 0, 1 1" 
                                                            TriangleIndices="0 2 1, 2 3 1" />
                                        </GeometryModel3D.Geometry>


                                        <GeometryModel3D.Material>
                                            <DiffuseMaterial>
                                                <DiffuseMaterial.Brush>
                                                    <VisualBrush>
                                                        <VisualBrush.Visual>



                                                            <local:ScalingCanvas  Background="Gray" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}">

                                                                <Grid Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}" ClipToBounds="True">


                                                                    <local:ScalingCanvas Width="{Binding RelativeSource={RelativeSource TemplatedParent}}" Height="{Binding RelativeSource={RelativeSource TemplatedParent}}" Background="AliceBlue" Opacity="0.5">
                                                                        <local:ScalingCanvas.RenderTransform>
                                                                            <ScaleTransform ScaleX="{Binding ScaleX, RelativeSource={RelativeSource TemplatedParent}}" ScaleY="{Binding ScaleY, RelativeSource={RelativeSource TemplatedParent}}"/>
                                                                        </local:ScalingCanvas.RenderTransform>
                                                                        <Rectangle Height="768" Width="1024"/>

                                                                        <Rectangle local:ScalingCanvas.Top="200" local:ScalingCanvas.Left="200"  Fill="Aqua" Width="100" Height="100" />
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="100,100" Fill="Blue" Width="100" Height="100" Opacity="0.7"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="0,0" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="1024,0" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="0,768" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="1024,768" Fill="Yellow" Width="100" Height="100" Opacity="0.7"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="500, 0" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="600, 768" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="500, 868" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="500, -100" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="0,350" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="1000,384" Fill="Black" Height="100" Width="100"/>
                                                                        <Rectangle local:CenterOnPoint.CenterPoint="512,384" Fill="YellowGreen" Height="153.6" Width="204.8" Opacity="0.5"/>

                                                                        <Image local:CenterOnPoint.CenterPoint="512,384" Source="IMG_4831.JPG" Width="100" Height="150" Stretch="Fill" />

                                                                    </local:ScalingCanvas>

                                                                </Grid>

                                                            </local:ScalingCanvas>

                                                        </VisualBrush.Visual>
                                                    </VisualBrush>

                                                </DiffuseMaterial.Brush>
                                            </DiffuseMaterial>
                                        </GeometryModel3D.Material>


                                        <GeometryModel3D.Transform >
                                            <Transform3DGroup>
                                                <MatrixTransform3D x:Name="xform2" />

                                            </Transform3DGroup>

                                        </GeometryModel3D.Transform>

                                    </GeometryModel3D>

                                        <!--Light source.--> 

                                        <AmbientLight Color="White" />
                                    </Model3DGroup>
                                </ModelVisual3D.Content>
                            </ModelVisual3D>

                            <!-- Camera. -->
                            <Viewport3D.Camera>
                                <OrthographicCamera Position="0.5 0.5 1"
                                                    LookDirection="0 0 -1"
                                                    UpDirection="0 1 0"
                                                    Width="1"

                                                   />

                            </Viewport3D.Camera>

                        </Viewport3D>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

由于字符的限制,Projektor 课程将作为答案发布。如果您需要任何事情来解决问题,请告诉我!& 这个问题一般来说大吗?我欢迎 cunstructive 批评家!:)

4

1 回答 1

0

具有计算功能的投影机类!是否可以将评论连接到主要问题?

HtProjektor.cs

        using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Media3D;

    namespace HtMatrix
    {
        public class HtProjektor : Control
        {



            /// <summary>
            /// Breite in mm
            /// </summary>
            public int Breite
            {
                get { return (int)GetValue(BreiteProperty); }
                set { SetValue(BreiteProperty, value); }
            }

            /// <summary>
            /// The <see cref="Breite"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty BreiteProperty = DependencyProperty.Register("Breite", typeof(int), typeof(HtProjektor), new PropertyMetadata(1024, _DisplayScaleChanged));


            /// Höhe in mm

            public int Hoehe
            {
                get { return (int)GetValue(HoeheProperty); }
                set { SetValue(HoeheProperty, value); }
            }


            /// The <see cref="Hoehe"/> DependencyProperty.

            public static readonly DependencyProperty HoeheProperty = DependencyProperty.Register("Hoehe", typeof(int), typeof(HtProjektor), new PropertyMetadata(768, _DisplayScaleChanged));

            private static void _DisplayScaleChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)

            {
                if (dependencyObject is HtProjektor projektor)
                {
                    projektor.ScaleX = projektor.ActualWidth / projektor.Breite;
                    projektor.ScaleY = projektor.ActualHeight / projektor.Hoehe;

                }
            }


            /// Skalierung X

            public double ScaleX
            {
                get { return (double)GetValue(ScaleXProperty); }
                set { SetValue(ScaleXProperty, value); }
            }


            /// The <see cref="ScaleX"/> DependencyProperty.

            public static readonly DependencyProperty ScaleXProperty = DependencyProperty.Register("ScaleX", typeof(double), typeof(HtProjektor), new PropertyMetadata(0.0));


            /// Skalierung Y

            public double ScaleY
            {
                get { return (double)GetValue(ScaleYProperty); }
                set { SetValue(ScaleYProperty, value); }
            }

            /// The <see cref="ScaleY"/> DependencyProperty.

            public static readonly DependencyProperty ScaleYProperty = DependencyProperty.Register("ScaleY", typeof(double), typeof(HtProjektor), new PropertyMetadata(0.0));

            /// The Top Left point

            public Point CurrentMousePosition
            {
                get { return (Point)GetValue(CurrentMousePositionProperty); }
                set { SetValue(CurrentMousePositionProperty, value); }
            }


            /// The <see cref="TopLeftPoint"/> DependencyProperty.

            public static readonly DependencyProperty CurrentMousePositionProperty = DependencyProperty.Register("CurrentMousePosition", typeof(Point), typeof(HtProjektor));


            /// The Top Left point

            public Point TopLeftPoint
            {
                get { return (Point)GetValue(TopLeftPointProperty); }
                set { SetValue(TopLeftPointProperty, value); }
            }


            /// The <see cref="TopLeftPoint"/> DependencyProperty.

            public static readonly DependencyProperty TopLeftPointProperty = DependencyProperty.Register("TopLeftPoint", typeof(Point), typeof(HtProjektor), new PropertyMetadata(_Coordinate_Changed));


            /// The Top Right point

            public Point TopRightPoint
            {
                get { return (Point)GetValue(TopRightPointProperty); }
                set { SetValue(TopRightPointProperty, value); }
            }


            /// The <see cref="TopRightPoint"/> DependencyProperty.

            public static readonly DependencyProperty TopRightPointProperty = DependencyProperty.Register("TopRightPoint", typeof(Point), typeof(HtProjektor), new PropertyMetadata(_Coordinate_Changed));


            /// The Bottom Left point

            public Point BottomLeftPoint
            {
                get { return (Point)GetValue(BottomLeftPointProperty); }
                set { SetValue(BottomLeftPointProperty, value); }
            }


            /// The <see cref="BottomLeftPoint"/> DependencyProperty.

            public static readonly DependencyProperty BottomLeftPointProperty = DependencyProperty.Register("BottomLeftPoint", typeof(Point), typeof(HtProjektor), new PropertyMetadata(_Coordinate_Changed));


            /// The Bottom Right point

            public Point BottomRightPoint
            {
                get { return (Point)GetValue(BottomRightPointProperty); }
                set { SetValue(BottomRightPointProperty, value); }
            }


            /// The <see cref="BottomRightPoint"/> DependencyProperty.

            public static readonly DependencyProperty BottomRightPointProperty = DependencyProperty.Register("BottomRightPoint", typeof(Point), typeof(HtProjektor), new PropertyMetadata(_Coordinate_Changed));

            private static void _Coordinate_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                if (dependencyObject is HtProjektor projektor)
                {
                    Point pointTl = projektor.Simple3Dto2D(projektor._Viewport3D, projektor.pointsTransformed[1]);
                    Point pointTr = projektor.Simple3Dto2D(projektor._Viewport3D, projektor.pointsTransformed[3]);
                    Point pointBl = projektor.Simple3Dto2D(projektor._Viewport3D, projektor.pointsTransformed[0]);
                    Point pointBr = projektor.Simple3Dto2D(projektor._Viewport3D, projektor.pointsTransformed[2]);
                    projektor.TLX = (int)pointTl.X;
                    projektor.TLY = (int)pointTl.Y;

                    projektor.TRX = (int)pointTr.X;
                    projektor.TRY = (int)pointTr.Y;

                    projektor.BLX = (int)pointBl.X;
                    projektor.BLY = (int)pointBl.Y;

                    projektor.BRX = (int)pointBr.X;
                    projektor.BRY = (int)pointBr.Y;
                }
            }

            /// <summary>
            /// The top left x coordinate
            /// </summary>
            public int TLX
            {
                get { return (int)GetValue(TLXProperty); }
                set { SetValue(TLXProperty, value); }
            }

            /// <summary>
            /// The <see cref="TLX"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty TLXProperty = DependencyProperty.Register("TLX", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Tl_CoordinateChanged));

            /// <summary>
            /// The top left y coordinate
            /// </summary>
            public int TLY
            {
                get { return (int)GetValue(TLYProperty); }
                set { SetValue(TLYProperty, value); }
            }

            /// <summary>
            /// The <see cref="TLY"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty TLYProperty = DependencyProperty.Register("TLY", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Tl_CoordinateChanged));

            private static void _Pixel_Tl_CoordinateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                if (dependencyObject is HtProjektor projektor)
                {
                    projektor.pointsTransformed[1] = projektor.Simple2Dto3D(projektor._Viewport3D, new Point(projektor.TLX, projektor.TLY)); //links oben
                    projektor._MatrixTransform3D.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);
                    projektor._MatrixTransform3D02.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);


                }
            }

            /// <summary>
            /// The top right X coordinate
            /// </summary>
            public int TRX
            {
                get { return (int)GetValue(TRXProperty); }
                set { SetValue(TRXProperty, value); }
            }

            /// <summary>
            /// The <see cref="TRX"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty TRXProperty = DependencyProperty.Register("TRX", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Tr_CoordinateChanged));

            /// <summary>
            /// The top right y coordinate
            /// </summary>
            public int TRY
            {
                get { return (int)GetValue(TRYProperty); }
                set { SetValue(TRYProperty, value); }
            }

            /// <summary>
            /// The <see cref="TRY"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty TRYProperty = DependencyProperty.Register("TRY", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Tr_CoordinateChanged));

            private static void _Pixel_Tr_CoordinateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                if (dependencyObject is HtProjektor projektor)
                {
                    projektor.pointsTransformed[3] = projektor.Simple2Dto3D(projektor._Viewport3D, new Point(projektor.TRX, projektor.TRY)); //rechts oben
                    projektor._MatrixTransform3D.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);
                    projektor._MatrixTransform3D02.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);


                }
            }

            /// <summary>
            /// The bottom left x coordinate
            /// </summary>
            public int BLX
            {
                get { return (int)GetValue(BLXProperty); }
                set { SetValue(BLXProperty, value); }
            }

            /// <summary>
            /// The <see cref="BLX"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty BLXProperty = DependencyProperty.Register("BLX", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Bl_CoordinateChanged));

            /// <summary>
            /// The bottom left y coordinate
            /// </summary>
            public int BLY
            {
                get { return (int)GetValue(BLYProperty); }
                set { SetValue(BLYProperty, value); }
            }

            /// <summary>
            /// The <see cref="BLY"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty BLYProperty = DependencyProperty.Register("BLY", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Bl_CoordinateChanged));

            private static void _Pixel_Bl_CoordinateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                if (dependencyObject is HtProjektor projektor)
                {
                    projektor.pointsTransformed[0] = projektor.Simple2Dto3D(projektor._Viewport3D, new Point(projektor.BLX, projektor.BLY)); //links unten
                    projektor._MatrixTransform3D.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);
                    projektor._MatrixTransform3D02.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);

                }
            }

            /// <summary>
            /// The bottom right x coordinate
            /// </summary>
            public int BRX
            {
                get { return (int)GetValue(BRXProperty); }
                set { SetValue(BRXProperty, value); }
            }

            /// <summary>
            /// The <see cref="BRX"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty BRXProperty = DependencyProperty.Register("BRX", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Br_CoordinateChanged));

            /// <summary>
            /// The bottom right y coordinate
            /// </summary>
            public int BRY
            {
                get { return (int)GetValue(BRYProperty); }
                set { SetValue(BRYProperty, value); }
            }

            /// <summary>
            /// The <see cref="BRY"/> DependencyProperty.
            /// </summary>
            public static readonly DependencyProperty BRYProperty = DependencyProperty.Register("BRY", typeof(int), typeof(HtProjektor), new PropertyMetadata(0, _Pixel_Br_CoordinateChanged));

            private static void _Pixel_Br_CoordinateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
            {
                if (dependencyObject is HtProjektor projektor)
                {              
                    projektor.pointsTransformed[2] = projektor.Simple2Dto3D(projektor._Viewport3D, new Point(projektor.BRX, projektor.BRY)); //rechts unten
                    projektor._MatrixTransform3D.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);
                    projektor._MatrixTransform3D02.Matrix = projektor.CalculateNonAffineTransform(projektor.pointsTransformed);


                }
            }

            #endregion


            // ##########################################################################################
            // Private Properties
            // ##########################################################################################

            private MeshGeometry3D _MeshGeometry3D;
           // private MeshGeometry3D _MeshGeometry3D02;
            private MatrixTransform3D _MatrixTransform3D;
            private MatrixTransform3D _MatrixTransform3D02;


            private Viewport3D _Viewport3D;

            #endregion

            // ##############################################################################################################################
            // Konstruktor
            // ##############################################################################################################################

            #region Konstruktor

            public HtProjektor()
            {
                DefaultStyleKey = typeof(HtProjektor);
                if (!DesignerProperties.GetIsInDesignMode(this))
                {
                    Loaded += _OnLoaded;
                }
            }

            private void _OnLoaded(object sender, RoutedEventArgs routedEventArgs)
            {
                _MeshGeometry3D = GetTemplateChild("mesh") as MeshGeometry3D;
               // _MeshGeometry3D02 = GetTemplateChild("mesh1") as MeshGeometry3D;
                _MatrixTransform3D = GetTemplateChild("xform") as MatrixTransform3D;
                _MatrixTransform3D02 = GetTemplateChild("xform2") as MatrixTransform3D;




                _Viewport3D = GetTemplateChild("viewport3d") as Viewport3D;

                for (int i = 0; i < 4; i++)
                    pointsTransformed[i] = _MatrixTransform3D.Matrix.Transform(_MeshGeometry3D.Positions[i]);

                for (int i = 0; i < 4; i++)
                    pointsTransformed[i] = _MatrixTransform3D02.Matrix.Transform(_MeshGeometry3D.Positions[i]);




                TopLeftPoint = new Point(pointsTransformed[1].X, pointsTransformed[1].Y);
                TopRightPoint = new Point(pointsTransformed[3].X, pointsTransformed[3].Y);
                BottomLeftPoint = new Point(pointsTransformed[0].X, pointsTransformed[0].Y);
                BottomRightPoint = new Point(pointsTransformed[2].X, pointsTransformed[2].Y);

                ScaleX = ActualWidth / Breite;
                ScaleY = ActualHeight / Hoehe;
            }

            protected override Size ArrangeOverride(Size arrangeBounds)
            {
                FixToBounds(arrangeBounds.Width, arrangeBounds.Height);
                return base.ArrangeOverride(arrangeBounds);                  
            }

            #endregion

            bool isDragging;
            int indexDragging;
            Point3D[] pointsTransformed = new Point3D[4];

            protected override void OnMouseLeftButtonDown(MouseButtonEventArgs args)
            {
                Point pt = args.GetPosition(_Viewport3D);

                // Obtain the Visual3D objects under the mouse pointer.
                HitTestResult result = VisualTreeHelper.HitTest(_Viewport3D, pt);

                // Cast result parameter to RayMeshGeometry3DHitTestResult.
                RayMeshGeometry3DHitTestResult resultMesh = result as RayMeshGeometry3DHitTestResult;

                // This should not happen, but play it safe anyway.
                if (resultMesh == null)
                    return;

                // Obtain clicked ModelVisual3D.
                ModelVisual3D vis = resultMesh.VisualHit as ModelVisual3D;

                // This should not happen, but play it safe anyway.
                if (vis == null)
                    return;

                // Determine which vertex the mouse is closest to.
                if (resultMesh.VertexWeight1 < resultMesh.VertexWeight2)
                {
                    if (resultMesh.VertexWeight2 < resultMesh.VertexWeight3)
                        indexDragging = resultMesh.VertexIndex3;
                    else
                        indexDragging = resultMesh.VertexIndex2;
                }
                else if (resultMesh.VertexWeight3 > resultMesh.VertexWeight1)
                    indexDragging = resultMesh.VertexIndex3;
                else
                    indexDragging = resultMesh.VertexIndex1;

                // Get current transformed points.
                for (int i = 0; i < 4; i++)
                    pointsTransformed[i] = _MatrixTransform3D.Matrix.Transform(_MeshGeometry3D.Positions[i]);

                // Obtain new transform and commence dragging operation.
                pointsTransformed[indexDragging] = Simple2Dto3D(_Viewport3D, pt);
                _MatrixTransform3D.Matrix = CalculateNonAffineTransform(pointsTransformed);

                _MatrixTransform3D02.Matrix = CalculateNonAffineTransform(pointsTransformed);


                isDragging = true;
                CaptureMouse();
                args.Handled = true;
            }

            protected override void OnMouseMove(MouseEventArgs args)
            {
                base.OnMouseMove(args);

                if (isDragging)
                {
                    Point ptMouse = args.GetPosition(_Viewport3D);
                    //if (ptMouse.Y <= 0.0)
                    //    ptMouse.Y = 0.0;
                    //else if (ptMouse.X <= 0.0)
                    //    ptMouse.X = 0.0;
                    //if (ptMouse.Y >= ActualHeight)
                    //    ptMouse.Y = ActualHeight;
                    //else if (ptMouse.X >= ActualWidth)
                    //    ptMouse.X = ActualWidth;

                    pointsTransformed[indexDragging] = Simple2Dto3D(_Viewport3D, ptMouse);
                    _MatrixTransform3D.Matrix = CalculateNonAffineTransform(pointsTransformed);

                    _MatrixTransform3D02.Matrix = CalculateNonAffineTransform(pointsTransformed);


                    args.Handled = true;

                    TopLeftPoint = new Point(pointsTransformed[1].X, pointsTransformed[1].Y);
                    TopRightPoint = new Point(pointsTransformed[3].X, pointsTransformed[3].Y);
                    BottomLeftPoint = new Point(pointsTransformed[0].X, pointsTransformed[0].Y);
                    BottomRightPoint = new Point(pointsTransformed[2].X, pointsTransformed[2].Y);
                }

                CurrentMousePosition = args.GetPosition(_Viewport3D);
            }

            protected override void OnMouseLeftButtonUp(MouseButtonEventArgs args)
            {
                base.OnMouseUp(args);

                if (isDragging)
                {
                    isDragging = false;
                    ReleaseMouseCapture();
                    args.Handled = true;
                }
            }

            private void FixToBounds(double width, double height)
            {
                if(_Viewport3D?.Camera == null)return;

                pointsTransformed[0] = Simple2Dto3D(_Viewport3D, new Point(0.0, height)); //links unten
                pointsTransformed[1] = Simple2Dto3D(_Viewport3D, new Point(0.0, 0.0)); //links oben
                pointsTransformed[2] = Simple2Dto3D(_Viewport3D, new Point(width, height)); //rechts unten
                pointsTransformed[3] = Simple2Dto3D(_Viewport3D, new Point(width, 0.0)); //rechts oben

                _MatrixTransform3D.Matrix = CalculateNonAffineTransform(pointsTransformed);

                _MatrixTransform3D02.Matrix = CalculateNonAffineTransform(pointsTransformed);







            #region Private Methods

            // The input array of points describes a 2D rectangle
            //  (with Z assumed to be zero) in the order
            //  lower-left, upper-left, lower-right, upper-right.
            // The returned transform maps the points (0, 0, 0),
            //  (0, 1, 0), (1, 0, 0), and (1, 1, 0) to these points.
            Matrix3D CalculateNonAffineTransform(Point3D[] points)
            {
                // Affine transform
                // ----------------
                // This matrix maps (0, 0) --> (x0, y0)
                //                  (0, 1) --> (x1, y1)
                //                  (1, 0) --> (x2, y2)
                //                  (1, 1) --> (x2 + x1 + x0, y2 + y1 + y0)
                Matrix3D A = new Matrix3D();
                A.M11 = points[2].X - points[0].X;
                A.M12 = points[2].Y - points[0].Y;
                A.M21 = points[1].X - points[0].X;
                A.M22 = points[1].Y - points[0].Y;
                A.OffsetX = points[0].X;
                A.OffsetY = points[0].Y;

                // Calculate point (a, b) that get mapped by the affine transform to (x3, y3)
                double den = A.M11 * A.M22 - A.M12 * A.M21;
                double a = (A.M22 * points[3].X - A.M21 * points[3].Y + 
                            A.M21 * A.OffsetY - A.M22 * A.OffsetX) / den;

                double b = (A.M11 * points[3].Y - A.M12 * points[3].X + 
                            A.M12 * A.OffsetX - A.M11 * A.OffsetY) / den;

                // Non-affine transform
                // --------------------
                // This matrix maps (0, 0) --> (0, 0)
                //                  (0, 1) --> (0, 1)
                //                  (1, 0) --> (1, 0)
                //                  (1, 1) --> (a, b)

                Matrix3D B = new Matrix3D();
                B.M11 = a / (a + b - 1);
                B.M22 = b / (a + b - 1);
                B.M14 = B.M11 - 1;
                B.M24 = B.M22 - 1;

                return B * A;
            }

            // The following two methods only work with OrthographicCamera,
            // with LookDirection of (0, 0, -1) and UpDirection of (0, 1, 0).
            // More advanced conversion routines can be found in the 
            // Petzold.Media3D library.

            // Converts a 2D point in device-independent coordinates relative 
            //  to Viewport3D to 3D space.
            Point3D Simple2Dto3D(Viewport3D vp, Point pt)
            {
                OrthographicCamera cam = CheckRestrictions(vp);
                double scale = cam.Width / vp.ActualWidth;
                double x = scale * (pt.X - vp.ActualWidth / 2) + cam.Position.X;
                double y = scale * (vp.ActualHeight / 2 - pt.Y) + cam.Position.Y;

                return new Point3D(x, y, 0);
            }

            // Converts a 3D point to 2D in device-independent coordinates
            //  relative to Viewport3D.
            Point Simple3Dto2D(Viewport3D vp, Point3D point)
            {
                OrthographicCamera cam = CheckRestrictions(vp);
                double scale = vp.ActualWidth / cam.Width;
              //  double scale2 = vp.ActualHeight / cam.Width;
                double x = vp.ActualWidth / 2 + scale * (point.X - cam.Position.X);
                double y = vp.ActualHeight / 2 - scale * (point.Y - cam.Position.Y);
                return new Point(x, y);
            }

            OrthographicCamera CheckRestrictions(Viewport3D vp)
            {
                OrthographicCamera cam = vp.Camera as OrthographicCamera;

                if (cam == null)
                    throw new ArgumentException("Camera must be OrthographicCamera");

                if (cam.LookDirection != new Vector3D(0, 0, -1))
                    throw new ArgumentException("Camera LookDirection must be (0, 0, -1)");

                if (cam.UpDirection != new Vector3D(0, 1, 0))
                    throw new ArgumentException("Camera UpDirection must be (0, 1, 0)");

                return cam;
            }

            #endregion

        }
    }
于 2018-03-02T10:33:09.473 回答