Examples of FMAP Usage
Add a layer by code
To add a layer by code usually it is necessary to create the driver and then to call LayerFactory. Let’s take a look:
LayerFactory.setDriversPath(
"C:\\eclipse3\\workspace\\Andami\\gvSIG\\extensiones\\com.iver.cit.gvsig\\drivers");
FLayer l = LayerFactory.createLayer("Vias",
(VectorialFileDriver) LayerFactory.getDM().getDriver("gvSIG shp driver"),
new File("C:/vias.shp"),
CRSFactory.getCRS("EPSG:23030"));
newMapControl.getMapContext().getLayers().addLayer(l);
A PostGIS layer is created as follows:
String dburl = "jdbc:postgresql://localhost/latin1";
String dbuser = "postgres";
String dbpass = "XXXXXXX";
// String dburl = "jdbc:postgresql://192.168.0.217/postgis";
// String dbuser = "gvsig";
// String dbpass = "";
// String dbtable = "carreteras_lin_5k_t10";
String dbtable = "provin"; // BECAREFUL WITH CAPITAL LETTERS!!!!!!!
IConnection conn = null;
System.out.println("Creating JDBC connection...");
Class.forName("org.postgresql.Driver");
conn = ConnectionFactory.createConnection(dburl, dbuser, dbpass);
((ConnectionJDBC)conn).getConnection().setAutoCommit(false);
DBLayerDefinition lyrDef = new DBLayerDefinition();
lyrDef.setName(dbtable);
lyrDef.setTableName(dbtable);
lyrDef.setWhereClause("");
String[] fields = {"nom_provin", "gid"};
lyrDef.setFieldNames(fields);
lyrDef.setFieldGeometry("the_geom");
lyrDef.setFieldID("gid");
Statement st = ((ConnectionJDBC)conn).getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rsGood = st.executeQuery("SELECT NOM_PROVIN, GID FROM " + dbtable + " ORDER BY GID");
driver.setData(conn, lyrDef);
}
catch (Exception e){
e.printStackTrace();
}
It is necessary to notice a vector layer is defined normally based on a driver and an object ILayerDefinition, where there are specified the layer’s name, fields, coordinate system, etc.
Spatial Query
Spatial queries are very common. For example, we search for features within a determined polygon (the same as searching for something using certain tolerance).
There are several ways to do it and they can be consulted by looking at the codes for the information and selection tools in gvSIG. Here we will show a simple one, especially to demonstrate the FBitMap usage.
The FBitMap class represents a selection of records. It is based on the Bitmap Java class, which contains 0 and 1, a “1” when the record is selected and a “0” when it is not selected. The advantage of this binary storage is the very low memory space taken by the selection and easiness to iterate, count, change the selection, etc.
The disadvantage is that we start from the assumption we always have a random access available to our driver. In other words, the operation to get the umpteenth record is available and fast. That allows us, if there are 10 records selected to obtain their record numbers, get their Feature and do something with them. The problem arises when the data sources do not allow for this type of random access and return their Features in a sequential manner, without knowing how many records will be returned before hand.
That is why we cover BitMap with FBitMap, so in the future we can deliver a selection adapted to databases with random or sequential access.
Then, upon a selection the driver is run from beginning to end while the condition is evaluated (spatial and/or alphanumeric) and the selected records are marked with bitmaps. If any driver were only sequential, we would have to storage the selected records in an array or something similar to avoid searching through the database to position the records, which would be a slow operation.
Nowadays, the drivers in gvSIG are sufficiently fast to allow for random access. Therefore, we can make a query such as:
Point2D p = event.getPoint();
Point2D mapPoint = mapCtrl.getViewPort().toMapPoint((int) p.getX(), (int) p.getY());
// 3 pixels tolerance
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);
}
}
This code has been extracted from the com.iver.cit.gvsig.fmap.tools.PointSelectionListener.java class. What is does is to receive a point in pixels, transform it to map coordinates and search through all the active layers. If they are of vector type, it uses the queryByPoint query to obtain the FBitSet (the selection).
Then we can use this selection for anything we want. The search through the selected records is done this way:
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);
}
Here we have selected the province that contains the point “mapPoint” and we have search through the selected records, recovering the field value “NOM_PROVIN”.
We will see more examples in chapter 6.