大家好日子,这是我的第一个问题。所以随时给我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)实现了这一目标。
到目前为止一切都很好。并没有消失的飞机。
因为我需要画笔/纹理在平面边缘上展开。我决定添加三角形直到我有5x5网格的平面。 (通过选择第一个平面的角点(它是中间的角点),整个几何体仍可变形。
可悲的是,我还不允许发布图片。
https://i.imgur.com/oG3gKRD.png
浅蓝色矩形是具有可选角落和矩形的矩形。紫色是其余部分(对于图片我包含另一个平面(没有连接到大平面,只是为了表明没有疯狂的转换效果) 值中只有1的差异(无论在哪个角落)
https://i.imgur.com/wSkywVk.png
据我所知,相机不是问题。改变很多东西的价值,比如相机/近距离和近距离farplanedistance。这种定位总是会产生不可见的几何形状(&它不是导致它的唯一位置,它们中有一些,但我无法看到连接) 如果我将网格缩小到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课程将作为答案发布。 如果您需要清理任何事情,请告诉我! &安培;一般来说这个问题有多大?我欢迎具有挑战性的评论家! :)
答案 0 :(得分:0)
带有计算的Projektor类!是否可以将评论连接到主要问题?
<强> 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
}
}