##現在できていること
テラテイルで質問をしながら何とかVisualStudioで画像がマウスに合わせて魚眼レンズ風に拡大されるプログラムを作ることができました.
現在は画像を拡大する座標をarduinoで計測した座標に置き換えようとしています
現在のプログラムはこんな感じです
MainWindow.xaml
xaml
1<Window 2 x:Class="Questions228869.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="clr-namespace:Questions228869" 6 xmlns:local1="clr-namespace:Primitive3DSurfaces" 7 Title="Sphere3D" 8 9 10 SizeToContent="WidthAndHeight"> 11 <Window.Resources> 12 <BitmapImage x:Key="earthImage" UriSource="Image/kyeboard.png" /> 13 </Window.Resources> 14 15 <Canvas Width="720" Height="480"> 16 <Image x:Name="sourceImage" Source="{StaticResource earthImage}" /> 17 <Viewport3D 18 x:Name="viewport" 19 Width="300" 20 Height="300"> 21 <Viewport3D.Camera> 22 <PerspectiveCamera 23 LookDirection="0,0,-1" 24 Position="0,0,3" 25 UpDirection="0,1,0" /> 26 </Viewport3D.Camera> 27 <ModelVisual3D> 28 <ModelVisual3D.Content> 29 <Model3DGroup> 30 <AmbientLight Color="#ffffff" /> 31 <DirectionalLight Direction="-1,-1,-1" Color="#ffffff" /> 32 </Model3DGroup> 33 </ModelVisual3D.Content> 34 </ModelVisual3D> 35 <local1:Sphere3D x:Name="sphere" /> 36 </Viewport3D> 37 <Button x:Name="Sencer" Content="start" Height="59" Width="211" FontSize="16" Click="Sencer_Click_1"/> 38 39 </Canvas> 40</Window>
MainWindow.xaml.cs
C#
1using System; 2using System.Windows; 3using System.Windows.Controls; 4using System.Windows.Input; 5using System.Windows.Media; 6using System.Windows.Media.Imaging; 7using System.Windows.Media.Media3D; 8using System.Collections.ObjectModel; 9using System.IO.Ports; 10using System.Text; 11using System.Windows.Forms; 12using System.Threading; 13using System.Threading.Tasks; 14 15namespace Questions228869 16{ 17 public partial class MainWindow : Window 18 { 19 SerialPort mySerialPort = new SerialPort("COM4"); 20 private readonly RenderTargetBitmap inflateImage; 21 // 倍率 それっぽくなるように現物合わせ 22 private const double scale = 1.2; 23 // 球に巻き始める余白部分 6時が正面とすると3時から反時計回り? 24 private const double offset = cropWidth / 4 * 3; 25 // 球に巻く画像の幅 高さから逆算 26 private const double cropWidth = Math.PI * cropHeight * scale; 27 // 球に巻く画像の高さ viewport.Height に合わせた 特に根拠なし 28 private const double cropHeight = 100 * scale; 29 30 string RxString; 31 int a; 32 33 public MainWindow() 34 { 35 InitializeComponent(); 36 37 // CroppedBitmapで例外が出るのでひと回り大きい画像を作る 38 // 上下右はもっと小さくていいが面倒なので全方向同じ数字で広げた 39 var image = (BitmapImage)Resources["earthImage"]; 40 var visual = new DrawingVisual(); 41 var dc = visual.RenderOpen(); 42 var rect = new Rect(0, 0, image.PixelWidth + offset * 2, image.PixelHeight + offset * 2); 43 dc.DrawRectangle(Brushes.White, null, rect); 44 dc.DrawImage(image, new Rect(offset, offset, image.PixelWidth, image.PixelHeight)); 45 dc.Close(); 46 47 inflateImage = new RenderTargetBitmap((int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Pbgra32); 48 inflateImage.Render(visual); 49 50 51 a = 1; 52 53 54 } 55 56 private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 57 { 58 if (a == 1) 59 { 60 RxString = mySerialPort.ReadLine(); 61 a = 2; 62 Console.Write(RxString); 63 } 64 65 RxString = mySerialPort.ReadLine(); 66 67 68 string[] strArrayData = RxString.Split(','); 69 Console.Write(strArrayData[0]); 70 Console.Write(","); 71 Console.Write(strArrayData[1]); 72 float x = float.Parse(strArrayData[0]); 73 float y = float.Parse(strArrayData[1]); 74 75 // 魚眼レンズ風に拡大 76 viewport.SetValue(Canvas.LeftProperty, x - viewport.Width / 2); 77 viewport.SetValue(Canvas.TopProperty, y - viewport.Height / 2); 78 79 var ratioX = sourceImage.Source.Width / sourceImage.ActualWidth; 80 var ratioY = sourceImage.Source.Height / sourceImage.ActualHeight; 81 82 var sourceX = ratioX * x; 83 var sourceY = ratioY * y; 84 85 var X = sourceX; // 巻き始め分を大きくしたのでちょうどxで合う 86 var Y = sourceY - cropHeight / 2 + offset; 87 var rect = new Int32Rect((int)X, (int)Y, (int)cropWidth, (int)cropHeight); 88 try 89 { 90 var croppedBitmap = new CroppedBitmap(inflateImage, rect); 91 sphere.Material = new DiffuseMaterial(new ImageBrush(croppedBitmap)); 92 } 93 catch { /* NOP CroppedBitmapが範囲外 */ } 94 95 96 } 97 98 99 100 private void Sencer_Click_1(object sender, RoutedEventArgs e) 101 { 102 103 mySerialPort.BaudRate = 9600; 104 mySerialPort.Parity = Parity.None; 105 mySerialPort.Encoding = Encoding.UTF8; 106 mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived); 107 mySerialPort.Open(); 108 109 } 110 111 112 } 113 114}
Class1.cs
c#
1using System; 2using System.Windows; 3using System.Windows.Media; 4using System.Windows.Media.Media3D; 5 6namespace Primitive3DSurfaces 7{ 8 public abstract class Primitive3D : ModelVisual3D 9 { 10 public Primitive3D() 11 { 12 Content = _content; 13 _content.Geometry = Tessellate(); 14 } 15 16 public static DependencyProperty MaterialProperty = 17 DependencyProperty.Register( 18 "Material", 19 typeof(Material), 20 typeof(Primitive3D), new PropertyMetadata( 21 null, new PropertyChangedCallback(OnMaterialChanged))); 22 23 public Material Material 24 { 25 get { return (Material)GetValue(MaterialProperty); } 26 set { SetValue(MaterialProperty, value); } 27 } 28 29 internal static void OnMaterialChanged(Object sender, DependencyPropertyChangedEventArgs e) 30 { 31 Primitive3D p = ((Primitive3D)sender); 32 33 p._content.Material = p.Material; 34 } 35 36 internal static void OnGeometryChanged(DependencyObject d) 37 { 38 Primitive3D p = ((Primitive3D)d); 39 40 p._content.Geometry = p.Tessellate(); 41 } 42 43 internal double DegToRad(double degrees) 44 { 45 return (degrees / 180.0) * Math.PI; 46 } 47 48 internal abstract Geometry3D Tessellate(); 49 50 internal readonly GeometryModel3D _content = new GeometryModel3D(); 51 } 52}
Class2.cs
c#
1using System; 2using System.Windows; 3using System.Windows.Media; 4using System.Windows.Media.Media3D; 5 6namespace Primitive3DSurfaces 7{ 8 public sealed class Sphere3D : Primitive3D 9 { 10 internal Point3D GetPosition(double t, double y) 11 { 12 double r = Math.Sqrt(1 - y * y); 13 double x = r * Math.Cos(t); 14 double z = r * Math.Sin(t); 15 16 return new Point3D(x, y, z); 17 } 18 19 public Vector3D GetNormal(double t, double y) 20 { 21 return (Vector3D)GetPosition(t, y); 22 } 23 24 public Point GetTextureCoordinate(double t, double y) 25 { 26 Matrix TYtoUV = new Matrix(); 27 TYtoUV.Scale(1 / (2 * Math.PI), -0.5); 28 29 //Point p = new Point(t, y); 30 Point p = new Point(1 - t, y); 31 p = p * TYtoUV; 32 33 return p; 34 } 35 36 internal override Geometry3D Tessellate() 37 { 38 int tDiv = 32; 39 int yDiv = 32; 40 double maxTheta = DegToRad(360.0); 41 double minY = -1.0; 42 double maxY = 1.0; 43 44 double dt = maxTheta / tDiv; 45 double dy = (maxY - minY) / yDiv; 46 47 MeshGeometry3D mesh = new MeshGeometry3D(); 48 49 for (int yi = 0; yi <= yDiv; yi++) 50 { 51 double y = minY + yi * dy; 52 53 for (int ti = 0; ti <= tDiv; ti++) 54 { 55 double t = ti * dt; 56 57 mesh.Positions.Add(GetPosition(t, y)); 58 mesh.Normals.Add(GetNormal(t, y)); 59 mesh.TextureCoordinates.Add(GetTextureCoordinate(t, y)); 60 } 61 } 62 63 for (int yi = 0; yi < yDiv; yi++) 64 { 65 for (int ti = 0; ti < tDiv; ti++) 66 { 67 int x0 = ti; 68 int x1 = (ti + 1); 69 int y0 = yi * (tDiv + 1); 70 int y1 = (yi + 1) * (tDiv + 1); 71 72 mesh.TriangleIndices.Add(x0 + y0); 73 mesh.TriangleIndices.Add(x0 + y1); 74 mesh.TriangleIndices.Add(x1 + y0); 75 76 mesh.TriangleIndices.Add(x1 + y0); 77 mesh.TriangleIndices.Add(x0 + y1); 78 mesh.TriangleIndices.Add(x1 + y1); 79 } 80 } 81 82 mesh.Freeze(); 83 return mesh; 84 } 85 } 86} 87
##起こっているエラー
MainWindow.xaml.csの魚眼レンズ風に拡大する部分でこのオブジェクトは別のスレッドに所有されているため,呼び出しスレッドはこのオブジェクトにアクセスできませんというエラーが出ます
このエラーの解消の仕方がわかりませんどなたか知恵をお貸しください!
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/05 01:53