Consulta espacial
La consulta espacial también es algo habitual. Por ejemplo, buscamos las entidades que entren dentro de un determinado rectángulo (equivale también a cuando buscas algo teniendo en cuenta una tolerancia.
Hay varias formas de hacerlo, y se pueden consultar viendo el código de la herramienta de información y de selección de gvSIG. Aquí vamos a presentar una simple, sobre todo para mostar el uso de FbitMap.
La clase FBitMap representa una selección de registros. Está basada en la clase Bitmap de Java, que contiene 0 y 1's, un bit a 1 cuando el registro está seleccionado, y un 0 si no está seleccionado. La ventaja de hacerlo así es que la selección ocupa muy poco espacio en memoria, y es muy rápido iterar por los elementos seleccionados, contarlos, cambiar la selección, etc.
La desventaja es que partimos de la suposición de que tenemos siempre disponible un acceso aleatorio a nuestro driver. Dicho de otro modo: que la operación de obtener el registro i-ésimo está disponible y es muy rápida. Eso nos permite, si hay 10 registros seleccionados, posicionarnos en sus números de registro, obtener la Feature y hacer algo con ellos. El problema viene cuando algunas fuentes de datos no permiten este tipo de acceso aleatorio, y entregan sus Features de una forma secuencial, y sin saber a priori cuántos registros van a entregar.
Por eso recubrimos BitMap con FBitMap, para que en el futuro podamos entregar una selección adaptada a fuentes de datos de acceso aleatorio, y otras veces a secuenciales.
Ahora, al hacer una selección, se recorre el driver de principio a fin y se evalúa la condición (espacial y/o alfanumérica), y se marcan en el bitmap los registros seleccionados. Si algun driver fuese solo secuencial, tendríamos que guardar un las features seleccionadas en algún array o algo por el estilo, para evitar volver a recorrer la fuente de datos posicionando en los registros seleccionados, lo cual sería una operación lenta.
Actualmente, los drivers que existen en gvSIG son lo suficientemente rápidos como para permitir el acceso aleatorio. Por lo tanto, podemos hacer una consulta de la manera siguiente:
Point2D p = event.getPoint();
Point2D mapPoint = mapCtrl.getViewPort().toMapPoint((int) p.getX(), (int) p.getY());
// Tolerancia de 3 pixels
double tol = mapCtrl.getViewPort().toMapDistance(3);
FLayer[] actives = mapCtrl.getMapContext()
.getLayers().getActives();
for (int i=0; i < actives.length; i++)
{
if (actives[i] instanceof FLyrVect) {
FLyrVect lyrVect = (FLyrVect) actives[i];
FBitSet oldBitSet = lyrVect.getSource().getRecordset().getSelection();
FBitSet newBitSet = lyrVect.queryByPoint(mapPoint, tol);
if (event.getEvent().isControlDown())
newBitSet.xor(oldBitSet);
lyrVect.getRecordset().setSelection(newBitSet);
}
}
Este código se ha extraído de la clase com.iver.cit.gvsig.fmap.tools.PointSelectionListener.java. Lo que hace es recibir un punto en pixels, lo transforma a coordenadas de mapa y recorre todas las capas activas. Si son de tipo vectorial, utiliza la llamada queryByPoint para obtener el FBitSet (la selección).
Luego, podríamos utilizar esa selección para lo que nosotros queramos. El recorrido de los elementos seleccionados se hace así:
SelectableDataSource ds =lyrVect.getRecordset();
int idField = ds.getFieldIndexByName("NOM_PROVIN");
FBitSet bs = lyrVect.queryByPoint(mapPoint, tol);
for (int i=bs.nextSetBit(0); i >=0; i=bs.nextSetBit(i+1))
{
long idRec = i;
String nom = ds.getFieldValue(idRec, idField).toString();
dlg.setProvinName(nom);
}
Aquí hemos seleccionado la provincia que contiene el punto “mapPoint” y hemos recorrido los elementos seleccionados, recuperando el valor del campo “NOM_PROVIN”.
Veremos más ejemplos en el capítulo 6.