Skip to content

Commit ed27f81

Browse files
committed
use matrix
1 parent 22d284d commit ed27f81

File tree

6 files changed

+163
-18
lines changed

6 files changed

+163
-18
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
using System.Windows;
2+
using System.Windows.Media;
3+
using static System.Math;
4+
5+
namespace SimpleStateMachineNodeEditor.Helpers.Extensions
6+
{
7+
public static class MatrixExtension
8+
{
9+
/// <summary>
10+
/// Creates a translation matrix using the specified offsets.
11+
/// </summary>
12+
/// <param name="offsetX">X-coordinate offset.</param>
13+
/// <param name="offsetY">Y-coordinate offset.</param>
14+
/// <returns>The created translation matrix.</returns>
15+
public static Matrix Translate(double offsetX, double offsetY)
16+
{
17+
return new Matrix(1.0, 0.0, 0.0, 1.0, offsetX, offsetY);
18+
}
19+
20+
/// <summary>
21+
/// Prepends a translation around the center of provided matrix.
22+
/// </summary>
23+
/// <param name="matrix">The matrix to prepend translation.</param>
24+
/// <param name="offsetX">X-coordinate offset.</param>
25+
/// <param name="offsetY">Y-coordinate offset.</param>
26+
/// <returns>The created translation matrix.</returns>
27+
public static Matrix TranslatePrepend(Matrix matrix, double offsetX, double offsetY)
28+
{
29+
return Translate(offsetX, offsetY) * matrix;
30+
}
31+
32+
/// <summary>
33+
/// Creates a matrix that scales along the x-axis and y-axis.
34+
/// </summary>
35+
/// <param name="scaleX">Scaling factor that is applied along the x-axis.</param>
36+
/// <param name="scaleY">Scaling factor that is applied along the y-axis.</param>
37+
/// <returns>The created scaling matrix.</returns>
38+
public static Matrix Scale(double scaleX, double scaleY)
39+
{
40+
return new Matrix(scaleX, 0, 0, scaleY, 0.0, 0.0);
41+
}
42+
43+
/// <summary>
44+
/// Creates a matrix that is scaling from a specified center.
45+
/// </summary>
46+
/// <param name="scaleX">Scaling factor that is applied along the x-axis.</param>
47+
/// <param name="scaleY">Scaling factor that is applied along the y-axis.</param>
48+
/// <param name="centerX">The center X-coordinate of the scaling.</param>
49+
/// <param name="centerY">The center Y-coordinate of the scaling.</param>
50+
/// <returns>The created scaling matrix.</returns>
51+
public static Matrix ScaleAt(double scaleX, double scaleY, double centerX, double centerY)
52+
{
53+
return new Matrix(scaleX, 0, 0, scaleY, centerX - (scaleX * centerX), centerY - (scaleY * centerY));
54+
}
55+
56+
/// <summary>
57+
/// Prepends a scale around the center of provided matrix.
58+
/// </summary>
59+
/// <param name="matrix">The matrix to prepend scale.</param>
60+
/// <param name="scaleX">Scaling factor that is applied along the x-axis.</param>
61+
/// <param name="scaleY">Scaling factor that is applied along the y-axis.</param>
62+
/// <param name="centerX">The center X-coordinate of the scaling.</param>
63+
/// <param name="centerY">The center Y-coordinate of the scaling.</param>
64+
/// <returns>The created scaling matrix.</returns>
65+
public static Matrix ScaleAtPrepend(Matrix matrix, double scaleX, double scaleY, double centerX, double centerY)
66+
{
67+
return ScaleAt(scaleX, scaleY, centerX, centerY) * matrix;
68+
}
69+
70+
/// <summary>
71+
/// Creates a skew matrix.
72+
/// </summary>
73+
/// <param name="angleX">Angle of skew along the X-axis in radians.</param>
74+
/// <param name="angleY">Angle of skew along the Y-axis in radians.</param>
75+
/// <returns>When the method completes, contains the created skew matrix.</returns>
76+
public static Matrix Skew(float angleX, float angleY)
77+
{
78+
return new Matrix(1.0, Tan(angleX), Tan(angleY), 1.0, 0.0, 0.0);
79+
}
80+
81+
/// <summary>
82+
/// Creates a matrix that rotates.
83+
/// </summary>
84+
/// <param name="radians">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis.</param>
85+
/// <returns>The created rotation matrix.</returns>
86+
public static Matrix Rotation(double radians)
87+
{
88+
double cos = Cos(radians);
89+
double sin = Sin(radians);
90+
return new Matrix(cos, sin, -sin, cos, 0, 0);
91+
}
92+
93+
/// <summary>
94+
/// Creates a matrix that rotates about a specified center.
95+
/// </summary>
96+
/// <param name="angle">Angle of rotation in radians.</param>
97+
/// <param name="centerX">The center X-coordinate of the rotation.</param>
98+
/// <param name="centerY">The center Y-coordinate of the rotation.</param>
99+
/// <returns>The created rotation matrix.</returns>
100+
public static Matrix Rotation(double angle, double centerX, double centerY)
101+
{
102+
return Translate(-centerX, -centerY) * Rotation(angle) * Translate(centerX, centerY);
103+
}
104+
105+
/// <summary>
106+
/// Creates a matrix that rotates about a specified center.
107+
/// </summary>
108+
/// <param name="angle">Angle of rotation in radians.</param>
109+
/// <param name="center">The center of the rotation.</param>
110+
/// <returns>The created rotation matrix.</returns>
111+
public static Matrix Rotation(double angle, Vector center)
112+
{
113+
return Translate(-center.X, -center.Y) * Rotation(angle) * Translate(center.X, center.Y);
114+
}
115+
116+
/// <summary>
117+
/// Transforms a point by this matrix.
118+
/// </summary>
119+
/// <param name="matrix">The matrix to use as a transformation matrix.</param>
120+
/// <param name="point">>The original point to apply the transformation.</param>
121+
/// <returns>The result of the transformation for the input point.</returns>
122+
public static Point TransformPoint(Matrix matrix, Point point)
123+
{
124+
return new Point(
125+
(point.X * matrix.M11) + (point.Y * matrix.M21) + matrix.OffsetX,
126+
(point.X * matrix.M12) + (point.Y * matrix.M22) + matrix.OffsetY);
127+
}
128+
}
129+
}

SimpleStateMachineNodeEditor/Helpers/MyUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public static void FindParents<TParent1, TParent2>(DependencyObject currentObjec
7777
} while ((parent1 == default(TParent1)) || (parent2 == default(TParent2)));
7878
}
7979

80-
public static void PanelToImage(Panel panel, string filename, ImageFormats format)
80+
public static void PanelToImage(FrameworkElement panel, string filename, ImageFormats format)
8181
{
8282
int width = (int)panel.ActualWidth;
8383
int height = (int)panel.ActualHeight;

SimpleStateMachineNodeEditor/SimpleStateMachineNodeEditor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ ReactiveUI 11.4.17</PackageReleaseNotes>
6969
<PackageReference Include="ReactiveUI.WPF" Version="11.4.17" />
7070
<PackageReference Include="Splat" Version="9.4.5" />
7171
<PackageReference Include="Splat.Drawing" Version="9.4.5" />
72-
<PackageReference Include="Wpf.Controls.PanAndZoom" Version="2.3.3" />
72+
<PackageReference Include="Wpf.Controls.PanAndZoom" Version="3.0.999-build20200622-01" />
7373
</ItemGroup>
7474

7575
<ItemGroup>

SimpleStateMachineNodeEditor/View/ViewNodesCanvas.xaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
xmlns:paz="clr-namespace:Wpf.Controls.PanAndZoom;assembly=Wpf.Controls.PanAndZoom"
1010
mc:Ignorable="d"
1111
d:DesignHeight="450" d:DesignWidth="800" Focusable="True" AllowDrop="True" ClipToBounds="True">
12-
<paz:ZoomBorder Name="zoomBorder" Stretch="None" ZoomSpeed="1.2"
12+
<!--<paz:ZoomBorder Name="zoomBorder" Stretch="None" ZoomSpeed="1.2"
1313
Background="SlateBlue" ClipToBounds="True" Focusable="True"
1414
VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
15-
Grid.Row="4" Grid.Column="1" >
16-
<Canvas x:Name="Canvas" Background="{DynamicResource ColorNodesCanvasBackground}">
17-
15+
Grid.Row="4" Grid.Column="1" EnablePan="False" MaxZoomX="5" MaxZoomY="5" MinZoomX="0.2" MinZoomY="0.2">-->
16+
<Border Name="BorderElement" Background="SlateBlue">
17+
<Canvas x:Name="Canvas" Background="{DynamicResource ColorNodesCanvasBackground}" ClipToBounds="True">
1818
<local:ViewSelector x:Name="Selector" Panel.ZIndex="999"/>
1919
<local:ViewCutter x:Name="Cutter" Panel.ZIndex="999"/>
2020

@@ -24,7 +24,6 @@
2424
VirtualizingPanel.CacheLength="1"
2525
VirtualizingPanel.CacheLengthUnit="Page"
2626
VirtualizingPanel.ScrollUnit="Pixel">
27-
2827
<ItemsControl.RenderTransform>
2928
<TransformGroup x:Name="TransformGroup">
3029
<ScaleTransform x:Name="Scale" ScaleX="1" ScaleY="1" />
@@ -35,7 +34,7 @@
3534
</ItemsControl.RenderTransform>
3635
<ItemsControl.ItemsPanel>
3736
<ItemsPanelTemplate>
38-
<Grid x:Name="ElementGrid" Background="{x:Null}">
37+
<Grid x:Name="ElementGrid" Background="Pink">
3938
</Grid>
4039
</ItemsPanelTemplate>
4140
</ItemsControl.ItemsPanel>
@@ -55,7 +54,7 @@
5554
</ItemsControl.ItemsSource>
5655
</ItemsControl>
5756
</Canvas>
58-
</paz:ZoomBorder>
57+
</Border>
5958
<UserControl.ContextMenu >
6059
<ContextMenu Template="{DynamicResource TemplateContextMenu}" Background="{DynamicResource ColorMenuBackground}" Foreground="{DynamicResource ColorMenuForeground}" BorderBrush="{DynamicResource ColorMenuBorder}" OpacityMask="{DynamicResource ColorMenuBackgroundMouseOver}" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Center" >
6160
<MenuItem Header="Add" x:Name="ItemAddNode" InputGestureText="Ctrl + N" Style="{DynamicResource StyleContextMenuItem}" >

SimpleStateMachineNodeEditor/View/ViewNodesCanvas.xaml.cs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,14 @@ public ViewNodesCanvas()
6262
private void SetupBinding()
6363
{
6464
this.WhenActivated(disposable =>
65-
{
66-
65+
{
6766
this.OneWayBind(this.ViewModel, x => x.NodesForView, x => x.Nodes.Collection).DisposeWith(disposable);
6867

6968
this.OneWayBind(this.ViewModel, x => x.Connects, x => x.Connects.Collection).DisposeWith(disposable);
7069

71-
this.OneWayBind(this.ViewModel, x => x.Scale.Scales.X, x => x.Scale.ScaleX).DisposeWith(disposable);
70+
//this.OneWayBind(this.ViewModel, x => x.Scale.Scales.X, x => x.Scale.ScaleX).DisposeWith(disposable);
7271

73-
this.OneWayBind(this.ViewModel, x => x.Scale.Scales.Y, x => x.Scale.ScaleY).DisposeWith(disposable);
72+
//this.OneWayBind(this.ViewModel, x => x.Scale.Scales.Y, x => x.Scale.ScaleY).DisposeWith(disposable);
7473

7574
this.OneWayBind(this.ViewModel, x => x.Selector, x => x.Selector.ViewModel).DisposeWith(disposable);
7675

@@ -114,6 +113,10 @@ private void SetupSubscriptions()
114113
this.WhenAnyValue(x => x.ViewModel.Selector.Size).WithoutParameter().InvokeCommand(ViewModel, x => x.CommandSelectorIntersect).DisposeWith(disposable);
115114
this.WhenAnyValue(x => x.ViewModel.Cutter.EndPoint).WithoutParameter().InvokeCommand(ViewModel, x => x.CommandCutterIntersect).DisposeWith(disposable);
116115
this.WhenAnyValue(x => x.ViewModel.ImagePath).Where(x => !string.IsNullOrEmpty(x)).Subscribe(value => SaveCanvasToImage(value, ImageFormats.JPEG)).DisposeWith(disposable);
116+
117+
//here need use ZoomIn and ZoomOut
118+
119+
//this.WhenAnyValue(x=>x.ViewModel.Scale.Value).Subscribe(x=> {this.zoomBorder.ZoomDeltaTo })
117120
});
118121
}
119122

@@ -128,12 +131,12 @@ private void SetupEvents()
128131
this.Events().MouseRightButtonDown.Subscribe(e => OnEventMouseRightDown(e)).DisposeWith(disposable);
129132
this.Events().MouseUp.Subscribe(e => OnEventMouseUp(e)).DisposeWith(disposable);
130133
this.Events().MouseMove.Subscribe(e => OnEventMouseMove(e)).DisposeWith(disposable);
131-
this.Events().MouseWheel.Subscribe(e => OnEventMouseWheel(e)).DisposeWith(disposable);
134+
this.BorderElement.Events().MouseWheel.Subscribe(e => OnEventMouseWheel(e)).DisposeWith(disposable);
132135
this.Events().DragOver.Subscribe(e => OnEventDragOver(e)).DisposeWith(disposable);
133136
this.Cutter.Events().MouseLeftButtonUp.InvokeCommand(this.ViewModel.CommandDeleteSelectedConnectors).DisposeWith(disposable);
134137
this.Events().PreviewMouseLeftButtonDown.Subscribe(e => OnEventPreviewMouseLeftButtonDown(e)).DisposeWith(disposable);
135138
this.Events().PreviewMouseRightButtonDown.Subscribe(e => OnEventPreviewMouseRightButtonDown(e)).DisposeWith(disposable);
136-
this.WhenAnyValue(x => x.ViewModel.Scale.Value).Subscribe(value => { this.Canvas.Height /= value; this.Canvas.Width /= value; }).DisposeWith(disposable);
139+
//this.WhenAnyValue(x => x.ViewModel.Scale.Value).Subscribe(value => { this.Canvas.Height /= value; this.Canvas.Width /= value; }).DisposeWith(disposable);
137140
});
138141
}
139142
private void OnEventMouseLeftDown(MouseButtonEventArgs e)
@@ -170,7 +173,20 @@ private void OnEventMouseRightDown(MouseButtonEventArgs e)
170173
}
171174
private void OnEventMouseWheel(MouseWheelEventArgs e)
172175
{
173-
this.ViewModel.CommandZoom.ExecuteWithSubscribe(e.Delta);
176+
//this.ElementItemControl.Width = ActualWidth + 100;
177+
Point point = e.GetPosition(this.Canvas);
178+
//this.Scale.CenterX = point.X;
179+
//this.Scale.CenterY = point.Y;
180+
181+
Matrix value = this.Canvas.RenderTransform.Value;
182+
double step = 1.2;
183+
double zoom = e.Delta > 0 ? step : 1 / step;
184+
value = MatrixExtension.ScaleAtPrepend(value,zoom, zoom, point.X, point.Y);
185+
this.Canvas.RenderTransform = new MatrixTransform(value);
186+
187+
//this.ViewModel.CommandZoom.ExecuteWithSubscribe(e.Delta);
188+
//_element.RenderTransform = new MatrixTransform(_matrix);
189+
174190
}
175191
private void OnEventMouseUp(MouseButtonEventArgs e)
176192
{
@@ -203,7 +219,7 @@ private void OnEventMouseMove(MouseEventArgs e)
203219
}
204220
private void OnEventDragOver(DragEventArgs e)
205221
{
206-
Point point = e.GetPosition(this);
222+
Point point = e.GetPosition(this.Canvas);
207223
if (this.ViewModel.DraggedConnect != null)
208224
{
209225
point = point.Subtraction(2);
@@ -236,6 +252,7 @@ private Point GetDeltaMove()
236252

237253
private void SaveCanvasToImage(string filename, ImageFormats format)
238254
{
255+
//this.zoomBorder.Uniform();
239256
MyUtils.PanelToImage(this.Canvas, filename, format);
240257
ViewModel.CommandLogDebug.ExecuteWithSubscribe(String.Format("Scheme was exported to \"{0}\"", filename));
241258
}

SimpleStateMachineNodeEditor/View/ViewSelector.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ private void OnMouseMoves(MouseEventArgs e)
9797
//find canvas
9898
ViewNodesCanvas NodesCanvas = MyUtils.FindParent<ViewNodesCanvas>(this);
9999

100-
ViewModel.Point2 = e.GetPosition(NodesCanvas);
100+
ViewModel.Point2 = e.GetPosition(NodesCanvas.Canvas);
101101

102102
e.Handled = true;
103103
}

0 commit comments

Comments
 (0)