View Javadoc
1   package fr.ifremer.dali.ui.swing.util.map;
2   
3   /*-
4    * #%L
5    * Dali :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  // docs start source
27  /*
28   *    GeoTools - The Open Source Java GIS Toolkit
29   *    http://geotools.org
30   *
31   *    (C) 2006-2008, Open Source Geospatial Foundation (OSGeo)
32   *
33   *    This file is hereby placed into the Public Domain. This means anyone is
34   *    free to do whatever they wish with this file. Use it well and enjoy!
35   */
36  
37          import com.vividsolutions.jts.geom.LineString;
38  import com.vividsolutions.jts.geom.MultiLineString;
39  import com.vividsolutions.jts.geom.MultiPolygon;
40  import com.vividsolutions.jts.geom.Polygon;
41  import org.geotools.data.FeatureSource;
42  import org.geotools.data.FileDataStore;
43  import org.geotools.data.FileDataStoreFinder;
44  import org.geotools.factory.CommonFactoryFinder;
45  import org.geotools.map.FeatureLayer;
46  import org.geotools.map.Layer;
47  import org.geotools.map.MapContent;
48  import org.geotools.styling.*;
49  import org.geotools.styling.Stroke;
50  import org.geotools.swing.JMapFrame;
51  import org.geotools.swing.data.JFileDataStoreChooser;
52  import org.geotools.swing.dialog.JExceptionReporter;
53  import org.geotools.swing.styling.JSimpleStyleDialog;
54  import org.opengis.feature.simple.SimpleFeatureType;
55  import org.opengis.filter.FilterFactory;
56  
57  import java.awt.*;
58  import java.io.File;
59  
60  public class StyleLab {
61  
62      static StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
63      static FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory();
64  
65      public static void main(String[] args) throws Exception {
66          StyleLab me = new StyleLab();
67          me.displayShapefile();
68      }
69  
70      // docs end main
71  
72      // docs start display
73      /**
74       * Prompts the user for a shapefile (unless a filename is provided
75       * on the command line; then creates a simple Style and displays
76       * the shapefile on screen
77       */
78      private void displayShapefile() throws Exception {
79          File file = JFileDataStoreChooser.showOpenFile("shp", null);
80          if (file == null) {
81              return;
82          }
83  
84          FileDataStore store = FileDataStoreFinder.getDataStore(file);
85          FeatureSource featureSource = store.getFeatureSource();
86  
87          // Create a map content and add our shapefile to it
88          MapContent map = new MapContent();
89          map.setTitle("StyleLab");
90  
91          // Create a basic Style to render the features
92          Style style = createStyle(file, featureSource);
93  
94          // Add the features and the associated Style object to
95          // the MapContent as a new Layer
96          Layer layer = new FeatureLayer(featureSource, style);
97          map.addLayer(layer);
98  
99          // Now display the map
100         JMapFrame.showMap(map);
101     }
102 
103     // docs end display
104 
105     // docs start create style
106     /**
107      * Create a Style to display the features. If an SLD file is in the same
108      * directory as the shapefile then we will create the Style by processing
109      * this. Otherwise we display a JSimpleStyleDialog to prompt the user for
110      * preferences.
111      */
112     private Style createStyle(File file, FeatureSource featureSource) {
113         File sld = toSLDFile(file);
114         if (sld != null) {
115             return createFromSLD(sld);
116         }
117 
118         SimpleFeatureType schema = (SimpleFeatureType)featureSource.getSchema();
119         return JSimpleStyleDialog.showDialog(null, schema);
120     }
121 
122     // docs end create style
123 
124     // docs start sld
125     /**
126      * Figure out if a valid SLD file is available.
127      */
128     public File toSLDFile(File file)  {
129         String path = file.getAbsolutePath();
130         String base = path.substring(0,path.length()-4);
131         String newPath = base + ".sld";
132         File sld = new File( newPath );
133         if( sld.exists() ){
134             return sld;
135         }
136         newPath = base + ".SLD";
137         sld = new File( newPath );
138         if( sld.exists() ){
139             return sld;
140         }
141         return null;
142     }
143 
144     /**
145      * Create a Style object from a definition in a SLD document
146      */
147     private Style createFromSLD(File sld) {
148         try {
149             SLDParser stylereader = new SLDParser(styleFactory, sld.toURI().toURL());
150             Style[] style = stylereader.readXML();
151             return style[0];
152 
153         } catch (Exception e) {
154             JExceptionReporter.showDialog(e, "Problem creating style");
155         }
156         return null;
157     }
158 
159     // docs end sld
160 
161 
162     // docs start alternative
163     /**
164      * Here is a programmatic alternative to using JSimpleStyleDialog to
165      * get a Style. This methods works out what sort of feature geometry
166      * we have in the shapefile and then delegates to an appropriate style
167      * creating method.
168      */
169     private Style createStyle2(FeatureSource featureSource) {
170         SimpleFeatureType schema = (SimpleFeatureType)featureSource.getSchema();
171         Class geomType = schema.getGeometryDescriptor().getType().getBinding();
172 
173         if (Polygon.class.isAssignableFrom(geomType)
174                 || MultiPolygon.class.isAssignableFrom(geomType)) {
175             return createPolygonStyle();
176 
177         } else if (LineString.class.isAssignableFrom(geomType)
178                 || MultiLineString.class.isAssignableFrom(geomType)) {
179             return createLineStyle();
180 
181         } else {
182             return createPointStyle();
183         }
184     }
185 
186     // docs end alternative
187 
188     /**
189      * Create a Style to draw polygon features with a thin blue outline and
190      * a cyan fill
191      */
192     private Style createPolygonStyle() {
193 
194         // create a partially opaque outline stroke
195         Stroke stroke = styleFactory.createStroke(
196                 filterFactory.literal(Color.BLUE),
197                 filterFactory.literal(1),
198                 filterFactory.literal(0.5));
199 
200         // create a partial opaque fill
201         Fill fill = styleFactory.createFill(
202                 filterFactory.literal(Color.CYAN),
203                 filterFactory.literal(0.5));
204 
205         /*
206          * Setting the geometryPropertyName arg to null signals that we want to
207          * draw the default geomettry of features
208          */
209         PolygonSymbolizer sym = styleFactory.createPolygonSymbolizer(stroke, fill, null);
210 
211         Rule rule = styleFactory.createRule();
212         rule.symbolizers().add(sym);
213         FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new Rule[]{rule});
214         Style style = styleFactory.createStyle();
215         style.featureTypeStyles().add(fts);
216 
217         return style;
218     }
219 
220     /**
221      * Create a Style to draw line features as thin blue lines
222      */
223     private Style createLineStyle() {
224         Stroke stroke = styleFactory.createStroke(
225                 filterFactory.literal(Color.BLUE),
226                 filterFactory.literal(1));
227 
228         /*
229          * Setting the geometryPropertyName arg to null signals that we want to
230          * draw the default geomettry of features
231          */
232         LineSymbolizer sym = styleFactory.createLineSymbolizer(stroke, null);
233 
234         Rule rule = styleFactory.createRule();
235         rule.symbolizers().add(sym);
236         FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new Rule[]{rule});
237         Style style = styleFactory.createStyle();
238         style.featureTypeStyles().add(fts);
239 
240         return style;
241     }
242 
243     /**
244      * Create a Style to draw point features as circles with blue outlines
245      * and cyan fill
246      */
247     private Style createPointStyle() {
248         Graphic gr = styleFactory.createDefaultGraphic();
249 
250         Mark mark = styleFactory.getCircleMark();
251 
252         mark.setStroke(styleFactory.createStroke(
253                 filterFactory.literal(Color.BLUE), filterFactory.literal(1)));
254 
255         mark.setFill(styleFactory.createFill(filterFactory.literal(Color.CYAN)));
256 
257         gr.graphicalSymbols().clear();
258         gr.graphicalSymbols().add(mark);
259         gr.setSize(filterFactory.literal(5));
260 
261         /*
262          * Setting the geometryPropertyName arg to null signals that we want to
263          * draw the default geomettry of features
264          */
265         PointSymbolizer sym = styleFactory.createPointSymbolizer(gr, null);
266 
267         Rule rule = styleFactory.createRule();
268         rule.symbolizers().add(sym);
269         FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(new Rule[]{rule});
270         Style style = styleFactory.createStyle();
271         style.featureTypeStyles().add(fts);
272 
273         return style;
274     }
275 
276 }
277 
278 // docs end source