]> git.llucax.com Git - z.facultad/75.07/algowars.git/blob - src/modelo/Vectores.pas
Import inicial después del "/var incident". :(
[z.facultad/75.07/algowars.git] / src / modelo / Vectores.pas
1 {** Es la implementación de un vector físico. Esta clase es el esqueleto de\r
2     la aplicación ya que todas las velocidades y posiciones son del tipo cVector.\r
3     Todos los calculos de movimientos, distancias, etc. se manejan con los metodos de esta clase<br>\r
4     <i>Cambios:</i>\r
5     <PRE>\r
6     05/10/00: Se corrigió el método mAddModulo para que al verificar el signo del modulo resultante,\r
7               si es negativo, setee el modulo a cero.\r
8     28/10/00: Se cambiaron todos los metodos en los que se realizan operaciones con el vector para\r
9               que devulvan un puntero a si mismo (para poder hacer asignaciones luego de la operacion).\r
10               Ahora todos los métodos son funciones\r
11     </PRE>}\r
12 unit Vectores;\r
13 \r
14 interface\r
15 \r
16 uses\r
17   ObjetoPersistente,\r
18   Tipos;\r
19 \r
20 type\r
21   {** La clase cVector es la implementación de un vector físico. Esta clase es el esqueleto de\r
22       la aplicación ya que todas las velocidades y posiciones son del tipo cVector.\r
23       Todos los calculos de movimientos, distancias, etc. se manejan con los metodos de esta clase}\r
24   cVector = class( cObjetoPersistente )\r
25     private\r
26       aX: tLongitud; // Componente del vector en X\r
27       aY: tLongitud; // Componente del vector en Y\r
28       aZ: tLongitud; // Componente del vector en Z\r
29     public\r
30       {** Constructor}\r
31       constructor create( x: tLongitud = 0; y: tLongitud = 0; z: tLongitud = 0 ); overload;\r
32       {** Constructor que copia los atributos de un Vector existente}\r
33       constructor create( v: cVector ); overload;\r
34       {$IFDEF DebugAlgoWars}\r
35       {** Método heredado que devuelve un string con el estado del Objeto. Se utiliza para depurar\r
36           y la información entregada depende del parámetro tDebugInfo.}\r
37       function mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string; override;\r
38       {$ENDIF}\r
39       {** Convierte el vector en un versor (norma 1)}\r
40       function mHacerVersor: cVector;\r
41       {** Establece los valores del vector x, y, z}\r
42       function mSet( x, y, z: tLongitud ): cVector; overload;\r
43       {** Modifica las componentes del vector basandose en otro}\r
44       function mSet( v: cVector ): cVector; overload;\r
45       {** Setea la componente X}\r
46       function mSetX( x: tLongitud ): cVector;\r
47       {** Setea la componente Y}\r
48       function mSetY( y: tLongitud ): cVector;\r
49       {** Setea la componente Z}\r
50       function mSetZ( z: tLongitud ): cVector;\r
51       {** Agrega un valor a la componente X}\r
52       function mAddX( x: tLongitud ): cVector;\r
53       {** Agrega un valor a la componente Y}\r
54       function mAddY( y: tLongitud ): cVector;\r
55       {** Agrega un valor a la componente Z}\r
56       function mAddZ( z: tLongitud ): cVector;\r
57       {** Setea el modulo del vector a un valor determinado}\r
58       function mSetModulo( modulo: tLongitud ): cVector;\r
59       {** Aumenta (o disminuye si el argumente es negativo) el modulo del vector}\r
60       function mAddModulo( modulo: tLongitud ): cVector;\r
61       {** Obtiene la componente X}\r
62       function mGetX: tLongitud;\r
63       {** Obtiene la componente Y}\r
64       function mGetY: tLongitud;\r
65       {** Obtiene la componente Z}\r
66       function mGetZ: tLongitud;\r
67       {** Obtiene el modulo del vector}\r
68       function mGetModulo: tLongitud;\r
69       {** Suma a si mismo el vector vec}\r
70       function mSumar( vec: cVector ): cVector;\r
71       {** Resta a si mismo el vector vec}\r
72       function mRestar( vec: cVector ): cVector;\r
73       {** Se multiplica vectorialmente a si mismo por el vector vec}\r
74       function mMultiplicar( vec: cVector ): cVector; overload;\r
75       {** Se multiplica por un escalar}\r
76       function mMultiplicar( esc: tLongitud ): cVector; overload;\r
77       {** Obtiene el producto escalar entre si mismo y el vector vec}\r
78       function mMultiplicarEsc( vec: cVector ): tLongitud;\r
79       {** Obtiene la distancia al a otro vector}\r
80       function mGetDistancia( vec: cVector ): tLongitud;\r
81       {** Modifica el vector con basandose en otro vector (pensado como velocidad) y un\r
82           intervalo de tiempo siguiendo la formula física X' = X + V * dt\r
83           (este metodo esta pensado basicamente para calcular los movimientos)}\r
84       function mModificarCon( vel: cVector; dT: tTiempo ): cVector;\r
85       // SERIALIZACION\r
86       {** Devuelve una cadena de texto con el objeto serializado.}\r
87       function mSerializar: string; override;\r
88       {** Recrea el objeto a partir de una cadena de texto con el objeto\r
89           serializado.}\r
90       procedure mDesSerializar( str: string ); override;\r
91   end;\r
92 \r
93 implementation\r
94 \r
95 uses\r
96   Sysutils,\r
97   RegExpr,\r
98   Math;\r
99 \r
100 { cVector }\r
101 \r
102 {** Crea un nuevo vector basandose en los atributos de uno existente.\r
103     @param v Vector a copiar}\r
104 constructor cVector.create(v: cVector);\r
105 begin\r
106   inherited create;\r
107   // Usa el metodo mSet para establecer los valores\r
108   mSet( v );\r
109 end;\r
110 \r
111 {** Crea un nuevo vector basandose en los atributos dados como parámetro.\r
112     @param x Componente en el eje X\r
113     @param y Componente en el eje Y\r
114     @param z Componente en el eje Z}\r
115 constructor cVector.create(x, y, z: tLongitud);\r
116 begin\r
117   inherited create;\r
118   // Usa el metodo mSet para establecer los valores\r
119   mSet( x, y, z );\r
120 end;\r
121 \r
122 {** Setea el modulo del vector a un valor determinado (sólo tiene sentido si el modulo actual es distinto de cero)\r
123     @param modulo Modulo a adherir al verctor}\r
124 function cVector.mAddModulo(modulo: tLongitud): cVector;\r
125 begin\r
126   // Disminuye el módulo sólo si el resultante no es negativo\r
127   if (mGetModulo + modulo) <= 0 then // Si el modulo resultante es negativo o cero\r
128     mSetModulo( 0 ) // Setea el modulo en 0\r
129   else // Si el modulo resultante es positivo\r
130     mSetModulo( mGetModulo + modulo );\r
131   result := self;\r
132 end;\r
133 \r
134 {** Agrega un valor a la componente X\r
135     @param x Valor a sumarle a la componente X}\r
136 function cVector.mAddX(x: tLongitud): cVector;\r
137 begin\r
138   aX := aX + x;\r
139   result := self;\r
140 end;\r
141 \r
142 {** Agrega un valor a la componente Y\r
143     @param y Valor a sumarle a la componente Y}\r
144 function cVector.mAddY(y: tLongitud): cVector;\r
145 begin\r
146   aY := aY + y;\r
147   result := self;\r
148 end;\r
149 \r
150 {** Agrega un valor a la componente Z\r
151     @param z Valor a sumarle a la componente Z}\r
152 function cVector.mAddZ(z: tLongitud): cVector;\r
153 begin\r
154   aZ := aZ + z;\r
155   result := self;\r
156 end;\r
157 \r
158 {** Obtiene el modulo del vector\r
159     @return Modulo (o norma) del vector}\r
160 function cVector.mGetModulo: tLongitud;\r
161 begin\r
162   // Devuelve la raiz cuadrada de la suma de los cuadrados de las componentes\r
163   result := sqrt( sqr( aX ) + sqr( aY ) + sqr( aZ ) );\r
164 end;\r
165 \r
166 {** Obtiene la componente X\r
167     @return Componente X del vector}\r
168 function cVector.mGetX: tLongitud;\r
169 begin\r
170   result := aX;\r
171 end;\r
172 \r
173 {** Obtiene la componente Y\r
174     @return Componente Y del vector}\r
175 function cVector.mGetY: tLongitud;\r
176 begin\r
177   result := aY;\r
178 end;\r
179 \r
180 {** Obtiene la componente Z\r
181     @return Componente Z del vector}\r
182 function cVector.mGetZ: tLongitud;\r
183 begin\r
184   result := aZ;\r
185 end;\r
186 \r
187 {** Se multiplica vectorialmente a si mismo por el vector vec\r
188     @param vec Vector por el cual se multiplica vectorialmente}\r
189 function cVector.mMultiplicar(vec: cVector): cVector;\r
190 var\r
191   x,\r
192   y,\r
193   z: tLongitud;\r
194 begin\r
195   // Obtiene el resultado siguiendo la formula de producto vectorial\r
196   x  := aY * vec.mGetZ - aZ * vec.mGetY;\r
197   y  := aX * vec.mGetZ - aZ * vec.mGetX;\r
198   z  := aX * vec.mGetY - aY * vec.mGetX;\r
199   aX := x;\r
200   aY := y;\r
201   aZ := z;\r
202   result := self;\r
203 end;\r
204 \r
205 {** Se multiplica por un escalar\r
206     @param esc Escalar por el cual se multiplica}\r
207 function cVector.mMultiplicar(esc: tLongitud): cVector;\r
208 begin\r
209   // Multiplica cada componente por el escalar\r
210   aX := aX * esc;\r
211   aY := aY * esc;\r
212   aZ := aZ * esc;\r
213   result := self;\r
214 end;\r
215 \r
216 {** Obtiene el producto escalar entre si mismo y el vector vec\r
217     @return      Producto escalar entre los vectores\r
218     @param   vec Vector por el cual se multiplica escalarmente}\r
219 function cVector.mMultiplicarEsc(vec: cVector): tLongitud;\r
220 begin\r
221   // Realiza el producto escalar (suma el producto componente a componente)\r
222   result := aX * vec.mGetX + aY * vec.mGetY + aZ * vec.mGetZ;\r
223 end;\r
224 \r
225 {** Resta a si mismo el vector vec\r
226     @param vec Vector que se resta}\r
227 function cVector.mRestar(vec: cVector): cVector;\r
228 begin\r
229   aX := aX - vec.mGetX;\r
230   aY := aY - vec.mGetY;\r
231   aZ := aZ - vec.mGetZ;\r
232   result := self;\r
233 end;\r
234 \r
235 {** Setea el modulo del vector a un valor determinado\r
236     @param modulo Valor del nuevo Módulo}\r
237 function cVector.mSetModulo(modulo: tLongitud): cVector;\r
238 begin\r
239   // Primero lo convertimos en un versor\r
240   mHacerVersor;\r
241   // Ahora multiplicamos el versor por la modulo deseada\r
242   mMultiplicar( modulo );\r
243   result := self;\r
244 end;\r
245 \r
246 {** Modifica las componentes del vector basandose en otro\r
247     @param v Vector del cual se obtendran los nuevos atributos}\r
248 function cVector.mSet(v: cVector): cVector;\r
249 begin\r
250   aX := v.mGetX;\r
251   aY := v.mGetY;\r
252   aZ := v.mGetZ;\r
253   result := self;\r
254 end;\r
255 \r
256 {** Establece las componentes del vector\r
257     @param x Nuevo valor de la componente en el eje X\r
258     @param y Nuevo valor de la componente en el eje Y\r
259     @param z Nuevo valor de la componente en el eje Z}\r
260 function cVector.mSet(x, y, z: tLongitud): cVector;\r
261 begin\r
262   aX := x;\r
263   aY := y;\r
264   aZ := z;\r
265   result := self;\r
266 end;\r
267 \r
268 {** Setea la componente X\r
269     @param x Nuevo valor de la componente en el eje X}\r
270 function cVector.mSetX(x: tLongitud): cVector;\r
271 begin\r
272   aX := x;\r
273   result := self;\r
274 end;\r
275 \r
276 {** Setea la componente Y\r
277     @param y Nuevo valor de la componente en el eje Y}\r
278 function cVector.mSetY(y: tLongitud): cVector;\r
279 begin\r
280   aY := y;\r
281   result := self;\r
282 end;\r
283 \r
284 {** Setea la componente Z\r
285     @param z Nuevo valor de la componente en el eje Z}\r
286 function cVector.mSetZ(z: tLongitud): cVector;\r
287 begin\r
288   aZ := z;\r
289   result := self;\r
290 end;\r
291 \r
292 {** Suma a si mismo el vector vec\r
293     @param vec Vector a sumarle}\r
294 function cVector.mSumar(vec: cVector): cVector;\r
295 begin\r
296   aX := aX + vec.mGetX;\r
297   aY := aY + vec.mGetY;\r
298   aZ := aZ + vec.mGetZ;\r
299   result := self;\r
300 end;\r
301 \r
302 {$IFDEF DebugAlgoWars}\r
303 {** Devuelve el estado del objeto basandose en la cantidad de datos requeridos:<br>\r
304     Siempre devuelve los valores de las componentes x, y, z y si debugLevel es mayor que DI_NORMAL,\r
305     también muestra el módulo.\r
306     @return             Cadena de texto con el estado del Objeto.\r
307     @param   debugLevel Cantidad de información requerida}\r
308 function cVector.mGetDebugInfo( debugLevel: tDebugInfo ): string;\r
309 begin\r
310   // Construye la cadena dependiendo de la cantidad de informacion que se quiera obtener\r
311   result := 'X: ' + FloatToStrF( mGetX, ffNumber, 5, 5 ) +\r
312             ' | Y: ' + FloatToStrF( mGetY, ffNumber, 5, 5 ) +\r
313             ' | Z: ' + FloatToStrF( mGetZ, ffNumber, 5, 5 );\r
314   if debugLevel > DI_NORMAL then\r
315     result := result + ' | Modulo: ' + FloatToStrF( mGetModulo, ffNumber, 5, 5 );\r
316 end;\r
317 {$ENDIF}\r
318 \r
319 {** Obtiene la distancia al a otro vector (en realidad se tratan como puntos)\r
320     @returns     Distancia al otro vector\r
321     @param   vec Punto al cual se calcula la distancia}\r
322 function cVector.mGetDistancia( vec: cVector ): tLongitud;\r
323 var\r
324   v: cVector;\r
325 begin\r
326   // Crea un nuevo vector basado en vec y le resta el vector actual\r
327   v := cVector.create( vec ).mRestar( self );\r
328   // devuelve el modulo\r
329   result := v.mGetModulo;\r
330   // Libera el vector temporal\r
331   v.free;\r
332 end;\r
333 \r
334 {** Modifica el vector con basandose en otro vector (pensado como velocidad) y un\r
335     intervalo de tiempo siguiendo la formula física X' = X + V * dt\r
336     (este metodo esta pensado basicamente para calcular los movimientos)\r
337     @param vel Vector velocidad\r
338     @param dT  Intervalo de tiempo}\r
339 function cVector.mModificarCon(vel: cVector; dT: tTiempo): cVector;\r
340 var\r
341   v: cVector;\r
342 begin\r
343   // formula de MRU: SELF = SELF + VELOCIDAD * TIEMPO\r
344   v := cVector.create( vel ).mMultiplicar( dT );\r
345   mSumar( v );\r
346   v.free;\r
347   result := self;\r
348 end;\r
349 \r
350 {** Convierte el vector en un versor (sólo tiene sentido si el modulo actual es distinto de cero)}\r
351 function cVector.mHacerVersor: cVector;\r
352 begin\r
353   // Si el modulo es mayor que cero...\r
354   if mGetModulo > 0 then\r
355     mMultiplicar( 1 / mGetModulo );\r
356   result := self;\r
357 end;\r
358 \r
359 {** Recrea el objeto a partir de una cadena de texto con el objeto\r
360     serializado.\r
361     @param str Cadena de texto con el objeto serializado.}\r
362 procedure cVector.mDesSerializar(str: string);\r
363 var\r
364   r: TRegExpr;\r
365 begin\r
366   inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo\r
367   r := TRegExpr.create;\r
368   try // ensure memory release\r
369     // X\r
370     r.Expression := '<X>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</X>';\r
371     if r.Exec ( str ) then\r
372       aX := StrToFloat( r.Match[1] )\r
373     else\r
374       raise ESerializacion.create( 'No se encontro la componente en X' );\r
375     // Y\r
376     r.Expression := '<Y>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</Y>';\r
377     if r.Exec ( str ) then\r
378       aY := StrToFloat( r.Match[1] )\r
379     else\r
380       raise ESerializacion.create( 'No se encontro la componente en Y' );\r
381     // Z\r
382     r.Expression := '<Z>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</Z>';\r
383     if r.Exec ( str ) then\r
384       aZ := StrToFloat( r.Match[1] )\r
385     else\r
386       raise ESerializacion.create( 'No se encontro la componente en Z' );\r
387   except\r
388     on e: ERegExpr do begin\r
389       r.Free;\r
390       raise ESerializacion.create( ClassName + ': Error utilizando expresiones regulares: ' + e.Message );\r
391     end;\r
392   end;\r
393   r.free;\r
394 end;\r
395 \r
396 {** Devuelve una cadena de texto con el objeto serializado.\r
397     @return Cadena de texto con el objeto serializado.}\r
398 function cVector.mSerializar: string;\r
399 begin\r
400   result := inherited mSerializar +\r
401             '<X>' + FloatToStrF( aX, ffGeneral, 18, 0 ) + '</X>' +\r
402             '<Y>' + FloatToStrF( aY, ffGeneral, 18, 0 ) + '</Y>' +\r
403             '<Z>' + FloatToStrF( aZ, ffGeneral, 18, 0 ) + '</Z>';\r
404 end;\r
405 \r
406 end.\r