トップ回答者
マウスの動きに合わせてオブジェクトを回転させたい

質問
-
Ellipseをマウスの動きに合わせて、ぐるぐると回転させるPGを作っております。
やり方としては、以下のサイトなどを参考に
マウスの座標(始点と終点の2点座標)を取得し、
Atan2メソッドで角度を求め、
RotateTransformで回転するようにしております。
http://www25.atwiki.jp/guru/pages/51.html
http://hakuhin.hp.infoseek.co.jp/main/as/math.html#MATH_01
ところが回転が1周もしないうちに途中で逆回転してしまうのです。
逆回転した後、Ellipseの真ん中のラベルにマウスを当てると「正常」に回転する動きになるのですが・・・。
※ここで言う「正常」な動きとは、何周でもマウスに合わせて回転出来る動きです。
原因がまったく分からず投稿させていただきました。
どうかアドバイス宜しくお願い致します。<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="511" Width="453"> <Grid> <Ellipse MouseEnter="myEllipse_MouseEnter" MouseMove="myEllipse_MouseMove" Margin="78,224,71,21" Name="myEllipse" Stroke="Black"> <Ellipse.Fill> <LinearGradientBrush StartPoint="0,0.1" EndPoint="2,3"> <GradientStop Color="Yellow"/> <GradientStop Color="Black" Offset="0.254"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> <Label Height="42" Margin="185,12,126,0" Name="label1" VerticalAlignment="Top" FontSize="18" Background="RoyalBlue"></Label> <Label Background="RoyalBlue" FontSize="18" Height="42" Margin="185,60,126,0" Name="lblFirstPoint" VerticalAlignment="Top" /> <Label Background="RoyalBlue" FontSize="18" Height="42" Margin="185,108,126,0" Name="lblLastPoint" VerticalAlignment="Top" /> <Label Background="Gray" FontSize="12" Height="42" Margin="85,60,0,0" Name="label4" VerticalAlignment="Top" HorizontalAlignment="Left" Width="90">MouseEnter時座標</Label> <Label Background="Gray" FontSize="12" Height="42" Margin="85,108,0,0" Name="label5" VerticalAlignment="Top" HorizontalAlignment="Left" Width="90">MouseMove時座標</Label> <Label Background="RoyalBlue" FontSize="18" Height="31" Margin="198,0,186,112" Name="lblTarget" VerticalAlignment="Bottom">回転</Label> <Label Background="Gray" FontSize="12" Height="42" HorizontalAlignment="Left" Margin="84,12,0,0" Name="label2" VerticalAlignment="Top" Width="90">角度</Label> </Grid> </Window>
using System; 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; namespace WpfApplication1 { /// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : Window { Point FirstPoint; Point CurrentPoint; public Window1() { InitializeComponent(); } private void myEllipse_MouseEnter(object sender, MouseEventArgs e) { //マウス座標 FirstPoint = e.GetPosition(this); CurrentPoint = e.GetPosition(this); //debug lblFirstPoint.Content = FirstPoint.X + "," + FirstPoint.Y; } private void myEllipse_MouseMove(object sender, MouseEventArgs e) { //マウス座標 CurrentPoint = e.GetPosition(this); //debug lblLastPoint.Content = CurrentPoint.X + "," + CurrentPoint.Y; //角度 double dblKakudo = Math.Atan2(CurrentPoint.Y - FirstPoint.Y, CurrentPoint.X - FirstPoint.X) * 180 / Math.PI; //debug label1.Content = (int)dblKakudo + "度"; //回転クラス生成 RotateTransform myRotateTran1 = new RotateTransform(); RotateTransform myRotateTran2 = new RotateTransform(); //回転時の中心座標 円 myRotateTran1.CenterX = myEllipse.ActualWidth / 2; myRotateTran1.CenterY = myEllipse.ActualHeight / 2; myRotateTran1.Angle = (int)dblKakudo; //回転時の中心座標 ラベル myRotateTran2.CenterX = lblTarget.ActualWidth / 2; myRotateTran2.CenterY = lblTarget.ActualHeight / 2; myRotateTran2.Angle = (int)dblKakudo; //変換実行 myEllipse.RenderTransform = myRotateTran1; lblTarget.RenderTransform = myRotateTran2; } } }
回答
-
回答済みになったのでヒントではなく動作確認したプログラムをUPします。
public partial class Window1 : Window { Point CenterPoint; Point FirstPoint; Point CurrentPoint; double FirstKakudo; public Window1() { InitializeComponent(); } private void myEllipse_MouseEnter(object sender, MouseEventArgs e) { Rect rect = myEllipse.RenderedGeometry.Bounds; Point center = myEllipse.PointToScreen(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2)); CenterPoint = this.PointFromScreen(center); FirstKakudo = Math.Atan2(FirstPoint.Y - CenterPoint.Y, FirstPoint.X - CenterPoint.X) * 180 / Math.PI; //マウス座標 FirstPoint = e.GetPosition(this); CurrentPoint = e.GetPosition(this); //debug lblFirstPoint.Content = FirstPoint.X + "," + FirstPoint.Y; } private void myEllipse_MouseMove(object sender, MouseEventArgs e) { //マウス座標 CurrentPoint = e.GetPosition(this); //debug lblLastPoint.Content = CurrentPoint.X + "," + CurrentPoint.Y; //角度 double dblKakudo = Math.Atan2(CurrentPoint.Y - CenterPoint.Y, CurrentPoint.X - CenterPoint.X) * 180 / Math.PI; dblKakudo = dblKakudo - FirstKakudo; //debug label1.Content = (int)dblKakudo + "度"; //回転クラス生成 RotateTransform myRotateTran1 = new RotateTransform(); RotateTransform myRotateTran2 = new RotateTransform(); //回転時の中心座標 円 myRotateTran1.CenterX = myEllipse.ActualWidth / 2; myRotateTran1.CenterY = myEllipse.ActualHeight / 2; myRotateTran1.Angle = (int)dblKakudo; //回転時の中心座標 ラベル myRotateTran2.CenterX = lblTarget.ActualWidth / 2; myRotateTran2.CenterY = lblTarget.ActualHeight / 2; myRotateTran2.Angle = (int)dblKakudo; //変換実行 myEllipse.RenderTransform = myRotateTran1; lblTarget.RenderTransform = myRotateTran2; } }
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2010/12- 回答としてマーク sumi_sumi 2010年2月10日 0:46
すべての返信
-
Point CenterPoint; を Window1 クラスのローカル変数に定義されているとして中心点は以下のコードでもとまります。
最初の点と中心点の角度を myEllipse_MouseEnter で求めておいて、myEllipse_MouseMove では CurrentPoint と中心点の角度を求めて、角度の差を Angle に入れればいいです。Rect rect = myEllipse.RenderedGeometry.Bounds; Point center = myEllipse.PointToScreen(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2)); CenterPoint = this.PointFromScreen(center);
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2010/12 -
フォーラムオペレーターの高橋春樹です。
えムナウさん、いつもお世話になっております。
サンプルコードも出して頂き、有難うございました。sumi_tanaさん、初めまして。
MSDNフォーラムのご利用有難うございます。
えムナウさんからアドバイスを頂いたと思うのですが、試して頂けたでしょうか?えムナウさんからのアドバイスが、有用な情報と思いましたので
勝手ながら、回答マークを付けさせて頂きました。sumi_tanaさんの現在の状況も気になるので、
えムナウさんの投稿に、返信して頂けると助かります(^_^)
マイクロソフト株式会社 フォーラム オペレーター 高橋春樹 -
回答済みになったのでヒントではなく動作確認したプログラムをUPします。
public partial class Window1 : Window { Point CenterPoint; Point FirstPoint; Point CurrentPoint; double FirstKakudo; public Window1() { InitializeComponent(); } private void myEllipse_MouseEnter(object sender, MouseEventArgs e) { Rect rect = myEllipse.RenderedGeometry.Bounds; Point center = myEllipse.PointToScreen(new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2)); CenterPoint = this.PointFromScreen(center); FirstKakudo = Math.Atan2(FirstPoint.Y - CenterPoint.Y, FirstPoint.X - CenterPoint.X) * 180 / Math.PI; //マウス座標 FirstPoint = e.GetPosition(this); CurrentPoint = e.GetPosition(this); //debug lblFirstPoint.Content = FirstPoint.X + "," + FirstPoint.Y; } private void myEllipse_MouseMove(object sender, MouseEventArgs e) { //マウス座標 CurrentPoint = e.GetPosition(this); //debug lblLastPoint.Content = CurrentPoint.X + "," + CurrentPoint.Y; //角度 double dblKakudo = Math.Atan2(CurrentPoint.Y - CenterPoint.Y, CurrentPoint.X - CenterPoint.X) * 180 / Math.PI; dblKakudo = dblKakudo - FirstKakudo; //debug label1.Content = (int)dblKakudo + "度"; //回転クラス生成 RotateTransform myRotateTran1 = new RotateTransform(); RotateTransform myRotateTran2 = new RotateTransform(); //回転時の中心座標 円 myRotateTran1.CenterX = myEllipse.ActualWidth / 2; myRotateTran1.CenterY = myEllipse.ActualHeight / 2; myRotateTran1.Angle = (int)dblKakudo; //回転時の中心座標 ラベル myRotateTran2.CenterX = lblTarget.ActualWidth / 2; myRotateTran2.CenterY = lblTarget.ActualHeight / 2; myRotateTran2.Angle = (int)dblKakudo; //変換実行 myEllipse.RenderTransform = myRotateTran1; lblTarget.RenderTransform = myRotateTran2; } }
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2010/12- 回答としてマーク sumi_sumi 2010年2月10日 0:46