Unfortunately I do not know how I adjust the axes scaling.
x and y axes should have the same scaling. As an example, you see two pictures below. Once with the blue strokes (same scaling) and once with red strokes (different scaling). How can I adjust that only the same scaling comes out (see the picture with the blue strokes). The x and y have the same distance from, for example, 0 (begin) to 10 ( end). It should not have different scaling as the picture with the red strokes. I should be able to say later that the x axis and the y axis are exactly equal to the distances of the points.
Could someone help me with the same scaling, please?
Could I also define the value range itself? Since say from -12 to + 12?
XAML
<UserControl x:Class="Vorschau.UCVorschau"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Vorschau"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d" Height="461" Width="624">
<Canvas HorizontalAlignment="Left" Height="461" VerticalAlignment="Top" Width="624">
<Button x:Name="btGenerate" Content="Generiere Koordinaten" Canvas.Left="25" Canvas.Top="409" Click="btGenerate_Click"/>
<oxy:Plot x:Name="oxyPlot" Title="{Binding Title}" Height="350" Canvas.Left="224" Width="350" Background="#FFD1CFD0">
<oxy:Plot.Axes>
<oxy:LinearAxis Position="Bottom" MinimumPadding="0.1" MaximumPadding="0.1"/>
<oxy:LinearAxis Position="Left" MinimumPadding="0.1" MaximumPadding="0.1"/>
</oxy:Plot.Axes>
<oxy:Plot.Series>
<oxy:LineSeries x:Name="ls" ItemsSource="{Binding Points}" LineStyle="None" MarkerType="Circle" MarkerSize="5" MarkerFill="Transparent" MarkerStroke="Black" MarkerStrokeThickness="2"/>
</oxy:Plot.Series>
</oxy:Plot>
<Button x:Name="btClear" Content="Koordianten löschen" Canvas.Left="181" Canvas.Top="409" Click="btClear_Click"/>
<Button x:Name="btRead" Content="Koordianten einlesen" Canvas.Left="473" Canvas.Top="409" Click="btRead_Click"/>
<Canvas HorizontalAlignment="Left" Height="579" VerticalAlignment="Top" Width="5" Background="#FFB8B8B8" RenderTransformOrigin="0.5,0.5" Canvas.Left="311" Canvas.Top="106">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="-1"/>
<SkewTransform/>
<RotateTransform Angle="90"/>
<TranslateTransform/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
</Canvas>
</UserControl>
UserControl
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OxyPlot;
using OxyPlot.Series;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections;
using System.Globalization;
using OxyPlot.Wpf;
using System.Diagnostics;
namespace Vorschau
{
/// <summary>
/// Interaktionslogik für UCVorschau.xaml
/// </summary>
public partial class UCVorschau : UserControl
{
public UCVorschau()
{
InitializeComponent();
try
{
DataContext = this;
this.Title = "Vorschaubild";
oxyPlot.Width = Vorschau.Properties.Settings.Default.BreiteBitmap;
oxyPlot.Height = Vorschau.Properties.Settings.Default.HoeheBitmap;
if (Vorschau.Properties.Settings.Default.MarkerTyp == 0)
{
ls.MarkerType = MarkerType.Circle;
ls.MarkerFill = System.Windows.Media.Colors.Transparent;
ls.MarkerStrokeThickness = Vorschau.Properties.Settings.Default.Kreisdurchmesser;
}
else
{
ls.MarkerType = MarkerType.Square;
ls.MarkerFill = System.Windows.Media.Colors.Black;
ls.MarkerStroke = System.Windows.Media.Colors.Black;
ls.MarkerStrokeThickness = 2;
}
}
catch (Exception error)
{
MessageBox.Show("Es trat ein unerwarteter Fehler auf. \nBitte Starten Sie die Anwendung neu." + error.ToString());
}
}
public string Title { get; set; }
public IList<DataPoint> Points { get; private set; }
/// <summary>
/// Einstelungs-Fenster wird geöffnet
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
//btEinstellung
private void btGenerate_Click(object sender, RoutedEventArgs e)
{
try
{
DateTime startZeit = DateTime.Now;
Cursor = Cursors.Wait;
if (Vorschau.Properties.Settings.Default.MarkerTyp == 0)
{
ls.MarkerType = MarkerType.Circle;
ls.MarkerFill = System.Windows.Media.Colors.Transparent;
ls.MarkerStrokeThickness = Vorschau.Properties.Settings.Default.Kreisdurchmesser;
}
else
{
ls.MarkerType = MarkerType.Square;
ls.MarkerFill = System.Windows.Media.Colors.Black;
ls.MarkerStroke = System.Windows.Media.Colors.Black;
ls.MarkerStrokeThickness = 2;
}
double zufallszahlX;
double zufallszahlY;
double XMax = 10;
double XMin = 0;
double YMax = 10;
double YMin = 0;
// Zur Erstellung des Seeds
int h = DateTime.Now.Hour;
int m = DateTime.Now.Minute;
int s = DateTime.Now.Second;
String u = h.ToString() + m.ToString() + s.ToString();
int iu = Int32.Parse(u);
Random zufall = new Random(iu);
Console.WriteLine("______________");
CultureInfo en = new CultureInfo("en-US", false); // Damit ein Punkt ist anstatt ein Komma
DataContext = this;
this.Points = new List<DataPoint>();
System.IO.File.WriteAllText(((Environment.CurrentDirectory + #"\files\koordinaten.txt")), string.Empty);
using (var fileStream = new FileStream(String.Format(Environment.CurrentDirectory + #"\files\koordinaten.txt"), FileMode.OpenOrCreate))
{
using (var streamWriter = new StreamWriter(fileStream))
{
for (int i = 0; i < Vorschau.Properties.Settings.Default.AnzahlKoordinaten; i++)
{
zufallszahlX = zufall.NextDouble() * (XMax - XMin) + XMin;
zufallszahlY = zufall.NextDouble() * (YMax - YMin) + YMin;
//Console.WriteLine("( " + zufallszahlX + " / " + zufallszahlY + " )" + " |" + i);
streamWriter.WriteLine("( " + zufallszahlX.ToString(en.NumberFormat) + " / " + zufallszahlY.ToString(en.NumberFormat) + " )" + " |" + (i + 1));
//ls.addPoint(zufallszahlX, zufallszahlY);
Points.Add(new DataPoint(zufallszahlX, zufallszahlY));
}
ls.ItemsSource = Points;
}
}
Cursor = Cursors.Arrow;
DateTime endZeit = DateTime.Now;
TimeSpan gemesseneZeit = endZeit - startZeit;
// statusbar.Text = "Gemessen Zeit für den Durchlauf: " + gemesseneZeit;
}
catch (Exception)
{
MessageBox.Show("Hoppla, da lief etwas schief.\nLeider konnten keine Koordinaten generiert werden.\nVersuchen Sie es bitte erneut.", "", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void btClear_Click(object sender, RoutedEventArgs e)
{
//botAxis.Minimum = botAxis.InternalAxis.ActualMinimum;
//botAxis.Maximum = botAxis.InternalAxis.ActualMaximum;
//lefAxis.Minimum = lefAxis.InternalAxis.ActualMinimum;
//lefAxis.Maximum = lefAxis.InternalAxis.ActualMaximum;
ls.ItemsSource = null;
}
private void btRead_Click(object sender, RoutedEventArgs e)
{
DateTime startZeit = DateTime.Now;
Cursor = Cursors.Wait;
String line;
Console.WriteLine("___________");
Console.WriteLine("Koordinaten: ");
using (System.IO.StreamReader file = new System.IO.StreamReader(Environment.CurrentDirectory + #"\files\koordinaten.txt"))
{
while ((line = file.ReadLine()) != null)
{
Regex myRegexKF = new Regex(#"^(?<koordinaet>\S\s*\S*\d+\s*\S\s*\S*\d+\s*\S)\s*\S\d+", RegexOptions.IgnoreCase);
Match matchSuccess = myRegexKF.Match(line);
if (matchSuccess.Success)
{
String koordinaten = matchSuccess.Groups["koordinate"].Value;
System.Console.WriteLine(koordinaten);
}
}
}
System.Console.ReadLine();
Cursor = Cursors.Arrow;
DateTime endZeit = DateTime.Now;
TimeSpan gemesseneZeit = endZeit - startZeit;
}
}
}
in modern OxyPlot 2.0+ you should set
plotModel.PlotType = PlotType.Cartesian;
and it will constraint the proportions, but minor zooming and padding issues might appear.
Set the MajorStep in both axis to be the same:
<oxy:Plot.Axes>
<oxy:LinearAxis ... MajorStep="1"/>
<oxy:LinearAxis ... MajorStep="1"/>
</oxy:Plot.Axes>
Note that there are other similar properties that you might want to control: MinorStep, MajorTickSize and MinorTickSize.
Also note that labels are put on Major Ticks.
I think original documentation will solve your problem.
1) To set axis Maximum\Minimum set same named properties at you Xaml for LinearAxis.
2) To define specific axis mark steps use Major/minor intervals of LinearAxis
Related
I am trying to make a virtual joystick that a user can move around with the mouse in WPF in C#. I am trying to use the polar coordinate system because I want the knob of the joystick to remain in the circle.
I am getting some really weird behavior - if anybody has experience with this sort of thing any tips would be nice. Thank you
EDIT: I got it working. I posted the updated code below. It is by no means a good/professional solution to this but it works. So I hope if somebody in the future is trying to do this same task it may help. I tried to add some comments to explain what was going on. Here you go!
NOTE: If you are trying to use this for your program make note that there are two hardcoded values you must change. The first is the x_starting/y_starting. Thats where your virtual joystick knob should reset to. And next is the radius when calculating the max possible value. Make sure it is half the width of the background joystick.
The code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication4
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
double radius;
bool captured = false;
double x_shape, x_canvas, y_shape, y_canvas; //Canvas is used to keep track of where the joystick is on screen,
// shape is used for where the knob is.
UIElement source = null;
double y_starting = 180; //The starting X and Y position for the Knob. (CHANGE TO WHERE UR CANVAS.TOP/CANVAS.LEFT IS FOR THE KNOB)
double x_starting = 105;
private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
string objname = ((Ellipse)sender).Name;
if (objname == "Knob")
{
source = (UIElement)sender;
Mouse.Capture(source);
captured = true;
x_shape = Canvas.GetLeft(reference);
x_canvas = e.GetPosition(Knob).X;
y_shape = Canvas.GetTop(reference);
y_canvas = e.GetPosition(Knob).Y;
}
}
private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
string objname = ((Ellipse)sender).Name;
Mouse.Capture(null);
captured = false;
if (objname == "Knob") {
// x_shape = x_starting;
// y_shape = y_starting;
Canvas.SetLeft(source, x_starting);
Canvas.SetTop(source, y_starting); //Reset to our starting values
XTextBlock.Text = x_starting.ToString();
YTextBlock.Text = y_starting.ToString();
}
}
private void Ellipse_MouseMove(object sender, MouseEventArgs e)
{
double x = e.GetPosition(reference).X; //Getting mouse pos relative to the center of your joystick (I have an empty textblock there called reference)
double y = e.GetPosition(reference).Y;
double r = Math.Sqrt((x * x) + (y * y)); //Calculate radius..
XMousePos.Text = x.ToString();
YMousePos.Text = y.ToString();
string objname = ((Ellipse)sender).Name;
double theta = Math.Atan2(y, x); //Calculate theta..
Theta.Text = theta.ToString();
double x1 = (r * Math.Cos(theta)); //This converts polar coordinates to cartesian plane coordinates.
double y1 = (r * Math.Sin(theta));
XPolPos.Text = x1.ToString();
YPolPos.Text = y1.ToString();
double xmax = (62.5 * Math.Cos(theta)); //Calculate a max so that your knob stays within the circle. The radius value should be half the width of the
double ymax = (62.5 * Math.Sin(theta)); // background of your joystick.
X2PolPos.Text = xmax.ToString();
Y2PolPos.Text = ymax.ToString();
if (objname == "Knob") {
if (captured)
{
if ((((x1 > 0) && (x1 < xmax)) || ((x1 <= 0) && (x1 > xmax))) && (((y1 > 0) && (y1 < ymax)) || ((y1 <= 0) && (y1 > ymax)))) //Seems like bad way to do it. But this is how i check to see if knob is in bounds.
{
x = e.GetPosition(reference).X; //Get the values and calculate it again.
y = e.GetPosition(reference).Y;
r = Math.Sqrt((x * x) + (y * y));
theta = Math.Atan2(y, x);
x1 = (r * Math.Cos(theta));
y1 = (r * Math.Sin(theta));
x_shape += x1 - x_canvas; //Changing our values and moving the knob.
Canvas.SetLeft(source, x_shape);
x_canvas = x1;
y_shape += y1 - y_canvas;
Canvas.SetTop(source, y_shape);
y_canvas = y1;
XTextBlock.Text = x_shape.ToString();
YTextBlock.Text = y_shape.ToString();
}
}
}
}
}
}
And the XAML just in case:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" MouseMove="Window_MouseMove" KeyDown="Window_KeyDown">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<TextBlock Text="KNOB POSITION"/>
<TextBlock Name="XTextBlock"/>
<TextBlock Name="YTextBlock"/>
<TextBlock Text="MOUSE POSITION"/>
<TextBlock Name="XMousePos"/>
<TextBlock Name="YMousePos"/>
<TextBlock Text="POLAR COORDINATES"/>
<TextBlock Name="XPolPos"/>
<TextBlock Name="YPolPos"/>
</StackPanel>
<Canvas Name="LayoutRoot" Grid.Column="1">
<Ellipse Fill="#FFF4F4F5" Name ="Joystick" Height="125" Canvas.Left="51" Stroke="Black" Canvas.Top="128" Width="125" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" MouseMove="Ellipse_MouseMove"/>
<Ellipse Fill="#FFF4F4F5" Name="Knob" Height="15" Canvas.Left="105" Stroke="Black" Canvas.Top="180" Width="15" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" MouseMove="Ellipse_MouseMove"/>
</Canvas>
</Grid>
When we're talking about joystick the polar coordinate system does not seems to be helpful.
What we need is X and Y offset in range [-1; 1]. We can easily evaluate it knowing Field (big) Radius, Filed Center point and Mouse coordinates.
Here is how it works (remove all events except Ellipse_MouseMove). Member m_vtJoystickPos holds selected Joystick position.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
UpdateKnobPosition();
}
/// <summary>
/// Current joystick position
/// </summary>
Vector m_vtJoystickPos = new Vector();
private void Ellipse_MouseMove(object sender, MouseEventArgs e)
{
double fJoystickRadius = Joystick.Height * 0.5;
//Make coords related to the center
Vector vtJoystickPos = e.GetPosition(Joystick) -
new Point(fJoystickRadius, fJoystickRadius);
//Normalize coords
vtJoystickPos /= fJoystickRadius;
//Limit R [0; 1]
if (vtJoystickPos.Length > 1.0)
vtJoystickPos.Normalize();
XMousePos.Text = vtJoystickPos.X.ToString();
YMousePos.Text = vtJoystickPos.Y.ToString();
//Polar coord system
double fTheta = Math.Atan2(vtJoystickPos.Y, vtJoystickPos.X);
XPolPos.Text = fTheta.ToString(); //Angle
YPolPos.Text = vtJoystickPos.Length.ToString(); //Radius
if (e.LeftButton == MouseButtonState.Pressed)
{
m_vtJoystickPos = vtJoystickPos;
UpdateKnobPosition();
}
}
void UpdateKnobPosition()
{
double fJoystickRadius = Joystick.Height * 0.5;
double fKnobRadius = Knob.Width * 0.5;
Canvas.SetLeft(Knob, Canvas.GetLeft(Joystick) +
m_vtJoystickPos.X * fJoystickRadius + fJoystickRadius - fKnobRadius);
Canvas.SetTop(Knob, Canvas.GetTop(Joystick) +
m_vtJoystickPos.Y * fJoystickRadius + fJoystickRadius - fKnobRadius);
}
}
I've also included Polar CS evaluation (commented). BTW Polar CS is (R, Angle).
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<TextBlock Text="KNOB POSITION"/>
<TextBlock Name="XTextBlock"/>
<TextBlock Name="YTextBlock"/>
<TextBlock Text="MOUSE POSITION"/>
<TextBlock Name="XMousePos"/>
<TextBlock Name="YMousePos"/>
<TextBlock Text="POLAR COORDINATES"/>
<TextBlock Name="XPolPos"/>
<TextBlock Name="YPolPos"/>
</StackPanel>
<Canvas Name="LayoutRoot" Grid.Column="1">
<Ellipse Fill="#FFF4F4F5" Name ="Joystick" Height="125" Canvas.Left="51" Stroke="Black" Canvas.Top="127" Width="125" MouseMove="Ellipse_MouseMove"/>
<Ellipse Fill="#FFF4F4F5" Name="Knob" Height="16" Canvas.Left="106" Stroke="Black" Canvas.Top="182" Width="15" MouseMove="Ellipse_MouseMove"/>
</Canvas>
</Grid>
</Window>
I need the functionality of an image scale, translate and cropping just like what a photo chooser task do in windows phone 8.1. I can not use photo chooser task because I will not select the photo from media photo library or capture the image. For my purpose the image will be selected from a server saved picture list. I have written some code for this but it's not working as I desire. I am working on it for 4 weeks but hardly find the perfect solution. Here is my code.
This is the xaml code
<phone:PhoneApplicationPage
x:Class="TransformationLearning.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="Transformation" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid Grid.Row="1" Background="Yellow">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Name="grid"
Grid.Row="0"
Height="400"
Width="400"
>
<Image x:Name="myImage" Source="/Assets/Lion.jpg"
Stretch="UniformToFill"
ManipulationCompleted="CompleteManipulation"
ManipulationDelta="DeltaManipulation"
Loaded="ImageLoaded"
Grid.Row="1"
>
<Image.RenderTransform>
<CompositeTransform x:Name="myComposite"
/>
</Image.RenderTransform>
</Image>
<Rectangle Width="200"
Height="200"
Name="myRectangle"
Margin="100 100"
Stroke="White"
StrokeThickness="3" Grid.Row="1">
</Rectangle>
</Grid>
<Image Name="myCropPicture" Grid.Row="1"/>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
and this is the code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using TransformationLearning.Resources;
using Microsoft.Xna.Framework;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
using Lumia.Imaging;
using Lumia.Imaging.Transforms;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Storage;
using System.Windows.Controls.Primitives;
using System.Runtime.InteropServices.WindowsRuntime;
namespace TransformationLearning
{
public partial class MainPage : PhoneApplicationPage
{
WriteableBitmap WB_CapturedImage;//for original image
WriteableBitmap WB_CroppedImage;//for cropped image
double width, height;
WriteableBitmap wb;
CompositeTransform transform;
GeneralTransform gt, gt1;
System.Windows.Point absolutePosition, absolutePosition1;
public MainPage()
{
InitializeComponent();
transform = new CompositeTransform();
}
private void ImageLoaded(object sender, RoutedEventArgs e)
{
wb = new WriteableBitmap(myImage, null);
myComposite.CenterX = 150;
myComposite.CenterY = 150;
}
private double BoundaryCheck(double value)
{
if (value < 1.0)
return 1.0;
else if (value > 2.0)
return 2.0;
else
return value;
}
private void DeltaManipulation(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
transform = myComposite;
if (e.DeltaManipulation.Scale.X == 0.0 || e.DeltaManipulation.Scale.Y == 0.0)
{
myComposite.ScaleX *= 1.0;
myComposite.ScaleY *= 1.0;
}
else if (e.DeltaManipulation.Scale.X > 0.0)
{
double value = BoundaryCheck(myComposite.ScaleX*e.DeltaManipulation.Scale.X);
myComposite.ScaleX = myComposite.ScaleY = value;
gt = myImage.TransformToVisual(grid);
absolutePosition = gt.Transform(new System.Windows.Point(0, 0));
gt1 = myRectangle.TransformToVisual(grid);
absolutePosition1 = gt1.Transform(new System.Windows.Point(0, 0));
if ((absolutePosition1.X <= absolutePosition.X)
|| (absolutePosition1.Y <= absolutePosition.Y)
|| (absolutePosition1.X + myRectangle.Width >= absolutePosition.X + wb.PixelWidth)
|| (absolutePosition1.Y + myRectangle.Height >= absolutePosition.Y + wb.PixelHeight))
{
myComposite = transform;
}
}
gt = myImage.TransformToVisual(grid);
absolutePosition = gt.Transform(new System.Windows.Point(0, 0));
gt1 = myRectangle.TransformToVisual(grid);
absolutePosition1 = gt1.Transform(new System.Windows.Point(0, 0));
if (e.DeltaManipulation.Translation.Y > 0.0 && (absolutePosition1.Y >= (absolutePosition.Y + e.DeltaManipulation.Translation.Y)))
{
myComposite.TranslateY += (e.DeltaManipulation.Translation.Y-2);
}
if (e.DeltaManipulation.Translation.X > 0.0 && (absolutePosition1.X >= (absolutePosition.X + e.DeltaManipulation.Translation.X)))
{
myComposite.TranslateX += (e.DeltaManipulation.Translation.X - 2);
}
if (e.DeltaManipulation.Translation.Y < 0.0 && ((absolutePosition1.Y + myRectangle.Height) <= (absolutePosition.Y + e.DeltaManipulation.Translation.Y + wb.PixelHeight)))
{
myComposite.TranslateY += (e.DeltaManipulation.Translation.Y + 2);
}
if (e.DeltaManipulation.Translation.X < 0.0 && ((absolutePosition1.X + myRectangle.Width) <= (absolutePosition.X + e.DeltaManipulation.Translation.X + wb.PixelWidth)))
{
myComposite.TranslateX += (e.DeltaManipulation.Translation.X + 2);
}
wb = new WriteableBitmap(myImage, myComposite);
gt = myImage.TransformToVisual(grid);
absolutePosition = gt.Transform(new System.Windows.Point(0, 0));
}
private void CompleteManipulation(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
{
App.RootFrame.RenderTransform = new CompositeTransform();
grid.UpdateLayout();
CropImage();
App.RootFrame.RenderTransform = new CompositeTransform();
grid.UpdateLayout();
}
private async void CropImage()
{
var ms = new MemoryStream();
wb.SaveJpeg(ms, wb.PixelWidth, wb.PixelHeight, 0, 100);
ms.Position = 0;
gt1 = myRectangle.TransformToVisual(myImage);
absolutePosition1 = gt1.Transform(new System.Windows.Point(0, 0));
using (var source = new StreamImageSource(ms))
{
using (var filterEffect = new FilterEffect(source))
{
var filter = new CropFilter(new Windows.Foundation.Rect(absolutePosition1.X, absolutePosition1.Y, myRectangle.Width, myRectangle.Height));
filterEffect.Filters = new IFilter[] { filter };
var target = new WriteableBitmap((int)(myRectangle.Width), (int)(myRectangle.Height));
using (var renderer = new WriteableBitmapRenderer(filterEffect, target))
{
try
{
await renderer.RenderAsync();
}
catch (Exception t)
{
System.Diagnostics.Debug.WriteLine(t.InnerException);
System.Diagnostics.Debug.WriteLine(t.Message);
}
}
myCropPicture.Source = target;
}
}
}
}
}
Here I have used Lumia Imaging SDK crop filter for cropping the image. "myImage" is the source image and "myCropPicture" is used for showing the cropped image. For transformation I have used composite transform. When I scale the source image this code can not crop that image accordingly.I need the help badly.
did you check this post. it might come in handy
Image crop control for Silverlight or Windows Phone
I'm trying to create a Paint Application in WPF using Canvas. I want to increase the thickness of my shape while drawing so I try increasing StrokeThickness.
This is how I want it to be:
And this is what I get:
As you can see the outline only extends inside the boundary. How can I make it extends on both side?
Here is my code:
In MouseDown Event:
Rectangle rect = new Rectangle();
rect.Stroke = _color;
rect.StrokeThickness = _size;
Canvas.SetLeft(rect, _startPoint.X);
Canvas.SetTop(rect, _startPoint.Y);
cv_PaintBoard.Children.Add(rect);
isDrawing = true;
In MouseMove Event:
if (isDrawing == true && e.LeftButton == MouseButtonState.Pressed)
{
Canvas canvas = (Canvas)sender;
Rectangle rect = canvas.Children.OfType<Rectangle>().LastOrDefault();
if (rect != null)
{
Point endPoint = e.GetPosition((IInputElement)sender);
Point startPoint = new Point(
Math.Min(endPoint.X, _startPoint.X),
Math.Min(endPoint.Y, _startPoint.Y)
);
rect.Width = Math.Max(endPoint.X, _startPoint.X) - startPoint.X;
rect.Height = Math.Max(endPoint.Y, _startPoint.Y) - startPoint.Y;
Canvas.SetLeft(rect, startPoint.X);
Canvas.SetTop(rect, startPoint.Y);
}
}
You need to update width/height and left/top too for your specific needs.
The below example demonstrates your needs. If it is ok with you, let me know.
MainWindow.xaml
<Window x:Class="WpfDrawing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="447.368" Width="606.579">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="13*"/>
<RowDefinition Height="7*"/>
</Grid.RowDefinitions>
<Canvas Grid.RowSpan="1">
<Rectangle x:Name="Rect1" Fill="Transparent" HorizontalAlignment="Left" Height="70" Canvas.Left="248" Canvas.Top="104" Stroke="Black" Width="94" Opacity="0.5" />
<Rectangle x:Name="Rect2" Fill="#FF52E03C" HorizontalAlignment="Left" Height="70" Canvas.Left="248" Canvas.Top="104" Stroke="Black" Width="94" Opacity="0.5" />
</Canvas>
<TextBox x:Name="tbThickness" HorizontalAlignment="Left" Height="23" Margin="84,27,0,0" Grid.Row="1" TextWrapping="Wrap" Text="5" VerticalAlignment="Top" Width="120"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="237,28,0,0" Grid.Row="1" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfDrawing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
double designWidth;
double designHeight;
double designLeft, designTop;
public MainWindow()
{
InitializeComponent();
designWidth = Rect2.Width;
designHeight = Rect2.Height;
designLeft = Canvas.GetLeft(Rect2);
designTop = Canvas.GetTop(Rect2);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Rect2.StrokeThickness = double.Parse(tbThickness.Text);
Canvas.SetLeft(Rect2,designLeft - (Rect2.StrokeThickness / 2));
Canvas.SetTop(Rect2, designTop - (Rect2.StrokeThickness / 2));
Rect2.Width = designWidth + Rect2.StrokeThickness;
Rect2.Height = designHeight + Rect2.StrokeThickness;
}
}
}
There is no need to do any calculations to correct the size of a rectangle by half of its stroke thickness.
Just use Path controls with RectangleGeometries instead of Rectangle controls:
private Brush stroke = Brushes.Red;
private double strokeThickness = 10;
private Path currentPath;
private Point startPoint;
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
if (canvas.CaptureMouse())
{
startPoint = e.GetPosition(canvas);
currentPath = new Path
{
Data = new RectangleGeometry(new Rect(startPoint, startPoint)),
Stroke = stroke,
StrokeThickness = strokeThickness
};
canvas.Children.Add(currentPath);
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (currentPath != null)
{
((RectangleGeometry)currentPath.Data).Rect
= new Rect(startPoint, e.GetPosition((UIElement)sender));
}
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
((UIElement)sender).ReleaseMouseCapture();
currentPath = null;
}
I just started learning C# and I want to plot a cosine when user presses the radiobutton using WPF GUI interface. I think I am having trouble how to use call objects within different class. Thanks in advance and below is my code:
namespace WpfApplication2
{
using OxyPlot;
using OxyPlot.Annotations;
using OxyPlot.Axes;
using OxyPlot.Series;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click_2(object sender, RoutedEventArgs e)
{
if (radioButton1.IsChecked == true)
{
MessageBox.Show("Plot Cosine");
//I think solution should be something like this
//MainViewModel.MyModel.Series.Add(new FunctionSeries(Math.Cos, -10, 10, 0.01, "cos(x)"));
}
}
}
public class MainViewModel : Window
{
//Plotting without any user input
public const double Pi = 3.14159265358979323846;
public const int SpeedOfLight = 3 * 10 ^ 8; // m per sec.
//OxyPlot.Wpf.PlotModel plot = new OxyPlot.Wpf.PlotView();
public MainViewModel()
{
MyModel = new PlotModel { Title = "Your Equation", LegendTitle = "Equations" };
MyModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Distance" });
MyModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Height" });
//Determine your range for the plot
//MyModel.Axes.Add(new LinearAxis(AxisPosition.Bottom, -10, 10));
//MyModel.Axes.Add(new LinearAxis(AxisPosition.Left, -5, 5));
MyModel.Series.Add(new FunctionSeries(Math.Cos, -10, 10, 0.01, "cos(x)"));
MyModel.Series.Add(new FunctionSeries(Math.Sin, -10, 10, 0.01, "sin(x)"));
LineSeries linePoints = new LineSeries() { };
double x, y;
DataPoint XYpoint = new DataPoint();
for (x = -10; x <= 10; x += 0.01)
{
//Make sure not 1/3 since C# will read it as integer divided by integer hence 1/3=0
//Use Math.Pow for powers
//Definately Matlab is easier to plot stuff XD
y = 1.0 / 2.0 * Math.Pow(x, 2) + 1;
XYpoint = new DataPoint(x, y);
linePoints.Points.Add(XYpoint);
}
MyModel.Series.Add(linePoints);
MyModel.InvalidatePlot(true);
}
public PlotModel MyModel { get; private set; }
}
}
Below is XAML code:
<Window x:Name="plot" x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:oxy="http://oxyplot.org/wpf"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="Plots" Height="450.307" Width="955.532" Background="White">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="73*"/>
<RowDefinition Height="11*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="145*"/>
<ColumnDefinition Width="329*"/>
</Grid.ColumnDefinitions>
<oxy:PlotView Title="{Binding Title}" Margin="4,0,0,0" Model="{Binding MyModel}" Grid.Column="1" >
<oxy:PlotView.Series>
<oxy:LineSeries ItemsSource="{Binding Points}"/>
</oxy:PlotView.Series>
</oxy:PlotView>
<Label x:Name="label" HorizontalAlignment="Left" Height="30" Margin="120,185,0,0" VerticalAlignment="Top" Width="142"/>
<RadioButton x:Name="radioButton1" Content="Plot Cosine" Grid.Column="1" HorizontalAlignment="Left" Height="20" Margin="50,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="85" />
<Button x:Name="button1" Content="Clear" HorizontalAlignment="Left" Height="35" Margin="120,7,0,0" Grid.Row="1" VerticalAlignment="Top" Width="142" Click="button_Click_2"/>
</Grid>
</Window>
C#
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OxyPlot;
using OxyPlot.Series;
using OxyPlot.Axes;
namespace WpfApplication2
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public PlotModel MyModel { get; private set; }
public MainWindow()
{
InitializeComponent();
MyModel = new PlotModel { Title = "Your Equation", LegendTitle = "Equations" };
MyModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Distance" });
MyModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Height" });
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (radioButton1.IsChecked == true)
{
//MessageBox.Show("Plot Cosine");
graph();
}
}
public double getValue(int x, int y)
{
return (10 * x * x + 11 * x * y * y + 12 * x * y);
}
//setting the values to the function
public FunctionSeries GetFunction()
{
int n = 100;
FunctionSeries serie = new FunctionSeries();
for (int x = 0; x < n; x++)
{
for (int y = 0; y < n; y++)
{
//adding the points based x,y
DataPoint data = new DataPoint(x, getValue(x, y));
//adding the point to the serie
serie.Points.Add(data);
}
}
//returning the serie
return serie;
}
public void graph()
{
MyModel = new PlotModel { Title = "example" };
MyModel.LegendPosition = LegendPosition.RightBottom;
MyModel.LegendPlacement = LegendPlacement.Outside;
MyModel.LegendOrientation = LegendOrientation.Horizontal;
MyModel.Series.Add(GetFunction());
var Yaxis = new OxyPlot.Axes.LinearAxis();
OxyPlot.Axes.LinearAxis XAxis = new OxyPlot.Axes.LinearAxis { Position = OxyPlot.Axes.AxisPosition.Bottom, Minimum = 0, Maximum = 100 };
XAxis.Title = "X";
Yaxis.Title = "10 * x * x + 11 * x*y*y + 12*x*y";
MyModel.Axes.Add(Yaxis);
MyModel.Axes.Add(XAxis);
this.plot.Model = MyModel;
}
}
}
XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="73*"/>
<RowDefinition Height="11*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="145*"/>
<ColumnDefinition Width="329*"/>
</Grid.ColumnDefinitions>
<oxy:PlotView Margin="4,0,0,0" Grid.Column="1" Name="plot" >
<!--<oxy:PlotView.Series>
<oxy:LineSeries ItemsSource="{Binding Points}"/>
</oxy:PlotView.Series>-->
</oxy:PlotView>
<Label x:Name="label" HorizontalAlignment="Left" Height="30" Margin="120,185,0,0" VerticalAlignment="Top" Width="142"/>
<RadioButton x:Name="radioButton1" IsChecked="True" Content="Plot Cosine" Grid.Column="1" HorizontalAlignment="Left" Height="20" Margin="50,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="85" />
<Button x:Name="button1" Content="Clear" HorizontalAlignment="Left" Height="35" Margin="120,7,0,0" Grid.Row="1" VerticalAlignment="Top" Width="142" Click="button1_Click"/>
</Grid>
</Window>
I have a user control which moves with my finger movement.The user control has its own manipulation delta set.
My problem is , when My finger is on the user control and I am trying to move it up , I am having lag because it is not moving up with my finger.
The user control appears when I long tap on my screen , the location of the user control is whereever my finger is pressed . It moves with my finger whereever I move my finger , but once my finger goes on the user control I am not having smooth movements .
Any help would be appreciated.
The XAML is
<Page x:Name="page1"
x:Class="controlMagnifier.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:controlMagnifier"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="ParentGrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" PointerReleased="ParentGrid_OnPointerReleased" >
<Canvas x:Name="InkPresenter" Height="auto" Width="auto">
<Image Stretch="None" x:Name="image2" >
<Image.Source >
<BitmapImage UriSource="/Assets/wallpaper.jpg" />
</Image.Source>
</Image>
</Canvas>
<local:MagnifierUsercontrol x:Name="MagnifyTip" Visibility="Collapsed" ManipulationDelta="MagnifyTip_ManipulationDelta" ManipulationMode="All" >
<local:MagnifierUsercontrol.RenderTransform>
<CompositeTransform/>
</local:MagnifierUsercontrol.RenderTransform>
</local:MagnifierUsercontrol>
</Grid>
</Page>
The CS Code Is
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Shapes;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Diagnostics;
using Windows.UI.Popups;
using Windows.UI.Input;
using Windows.Storage;
using Windows.UI.Xaml.Media.Imaging;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace controlMagnifier
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public const int XAxis = 105;
public const int YAxis = 270;
public Thickness margin;
public WriteableBitmap CurrentBitmapObj, CurrentCroppedImage = null;
public MainPage()
{
this.InitializeComponent();
ParentGrid.Holding += Grid_Holding;
image2.PointerMoved += InkCanvas_PointerMoved;
image2.PointerReleased += ParentGrid_OnPointerReleased;
image2.CacheMode=new BitmapCache();
StoreCrrentImage();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_Holding(object sender, HoldingRoutedEventArgs e)
{
//Point p;
try
{
Point p = e.GetPosition(ParentGrid);
double height = MagnifyTip.Height;
double width = MagnifyTip.Width;
margin = MagnifyTip.Margin;
margin.Left = p.X - XAxis;
margin.Right = p.Y - YAxis;
MagnifyTip.Margin = margin;
// MagnifyTip.Margin = new Thickness(p.X - XAxis, p.Y - YAxis, 0, 0);
MagnifyTip.Visibility = Visibility.Visible;
}
catch (Exception)
{
throw;
}
}
private void InkCanvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
try
{
PointerPoint pt = e.GetCurrentPoint(image2);
Point currentContactPt = pt.Position;
double xValue = currentContactPt.X;
double yValue = currentContactPt.Y;
// MagnifyTip.
double height = MagnifyTip.Height;
double width = MagnifyTip.Width;
MagnifyTip.image1.ImageSource = CropBitmap(currentContactPt);
MagnifyTip.Margin = new Thickness(xValue - XAxis, yValue - YAxis, 0, 0);
}
catch (Exception)
{
throw;
}
finally
{e.Handled = true;}
}
private async void StoreCrrentImage()
{
try
{
StorageFile storageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/wallpaper.jpg", UriKind.RelativeOrAbsolute));
using (
Windows.Storage.Streams.IRandomAccessStream fileStream =
await storageFile.OpenAsync(FileAccessMode.Read))
{
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
WriteableBitmap writeableBitmap =
new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
fileStream.Seek(0);
await writeableBitmap.SetSourceAsync(fileStream);
CurrentBitmapObj = writeableBitmap;
writeableBitmap.Invalidate();
}
}
catch (Exception )
{
throw;
}
finally
{}
}
/// <summary>
/// This method crops the image by accepting x and y as Arguments
/// </summary>
/// <param name="point"></param>
/// <returns>Cropped Image</returns>
private WriteableBitmap CropBitmap(Point point)
{
try
{
CurrentCroppedImage = CurrentBitmapObj.Crop(Convert.ToInt32(point.X), Convert.ToInt32(point.Y), 100, 100);
// var resized = CurrentCroppedImage.Resize(200, 300, WriteableBitmapExtensions.Interpolation.Bilinear);
}
catch (Exception)
{
throw;
}
return CurrentCroppedImage;
}
private void MagnifyTip_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Point p;
p.X = e.Delta.Translation.X;
p.Y = e.Delta.Translation.Y;
var Dragme = (CompositeTransform)MagnifyTip.RenderTransform;
Dragme.TranslateX += p.X;
Dragme.TranslateY += p.Y;
// MagnifyTip.controlCanvas.SetValue(Canvas.SetLeft, p.X);
}
private void ParentGrid_OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
MagnifyTip.Visibility = Visibility.Collapsed;
// throw new NotImplementedException();
}
}
}
The user control looks like
If you want to avoid the lag which is intentionally implemented in ManipulationDelta to distinguish it from Tap, use PointerMove instead.
I have answered similar question here.