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
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
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
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
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
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
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
90 procedure mDesSerializar( str: string ); override;
\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
107 // Usa el metodo mSet para establecer los valores
\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
118 // Usa el metodo mSet para establecer los valores
\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
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
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
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
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
158 {** Obtiene el modulo del vector
\r
159 @return Modulo (o norma) del vector}
\r
160 function cVector.mGetModulo: tLongitud;
\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
166 {** Obtiene la componente X
\r
167 @return Componente X del vector}
\r
168 function cVector.mGetX: tLongitud;
\r
173 {** Obtiene la componente Y
\r
174 @return Componente Y del vector}
\r
175 function cVector.mGetY: tLongitud;
\r
180 {** Obtiene la componente Z
\r
181 @return Componente Z del vector}
\r
182 function cVector.mGetZ: tLongitud;
\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
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
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
209 // Multiplica cada componente por el escalar
\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
221 // Realiza el producto escalar (suma el producto componente a componente)
\r
222 result := aX * vec.mGetX + aY * vec.mGetY + aZ * vec.mGetZ;
\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
229 aX := aX - vec.mGetX;
\r
230 aY := aY - vec.mGetY;
\r
231 aZ := aZ - vec.mGetZ;
\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
239 // Primero lo convertimos en un versor
\r
241 // Ahora multiplicamos el versor por la modulo deseada
\r
242 mMultiplicar( modulo );
\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
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
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
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
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
292 {** Suma a si mismo el vector vec
\r
293 @param vec Vector a sumarle}
\r
294 function cVector.mSumar(vec: cVector): cVector;
\r
296 aX := aX + vec.mGetX;
\r
297 aY := aY + vec.mGetY;
\r
298 aZ := aZ + vec.mGetZ;
\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
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
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
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
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
343 // formula de MRU: SELF = SELF + VELOCIDAD * TIEMPO
\r
344 v := cVector.create( vel ).mMultiplicar( dT );
\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
353 // Si el modulo es mayor que cero...
\r
354 if mGetModulo > 0 then
\r
355 mMultiplicar( 1 / mGetModulo );
\r
359 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
361 @param str Cadena de texto con el objeto serializado.}
\r
362 procedure cVector.mDesSerializar(str: string);
\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
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
374 raise ESerializacion.create( 'No se encontro la componente en X' );
\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
380 raise ESerializacion.create( 'No se encontro la componente en Y' );
\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
386 raise ESerializacion.create( 'No se encontro la componente en Z' );
\r
388 on e: ERegExpr do begin
\r
390 raise ESerializacion.create( ClassName + ': Error utilizando expresiones regulares: ' + e.Message );
\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
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