Yet another blog about WPF, Surface, SL, MVVM, NUI....

2010

2009

 

How to create an hand writing to text control (ink recognizer)

25 October 2010

When building a (multi)touch application you may need one nice feature : translate hand-written text to real words. This open a whole new world full of possibilities like starting some actions when keywords are recognized or simply allow the users to write some text for later use. 

In this post we'll see all the step to create an hand writing to text control and how to tune it.

Continue reading...

 

How to scale around a specific point and not the center of the Element

11 October 2009

The problem


The most popular controls which has been brought by the Microsoft SDK is certainly the scatterView. Each item is positioned at a random place with a random orientation.
ExampleOfScatterView

You can then rotate, move or scale them with your fingers. Here we will focus on this last point : the scaling. This is a really nice feature and you may wants to put it in your application (it may also be replace my a mouse wheel or stylus events, etc.).

If an user wants to zoom-in on a specific part of the presented items, he wills do a 'scale manipulation' with it's fingers on the specific part.

Simple, will you think : we just have to change the width and the height of the control based on the scale delta ! But the problem is that, the control will grow but the specific part wanted by the user will no more be under it's fingers. A figure worth a thousand words :
Schema example



My solution

Here we are going to scale a scatterViewItem with the property 'CanMove' set to false. We do it because, the scatterView item does already what we wants and this is done by a translation.


Also we are going to use a Affine2DManipulationProcessor which will gives us the scale value for a manipulation done by multiple fingers. If some are catching stylus events, you could use a ManipulationProcessor from the multiTouch SDK (available here :http://www.microsoft.com/downloads/details.aspx?FamilyID=12100526-ed26-476b-8e20-69662b8546c1&displaylang=en).

The XAML :

<s:ScatterView VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
      <s:ScatterViewItem x:Name="_myObjectToScale" Orientation="0" CanRotate="False" 
            CanScale="False" CanMove="False"
            Center="512.0,384.0"  ShowsActivationEffects="False"
            PreviewContactDown="_myObjectToScale_ContactDown" 
            PreviewContactUp="_myObjectToScale_ContactUp">
         <Image Source="Resources/myself.jpg" />
      </s:ScatterViewItem>


The code :

private Affine2DManipulationProcessor _ourManipProc;
public Affine2DManipulationProcessor OurManipProc { 
   get { return _ourManipProc; } 
   set { _ourManipProc = value; }
 }
 
public SurfaceWindow1()
{
    InitializeComponent();
    DataContext = this;
    _ourManipProc = new Affine2DManipulationProcessor(Affine2DManipulations.Scale, this);
 
    //Catch the event from our manipulation processor
    OurManipProc.Affine2DManipulationDelta += OurManipProc_Affine2DManipulationDelta;
}
 
 
private void _myObjectToScale_ContactDown(object sender, ContactEventArgs e)
{
    //this contact is tracked by ou MP
    OurManipProc.BeginTrack(e.Contact);
}
 
private void _myObjectToScale_ContactUp(object sender, ContactEventArgs e)
{
    //this contact is no more tracked by ou MP
    OurManipProc.EndTrack(e.Contact);
}



Then the important part, the Affine2DManipulationDelta handler which will do what we wants, I will describe it below.

void OurManipProc_Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
{
    double scaleDelta = e.ScaleDelta;
    if (scaleDelta == 1.0) return;
 
 
    Point manipOrigin = e.ManipulationOrigin;
    Point oldCenter = new Point(_myObjectToScale.Center.X, _myObjectToScale.Center.Y);
 
    double oldHeight = _myObjectToScale.ActualHeight;
    double newHeight = _myObjectToScale.ActualHeight * scaleDelta;
 
    double oldWidth = _myObjectToScale.ActualWidth;
    double newWidth = _myObjectToScale.ActualWidth * scaleDelta;
 
    _myObjectToScale.Height = newHeight;
    _myObjectToScale.Width = newWidth;
 
    double ratioX = Math.Abs(manipOrigin.X - oldCenter.X) / (oldWidth / 2);
    double newCenterXD = ratioX
        * Math.Sign(oldCenter.X - manipOrigin.X) * (newWidth - oldWidth) / 2;
 
    double ratioY = Math.Abs(manipOrigin.Y - oldCenter.Y) / (oldHeight / 2);
    double newCenterYD = ratioY *
        Math.Sign(oldCenter.Y - manipOrigin.Y) * (newHeight - oldHeight) / 2;
 
    if (scaleDelta > 1.0)
        _myObjectToScale.Center += new Vector(newCenterXD, newCenterYD);
    else
        _myObjectToScale.Center += new Vector(newCenterXD, newCenterYD);
}



Explanation


First we need to calculate the new size of our control. This is done by multiplying it's actual size by the scaleDelta gived by our processor.

Then we store some interesting values as the old size, the old center position, etc.

Then we calculate the ration for X and for Y. What is it ? It's ratio of the aimed point (the point on top of which the manipulation is done) and the half of the control size. But why do we need it ? Because we wants the controls to grow on each side of the aimed point, not only the one near the center. If we does not calculate this, one side of the control would stay at the same position during our manipulation. algo explanation

Next we calculate the center delta which is the translation we must operate on our control for the focused point to stay under our fingers (or mouse pointer, or stylus, whatever you wants :D).



We finaly apply all this measure to our control. That's it !

kick it on DotNetKicks.com Shout it


 

GUI to NUI : representations and manipulation of OLAP data in 3D

21 July 2009

Hello,

Here is a little post to show you a little video presenting the project I have worked on during my 6 months of training. I am very proud of it :) :



The subject was to find the new way of representations and manipulations of OLAP Data without using a keyboard or a mouse.
This is done in 3D on the Microsoft Surface plateform.

The technologies involved are :

  1. Microsoft Surface for the NUI (Natural User Interface),
  2. (M)Ogre to create the 3D World,
  3. OLAP for the acquisition of datas.




Here are some links for those interested :

  1. What is OLAP ? (wikipedia)
  2. What are the NUI ? (wikipedia)
  3. What is Ogre the 3D engine ?
  4. What is Microsoft Surface ?
  5. What is the company in which I have done my training ?



People who worked on it :

  1. Development: Jonathan ANTOINE
  2. Supervision of the project : Elise DUPONT
  3. 3D Expert : Laurent TRUDU



Enjoy !


kick it on DotNetKicks.com


Shout it
 

Calculate the real difference between two angles, keeping the correct sign

1 April 2009

When you build some animations with WPF, Surface or JavaFX you sometimes need to know how evolve an angle. For example, you have the new angle (orientation) of an object and you have store before the last measure of this orientation : how to calculate the evolution ?
calculateAnglesBetweenOrientationExemple1

A first solution

"This is simple" will you say, just do this :

double difference = secondAngle - firstAngle;

But this snippet leads to errors. This is because the orientation value given is relative to a certain initial value, and restart to 0° if you pass the 360°. Lets give you an example: if the object was oriented at 358° and the user turns it of 5° you will obtain a difference of (3-358=) -355° where you actually wants to find 5....

A better solution

A solution I propose is to consider that the methods is called enough frequently that if the object rotate to the left or to the right it has not enough time to rotate more than 180° (half a tour).

Based on this, we consider that the direction of the rotation is given by the "shortest way". If it shorter to turn to the left to go to the new angle, then we select the angle sign which tells we have turned to the left. It may be easiest to understand by looking atentivly to the image above.

An image is maybe better than word : calculateAnglesBetweenOrientationExemple2



We then have this method in C#:

private double calculateDifferenceBetweenAngles(double firstAngle, double secondAngle)
  {
        double difference = secondAngle - firstAngle;
        while (difference < -180) difference += 360;
        while (difference > 180) difference -= 360;
        return difference;
 }


A case of use

When do use it ? For example when you build a carousel: the user can click on a specific item and the carousel rotate so it is in front of you. You then need to have the correct angle. I found no other way to do it.

Does someone have a better way to proceed ?



Shout it