TransformationsPJE Multi-touch
Fabrice [email protected]
Master Informatique
UFR IEEA
2016-2017
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 1 / 34
1 Objectifs
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 2 / 34
Placer un composant
I Géométrie d’un composant : OBB (Oriented Bounded Box)
I Placer le composant = placer son OBB⇒ donner sa position/son orientation/sesdimensions
public class OBB {Point2 p o s i t i o n ; / / / o r i g i n p o s i t i o n o f the OBBdouble angle ; / / / r o t a t i o n around o r i g i ndouble width , he igh t ; / / / dimensions
. . .}
I Interaction = transformer l’OBB selon la position de deux curseurs. Contrainte = chaquecurseur doit rester « fixe »par rapport à l’image.
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 3 / 34
Interprétation du placement par changement de repère
Le repère 2 est placé dans le repère 1 en déplaçant 1 vers 2 (on dit qu’on passe du repère 1 au repère 2, et sera noté
M1→2) :
1 En faisant une translation (donnée par le champs position) notée T
2 Puis une rotation autour de l’origine actuelle (l’angle est donné par angle) notée R
3 Puis un changement d’échelle (l’axe x actuel est multiplié par width, l’axe actuel y parheight) notée S.
4 ⇒ on note ainsi le passage de 1 vers 2 : M1→2 = TRS.F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 4 / 34
Interprétation du placement par changement de repère
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 5 / 34
Remarque : 2 interprétations relatives des changements derepère
⇒ P1 = M1→2P2
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 6 / 34
2 Placement et tracé en JAVA 2D
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 7 / 34
Tracé en déplaçant un repère courant
L’approche permet de mieux découpler la définition d’un objet et son placement.
I On définit l’objet dans un repère qui permet de le définir le plus aisément possible (repèredit repère local).
I On place le repère local où on souhaite en déplaçant le repère courant en partant d’unrepère initial (pour Java2D : en haut à gauche) : on définit ainsi Tinitial→local
I En rêgle générale : le repère courant est déplacé par compositions successives detranslations, rotations, et changements d’échelle.
I Lorsque l’objet est tracé, ses coordonnées sont interprétées dans le repère courant.
I C’est la librairie qui applique automatiquement Tinitial→local pour exprimer les coordonnéesdans le repère initial et ainsi exécuter le tracé (les algorithmes de tracé étant définis dans lerepère initial de la librairie).
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 8 / 34
Exemples en JAVA 2D
public void draw ( Graphics2D g , double angle ) {/ / sauvegarde du ( changement de ) repère courant ( c r é a t i on d ’ une copie )/ / ( é v i t e les e f f e t s de bord sur l e repère courant )Af f ineTransform save=g . getTransform ( ) ;
g . t r a n s l a t e (256 ,256) ; / / passage en 1g . r o t a t e ( angle ) ; / / passage en 2g . t r a n s l a t e (30 ,30 ) ; / / passage en 3
g . drawImage ( img ,0 ,0 ,150 ,150 , nul l ) ; / / dans repère courant
/ / r e s t i t u e r l e repère l o r s de l ’ en t r ée dans draw/ / ( é v i t e les e f f e t s de bord sur l e repère courant )g . setTransform ( save ) ;
}
public void draw ( Graphics2D g , double angle ) {Af f ineTransform save=g . getTransform ( ) ;
g . t r a n s l a t e (256 ,256) ; / / passage en 1g . t r a n s l a t e (30 ,30 ) ; / / passage en 2g . r o t a t e ( angle ) ; / / passage en 3
g . drawImage ( img ,0 ,0 ,150 ,150 , nul l ) ;
g . setTransform ( save ) ;}
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 9 / 34
Exemples en JAVA 2D
public void draw ( Graphics2D g , double angle ) {/ / sauvegarde du repère courant ( c r é a t i on d ’ une copie )Af f ineTransform save=g . getTransform ( ) ;
g . t r a n s l a t e (256 ,256) ;g . t r a n s l a t e (75 ,75 ) ;g . r o t a t e ( angle ) ;g . t r a n s l a t e (−75,−75);
g . drawImage ( img ,0 ,0 ,150 ,150 , nul l ) ;
/ / r e s t i t u e r l e repère à l ’ en t r ée de drawg . setTransform ( save ) ;
}
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 10 / 34
Représentation des changements de repère par matrice
I Les librairies graphiques utilisent (généralement) un outil mathématique pour représenter etstocker tout changement de repère par une matrice unique : les coordonnées homogènes.
I Passer en coordonnées homogènes :
P2D =
(xy
)⇐⇒ PH =
xwyww
avec w ∈ R∗(cad w 6= 0)I Repasser en 2D :
PH =
xyw
⇐⇒ P2D = ( x/wy/w)
I Changement de repères : P1 = M1→2P2, M1→2 étant une matrice 3×3.I Exemples :
T =
1 0 tx0 1 ty0 0 1
R =
cosθ −sinθ 0sinθ cosθ 00 0 1
S = kx 0 00 ky 0
0 0 1
Translation Rotation Scale
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 11 / 34
Composition
La composition des changements de repère consiste à multiplier les matrices. Exemples :
I Ma→c = Ma→bMb→cI Ma→d = Ma→bMb→cMc→dI M1→2 = TRS.
I Déplacement du repère courant de old à new : Minitial→new = Minitial→old Mold→new
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 12 / 34
En JAVA 2D
I Chaque environement graphique (Graphics2D g) dispose d’une matrice homogène Minitial→couranttraduisant le passage du repère initial au repère courant (obtenue par g.getTransform()).
I Lorsque Java2D trace (draw, fill, ...) tout point P = (x ,y) (interprété dans le repèrecourant : P = Pcourant ), P subit la matrice pour obtenir Pinitial = Minitial→courant Pcourant
I On modifie, à loisir, la matrice courante pour positionner les objets à tracer (translate,rotate, scale par exemple).
I Exemple : g. translate(10,20) modifie la matrice courante en la multipliant à droite par la matrice
de translation T =
1 0 100 1 200 0 1
I Remarque : on peut affecter directement le repère courant par g.setTransform(a00,a10,a01,a11,a02,a12) :
Minitial→courant =
a00 a01 a02a10 a11 a120 0 1
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 13 / 34
Tracer un composant avec changement de repère
I Placement d’un composant exprimé dans le repère de son container (repère 0) :
public class OBB {private Point2 p o s i t i o n ;private double angle ;private double width , he igh t ;
. . .}
public class MTComponent {private OBB geom ;
. . .}
I Tracer les composants d’un container :
public void draw ( Graphics2D g ) {Af f ineTransform save=g . getTransform ( ) ; / / mé mor isa t ion du repère courant ( repère du con ta ine r )
for (MTComponent c : content ) { / / content = l i s t e des composantsg . t r a n s l a t e ( c . p o s i t i o n ( ) . x , c . p o s i t i o n ( ) . y ) ;g . r o t a t e ( c . angle ( ) ) ;/ / pourquoi pas l e scale avec width e t he igh t ? => r e p o r t sur drawImage ( . . . , width , he ight , . . . )c . draw ( g ) ; / / t r a c e r c dans son repère l o c a lg . setTransform ( save ) ; / / on r e v i e n t au repère du con ta ine r
}}
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 14 / 34
3 Sélection d’un composant
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 15 / 34
Localiser un point dans une OBB (1/2)
I Sélection d’un composant = lors d’un "addCursor(x,y)" on doit déterminer à quelcomposant correspond (x ,y) (exprimé dans le repère initial).
I Donnée : un point P(x ,y) dans le repère initial 0 (curseur en coordonnée pixel).
I Problème : à quel composant appartient P ?
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 16 / 34
Localiser un point dans une OBB (2/2)
I une OBB est un carré défini dans un repère local 1 dont on a fait subir M0→1 = TRS pourle placer par rapport au repère initial 0 (T donnée par le champ position, R par angle, etS par width,height).
I il est plus aisé de tester l’appartenance du point P dans le carré⇒ on exprime donc Pdans 1 par P1 = M1→0P0.
I or on connait M0→1 (placement de l’OBB) et non M1→0 (passage inverse) :
• Cas général : il faut inverser Mp→q pour obtenir Mq→p .• Cas d’une Composition : l’inverse de Mp→qMq→r est Mr→qMq→p• Par ailleurs T−1 =−T , R−1(θ) = R(−θ) et S−1(kx ,ky ) = S( 1kx ,
1ky).
I On a donc M1→0 = S−1R−1T−1 et on a le curseur dans le repère du carré (repère localde l’OBB) par P1 = M1→0P0
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 17 / 34
Appliquer un changement de repère à un point en JAVA 2D
On utilise la classe AffineTransform pour exprimer n’importe quel changement de repère et l’appliquer aux pointssouhaités :
/ / Prob lème : curseur dans l e repère g loba l => l ’ expr imer dans l e repère l o c a l d ’ une bo i t e OBBAf f ineTransform obbToWorld=new Af f ineTransform ( ) ; / / changement de repèreobbToWorld . s e t T o I d e n t i t y ( ) ;obbToWorld . sca le ( 1 . 0 / obb . width , 1 . 0 / obb . he igh t ) ;obbToWorld . r o t a t e (−obb . angle ) ;obbToWorld . t r a n s l a t e (−obb . p o s i t i o n . x,−obb . p o s i t i o n . y ) ;Point2D curseur2=new Point2D . Double ( curseur . x , curseur . y ) ; / / cast dans l e type Point2D (JAVA 2D)Point2D curseurOBB=new Point2D . Double ( ) ; / / con t iendra l e curseur dans l e repère l o c a l de OBBobbToWorld . t rans form ( curseur2 , curseurOBB ) ; / / méthode JAVA 2D : app l ique r l e changement de repère au po in t curseur2
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 18 / 34
Superposition des composants
I L’ordre dans la liste des composants définit l’ordre d’affichage (le premier à l’arrière-plan),ou profondeur d’affichage.
I Si il y a superposition de composants lors d’une sélection⇒ le composant sélectionné estcelui qui est visible (i.e. le moins profond).
I Une fois sélectionné, le composant passe à l’avant plan.
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 19 / 34
4 Mouvement d’un composant
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 20 / 34
Problème
I 2 curseurs sur l’image : A et B.
I Attacher l’image aux curseurs (l’image doit rester fixe par rapport aux curseurs).
I Mouvement des curseurs : A déplacé en A′ et B en B′.
I Où est placée l’image résultante ?
public class OBB {private Point2 p o s i t i o n ; / / = o r i g i n e = P0 sur l e schéma, mais peut correspondre à un aut re po in tprivate double angle ;private double width , he igh t ;
. . .}
I Problème = comment modifier position, angle, width et height en fonction dudéplacement des curseurs (AB) sur (A′B′)?
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 21 / 34
Transformation du segment AB
I On "attache" AB à un repère 1 (l’origine de 1 est A) et on exprime le changement de repèreM1→2 pour aller en A′B′ (l’origine de 2 est A′) :
I T = translation de vecteur AA′.
I puis R = rotation d’angle ? (on détaille le calcul plus loin : transparent 31).
I puis S = rapport des longueurs entre AB et A′B′.
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 22 / 34
Transformation de l’image
I Curseurs fixes par rapport à l’image = on "attache" l’image au repère 1.
• Changement d’échelle de l’image = changement d’échelle du segment (⇒ width etheight multiplié par S).
• Rotation de l’image = rotation du segment ("tourne" d’un angle θ).• Translation de l’image = comment passe t-on de l’origine P0 à l’origine P′0 en fonction
du mouvement de AB en A′B′ ? (plus délicat)
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 23 / 34
Calcul de la nouvelle position de l’OBB
I le repère 2 correspond au mouvement du repère 1 lorsque AB bouge en A′B′.
I attacher l’image et les curseurs au repère 1 lorsqu’il est déplacé sur le repère 2 signifie queles coordonnées restent identiques entre les 2 repères.
I ⇒ les coordonnées de P′,A′ et B′ exprimées dans le repère 2 sont donc les même quecelles de P,A et B exprimées dans le repère 1.
I Autrement dit : P′2 = P1.
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 24 / 34
Calcul de la nouvelle position de l’OBB (2)
On résout alors par changement de repères pour trouver P ′0 à partir de P0 :
I P′0 = M0→1M1→2P′2 avec P
′2 = P1 (car image attachée au repère : cf transparent
précédent et figure).
I et P1 = M1→0P0I ⇒ P′0 = M0→1M1→2M1→0P0.I M0→1 = est la translation de vecteur A (et donc M1→0 = translation de vecteur −A)I et M1→2 correspond à la transformation de AB en A′B′ (cf transparent 22 : M1→2 = TRS).
I (la translation de l’image est donc T = P′0−P0).
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 25 / 34
Utiliser les transformations JAVA 2D pour calculer P’0
/ / curseurs (A,B) se dé p lacent en (A ’ ,B ’ ) : comment c a l c u l e r P ’0 du à p a r t i r de P0 ?
Af f ineTransform transform=new Af f ineTransform ( ) ;
/ / passage de 0 à 1 du schémat rans form . se tToTrans la t ion (A . x ,A . y ) ;
/ / passage de 1 à 2 ( t r an fo rma t i on du segment )t rans form . t r a n s l a t e (A ’ . x− A. x ,A ’ . y−A. y ) ; / / t r a n s l a t i o n de A à A ’t rans form . r o t a t e ( angle ) ; / / angle ent re [AB] e t [A ’B ’ ] ( v o i r t ransparen t su ivan t )t rans form . scale ( scale , sca le ) ; / / sca le = rappor t des longueurs ent re [A ’B ’ ] e t [AB]
/ / passage de 1 à 0t rans form . t r a n s l a t e (−A. x,−A. y ) ;
/ / a p p l i c a t i o n à P0Point2D P0=new Point2D . Double ( obb . p o s i t i o n ( ) . x , obb . p o s i t i o n ( ) . y ) ; / / cast en Point2D de javaPoint2D Pp0=new Point2D . Double ( ) ; / / con t iendra P ’0t rans form . t rans form (P0 , Pp0 ) ; / / on a Pp0 : res te à f a i r e l a d i f f érence Pp0−P0 pour avo i r l e vecteur de t r a n s l a t i o n
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 26 / 34
Calcul de l’angle de rotation
I On utilise le produit scalaire entre AB et A′B′, car AB ·A′B′ = ‖AB‖‖A′B′‖cosθ.
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 27 / 34
Produit scalaire
Soient u =
(uxuy
), v =
(vxvy
), le produit scalaire u · v (appelé dot en anglais) est le nombre donné par :
I u · v = ux vx +uy vy (Calcul par coordonnées)I u · v = ‖u‖‖v‖cos(u,v) (Calcul par cosinus)
Relation avec la norme (la « longueur ») du vecteur u :
I Norme (euclidienne) : ‖u‖=√
u ·u =√ux ux +uy uyI Remarque : Normer u consiste à « rendre »le vecteur u de norme 1 : u′ = u‖u‖
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 28 / 34
Produit scalaire : interprétation
I Projection du vecteur v sur u :• u · v = u ·h• ‖h‖= |u·v |‖u‖• Si u est unitaire : h = (u.v)u
I Localisation relative des vecteurs u et v :
u · v = 0 (orthonormal) u · v > 0 (aigu) u · v < 0 (obtus)I Si u et v sont de norme 1 :
• u · v = cos(u,v)• acos(u · v) donne un angle dans [0,π].• ⇒ le produit scalaire ne suffit pas à lui seul :
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 29 / 34
Déterminant
I Calcul :
Soient u =
(uxuy
), v =
(vxvy
), le déterminant est donné par le nombre :
det(u,v) = ux vy −uy vx
Remarque : il s’agit de la 3ième coordonnée du produit vectoriel entre
uxuyuz = 0
et vxvyvz = 0
I Interprétation :
det(u,v)> 0 det(u,v)< 0 det(u,v) = 0u vers v : dans le sens direct u vers v : dans le sens indirect
appliquer θ appliquer -θ
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 30 / 34
Pour résumer le calcul de l’angle de rotation
I u = AB, v = A′B′
I On norme u et v ⇒ u · v = cos(θ)⇒ θ = acos(u · v)I Calculer det(u,v) pour savoir si θ est négatif ou positif (i.e. si négatif, prendre −θ comme
angle de rotation).
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 31 / 34
5 Résumé de la transformation del’image issue du mouvement des deux
curseurs
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 32 / 34
Rappel du problème
I 2 curseurs sur l’image : A et B.
I Mouvement des curseurs : A déplacé en A′ et B en B′.
public class OBB {private Point2 p o s i t i o n ;private double angle ;private double width , he igh t ;
. . .}
⇒ Comment modifier position, angle, width et height en fonction du déplacement de (AB) sur (A′B′)?
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 33 / 34
Résumé de la (d’une) solution complête
I Dans le projet, l’événement provoqué par le mouvement de 2 curseurs A et B sur uneimage est paramétré par les valeurs Tevent , Revent et Sevent :
• Sevent est le rapport‖A′B′‖‖AB‖ (scale).
• Revent est l’angle entre AB et A′B′ (cf transparent 31) (rotation)• Tevent est le vecteur P′0−P0 (cf transparents 25 et 26) (translation)
I Si l’image répond à cet événement (listener actif), on modifie ses champs :
• les champs width et height : on les multiplie par Sevent• le champ angle : on lui ajoute Revent• le champ position : on lui ajoute Tevent
F. Aubert (MS1) PJE MultiTouch/ Transformations 2016-2017 34 / 34
Placement et tracé en JAVA 2DSélection d'un composantMouvement d'un composantRésumé de la transformation de l'image issue du mouvement des deux curseurs