Cours-Gratuit
  • Accueil
  • Blog
  • Cours informatique
home icon Cours gratuits » Cours informatique » Cours programmation » Cours JAVA » Cours Framework JAVA

Tutoriel avancé avec exemples sur l’utilisation de la librairie JAVA GeoTools

Tutoriel avancé avec exemples sur l’utilisation de la librairie JAVA GeoTools
Participez au vote ☆☆☆☆☆★★★★★

Cartographie avec GeoTools

Par johann Sorel

Date de publication : 5 juillet 2007 Dernière mise à jour : 17 janvier 2008

Articles sur la manipulation de la librairie GeoTools.


On peut voir de nos jours de plus en plus d'applications tournant autour des SIG (Systèmes d'Informations Géographiques). Vous les utilisez sans vous en rendre compte peut-être, si vous utilisez une carte IGN, mappy, googleEarth, un GPS de voiture ou une simple carte touristique de la ville, alors vous pouvez être sûr qu'il y a un SIG derrière.

Faisons un tour rapide des données utilisées pour les SIG :

-  les images rasters (photo aérienne, satellite, altimétrique )

-  les images vectorielles (polygone, linéaire, ponctuel )

-  les attributs (nom, etat, catégorie )

Ces données peuvent être stockées sous plusieurs formes, voici les 3 plus en vogue du moment :

-  format GeoTiff, comme son nom l'indique c'est un tiff avec des données de référencement géographique

-  format shape, le fichier shape n'est pas nouveau, il permet de stocker les données vectorielles

-  PostGIS, il s'agit d'une amélioration de la base de données libre PostgreSQL, cette "cartouche spatiale" comme onl'appelle permet de stocker les formes géométriques 2D et 3D dans la base de données.

GeoTools est une librairie Java sous licence LGPL qui regroupe une quantité d'autres librairies, ce qui explique sa taille d'une vingtaine de méga-octets. Elle se base sur les normes en vigueur dans le domaine des SIG, j'entends par là les normes ISO ainsi que celles particulières à la géographie de l'OGC (Open Geospatial Consortium).

La première version de GeoTools date de 1996 et la deuxième de 2000. Actuellement la version stable est la 2.3.2 et une version 2.4 est en cours de développement.

Parmi les librairies qui sont regroupées on note la présence de :

-  GeoAPI : qui fournit les classes de type interfaces afin de normaliser et améliorer l'interopérabilité des applicationsSIG.

-  JTS : pour Java Topology Suite, librairie qui permet de faire des opérations sur les géométries

-  et de nombreuses librairies de connexion aux bases de données et de lecture de fichier

GeoTools :

GeoTools, documentation utilisateur :

GeoTools, tutoriaux (pour anciennes versions) :

GeoTools, javadoc :

JTS :    

GeoAPI :    

OGC :   Forum java : Forum SIG :

Vincent Heurteaux : Directeur/cofondateur de Geomatys

Commençons par récupérer les librairies qui nous seront nécessaires.

GeoTools :

JAI :

Et deux fichiers de données :

JAI est une API pour la lecture et le traitement des images, il est fortement conseillé de l'avoir avec Geotools car certaines fonctions nécessitent celle-ci afin d'améliorer la vitesse ou simplement afin de marcher. Commençons par une petite fenêtre, rien que du classique :

public Main() {       

 JFrame frm = new JFrame();

 frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 frm.setSize(800,600);

 frm.setTitle("Ma Première carte avec GeoTools");

 JPanel pfond = new JPanel(new BorderLayout());

 frm.setContentPane(pfond);

 frm.setJMenuBar(buildMenu());

 frm.getContentPane().add(BorderLayout.CENTER,buildMap());  frm.getContentPane().add(BorderLayout.NORTH,buildTool());

 frm.setVisible(true);       

}  

private JMenuBar buildMenu() {  JMenuBar menu = new JMenuBar();

 JMenu mfichier = new JMenu("Fichier");

 JMenuItem iquitter = new JMenuItem("Quitter"); iquitter.addActionListener(new ActionListener() {   public void actionPerformed(ActionEvent e) {

   (0);

  }

 });

 (iquitter); (mfichier);

return menu;

}

Voyons maintenant ce qui nous intéresse vraiment.

Nous allons prendre soin de déclarer un objet JMapPane pour la classe :

private JMapPane mappane = new JMapPane();

Cet objet est le composant graphique qui va nous permettre de voir notre carte. Ce genre de composant graphique est assez rare dans GeoTools. GeoTools essaie de séparer le côté pratique (calcul, chargement des données ) de l'aspect visuel. On ne trouve donc que le strict minimum graphique dans GeoTools. La tâche de présentation est laissée aux développeurs que nous sommes.

private JPanel buildMap() {

mappane.setBackground(new Color(157,201,255));

try{

MapContext mapcontext = new DefaultMapContext();

mapcontext.setTitle( "Projet" );

mappane.setContext(mapcontext);

MapLayer maplayer;  

On commence par donner une couleur de fond bleu à notre composant graphique.

Voilà un nouvel objet, le MapContext, celui-ci représente notre projet au sens cartographique. Cet objet va stocker les informations, par exemple les différentes couches (fichiers) qui ont été chargées, la projection (la représentation du global terrestre) ou encore l'ordre des couches présentes.

La classe Mapcontext est une interface tandis que DefaultMapContext en est une implémentation. Dans GeoTools il y a de très nombreuses interfaces, il est conseillé de manipuler les objets par leur interface.

Petite chose à noter, GeoTools est en constante mutation, si vous tombez sur des méthodes ou des classes dépréciées parmi les exemples que je donne ou sur le site officiel, ne soyez pas surpris.

L'objet MapLayer est une couche qui sera ajoutée au MapContext.

Si vous êtes assez peu familier avec les termes SIG, je vous propose d'aller explorer les liens ci-dessous :

Ainsi que ce document (trouvé au hasard) qui montre bien le problème de la représentation cartographique : Il ne s'agit pas de le comprendre mais juste de constater que ce n'est pas chose aisée.

URL shapeURL = Main.class.getResource("");

ShapefileDataStore store = new ShapefileDataStore(shapeURL);

String name = store.getTypeNames()[0];

FeatureSource source = store.getFeatureSource(name);

Ci-dessus il s'agit de récupérer des données vectorielles contenues dans un fichier shape (.shp).

On récupère l'URL de ce fichier puis on construit un ShapefileDataStore avec. Le fichier peut être situé à différents endroits, en local, sur un serveur ou dans le jar de l'application.

Le ShapefileDataStore ou plus généralement les DataStore sont des classes qui vont nous permettre de lire et écrire nos données.

Le FeatureSource correspond au jeu de données une fois en mémoire, on pourra parcourir les éléments grâce à lui. Je reviendrai plus avant sur les DataStore dans un prochain article.

StyleBuilder sb = new StyleBuilder();

PolygonSymbolizer ps =

 sb.createPolygonSymbolizer( new Color(253,241,187),new Color(163,151,97),1);

            Style solstyle = sb.createStyle();             solstyle.addFeatureTypeStyle(sb.createFeatureTypeStyle(ps));

Maintenant que nous avons chargé nos données vectorielles, il faut leur attribuer un style, autrement la façon dont on visualisera les géométries sur la carte. Ici on crée une symbologie pour un polygone avec sa couleur de fond, sa couleur de contour et l'epaisseur du contour.

Je reviendrai plus avant sur la Symbologie dans un prochain article.

            maplayer = new DefaultMapLayer(source,solstyle);

maplayer.setTitle(""); maplayer.setVisible(true);             maplayer.setQuery(); mapcontext.addLayer(maplayer);

Les données et le style définis, on peut maintenant créer notre couche, lui donner un nom et la rendre visible, on termine en l'ajoutant au mapcontext. Le "maplayer.setQuery();" signifie que l'on veut que toutes les données soient visibles, on pourrait très bien choisir de n'afficher que les données selon un certain attribut. Je reviendrai plus avant sur le requêtage dans un prochain article.

            shapeURL = Menu.class.getResource("");

            store = new ShapefileDataStore(shapeURL);

            name = store.getTypeNames()[0]; source = store.getFeatureSource(name);

            sb = new StyleBuilder();

            LineSymbolizer ls2 = sb.createLineSymbolizer(, 1);

            Style roadsStyle = sb.createStyle();

            roadsStyle.addFeatureTypeStyle(sb.createFeatureTypeStyle(ls2));

            maplayer = new DefaultMapLayer(source,roadsStyle);

            maplayer.setTitle("");

            maplayer.setVisible(true); maplayer.setQuery(); mapcontext.addLayer(maplayer);

Même chose que précédemment, on charge une nouvelle couche de données.

StreamingRenderer render = new StreamingRenderer();

mappane.setRenderer(render);

mappane.setMapArea(mapcontext.getLayerBounds());

        } catch(Exception e){

e.printStackTrace();

        }       

return mappane;     }

Le StreamingRenderer est un objet qui définit divers paramètres pour le rendu graphique des données, ignorez cela pour le moment.

On définit ensuite le MapArea (la zone visible de la carte) avec le rectangle englobant de nos données.

private JPanel buildTool() {

        JPanel outil = new JPanel(new FlowLayout());

        JButton plus = new JButton("+");

        plus.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 mappane.setState(JMapPane.ZoomIn);

            }

        });

        (plus);

        JButton moins = new JButton("-");

        moins.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 mappane.setState(JMapPane.ZoomOut);

            }

        });

(moins);

JButton pan = new JButton("Pan"); pan.addActionListener(new ActionListener() {             public void actionPerformed(ActionEvent e) {                 mappane.setState();

            }

        });

(pan);

return outil;     }

Un seul élément à noter ici :

-  mappane.setState(JMapPane.ZoomIn);

-  mappane.setState(JMapPane.ZoomOut);

-  mappane.setState();

Cela va changer le comportement de la navigation sur la carte quand on cliquera avec la souris.

Si tout s'est bien passé vous devriez obtenir ceci :

Voilà déjà un début intéressant.

L'interface DataStore est utilisée par les classes offrant la lecture et éventuellement l'écriture des données. Il faut savoir qu'il y un grand nombre de formats SIG existant et en conséquence des méthodes pour accéder aux données très variées. Il peut s'agir de bases de données, auquel cas la communication sera en SQL, de fichier donc de flux ou encore de serveur distant avec des flux RSS, WMS sans oublier des connexions temps réel.

Rassurez-vous, l'interface DataStore est là pour offrir des méthodes communes pour récupérer les données quelque soit leur source d'origine.

La façon la plus simple de récupérer un DataStore est d'utiliser la fabrique dédiée à cet effet.

Map config = new HashMap(); ("url", file.toURL() );

DataStore dataStore = DataStoreFinder.getDataStore( config );

La fabrique va parcourir chaque implémentation de DataStore qu'elle connait et va essayer d'en créer une instance avec les paramètres fournis.

Dans le cas ci-dessus, nous n'avons qu'une url donc en fonction du fichier on pourrait obtenir un datastore correspondant à un fichier shape, GML etc

Pour une base de données il faut fournir d'avantage d'informations. Voici un exemple pour une source de type PostGIS.

Map config = new HashMap();

( , "postgis" );  ( , "127.0.0.1" ); ( , "5432" );  ( , "public" ); ( , "mabase" ); ( , "user" ); ( , "mdp" ); DataStore dataStore = DataStoreFinder.getDataStore( config );

Les clés possibles peuvent être trouvées de plusieurs façons :

-  comme proriétés statiques dans les datastores

-  dynamiquement (code ci-dessous)

-  dans la javadoc

PostgisDataStoreFactory pdsf = new PostgisDataStoreFactory();

Param[] params = pdsf.getParametersInfo();

for(Param pm : params){

 //une description de la clé

    String desc = pm.description;

    //la clé

    String key = ;

    //Vrai si cette clé est obligatoire     boolean needed = pm.required;     //un exemple de valeur possible

    Object value = pm.sample;

    //la classe nécessaire

    Class classe = ;

}

Il y a aussi un bon nombre de méthodes disponibles sur la classe DataStoreFinder qui peuvent vous servir.

L'autre méthode consiste à créer un Datastore directement avec un objet de classe DataStore que l'on souhaite, vous en avez un exemple au chapitre 1. Toutefois tous les constructeurs vont devenir privés et seul le DataStoreFinder pourra créer ce genre d'objet.

Pour les rasters il existe un GridCoverageFinder mais il n'est pas encore au point, il est préférable que vous utilisiez les classes qu'il vous faut plutôt que celui-ci.

Pour les fichiers rasters voici une fonction qui peut être utilisée.

privatestaticfinal String GEOTIFF = ".tif"; privatestaticfinal String BMP = ".bmp"; privatestaticfinal String JPG = ".jpg"; privatestaticfinal String JPEG = ".jpeg"; privatestaticfinal String PNG = ".png";

/**

*  return a gridcoverage for Raster file. Use a Map containing key "url"

*  @param params

*  @return GridCoverage

*/

publicstatic GridCoverage getGridCoverage(Map params){

        GridCoverage cover = null;

        URL url = (URL) ("url");

if (url != null) {

            String name = url.getFile().toLowerCase();

            File file = null;

try {

                file = new File(url.toURI()); } catch (URISyntaxException ex) {

                ex.printStackTrace();

            }

if (file != null) {

                // try a geotiff gridcoverage                 if (name.endsWith(GEOTIFF)) {

try {

GeoTiffReader

 reader = new GeoTiffReader(file, new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, ));

cover = (GridCoverage2D) (null);

                    } catch (DataSourceException ex) {

                        cover = null; ex.printStackTrace();                     }catch (IOException ex){                         cover = null;

                        ex.printStackTrace();

                    }

                }

                // try a world image file

elseif (name.endsWith(BMP) || name.endsWith(JPG) || name.endsWith(JPEG) ||

 name.endsWith(PNG)) {

try {

WorldImageReader reader = new WorldImageReader(file);

cover = (GridCoverage2D) (null);

                    } catch (DataSourceException ex) {

                        cover = null; ex.printStackTrace();                     }catch (IOException ex){

cover = null;                         ex.printStackTrace();

}

}

            }

        }

return cover;     }

Nous allons créer un MapLayer à partir d'un fichier shape.

public Chap2Donnees() {

        URL url = null;         try {

            url = new File("").toURI().toURL();

        } catch (MalformedURLException ex) {

            ex.printStackTrace();

        }

if (url != null) {

            MapLayer layer = createLayer(url);

try {

                explorer(layer); parcourir(layer);                 ajouter(layer); supprimer(layer);                 modifier(layer);

            } catch (IOException ex) {                 ex.printStackTrace();

            }

        }

    }

private MapLayer createLayer(URL url) {

        MapLayer layer = null;

        FeatureSource source = null;

try {

            DataStore store = new ShapefileDataStore(url);

            String name = store.getTypeNames()[0]; source = store.getFeatureSource(name);

        } catch (IOException ex) {             ex.printStackTrace();

        }

if (source != null) {

            Style style = createStyle();

            layer = new DefaultMapLayer(source, style);

        }

return layer;

    }

Le schéma correspond à la structure des données, un peu comme une table dans une base de données, on peut connaitre quelles sont les colonnes et leur type.

private void explorer(MapLayer layer) throws IOException {

FeatureType type = layer.getFeatureSource().getSchema();

GeometryDescriptor geodesc = type.getDefaultGeometry();

.println("GEOM : " + geodesc.getName());

.println("GEOM : " + geodesc.getType().getBinding());

Collection properties = type.getProperties(); Iterator propertiesIte = properties.iterator();

while (propertiesIte.hasNext()) {

PropertyDescriptor oneProperty = ();

.println(oneProperty.getName() + " : " + oneProperty.getType().getBinding());

        }

    }

La méthode getDefaultGeometry() nous permet de récupérer les informations sur la géométrie.

Les interfaces concernant la description des attributs sont les suivantes : PropertyDescriptor - AttributDescriptor - GeometryDescriptor

La méthode getName() est assez claire, c'est le nom de l'attribut.

getType().getBinding() va nous permettre de récupérer le type de l'attribut. Dans le cas de la "colonne" correspondant à la géométrie nous pourrons avoir les classes de géométrie de la librairie JTS (Java Topology Suite).

private void parcourir(MapLayer layer) throws IOException {

FeatureCollection features = layer.getFeatureSource().getFeatures();

FeatureIterator featuresIte = features.features();

while (featuresIte.hasNext()) {

SimpleFeature oneFeature = ();

for (int i = 0,  max = oneFeature.getAttributeCount(); i < max; i++) {

.println(oneFeature.getAttribute(i));

            }

        }

    }

On récupère d'abord une collection de nos éléments que l'on parcourt avec un itérateur.

- Pourquoi ne pas fournir un tableau de tous les éléments ?

Car on ne sait pas combien il y en a, il n'est pas rare d'avoir quelques centaines de milliers d'enregistrements. En plus, il ne faut pas oublier le champ géométrique qui peut être très volumineux. On arriverait très vite en saturation mémoire. Il y a eu un bon nombre de discussions à propos de l'usage de la classe FeatureCollection, à cause de certaines limites dans la flexibilité de celle-ci. Donc dans l'avenir cette facon de procéder devrait peut être changer.

private void modifier(MapLayer layer) throws IOException {

        FeatureStore store;

        // (1)

        FeatureCollection features = layer.getFeatureSource().getFeatures();

        SimpleFeature oneFeature = features.features().next();

        // (2)

        AttributeDescriptor oneAttribut =

 layer.getFeatureSource().getSchema().getAttribute("NB_VOIES");

        // (3)

        String value = "4";

        // (4)

if (layer.getFeatureSource() instanceof FeatureStore) {

            store = (FeatureStore) layer.getFeatureSource();

            // (5)

DefaultTransaction transaction = new DefaultTransaction("trans_maj");

            store.setTransaction(transaction);

            // (6)

            FilterFactory factory = CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints());             Filter filter = (Collections.singleton(factory.featureId(oneFeature.getID())));

            // (7)             try {

                store.modifyFeatures(oneAttribut, value, filter);                 transaction.commit(); } catch (IOException ex) {                 ex.printStackTrace();

try {

                    transaction.rollback(); } catch (IOException e) {

                    e.printStackTrace();

                }

            }finally{

transaction.close();

            }

        }

    }

Voilà qui doit paraître compliqué.

1)  La première chose à faire c'est de récupérer l'élément que l'on veut modifier, dans le cas ci-dessus on prend toutsimplement le premier qui vient.

2)  Il faut ensuite savoir quel champ on va modifier, pour cela on passe par le schéma et on récupère le descripteurcorrespondant.

3)  On récupère/crée la nouvelle valeur à affecter.

4)  Ce test peut être fait en premier, c'est selon votre application. FeatureStore est une interface qui correspond à unFeatureSource éditable. Autrement dit si le FeatureSource possède cette interface il permet l'édition.

5)  Toute communication, pour une modification un ajout ou une suppression passe par une transaction. La transactionpeut concerner 1 ou N éléments, c'est pour ça que l'on utilise un filtre. 6) Ce filtre va permettre de limiter l'étendue des modifications uniquement aux éléments qui seront en sortie de celui-ci. Un filtre peut être très complexe, j'y reviendrai dans le chapître sur le requêtage.

7) Et on applique nos modifications, ainsi qu'un commit(). Vous remarquerez le rollback() comme en SQL .

private void ajouter(MapLayer layer) {

        FeatureStore store;

        // (1)

        GeometryFactory geoFactory = new GeometryFactory();

        // (2)

        Coordinate coord1 = new Coordinate(50, 430);

        Coordinate coord2 = new Coordinate(21, 712);

        LineString line = geoFactory.createLineString(new Coordinate[]{coord1, coord2}); MultiLineString lines = geoFactory.createMultiLineString(new LineString[]{line});

        SimpleFeatureType featureType = layer.getFeatureSource().getSchema();

        // (3)

        Object[] values = new Object[featureType.getAttributeCount()];

        AttributeDescriptor geomAttribut = featureType.getDefaultGeometry();         List attributes = featureType.getAttributes();

        // (4)

for (int i = 0,  max = (); i < max; i++) {             AttributeDescriptor oneAttribut = (i);

            // (5)

if (oneAttribut.equals(geomAttribut)) {

                values[i] = lines;

            } else {

                values[i] = oneAttribut.getDefaultValue();

            }

        }

        // (6)

        SimpleFeature myFeature = SimpleFeatureBuilder.build(featureType, values, null);

        // (7)

        FeatureCollection lstFeatures = FeatureCollections.newCollection();

        (myFeature);

        // (8)

if (layer.getFeatureSource() instanceof FeatureStore) {             store = (FeatureStore) layer.getFeatureSource();

DefaultTransaction transaction = new DefaultTransaction();

            store.setTransaction(transaction);

            // (9)             try {

                store.addFeatures(lstFeatures); transaction.commit();               

            } catch (Exception ex) {                 ex.printStackTrace();

try {

                    store.getTransaction().rollback();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }finally{

transaction.close();

            }

        }

    }

1)  GeometryFactory vient de la librairie JTS, elle permet de créer les différents objets géometriques.

2)  Ici on fabrique une multi-ligne, j'en reparlerai dans un article sur JTS.

3)  On prépare un tableau de la taille du nombre d'attribut que possède notre couche.

4)  On remplit le tableau

5)  On fait attention à placer des valeurs correctes pour chaque attribut, pour avoir la valeur par défaut on utilise legetDefaultValue() du descripteur.

6)  On crée un objet correspondant à un enregistrement

7)  On le place dans une collection d'enregistrements

8)  On vérifie que notre couche est bien éditable

9)  et on ajoute la collection d'enregistrements

        FeatureStore store;

        // (1)

        FeatureCollection features = layer.getFeatureSource().getFeatures();

        SimpleFeature oneFeature = features.features().next();

        // (2)

if (layer.getFeatureSource() instanceof FeatureStore) {

            store = (FeatureStore) layer.getFeatureSource();

            // (3)

DefaultTransaction transaction = new DefaultTransaction("trans_maj");

            store.setTransaction(transaction);

            // (4)

            FilterFactory factory = CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints()); Filter filter = (Collections.singleton(factory.featureId(oneFeature.getID())));

            // (5)             try {

                store.removeFeatures(filter); transaction.commit();             } catch (IOException ex) {                 ex.printStackTrace();

try {

                    transaction.rollback(); } catch (IOException e) {

                    e.printStackTrace();

                }

            }finally{

transaction.close();

            }

        }

    }

Le principe ici est très proche de la modification, même plus simple.

1)      La première chose à faire c'est récupérer l'élément que l'on veut supprimer, dans le cas ci-dessus on prend toutsimplement le premier qui vient.

2)      On vérifie que notre couche est bien éditable3) On crée une transaction.

4)  On crée le filtre.

5)  Et on applique la suppresion.

ATTENTION : Les Widgets Swing sont encore en développement ! Aucun support n'est assuré.

Ce widget est semblable à un JFileChooser, bien qu'il ne soit pas terminé il permet déjà de se simplifier la vie si on a besoin de récupérer rapidement des objets MapLayer.

Utilisation :

//liste des panneaux visibles

List lst = new ArrayList();

(new JFileDataPanel()); (new JDatabaseDataPanel());

JDataChooser jdc = new JDataChooser(null,lst);

JDataChooser.ACTION ret = jdc.showDialog();

if (ret == JDataChooser.ACTION.APPROVE) {

 //tous les MapLayers correspondants aux fichiers/tables sélectionnées.

 List layers = jdc.getLayers();

 }

if (layer.getFeatureSource().getSchema().getTypeName().equals("GridCoverage")) {

 .println("Layer de type raster");

}else{

 .println("Layer de type vecteur");

}

import .LineString; import .MultiLineString; import .MultiPolygon; import .Point; import .MultiPoint; import .Polygon;

Class jtsClass = layer.getFeatureSource().getSchema().getDefaultGeometry().getType().getBinding();

if (jtsClass.equals(Point.class)) {

 .println("Geometrie de type POINT");

} elseif (jtsClass.equals(MultiPoint.class)) {

    .println("Geometrie de type MULTI-POINT");

 } elseif (jtsClass.equals(LineString.class)) {

    .println("Geometrie de type LIGNE");

} elseif (jtsClass.equals(MultiLineString.class)) {

    .println("Geometrie de type MULTI-LIGNE");

} elseif (jtsClass.equals(Polygon.class)) {

    .println("Geometrie de type POLYGONE");

} elseif (jtsClass.equals(MultiPolygon.class)) {

    .println("Geometrie de type MULTI-POLYGONE");

}

if (layer.getFeatureSource() instanceof FeatureStore) {

 FeatureStore store = (FeatureStore) layer.getFeatureSource(); 

 .println("Ce layer est éditable");

}else{

 .println("Ce layer n'est pas éditable");

}

Decouvrir ces documents

  • Manuel avancé sur l’utilisation du Framework JAVA apache Accumulo

    Manuel avancé sur l’utilisation du Framework JAVA apache Accumulo

  • Formation avancé sur l’utilisation du Framework Apache Nutch pour Java [Eng]

    Formation avancé sur l’utilisation du Framework Apache Nutch pour Java [Eng]

  • Tutoriel sur la sécurité des applications Web JAVA avec Apache Shiro [Eng]

    Tutoriel sur la sécurité des applications Web JAVA avec Apache Shiro [Eng]

  • Démarrer avec le Framework JAVA MapReduce Hadoop et Spark

    Démarrer avec le Framework JAVA MapReduce Hadoop et Spark

  • Support de cours Java : gestion des exceptions avec exemples

    Support de cours Java : gestion des exceptions avec exemples

  • Application gestion d’agence de voyage avec JAVA

    Application gestion d’agence de voyage avec JAVA

  • Framework JasperReports tutoriel avancé

    Framework JasperReports tutoriel avancé

  • Application en JAVA jeu de loterie

    Application en JAVA jeu de loterie

Articles connexes

  • Tutoriel Excel : la fonction CHOISIR avec des exemples
  • Tutoriel Python : les instructions imbriquées
  • Exercice comptabilité : enregistrer des opérations pour une librairie dans le journal
  • Tutoriel Python: la librairie Numpy
  • Exercice liste chainée générique JAVA - Structures de données abstraites
  • Tutoriel Excel : les tableaux croisés dynamiques
  • TD ASRA: introduction à l'utilisation de pf avec correction
  • Tuto Excel : la fonction RECHERCHEH avec des exemples
  • Contactez-nous
  • A propos de nous
  • On recrute
  • Rechercher dans le site
  • Politique de confidentialité
  • Droit d'auteur/Copyright
  • Conditions générales d'utilisation
  • Plan du site
  • Accueil
  • Blog
  • Finance et compta.
  • Formations Pro.
  • Logiciels & Apps
  • Organisation
  • Cours informatique
  • Aide à la rédaction
  • Etudes et Metiers
  • Science et Tech
  • Titans de la Tech
id 11354 02