If there is a PNG image connects two coordinates (like a rope),
coordinateA.x;
coordinateA.y;
coordinateB.x;
coordinateB.y;
The two coordinates will keep changing all the time, so the PNG image connects between two coordinates needs to resize and rotate.
Any sample code to make this easier?
This is my approach:
Coordinates.cs:
public class Coordinates : DependencyObject
{
public Coordinates(double x, double y)
{
X = x;
Y = y;
}
public Coordinates()
{
X = 0;
Y = 0;
}
//X Dependency Property
public double X
{
get { return (double)GetValue(XProperty); }
set { SetValue(XProperty, value); }
}
public static readonly DependencyProperty XProperty =
DependencyProperty.Register("X", typeof(double), typeof(Coordinates), new UIPropertyMetadata(0d));
//Y Dependency Property
public double Y
{
get { return (double)GetValue(YProperty); }
set { SetValue(YProperty, value); }
}
public static readonly DependencyProperty YProperty =
DependencyProperty.Register("Y", typeof(double), typeof(Coordinates), new UIPropertyMetadata(0d));
}
Geometry.cs:
public class ConnectorLocationConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var start = (Coordinates)values[0];
var end = (Coordinates)values[1];
return new Thickness(start.X, start.Y, 0, 0);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
public class ConnectorAngleConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var start = (Coordinates)values[0];
var end = (Coordinates)values[1];
//dy/dx = tan(t) => t = arcTan(dy/dx)
double t = Math.Atan2(
Math.Abs(start.Y - end.Y),
Math.Abs(start.X - end.X)) * 180 / Math.PI;
if (end.X <= start.X && end.Y >= start.Y) return 180 - t;
if (end.X >= start.X && end.Y <= start.Y) return -t;
if (end.X <= start.X && end.Y <= start.Y) return 180 + t;
return t;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
public class ConnectorWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var start = (Coordinates)values[0];
var end = (Coordinates)values[1];
//get side for states
return Math.Abs(start.X - end.X);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
public class ConnectorHeightConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var start = (Coordinates)values[0];
var end = (Coordinates)values[1];
//get side for states
return Math.Abs(start.Y - end.Y);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
MainWindow.xaml.cs:
//nothing fancy here
public MainWindow()
{
Start = new Coordinates();
End = new Coordinates();
DataContext = this;
InitializeComponent();
}
//Start Dependency Property
public Coordinates Start
{
get { return (Coordinates)GetValue(StartProperty); }
set { SetValue(StartProperty, value); }
}
public static readonly DependencyProperty StartProperty =
DependencyProperty.Register("Start", typeof(Coordinates), typeof(MainWindow), new UIPropertyMetadata(null));
//End Dependency Property
public Coordinates End
{
get { return (Coordinates)GetValue(EndProperty); }
set { SetValue(EndProperty, value); }
}
public static readonly DependencyProperty EndProperty =
DependencyProperty.Register("End", typeof(Coordinates), typeof(MainWindow), new UIPropertyMetadata(null));
//--------------------------------------------------
//Click causes the mouse position stick to Start/End
//--------------------------------------------------
bool flag = false;
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
var p = e.GetPosition(this);
if(flag) Start = new Coordinates(p.X, p.Y);
else End = new Coordinates(p.X, p.Y);
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
flag = !flag;
}
And finally MainWindow.xaml:
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfTest"
Title="MainWindow" Height="650" Width="825">
<Window.Resources>
<local:ConnectorLocationConverter x:Key="connectorLocationConverter"/>
<local:ConnectorAngleConverter x:Key="connectorAngleConverter"/>
<local:ConnectorWidthConverter x:Key="connectorWidthConverter"/>
<local:ConnectorHeightConverter x:Key="connectorHeightConverter"/>
</Window.Resources>
<Canvas Background="#2000"
MouseMove="Canvas_MouseMove" MouseDown="Canvas_MouseDown">
<Canvas Width="0" Height="0">
<Image Source="/WpfTest;component/im.png" Stretch="Fill">
<Image.Margin>
<MultiBinding Converter="{StaticResource connectorLocationConverter}">
<Binding Path="Start"/>
<Binding Path="End"/>
</MultiBinding>
</Image.Margin>
<Image.Width>
<MultiBinding Converter="{StaticResource connectorWidthConverter}">
<Binding Path="Start"/>
<Binding Path="End"/>
</MultiBinding>
</Image.Width>
<Image.Height>
<MultiBinding Converter="{StaticResource connectorHeightConverter}">
<Binding Path="Start"/>
<Binding Path="End"/>
</MultiBinding>
</Image.Height>
<Image.RenderTransform>
<RotateTransform CenterX="0" CenterY="0">
<RotateTransform.Angle>
<MultiBinding Converter="{StaticResource connectorAngleConverter}">
<Binding Path="Start"/>
<Binding Path="End"/>
</MultiBinding>
</RotateTransform.Angle>
</RotateTransform>
</Image.RenderTransform>
</Image>
</Canvas>
</Canvas>
</Window>