使用大小为4的数组来表示一个单点

问题描述:

我与Wiimote的API工作,我碰到这个代码来了,使用大小为4的数组来表示一个单点

float[] srcX = new float[4]; 
float[] srcY = new float[4]; 
float[] dstX = new float[4]; 
float[] dstY = new float[4]; 

我无法理解为什么会有4辆彩车代表一个数组单点。请指导。谢谢。

这里是整个代码,

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Text; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.Threading; 
using System.Runtime.InteropServices;//for firing keyboard and mouse events (optional) 
using System.IO;//for saving the reading the calibration data 


using WiimoteLib; 

namespace WiimoteWhiteboard 
{ 
    public partial class Form1 : Form 
    { 
     //instance of the wii remote 
     Wiimote wm = new Wiimote(); 

     const int smoothingBufferSize = 50; 

     PointF[] smoothingBuffer = new PointF[smoothingBufferSize]; 
     int smoothingBufferIndex = 0; 
     int smoothingAmount = 4; 
     bool enableSmoothing = true; 

     bool cursorControl = false; 

     int screenWidth = 1024;//defaults, gets replaced by actual screen size 
     int screenHeight = 768; 

     int calibrationState = 0; 
     float calibrationMargin = .1f; 

     CalibrationForm cf = null; 

     Warper warper = new Warper(); 
     float[] srcX = new float[4]; 
     float[] srcY = new float[4]; 
     float[] dstX = new float[4]; 
     float[] dstY = new float[4]; 


     //declare consts for mouse messages 
     public const int INPUT_MOUSE = 0; 
     public const int INPUT_KEYBOARD = 1; 
     public const int INPUT_HARDWARE = 2; 

     public const int MOUSEEVENTF_MOVE = 0x01; 
     public const int MOUSEEVENTF_LEFTDOWN = 0x02; 
     public const int MOUSEEVENTF_LEFTUP = 0x04; 
     public const int MOUSEEVENTF_RIGHTDOWN = 0x08; 
     public const int MOUSEEVENTF_RIGHTUP = 0x10; 
     public const int MOUSEEVENTF_MIDDLEDOWN = 0x20; 
     public const int MOUSEEVENTF_MIDDLEUP = 0x40; 
     public const int MOUSEEVENTF_ABSOLUTE = 0x8000; 

     //declare consts for key scan codes 
     public const byte VK_TAB = 0x09; 
     public const byte VK_MENU = 0x12; // VK_MENU is Microsoft talk for the ALT key 
     public const byte VK_SPACE = 0x20; 
     public const byte VK_RETURN = 0x0D; 
     public const byte VK_LEFT =0x25; 
     public const byte VK_UP  =0x26; 
     public const byte VK_RIGHT =0x27; 
     public const byte VK_DOWN =0x28; 
     public const int KEYEVENTF_EXTENDEDKEY = 0x01; 
     public const int KEYEVENTF_KEYUP = 0x02; 

     //for firing mouse and keyboard events 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); 

     [StructLayout(LayoutKind.Sequential)] 
     public struct MOUSEINPUT 
     { 
      public int dx;//4 
      public int dy;//4 
      public uint mouseData;//4 
      public uint dwFlags;//4 
      public uint time;//4 
      public IntPtr dwExtraInfo;//4 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct KEYBDINPUT 
     { 
      public ushort wVk;//2 
      public ushort wScan;//2 
      public uint dwFlags;//4 
      public uint time;//4 
      public IntPtr dwExtraInfo;//4 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct HARDWAREINPUT 
     { 
      public uint uMsg; 
      public ushort wParamL; 
      public ushort wParamH; 
     } 

     [StructLayout(LayoutKind.Explicit, Size = 28)] 
     public struct INPUT 
     { 
      [FieldOffset(0)] 
      public int type; 
      [FieldOffset(4)] //* 
      public MOUSEINPUT mi; 
      [FieldOffset(4)] //* 
      public KEYBDINPUT ki; 
      [FieldOffset(4)] //* 
      public HARDWAREINPUT hi; 
     } 
     //imports mouse_event function from user32.dll 

     [DllImport("user32.dll")] 
     private static extern void mouse_event(
     long dwFlags, // motion and click options 
     long dx, // horizontal position or change 
     long dy, // vertical position or change 
     long dwData, // wheel movement 
     long dwExtraInfo // application-defined information 
     ); 

     [DllImport("user32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     public static extern bool SetCursorPos(int X, int Y); 

     //imports keybd_event function from user32.dll 
     [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
     public static extern void keybd_event(byte bVk, byte bScan, long dwFlags, long dwExtraInfo); 
     WiimoteState lastWiiState = new WiimoteState();//helps with event firing 

     //end keyboard and mouse input emulation variables---------------------------------------- 

     Mutex mut = new Mutex(); 

     public Form1() 
     { 
      screenWidth = Screen.GetBounds(this).Width; 
      screenHeight = Screen.GetBounds(this).Height; 
      InitializeComponent(); 

      for (int i = 0; i < smoothingBufferSize; i++) 
       smoothingBuffer[i] = new PointF(); 

      setSmoothing(smoothingAmount); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      //add event listeners to changes in the wiiremote 
      //fired for every input report - usually 100 times per second if acclerometer is enabled 
      wm.WiimoteChanged += new WiimoteChangedEventHandler(wm_OnWiimoteChanged); 
      //fired when the extension is attached on unplugged 
      wm.WiimoteExtensionChanged += new WiimoteExtensionChangedEventHandler(wm_OnWiimoteExtensionChanged); 

      try 
      { 
       //connect to wii remote 
       wm.Connect(); 

       //set what features you want to enable for the remote, look at Wiimote.InputReport for options 
       wm.SetReportType(Wiimote.InputReport.IRAccel, true); 


       //set wiiremote LEDs with this enumerated ID 
       wm.SetLEDs(true, false, false, false); 
      } 
      catch (Exception x) 
      { 
       MessageBox.Show("Exception: " + x.Message); 
       this.Close(); 
      } 
      loadCalibrationData(); 
     } 

     void wm_OnWiimoteExtensionChanged(object sender, WiimoteExtensionChangedEventArgs args) 
     { 

      //if extension attached, enable it 
      if(args.Inserted) 
       wm.SetReportType(Wiimote.InputReport.IRExtensionAccel, true); 
      else 
       wm.SetReportType(Wiimote.InputReport.IRAccel, true); 
     } 

     float UpdateTrackingUtilization() 
     { 
      //area of ideal calibration coordinates (to match the screen) 
      float idealArea = (1 - 2*calibrationMargin) * 1024 * (1 - 2*calibrationMargin) * 768; 

      //area of quadrliatera 
      float actualArea = 0.5f * Math.Abs((srcX[1] - srcX[2]) * (srcY[0] - srcY[3]) - (srcX[0] - srcX[3]) * (srcY[1] - srcY[2])); 
      float util = (actualArea/idealArea)*100; 
      BeginInvoke((MethodInvoker)delegate() { lblTrackingUtil.Text = util.ToString("f0"); }); 
      BeginInvoke((MethodInvoker)delegate() { pbTrackingUtil.Value = (int)util; }); 

      return util; 

     } 

     PointF getSmoothedCursor(int amount) 
     { 
      int start = smoothingBufferIndex - amount; 
      if (start < 0) 
       start = 0; 
      PointF smoothed = new PointF(0,0); 
      int count = smoothingBufferIndex - start; 
      for (int i = start; i < smoothingBufferIndex; i++) 
      { 
       smoothed.X += smoothingBuffer[i%smoothingBufferSize].X; 
       smoothed.Y += smoothingBuffer[i % smoothingBufferSize].Y; 
      } 
      smoothed.X /= count; 
      smoothed.Y /= count; 
      return smoothed; 
     } 

     void wm_OnWiimoteChanged(object sender, WiimoteChangedEventArgs args) 
     { 
      mut.WaitOne(); 

      //extract the wiimote state 
      WiimoteState ws = args.WiimoteState; 

      if (ws.IRState.Found1) 
      { 
       int x = ws.IRState.RawX1; 
       int y = ws.IRState.RawY1; 
       float warpedX = x; 
       float warpedY = y; 
       warper.warp(x, y, ref warpedX, ref warpedY); 

       smoothingBuffer[smoothingBufferIndex % smoothingBufferSize].X = warpedX; 
       smoothingBuffer[smoothingBufferIndex % smoothingBufferSize].Y = warpedY; 
       smoothingBufferIndex++; 

       if (!lastWiiState.IRState.Found1)//mouse down 
       { 
        lastWiiState.IRState.Found1 = ws.IRState.Found1; 
        smoothingBufferIndex = 0;//resets the count 

        if (cursorControl) 
        { 
         INPUT[] buffer = new INPUT[2]; 
         buffer[0].type = INPUT_MOUSE; 
         buffer[0].mi.dx = (int)(warpedX *65535.0f/screenWidth); 
         buffer[0].mi.dy = (int)(warpedY * 65535.0f/screenHeight); 
         buffer[0].mi.mouseData = 0; 
         buffer[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; 
         buffer[0].mi.time = 0; 
         buffer[0].mi.dwExtraInfo = (IntPtr)0; 

         buffer[1].type = INPUT_MOUSE; 
         buffer[1].mi.dx = 0; 
         buffer[1].mi.dy = 0; 
         buffer[1].mi.mouseData = 0; 
         buffer[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; 
         buffer[1].mi.time = 1; 
         buffer[1].mi.dwExtraInfo = (IntPtr)0; 

         SendInput(2, buffer, Marshal.SizeOf(buffer[0])); 

        }//cusor control 

        switch (calibrationState) 
        { 
         case 1: 
          srcX[calibrationState - 1] = x; 
          srcY[calibrationState - 1] = y; 
          calibrationState = 2; 
          doCalibration(); 
          break; 
         case 2: 
          srcX[calibrationState - 1] = x; 
          srcY[calibrationState - 1] = y; 
          calibrationState = 3; 
          doCalibration(); 
          break; 
         case 3: 
          srcX[calibrationState - 1] = x; 
          srcY[calibrationState - 1] = y; 
          calibrationState = 4; 
          doCalibration(); 
          break; 
         case 4: 
          srcX[calibrationState - 1] = x; 
          srcY[calibrationState - 1] = y; 
          calibrationState = 5; 
          doCalibration(); 
          break; 
         default: 
          break; 
        }//calibtation state 
       }//mouse down     
       else 
       { 
        if (cursorControl)//dragging 
        { 
         INPUT[] buffer = new INPUT[1]; 
         buffer[0].type = INPUT_MOUSE; 
         if (enableSmoothing) 
         { 
          PointF s = getSmoothedCursor(smoothingAmount); 
          buffer[0].mi.dx = (int)(s.X * 65535.0f/screenWidth); 
          buffer[0].mi.dy = (int)(s.Y * 65535.0f/screenHeight); 
         } 
         else 
         { 
          buffer[0].mi.dx = (int)(warpedX * 65535.0f/screenWidth); 
          buffer[0].mi.dy = (int)(warpedY * 65535.0f/screenHeight); 
         } 
         buffer[0].mi.mouseData = 0; 
         buffer[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; 
         buffer[0].mi.time = 0; 
         buffer[0].mi.dwExtraInfo = (IntPtr)0; 
         SendInput(1, buffer, Marshal.SizeOf(buffer[0])); 

        } 
       } 
      }//ir visible 
      else 
      { 
       if (lastWiiState.IRState.Found1)//mouse up 
       { 
        lastWiiState.IRState.Found1 = ws.IRState.Found1; 
        if (cursorControl) 
        { 
         INPUT[] buffer = new INPUT[2]; 
         buffer[0].type = INPUT_MOUSE; 
         buffer[0].mi.dx = 0; 
         buffer[0].mi.dy = 0; 
         buffer[0].mi.mouseData = 0; 
         buffer[0].mi.dwFlags = MOUSEEVENTF_LEFTUP; 
         buffer[0].mi.time = 0; 
         buffer[0].mi.dwExtraInfo = (IntPtr)0; 

         buffer[1].type = INPUT_MOUSE; 
         buffer[1].mi.dx = 0; 
         buffer[1].mi.dy = 0; 
         buffer[1].mi.mouseData = 0; 
         buffer[1].mi.dwFlags = MOUSEEVENTF_MOVE; 
         buffer[1].mi.time = 0; 
         buffer[1].mi.dwExtraInfo = (IntPtr)0; 

         SendInput(2, buffer, Marshal.SizeOf(buffer[0])); 

        } 
       }//ir lost 
      } 
      if (!lastWiiState.ButtonState.A && ws.ButtonState.A) 
      { 
       BeginInvoke((MethodInvoker)delegate() { btnCalibrate.PerformClick(); }); 
      } 
      lastWiiState.ButtonState.A = ws.ButtonState.A; 

      if (!lastWiiState.ButtonState.B && ws.ButtonState.B) 
       keybd_event(VK_SPACE, 0x45, 0, 0); 
      if (lastWiiState.ButtonState.B && !ws.ButtonState.B) 
       keybd_event(VK_SPACE, 0x45, KEYEVENTF_KEYUP, 0); 
      lastWiiState.ButtonState.B = ws.ButtonState.B; 

      if (!lastWiiState.ButtonState.Up && ws.ButtonState.Up) 
       keybd_event(VK_UP, 0x45, 0, 0); 
      if (lastWiiState.ButtonState.Up && !ws.ButtonState.Up) 
       keybd_event(VK_UP, 0x45, KEYEVENTF_KEYUP, 0); 
      lastWiiState.ButtonState.Up = ws.ButtonState.Up; 

      if (!lastWiiState.ButtonState.Down && ws.ButtonState.Down) 
       keybd_event(VK_DOWN, 0x45, 0, 0); 
      if (lastWiiState.ButtonState.Down && !ws.ButtonState.Down) 
       keybd_event(VK_DOWN, 0x45, KEYEVENTF_KEYUP, 0); 
      lastWiiState.ButtonState.Down = ws.ButtonState.Down; 

      if (!lastWiiState.ButtonState.Left && ws.ButtonState.Left) 
       keybd_event(VK_LEFT, 0x45, 0, 0); 
      if (lastWiiState.ButtonState.Left && !ws.ButtonState.Left) 
       keybd_event(VK_LEFT, 0x45, KEYEVENTF_KEYUP, 0); 
      lastWiiState.ButtonState.Left = ws.ButtonState.Left; 

      if (!lastWiiState.ButtonState.Right && ws.ButtonState.Right) 
       keybd_event(VK_RIGHT, 0x45, 0, 0); 
      if (lastWiiState.ButtonState.Right && !ws.ButtonState.Right) 
       keybd_event(VK_RIGHT, 0x45, KEYEVENTF_KEYUP, 0); 
      lastWiiState.ButtonState.Right = ws.ButtonState.Right; 


      lastWiiState.IRState.Found1 = ws.IRState.Found1; 
      lastWiiState.IRState.RawX1 = ws.IRState.RawX1; 
      lastWiiState.IRState.RawY1 = ws.IRState.RawY1; 
      lastWiiState.IRState.Found2 = ws.IRState.Found2; 
      lastWiiState.IRState.RawX2 = ws.IRState.RawX2; 
      lastWiiState.IRState.RawY2 = ws.IRState.RawY2; 
      lastWiiState.IRState.Found3 = ws.IRState.Found3; 
      lastWiiState.IRState.RawX3 = ws.IRState.RawX3; 
      lastWiiState.IRState.RawY3 = ws.IRState.RawY3; 
      lastWiiState.IRState.Found4 = ws.IRState.Found4; 
      lastWiiState.IRState.RawX4 = ws.IRState.RawX4; 
      lastWiiState.IRState.RawY4 = ws.IRState.RawY4; 

      //draw battery value on GUI 
      //BeginInvoke((MethodInvoker)delegate() { pbBattery.Value = (ws.Battery > 0xc8 ? 0xc8 : (int)ws.Battery); }); 
      //float f = (((100.0f * 48.0f * (float)(ws.Battery/48.0f)))/192.0f); 
      //BeginInvoke((MethodInvoker)delegate() { lblBattery.Text = f.ToString("f0") + "%"; }); 

      //check the GUI check boxes if the IR dots are visible 
      //String irstatus = "Visible IR dots: "; 
      //if (ws.IRState.Found1) 
      // irstatus += "1 "; 
      //if (ws.IRState.Found2) 
      // irstatus += "2 "; 
      //if (ws.IRState.Found3) 
      // irstatus += "3 "; 
      //if (ws.IRState.Found4) 
      // irstatus += "4 "; 

      //BeginInvoke((MethodInvoker)delegate() { lblIRvisible.Text = irstatus; }); 

      mut.ReleaseMutex();   
     } 


     public void loadCalibrationData() 
     { 
      // create reader & open file 
      try 
      { 
       TextReader tr = new StreamReader("calibration.dat"); 
       for (int i = 0; i < 4; i++) 
       { 
        srcX[i] = float.Parse(tr.ReadLine()); 
        srcY[i] = float.Parse(tr.ReadLine()); 
       } 
       smoothingAmount = int.Parse(tr.ReadLine()); 

       // close the stream 
       tr.Close(); 
      } 
      catch (Exception x) 
      { 
       //no prexsting calibration 
       return; 
      } 

      warper.setDestination( screenWidth * calibrationMargin, 
            screenHeight * calibrationMargin, 
            screenWidth * (1.0f-calibrationMargin), 
            screenHeight * calibrationMargin, 
            screenWidth * calibrationMargin, 
            screenHeight * (1.0f - calibrationMargin), 
            screenWidth * (1.0f - calibrationMargin), 
            screenHeight * (1.0f - calibrationMargin)); 
      warper.setSource(srcX[0], srcY[0], srcX[1], srcY[1], srcX[2], srcY[2], srcX[3], srcY[3]); 

      warper.computeWarp(); 

      setSmoothing(smoothingAmount); 

      cursorControl = true; 
      // BeginInvoke((MethodInvoker)delegate() { cbCursorControl.Checked = cursorControl; }); 

      UpdateTrackingUtilization(); 
     } 

     public void saveCalibrationData() 
     { 
      TextWriter tw = new StreamWriter("calibration.dat"); 

      // write a line of text to the file 
      for (int i = 0; i < 4; i++) 
      { 
       tw.WriteLine(srcX[i]); 
       tw.WriteLine(srcY[i]); 
      } 
      tw.WriteLine(smoothingAmount); 
      // close the stream 
      tw.Close(); 
     } 

     public void doCalibration(){ 
      if (cf == null) 
       return; 
      int x = 0; 
      int y = 0; 
      int size = 25; 
      Pen p = new Pen(Color.Red); 
      switch (calibrationState) 
      { 
       case 1: 
        x = (int)(screenWidth * calibrationMargin); 
        y = (int)(screenHeight * calibrationMargin); 
        cf.showCalibration(x, y, size, p); 
        dstX[calibrationState - 1] = x; 
        dstY[calibrationState - 1] = y; 
        break; 
       case 2: 
        x = screenWidth - (int)(screenWidth * calibrationMargin); 
        y = (int)(screenHeight * calibrationMargin); 
        cf.showCalibration(x, y, size, p); 
        dstX[calibrationState - 1] = x; 
        dstY[calibrationState - 1] = y; 
        break; 
       case 3: 
        x = (int)(screenWidth * calibrationMargin); 
        y = screenHeight -(int)(screenHeight * calibrationMargin); 
        cf.showCalibration(x, y, size, p); 
        dstX[calibrationState - 1] = x; 
        dstY[calibrationState - 1] = y; 
        break; 
       case 4: 
        x = screenWidth - (int)(screenWidth * calibrationMargin); 
        y = screenHeight -(int)(screenHeight * calibrationMargin); 
        cf.showCalibration(x, y, size, p); 
        dstX[calibrationState - 1] = x; 
        dstY[calibrationState - 1] = y; 
        break; 
       case 5: 
        //compute warp 
        warper.setDestination(dstX[0], dstY[0], dstX[1], dstY[1], dstX[2], dstY[2], dstX[3], dstY[3]); 
        warper.setSource(srcX[0], srcY[0], srcX[1], srcY[1], srcX[2], srcY[2], srcX[3], srcY[3]); 
        warper.computeWarp(); 
        cf.Close(); 
        cf = null; 
        calibrationState = 0; 
        cursorControl = true; 
        // BeginInvoke((MethodInvoker)delegate() { cbCursorControl.Checked = cursorControl; }); 
//     saveCalibrationData(); 
        UpdateTrackingUtilization(); 
        break; 
       default: 
        break; 
      } 

     } 

     private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
     { 
      //disconnect the wiimote 
      wm.Disconnect(); 
      saveCalibrationData(); 
     } 

     private void btnCalibrate_Click(object sender, EventArgs e) 
     { 
      if (cf == null) 
      { 
       cf = new CalibrationForm(); 
       cf.Show(); 
      } 
      if (cf.IsDisposed) 
      { 
       cf = new CalibrationForm(); 
       cf.Show(); 
      } 
      cursorControl = false; 
      calibrationState = 1; 
      doCalibration(); 
     } 

     private void cbCursorControl_CheckedChanged(object sender, EventArgs e) 
     { 
      //cursorControl = cbCursorControl.Checked; 
     } 

     private void label1_Click(object sender, EventArgs e) 
     { 

     } 

     private void setSmoothing(int smoothing) 
     { 
      smoothingAmount = smoothing; 
      //trackBar1.Value = smoothing; 
      enableSmoothing = (smoothingAmount != 0); 
      // lblSmoothing.Text = "Smoothing: " + smoothingAmount; 
     } 

     //private void trackBar1_Scroll(object sender, EventArgs e) 
     //{ 

     // smoothingAmount = trackBar1.Value; 
     // enableSmoothing = (smoothingAmount != 0); 
     // lblSmoothing.Text = "Smoothing: " + smoothingAmount; 
     //} 

     private void lblIRvisible_Click(object sender, EventArgs e) 
     { 

     } 
    } 
} 

它通过矩阵计算用于校准。

Warper实际上处理矩阵转换来校准屏幕位置等我猜。

的矩阵是4×4 - > 4个阵列具有4

这里尺寸可以有一个look into the Code