|
15
|
1 |
/* |
|
|
2 |
* This file is part of the TraKERS\Middleware package. |
|
|
3 |
* |
|
|
4 |
* (c) IRI <http://www.iri.centrepompidou.fr/> |
|
|
5 |
* |
|
27
|
6 |
* For the full copyright and license information, please view the LICENSE |
|
15
|
7 |
* file that was distributed with this source code. |
|
|
8 |
*/ |
|
|
9 |
|
|
|
10 |
/* |
|
|
11 |
* Projet : TraKERS |
|
|
12 |
* Module : MIDDLEWARE |
|
|
13 |
* Sous-Module : Search |
|
|
14 |
* Classe : Segmenter |
|
|
15 |
* |
|
|
16 |
* Auteur : alexandre.bastien@iri.centrepompidou.fr |
|
|
17 |
* |
|
|
18 |
* Fonctionnalités : Permet d'extraire à la volée les segments du tracé en cours. |
|
|
19 |
*/ |
|
|
20 |
|
|
|
21 |
using System; |
|
|
22 |
using System.Collections.Generic; |
|
|
23 |
using System.Linq; |
|
|
24 |
using System.Text; |
|
|
25 |
using System.Windows.Media.Media3D; |
|
|
26 |
|
|
17
|
27 |
namespace Trakers.Tracking.Search |
|
15
|
28 |
{ |
|
|
29 |
public class Segmenter |
|
|
30 |
{ |
|
|
31 |
//Stocke les positions d'une main au cours du temps. |
|
|
32 |
private List<Point3D> handPointerHistory; |
|
|
33 |
//Point précédent. |
|
|
34 |
private Point3D prevPt; |
|
|
35 |
//Ratio : on prend 1/ratio points. |
|
|
36 |
private int ratio; |
|
|
37 |
//Indique le numéro du point actuellement enregistré (pour le ratio). |
|
|
38 |
private int currentPointNumber; |
|
|
39 |
//Extremums enregistrés parmi les 3 axes pour détecter les changements de sens. |
|
|
40 |
private double Xmax, Ymax, Zmax; |
|
|
41 |
private double Xmin, Ymin, Zmin; |
|
|
42 |
//On établit une distance en nombre de points entre le point actuel l'extremum |
|
|
43 |
//local détecté dans les 3 axes (pour copier le segment : points de 0 à id de l'extremum). |
|
|
44 |
private int distToXmax, distToYmax, distToZmax; |
|
|
45 |
private int distToXmin, distToYmin, distToZmin; |
|
|
46 |
//Points critiques. |
|
|
47 |
private Point3D minPt, maxPt; |
|
|
48 |
//Tendance actuelle du tracé. |
|
|
49 |
private bool XtowardRight, YtowardUp, ZtowardFront; |
|
|
50 |
//Limites de différences à partir desquelles . |
|
|
51 |
private int directionChangeTresholdXY; |
|
|
52 |
private float directionChangeTresholdZ; |
|
|
53 |
|
|
|
54 |
/* |
|
|
55 |
* Initialisation du segmenter. |
|
|
56 |
* Coupe une courbe en deux dès qu'il repère un changement important de trajectoire. |
|
|
57 |
*/ |
|
|
58 |
public Segmenter(int _ratio) |
|
|
59 |
{ |
|
|
60 |
//directionChangeTresholdXY = kinectMain.getDirectionChangeTresholdXY(); |
|
|
61 |
//directionChangeTresholdZ = kinectMain.getDirectionChangeTresholdZ(); |
|
|
62 |
handPointerHistory = new List<Point3D>(); |
|
|
63 |
ratio = _ratio; |
|
|
64 |
currentPointNumber = 1; |
|
|
65 |
prevPt = new Point3D(0, 0, 0); |
|
|
66 |
|
|
|
67 |
Xmax = Ymax = Zmax = Xmin = Ymin = Zmin = -1; |
|
|
68 |
distToXmax = distToYmax = distToZmax = distToXmin = distToYmin = distToZmin = -1; |
|
|
69 |
} |
|
|
70 |
|
|
|
71 |
/* |
|
|
72 |
* Getters et setters. |
|
|
73 |
*/ |
|
|
74 |
public void SetRatio(int _ratio) |
|
|
75 |
{ |
|
|
76 |
ratio = _ratio; |
|
|
77 |
} |
|
|
78 |
public void SetDirectionChangeTresholdXY(int _directionChangeTresholdXY) |
|
|
79 |
{ |
|
|
80 |
directionChangeTresholdXY = _directionChangeTresholdXY; |
|
|
81 |
} |
|
|
82 |
public void SetDirectionChangeTresholdZ(float _directionChangeTresholdZ) |
|
|
83 |
{ |
|
|
84 |
directionChangeTresholdZ = _directionChangeTresholdZ; |
|
|
85 |
} |
|
|
86 |
|
|
|
87 |
public int GetRatio() |
|
|
88 |
{ |
|
|
89 |
return ratio; |
|
|
90 |
} |
|
|
91 |
public int SetDirectionChangeTresholdXY() |
|
|
92 |
{ |
|
|
93 |
return directionChangeTresholdXY; |
|
|
94 |
} |
|
|
95 |
public float SetDirectionChangeTresholdZ() |
|
|
96 |
{ |
|
|
97 |
return directionChangeTresholdZ; |
|
|
98 |
} |
|
|
99 |
|
|
|
100 |
/* |
|
|
101 |
* On charge tous les paramètres d'un coup. |
|
|
102 |
*/ |
|
|
103 |
public void setParams(int _ratio, int _directionChangeTresholdXY, float _directionChangeTresholdZ) |
|
|
104 |
{ |
|
|
105 |
ratio = _ratio; |
|
|
106 |
directionChangeTresholdXY = _directionChangeTresholdXY; |
|
|
107 |
directionChangeTresholdZ = _directionChangeTresholdZ; |
|
|
108 |
} |
|
|
109 |
|
|
|
110 |
/* |
|
|
111 |
* Enregistre le point passé en paramètre d'après le ratio. |
|
|
112 |
*/ |
|
|
113 |
public void RecordPoint(Point3D pt) |
|
|
114 |
{ |
|
|
115 |
//Indique l'ID du point à couper. |
|
|
116 |
int whereToCut; |
|
|
117 |
//Si le ratio est excédé, on peut enregistrer. |
|
|
118 |
if (currentPointNumber > ratio) |
|
|
119 |
currentPointNumber = 1; |
|
|
120 |
|
|
|
121 |
//Si le point précédent est à une position différente du point actuel. |
|
|
122 |
if(prevPt.X != pt.X || prevPt.Y != pt.Y || prevPt.Z != pt.Z) |
|
|
123 |
{ |
|
|
124 |
//Si le numéro est 1 (début ou ratio atteint), on enregistre. |
|
|
125 |
if(currentPointNumber == 1) |
|
|
126 |
handPointerHistory.Add(pt); |
|
|
127 |
|
|
|
128 |
//Si le point précédent a été initialisé avec un vrai point. |
|
|
129 |
if (prevPt.X > 0 && prevPt.Y > 0 && prevPt.Z > 0) |
|
|
130 |
{ |
|
|
131 |
//Appel aux detecteurs d'extremums. |
|
|
132 |
if ((whereToCut = DetectDirectionChangeAtXAxis(pt)) > 0) |
|
|
133 |
Segment(whereToCut); |
|
|
134 |
else if((whereToCut = DetectDirectionChangeAtYAxis(pt)) > 0) |
|
|
135 |
Segment(whereToCut); |
|
|
136 |
else if ((whereToCut = DetectDirectionChangeAtZAxis(pt)) > 0) |
|
|
137 |
Segment(whereToCut); |
|
|
138 |
} |
|
|
139 |
//On met à jour le point précédent. |
|
|
140 |
prevPt = pt; |
|
|
141 |
//On passe au numéro suivant (jusqu'à atteindre le ration plus tard). |
|
|
142 |
currentPointNumber++; |
|
|
143 |
} |
|
|
144 |
} |
|
|
145 |
|
|
|
146 |
/* |
|
|
147 |
* Détecte un changement de sens (extremum) dans l'axe X. |
|
|
148 |
*/ |
|
|
149 |
public int DetectDirectionChangeAtXAxis(Point3D pt) |
|
|
150 |
{ |
|
|
151 |
//ID où couper en cas d'extremum. |
|
|
152 |
int whereToCut = -1; |
|
|
153 |
|
|
|
154 |
//Mise à jour des extremums. |
|
|
155 |
if (Xmax == -1 || Xmax < pt.X) |
|
|
156 |
{ |
|
|
157 |
//Si le point est plus grand en X que Xmax, alors il est remplacé et on réinitialise la |
|
|
158 |
//distance au dernier maximum en X. |
|
|
159 |
Xmax = pt.X; |
|
|
160 |
maxPt = pt; |
|
|
161 |
distToXmax = 0; |
|
|
162 |
} |
|
|
163 |
else |
|
|
164 |
distToXmax++; |
|
|
165 |
if (Xmin == -1 || Xmin > pt.X) |
|
|
166 |
{ |
|
|
167 |
//Si le point est plus petit en X que Xmin, alors il est remplacé et on réinitialise la |
|
|
168 |
//distance au dernier minimum en X. |
|
|
169 |
Xmin = pt.X; |
|
|
170 |
minPt = pt; |
|
|
171 |
distToXmin = 0; |
|
|
172 |
} |
|
|
173 |
else |
|
|
174 |
distToXmin++; |
|
|
175 |
|
|
|
176 |
//Si X max est plus grand que la position actuelle additionnée du seuil |
|
|
177 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
178 |
if (Xmax > pt.X + directionChangeTresholdXY && maxPt != handPointerHistory.First()) |
|
|
179 |
whereToCut = currentPointNumber - distToXmax; |
|
|
180 |
//Si X min est plus petit que la position actuelle à laquelle on a retiré le seuil |
|
|
181 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
182 |
if (Xmin < pt.X - directionChangeTresholdXY && minPt != handPointerHistory.First()) |
|
|
183 |
whereToCut = currentPointNumber - distToXmin; |
|
|
184 |
|
|
|
185 |
return whereToCut; |
|
|
186 |
} |
|
|
187 |
|
|
|
188 |
/* |
|
|
189 |
* Détecte un changement de sens (extremum) dans l'axe Y. |
|
|
190 |
*/ |
|
|
191 |
public int DetectDirectionChangeAtYAxis(Point3D pt) |
|
|
192 |
{ |
|
|
193 |
//ID où couper en cas d'extremum. |
|
|
194 |
int whereToCut = -1; |
|
|
195 |
|
|
|
196 |
//Mise à jour des extremums. |
|
|
197 |
if (Ymax == -1 || Ymax < pt.Y) |
|
|
198 |
{ |
|
|
199 |
//Si le point est plus grand en Y que Ymax, alors il est remplacé et on réinitialise la |
|
|
200 |
//distance au dernier maximum en Y. |
|
|
201 |
Ymax = pt.Y; |
|
|
202 |
maxPt = pt; |
|
|
203 |
distToYmax = 0; |
|
|
204 |
} |
|
|
205 |
else |
|
|
206 |
distToYmax++; |
|
|
207 |
if (Ymin == -1 || Ymin > pt.Y) |
|
|
208 |
{ |
|
|
209 |
//Si le point est plus petit en Y que Ymin, alors il est remplacé et on réinitialise la |
|
|
210 |
//distance au dernier minimum en Y. |
|
|
211 |
Ymin = pt.Y; |
|
|
212 |
minPt = pt; |
|
|
213 |
distToYmin = 0; |
|
|
214 |
} |
|
|
215 |
else |
|
|
216 |
distToYmin++; |
|
|
217 |
|
|
|
218 |
//Si Y max est plus grand que la position actuelle additionnée du seuil |
|
|
219 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
220 |
if (Ymax > pt.Y + directionChangeTresholdXY && maxPt != handPointerHistory.First()) |
|
|
221 |
whereToCut = currentPointNumber - distToYmax; |
|
|
222 |
//Si Y min est plus petit que la position actuelle à laquelle on a retiré le seuil |
|
|
223 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
224 |
if (Ymin < pt.Y - directionChangeTresholdXY && minPt != handPointerHistory.First()) |
|
|
225 |
whereToCut = currentPointNumber - distToYmin; |
|
|
226 |
|
|
|
227 |
return whereToCut; |
|
|
228 |
} |
|
|
229 |
|
|
|
230 |
/* |
|
|
231 |
* Détecte un changement de sens (extremum) dans l'axe Z. |
|
|
232 |
*/ |
|
|
233 |
public int DetectDirectionChangeAtZAxis(Point3D pt) |
|
|
234 |
{ |
|
|
235 |
//ID où couper en cas d'extremum. |
|
|
236 |
int whereToCut = -1; |
|
|
237 |
|
|
|
238 |
//Mise à jour des extremums. |
|
|
239 |
if (Zmax == -1 || Zmax < pt.Z) |
|
|
240 |
{ |
|
|
241 |
//Si le point est plus grand en Z que Ymax, alors il est remplacé et on réinitialise la |
|
|
242 |
//distance au dernier maximum en Z. |
|
|
243 |
Zmax = pt.Z; |
|
|
244 |
maxPt = pt; |
|
|
245 |
distToZmax = 0; |
|
|
246 |
} |
|
|
247 |
else |
|
|
248 |
distToZmax++; |
|
|
249 |
if (Zmin == -1 || Zmin > pt.Z) |
|
|
250 |
{ |
|
|
251 |
//Si le point est plus petit en Z que Zmin, alors il est remplacé et on réinitialise la |
|
|
252 |
//distance au dernier minimum en Z. |
|
|
253 |
Zmin = pt.Z; |
|
|
254 |
minPt = pt; |
|
|
255 |
distToZmin = 0; |
|
|
256 |
} |
|
|
257 |
else |
|
|
258 |
distToZmin++; |
|
|
259 |
|
|
|
260 |
//Si Z max est plus grand que la position actuelle additionnée du seuil |
|
|
261 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
262 |
if (Zmax > pt.Z + directionChangeTresholdXY && maxPt != handPointerHistory.First()) |
|
|
263 |
whereToCut = currentPointNumber - distToZmax; |
|
|
264 |
//Si Z min est plus petit que la position actuelle à laquelle on a retiré le seuil |
|
|
265 |
//et que l'extremum n'est pas le premier point sauvegardé. |
|
|
266 |
if (Zmin < pt.Z - directionChangeTresholdXY && minPt != handPointerHistory.First()) |
|
|
267 |
whereToCut = currentPointNumber - distToZmin; |
|
|
268 |
|
|
|
269 |
return whereToCut; |
|
|
270 |
} |
|
|
271 |
|
|
|
272 |
/* |
|
|
273 |
* Découpe le tracé en cours en segment allant du premier point au premier extremum trouvé. |
|
|
274 |
*/ |
|
|
275 |
public void Segment(int whereToCut) |
|
|
276 |
{ |
|
|
277 |
handPointerHistory.RemoveRange(0, whereToCut); |
|
|
278 |
currentPointNumber -= whereToCut; |
|
|
279 |
} |
|
|
280 |
} |
|
|
281 |
} |