1 {** Es una clase abstracta que representa filtro que recibe una lista de objetos y devuelve otra filtrada.<br>
\r
4 06/12/00: Se agregan nuevos métodos (protegidos) para obtener información del filtro para poder crear subclases,
\r
5 para lo cual tambien se hace virtual el método mVisible.
\r
6 08/12/00: Se cambia esta clase para que sea abstracta. Se deja la implementacion del método mVisible para las
\r
7 subclases exlusivamente ya que ahora es abstracto. El filtro frontal (que antes se implementaba en
\r
8 esta unidad), ahora está implementado la unidad Filtros al igual que el resto.
\r
23 {** Excepcion producida por el filtro si se utiliza cuando el observador fue destruido}
\r
24 EObservadorDestruido = class( Exception )
\r
30 {** Es una clase abstracta que representa un filtro que recibe una lista de objetos y devuelve otra filtrada.}
\r
31 cFiltro = class( cObjetoPersistente )
\r
33 aObservador: cObjetoVolador; // Objeto volador que observa a traves del filtro
\r
34 aRadioMaximo: tLongitud; // Alcance maximo del filtro (los
\r
35 // objetos mas lejanos no se veran)
\r
36 aRadioMinimo: tLongitud; // Alcance minimo del filtro (los
\r
37 // objetos mas cercanos no se veran)
\r
38 aCosApertura: tAngulo; // Coseno del Angulo de captación del filtro,
\r
39 // se almacena sólo el coseno porque el
\r
40 // ángulo en sí no se usa.
\r
42 {** Verifica que un objeto volador pueda ser visto por la cámara}
\r
43 function mVisible( ov: cObjetoVolador ): boolean; virtual; abstract;
\r
44 {** Obtiene el radio mínimo}
\r
45 function mGetRadioMinimo: tLongitud;
\r
46 {** Obtiene el radio máximo}
\r
47 function mGetRadioMaximo: tLongitud;
\r
48 {** Obtiene el coseno de la apertura}
\r
49 function mGetCosApertura: tAngulo;
\r
52 constructor create( observador: cObjetoVolador; angulo: tAngulo = PI/4; maximo: tLongitud = 5000; minimo: tLongitud = -1 );
\r
53 {** Procesa una lista de objetos, devolviendo solo los visibles en una lista ordenada ascendentemente por la distancia
\r
54 (es decir, el objeto más cercano está primero en la lista).}
\r
55 function mFiltrar( l: TList ): TList;
\r
56 {** Obtiene un puntero al observador}
\r
57 function mGetObservador: cObjetoVolador;
\r
58 {** Establece el observador con un nuevo puntero}
\r
59 procedure mSetObservador( ov: cObjetoVolador );
\r
60 {$IFDEF DebugAlgoWars}
\r
61 {** Método heredado que devuelve un string con el estado del Objeto. Se utiliza para depurar
\r
62 y la información entregada depende del parámetro tDebugInfo.}
\r
63 function mGetDebugInfo( debugLevel: tDebugInfo = DI_MINI ): string; override;
\r
66 {** Devuelve una cadena de texto con el objeto serializado.}
\r
67 function mSerializar: string; override;
\r
68 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
70 procedure mDesSerializar( str: string ); override;
\r
83 @param observador Objeto Volador en el que estará montado el filtro (obligatorio)
\r
84 @param angulo Angulo de apertura (visión) del filtro (default = pi/4)
\r
85 @param maximo Distancia máxima en la que se considera visible a un objeto (default = 5000)
\r
86 @param minimo Distancia mínima en la que se considera visible a un objeto (default = -1).
\r
87 Si se especifica un valor negativo o cero, se toma la dimension del objeto volador}
\r
88 constructor cFiltro.create(observador: cObjetoVolador; angulo: tAngulo;
\r
89 maximo: tLongitud; minimo: tLongitud);
\r
92 aObservador := observador;
\r
93 aRadioMaximo := maximo;
\r
94 aCosApertura := cos( angulo );
\r
95 if minimo > 0 then // Si el radio minimo es positiva se lo asigna
\r
96 aRadioMinimo := minimo
\r
97 else // Si es negativo o cero (se paso como default o mal), lo extrae del objeto volador
\r
98 aRadioMinimo := aObservador.mGetDimension;
\r
101 {** Filtra una lista de objetos, devolviendo solo los visibles.
\r
102 @return Lista con los objetos visibles.
\r
103 @param l Lista con los objetos a procesar.}
\r
104 function cFiltro.mFiltrar( l: TList ): TList;
\r
107 oOV: cObjetoVolador;
\r
110 lProcesada := TList.create;
\r
111 for i:=0 to l.count - 1 do begin // recorre la lista de objetos
\r
112 oOV := l.items[i]; // obtiene el ObjetoVolador actual
\r
113 if mVisible( oOV ) then
\r
114 lProcesada.Add( oOV );
\r
116 result := lProcesada;
\r
119 {$IFDEF DebugAlgoWars}
\r
120 {** Devuelve el estado del objeto basandose en la cantidad de datos requeridos:<br>
\r
121 Siempre devuelve los valores de las componentes x, y, z y si debugLevel es mayor que DI_NORMAL,
\r
122 también muestra el módulo.
\r
123 @return Cadena de texto con el estado del Objeto.
\r
124 @param debugLevel Cantidad de información requerida}
\r
125 function cFiltro.mGetDebugInfo( debugLevel: tDebugInfo ): string;
\r
127 // Construye la cadena dependiendo de la cantidad de informacion que se quiera obtener
\r
128 result := 'Radio Máximo: ' + FloatToStrF( aRadioMaximo, ffNumber, 5, 5 ) +
\r
129 ' | Radio Mínimo: ' + FloatToStrF( aRadioMinimo, ffNumber, 5, 5 );
\r
130 try // Probamos que el cameraman no este destruido
\r
131 if debugLevel = DI_NORMAL then
\r
132 result := result + #13 + #10 +
\r
133 'Cameraman: ' + aObservador.mGetDebugInfo;
\r
134 if debugLevel = DI_MAXI then
\r
135 result := result + #13 + #10 +
\r
136 'Cameraman: ' + aObservador.mGetDebugInfo( debugLevel ); // + #13 + #10 +
\r
137 except // Si esta destruido cae en una excepcion
\r
138 on e: EAccessViolation do
\r
139 raise EObservadorDestruido.create; // Creamos una nueva excepcion especial
\r
144 {** Obtiene un puntero al observador
\r
145 @return Puntero al obervador}
\r
146 function cFiltro.mGetObservador: cObjetoVolador;
\r
148 result := aObservador;
\r
151 {** Establece el observador con un nuevo puntero
\r
152 @param Puntero al nuevo obervador}
\r
153 procedure cFiltro.mSetObservador(ov: cObjetoVolador);
\r
158 {** Recrea el objeto a partir de una cadena de texto con el objeto
\r
160 @param str Cadena de texto con el objeto serializado.}
\r
161 procedure cFiltro.mDesSerializar(str: string);
\r
165 inherited mDesSerializar( str ); // SIEMPRE el ID debe ser el PRIMER atributo
\r
166 r := TRegExpr.create;
\r
168 try // se fija si hay errores al extraer los datos
\r
169 r.Expression := '<observador\s+class=([\w\d]+)\s*>\s*(.+)\s*</observador>'; // contruye la expresion regular a buscar
\r
170 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
171 if r.Match[1] <> '0' then // Si tiene una clase determinada...
\r
172 if aObservador <> nil then // Si no es nulo
\r
173 // Puede caer en una EAccessViolation si esta destruido
\r
174 aObservador.mDesSerializar( r.Match[2] ) // Lo deserializa
\r
176 aObservador := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase
\r
177 else // Si no tiene una clase determinada, entonces se lo pone en nil
\r
179 else // si no encontro la experesion...
\r
180 raise ESerializacion.create( 'No se encontro el objetivo' ); // cae en una excepcion
\r
181 except // Si hubieron errores ...
\r
182 on e: ESerializacion do begin // Si fueron de serializacion...
\r
183 r.Free; // libera memoria
\r
184 raise ESerializacion.create( ClassName + ': Error al deserializar la posicion: ' + e.Message ); // cae en una excepcion
\r
186 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
187 r.Free; // libera memoria
\r
188 raise ESerializacion.create( ClassName + ': Error al extraer la posicion utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
190 on e: EAccessViolation do begin // si el Objetivo fue destruido...
\r
191 aObservador := restaurarObjeto( r.Match[1], r.Match[2] ) // lo crea segun su clase
\r
195 try // se fija si hay errores al extraer los datos
\r
196 r.Expression := '<radiomaximo>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</radiomaximo>'; // contruye la expresion regular a buscar
\r
197 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
198 aRadioMaximo := StrToFloat( r.Match[1] )
\r
199 else // si no encontro la experesion...
\r
200 raise ESerializacion.create( 'No se encontro el radio maximo' ); // cae en una excepcion
\r
201 except // Si hubieron errores ...
\r
202 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
203 r.Free; // libera memoria
\r
204 raise ESerializacion.create( ClassName + ': Error al extraer el radio maximo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
208 try // se fija si hay errores al extraer los datos
\r
209 r.Expression := '<radiominimo>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</radiominimo>'; // contruye la expresion regular a buscar
\r
210 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
211 aRadioMinimo := StrToFloat( r.Match[1] )
\r
212 else // si no encontro la experesion...
\r
213 raise ESerializacion.create( 'No se encontro el radio minimo' ); // cae en una excepcion
\r
214 except // Si hubieron errores ...
\r
215 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
216 r.Free; // libera memoria
\r
217 raise ESerializacion.create( ClassName + ': Error al extraer el radio minimo utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
221 try // se fija si hay errores al extraer los datos
\r
222 r.Expression := '<cosapertura>\s*([+\-]?\d+(\,\d+)?([eE][+\-]?\d+)?)\s*</cosapertura>'; // contruye la expresion regular a buscar
\r
223 if r.Exec ( str ) then // Ejecuta la expresion. Si la encuentra...
\r
224 aCosApertura := StrToFloat( r.Match[1] )
\r
225 else // si no encontro la experesion...
\r
226 raise ESerializacion.create( 'No se encontro el coseno de la apertura' ); // cae en una excepcion
\r
227 except // Si hubieron errores ...
\r
228 on e: ERegExpr do begin // si fueron de expresiones regulares...
\r
229 r.Free; // libera memoria
\r
230 raise ESerializacion.create( ClassName + ': Error al extraer el coseno de la apertura utilizando expresiones regulares: ' + e.Message ); // cae en una excepcion
\r
236 {** Devuelve una cadena de texto con el objeto serializado.
\r
237 @return Cadena de texto con el objeto serializado.}
\r
238 function cFiltro.mSerializar: string;
\r
241 observador: string;
\r
243 // Si el observador es nil o está destruido, se setea el atributo class del
\r
244 // TAG objetivo como '0' y entre el TAG se indica que es nil. Si no se
\r
245 // setea como el nombre de la clase y su expresion serializada respectivamente
\r
246 observador := 'nil';
\r
248 if aObservador <> nil then
\r
250 observador := aObservador.mSerializar;
\r
251 clase := aObservador.ClassName;
\r
252 except // Si esta destruido cambia la cadena de texto
\r
253 on e: EAccessViolation do begin
\r
254 observador := 'nil';
\r
258 result := inherited mSerializar +
\r
259 '<observador class=' + clase + '>' + observador + '</observador>' +
\r
260 '<radiomaximo>' + FloatToStrF( aRadioMaximo, ffGeneral, 18, 0 ) + '</radiomaximo>' +
\r
261 '<radiominimo>' + FloatToStrF( aRadioMinimo, ffGeneral, 18, 0 ) + '</radiominimo>' +
\r
262 '<cosapertura>' + FloatToStrF( aCosApertura, ffGeneral, 18, 0 ) + '</cosapertura>';
\r
265 {** Obtiene el radio máximo
\r
266 @return Radio máximo}
\r
267 function cFiltro.mGetRadioMaximo: tLongitud;
\r
269 result := aRadioMaximo;
\r
272 {** Obtiene el radio mínimo
\r
273 @return Radio mínimo}
\r
274 function cFiltro.mGetRadioMinimo: tLongitud;
\r
276 result := aRadioMinimo;
\r
279 {** Obtiene el coseno de la apertura
\r
280 @return Coseno de la apertura}
\r
281 function cFiltro.mGetCosApertura: tAngulo;
\r
283 result := aCosApertura;
\r
286 { EObservadorDestruido }
\r
289 constructor EObservadorDestruido.create;
\r
291 inherited create( 'El Observador fue destruido.' );
\r