none
Inkcollector or RealTimeStylus

    Question

  • Hi,
    I work in online graphic recognition, so I need low level informations of ink. What is the best choise to collect ink for me?
    I need (x,y) and time. I think that getting x and y is easy. But how can I get time information (the best way).
    Thank you in advance
    Tuesday, March 25, 2008 9:31 PM

Answers

  • The TimerTick values are calculated by Microsoft.Ink - it doesn't matter if the stroke comes from a graphical tablet.  However, if you want to do things with the XY values as they are generated, you can use the NewPackets event:

     

    int prevX;

    int prevY;

    void myCollector_NewPackets(object sender, InkCollectorNewPacketsEventArgs e)

    {

    //first figure out which index in

    //the PacketData array is for X and Y

    int indexX = -1;

    int indexY = -1;

    int numProps = e.Stroke.PacketDescription.Length;

    for (int p = 0; p < numProps; p++)

    {

    Guid guid = e.Stroke.PacketDescription[p];

    if (guid == PacketProperty.X)

    {

    indexX = p;

    }

    else if (guid == PacketProperty.Y)

    {

    indexY = p;

    }

    if (indexX >= 0 && indexY >= 0)

    {

    break;

    }

    }

    if (indexX >= 0 && indexY >= 0)

    {

    for (int i = 0; i < e.PacketData.Length; i += numProps)

    {

    //pull out the sub-array representing a single PacketData

    int[] packet = (int[])Array.CreateInstance(typeof(int), numProps);

    Array.Copy(e.PacketData, i, packet, 0, numProps);

    //check if this is the first packet in the stroke

    if (e.Stroke.PacketCount == 0 && i == 0)

    {

    prevX = e.PacketData[indexX];

    prevY = e.PacketData[indexY];

    continue;

    }

    int currentX = packet[indexX];

    int currentY = packet[indexY];

    int deltaX = currentX - prevX;

    int deltaY = currentY - prevY;

    //do something with the delta values...

    prevX = currentX;

    prevY = currentY;

    }

    }

     

    }

    Friday, March 28, 2008 5:10 AM

All replies

  • If you want a lot of control over how your ink is displayed, RTS is probably better than the InkCollector.  In either case, the time info will have to be added by the application.  Do you need timestamps at the stroke level or the point level?

    Thursday, March 27, 2008 10:12 PM
  •  

    If you want to collect packet-level time info, you will need to set the DesiredPacketDescription of the InkCollector or RealTimeStylus object to include the TimerTick property. (The default is X, Y, Pressure).  Here is some code to illustrate both stroke and packet level time-stamping:

     

    using System;

    using System.Windows.Forms;

    using Microsoft.Ink;

    namespace TestApp

    {

    class Program : Form

    {

    InkCollector myCollector;

    static Guid strokeStart = new Guid("BD5EAA3C-8905-4cc1-8C6F-50858CE1C547");

    static Guid strokeEnd = new Guid("064F487F-FA28-48d7-9EA6-D20697545275");

    public Program()

    {

    this.Height = 200;

    this.Width = 200;

    myCollector = new InkCollector(this);

    //set the DesiredPacketDescription before enabling the control

    myCollector.DesiredPacketDescription = new Guid[]{

    PacketProperty.X,

    PacketProperty.Y,

    //TimerTick shows number of milliseconds

    //between the current packet and previous packet,

    //with the first packet being zero

    PacketProperty.TimerTick};

    myCollector.Enabled = true;

    myCollector.Stroke += new InkCollectorStrokeEventHandler(myCollector_Stroke);

    }

    void myCollector_Stroke(object sender, InkCollectorStrokeEventArgs e)

    {

    DateTime end = DateTime.Now;

    int[] tticks = e.Stroke.GetPacketValuesByProperty(PacketProperty.TimerTick);

    int ms = tticks[tticks.Length - 1];

    //calculate start time by subtracting final amount

    //of milliseconds from the end time

    DateTime start = end.AddMilliseconds(-(ms));

    //ExtendedProperty data must be long, string, bool or byte[]

    e.Stroke.ExtendedProperties.Add(Program.strokeStart, start.Ticks);

    e.Stroke.ExtendedProperties.Add(Program.strokeEnd, end.Ticks);

    }

     

    static void Main(string[] args)

    {

    Application.Run(new Program());

    }

    }

    }

     

    Hope this helps!

    Friday, March 28, 2008 12:15 AM
  • Thank for your helpful answers. I just begin to work in sketch understanding domain. Actually I work with a graphic tablet. The information that I got from the tablet is only X and Y. I think that time information is concluded from the distance between (x , y) and the next captured point (x’, y’) in the offline mode of graphic tablet. So to get the same information with the online mode. What I can do then?

    Friday, March 28, 2008 12:36 AM
  • The TimerTick values are calculated by Microsoft.Ink - it doesn't matter if the stroke comes from a graphical tablet.  However, if you want to do things with the XY values as they are generated, you can use the NewPackets event:

     

    int prevX;

    int prevY;

    void myCollector_NewPackets(object sender, InkCollectorNewPacketsEventArgs e)

    {

    //first figure out which index in

    //the PacketData array is for X and Y

    int indexX = -1;

    int indexY = -1;

    int numProps = e.Stroke.PacketDescription.Length;

    for (int p = 0; p < numProps; p++)

    {

    Guid guid = e.Stroke.PacketDescription[p];

    if (guid == PacketProperty.X)

    {

    indexX = p;

    }

    else if (guid == PacketProperty.Y)

    {

    indexY = p;

    }

    if (indexX >= 0 && indexY >= 0)

    {

    break;

    }

    }

    if (indexX >= 0 && indexY >= 0)

    {

    for (int i = 0; i < e.PacketData.Length; i += numProps)

    {

    //pull out the sub-array representing a single PacketData

    int[] packet = (int[])Array.CreateInstance(typeof(int), numProps);

    Array.Copy(e.PacketData, i, packet, 0, numProps);

    //check if this is the first packet in the stroke

    if (e.Stroke.PacketCount == 0 && i == 0)

    {

    prevX = e.PacketData[indexX];

    prevY = e.PacketData[indexY];

    continue;

    }

    int currentX = packet[indexX];

    int currentY = packet[indexY];

    int deltaX = currentX - prevX;

    int deltaY = currentY - prevY;

    //do something with the delta values...

    prevX = currentX;

    prevY = currentY;

    }

    }

     

    }

    Friday, March 28, 2008 5:10 AM
  • Hi,
    This looks like exactly what I've been looking for. Thanks.
    However, when I try to implement your example, I run into the following problem:
    The 'using Microsoft.Ink' statement gives me a missing assembly error. When I try to add Microsoft.Ink as a reference to the project, it's not there, under the .COM or .NET tabs. That implies to me that I need to install Tablet SDK.
    So:  *** Do I need to install tablet SDK 1.7 if I'm using Windows Vista on a desktop and VS2008? ***

    Full project samples that I download from msdn have 'using Microsoft.Ink' in them and work fine. Which implies I don't need to install the SDK.
    Some discussion threads say I need the SDK.
    Some say I don't.
    And the most recent SDK 1.7 is from 2005. Can that really be the most recent version?
    This seems like a very simple question, but I just can't find a clear answer. And it's pretty much stopping my tablet development before it starts.
    Any help or pointers would be greatly appreciated.
    Thanks very much!!
    Adrian
    Tuesday, April 08, 2008 4:34 PM
  • Hi Adrian,

    You don't need to install the tablet pc sdk 1.7.

    You need juste to add Tablet Pc SDK in the reference of your project.

    I hope that work for you. 

     

    Tuesday, April 08, 2008 4:48 PM
  • Thanks, but I must still be missing something.
    I create a brand new project as type Windows Forms Application.
    Then I go to project | Add Reference...
    I look under both the .COM and .NET tabs, but can't find anything listed as "Tablet Pc SDK" as you suggest.
    The closest I can find is this: Under the .COM tab I find
    Microsoft Tablet PC COM InkAnalysis Library, version 1.0
    Microsoft Tablet PC Type Library, version 1.0

    Are these what you mean? So anyhow, I add both these. (I can't find anything else containing the word "tablet").
    Then I add
    using Microsoft.Ink;
    to my form1.cs. It gives an error saying "Ink" does not exist in namespace "Microsoft".
    Same result if I try
    using System.Windows.Ink;
    Sad

    Tuesday, April 08, 2008 5:39 PM
  • Hi,

    I just verified this in my PC.

    The exact name is microsft Tablet PC API and choose the 6.0 version.

    You find this in the .Net tab.

    If you don't find, i think you didn't install it in your PC.

     

    Tuesday, April 08, 2008 5:53 PM
  • No, it's not there. So I reinstalled Visual Studio 2008 Professional trial edition, with full install options. And I installed MSDN Library too. And it's still not there.
    Any idea how I'm supposed to install it? If it's not the Tablet SDK 1.7 I need, then what do I need to install?
    Tuesday, April 08, 2008 7:14 PM
  • Sorry I have any idea. But I think that Tablet SDK 1.7 will resolve this problem.

    I use also Visual Studio 2008 Professional edition, but it's not a trial ...

    Tuesday, April 08, 2008 7:18 PM
  • Ok, so in case it helps anyone else I think I've resolved my problem:
    I couldn't find Microsoft.Ink under the .Net tab of Project | Add Reference
    So instead, I went to the Browse tab. Browse to C:\Windows\winsxs. Then there are (3 in my case) long named folders beginning with x86_microsoft.ink....
    In the middle of the name is a 1.0, 1.7, or 6.0. I chose the 6.0 since it sounded most recent. Inside that folder is one file named Microsoft.Ink.dll.
    Choose this, and the Microsoft.Ink resource is now added to your project. Then 'using Microsoft.Ink' actually works.
    Note I did NOT need to install Tablet SDK 1.7. Everything was present from the initial (full) install of VS2008 Trial Professional. It just took some finding.
    Thanks for your help akarray.
    Tuesday, April 08, 2008 9:26 PM
  • So If I want to use InkCanvas instead of InkCollector, how could I do this most efficiently? The WPF documentation claims InkCanvas is a superset of InkCollector, but it doesn't seem to contain the DesiredPacketDescription property. I don't need stylus info in real time, so using a RealTimeStylus looks like overkill. (And I'm not sure how to do that anyway.)
    Thanks for any help.

    Wednesday, April 09, 2008 6:43 AM
  • I'm not an expert in .net But I think that InkCanvas is used in WPF project and InkCollektor for .NET project.

    WPF is more resent but I think that for you it's more easy to use inkCollector.

     

    Wednesday, April 09, 2008 11:56 AM
  • I am working on VB, and is very similar...

    Can you tell me how I put in a textbox  the position X and Y?

    Thanks

    Friday, June 18, 2010 6:49 PM
  •  

    If you want to collect packet-level time info, you will need to set the DesiredPacketDescription of the InkCollector or RealTimeStylus object to include the TimerTick property. (The default is X, Y, Pressure).  Here is some code to illustrate both stroke and packet level time-stamping:

     

    using

     

    System;

    using

     

    System.Windows.Forms;

    using

     

    Microsoft.Ink;

    namespace

     

    TestApp

    {

     

     

    class Program : Form

    {

     

     

    InkCollector myCollector;

     

     

    static Guid strokeStart = new Guid("BD5EAA3C-8905-4cc1-8C6F-50858CE1C547");

     

     

    static Guid strokeEnd = new Guid("064F487F-FA28-48d7-9EA6-D20697545275");

     

     

    public Program()

    {

     

     

    this.Height = 200;

     

     

    this.Width = 200;

    myCollector =

     

    new InkCollector(this);

     

     

    //set the DesiredPacketDescription before enabling the control

    myCollector.DesiredPacketDescription =

     

    new Guid[]{

     

     

    PacketProperty.X,

     

     

    PacketProperty.Y,

     

     

    //TimerTick shows number of milliseconds

     

     

    //between the current packet and previous packet,

     

     

    //with the first packet being zero

     

     

    PacketProperty.TimerTick};

    myCollector.Enabled =

     

    true;

    myCollector.Stroke +=

     

    new InkCollectorStrokeEventHandler(myCollector_Stroke);

    }

     

     

     

    void myCollector_Stroke(object sender, InkCollectorStrokeEventArgs e)

    {

     

     

    DateTime end = DateTime.Now;

     

     

    int[] tticks = e.Stroke.GetPacketValuesByProperty(PacketProperty.TimerTick);

     

     

    int ms = tticks[tticks.Length - 1];

     

     

    //calculate start time by subtracting final amount

     

     

    //of milliseconds from the end time

     

     

    DateTime start = end.AddMilliseconds(-(ms));

     

     

    //ExtendedProperty data must be long, string, bool or byte[]

    e.Stroke.ExtendedProperties.Add(

     

    Program.strokeStart, start.Ticks);

    e.Stroke.ExtendedProperties.Add(

     

    Program.strokeEnd, end.Ticks);

    }

     

     

     

    static void Main(string[] args)

    {

     

     

    Application.Run(new Program());

    }

     

    }

    }

     

    Hope this helps!

     

     

    How would this work to attach such time-tick properties to a Silverlight Ink app?

     

    Wednesday, July 14, 2010 2:13 AM