/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2003-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.gui.swing.map.map2d.stream.handler; import java.awt.Cursor; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.ImageIcon; import org.geotools.data.DataStore; import org.geotools.data.DataUtilities; import org.geotools.data.DefaultTransaction; import org.geotools.data.FeatureSource; import org.geotools.data.FeatureStore; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.GeoTools; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureCollections; import org.geotools.feature.FeatureIterator; import org.geotools.feature.SchemaException; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.gui.swing.icon.IconBundle; import org.geotools.gui.swing.map.map2d.stream.EditableMap2D; import org.geotools.gui.swing.map.map2d.stream.TempMemoryDataStore; import org.geotools.map.DefaultMapLayer; import org.geotools.map.MapLayer; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import org.geotools.gui.swing.map.map2d.stream.strategy.StreamingStrategy; import org.geotools.gui.swing.misc.FacilitiesFactory; import org.geotools.gui.swing.misc.GeometryClassFilter; import org.geotools.styling.Rule; import org.geotools.styling.Style; import org.geotools.styling.StyleBuilder; import org.geotools.styling.Symbolizer; /** * Abstract edition handler * * @author Johann Sorel */ abstract class AbstractEditionHandler implements EditionHandler { protected final StyleBuilder STYLE_BUILDER = new StyleBuilder(); protected final FacilitiesFactory FACILITIES_FACTORY = new FacilitiesFactory(); protected final ImageIcon ICON; protected final String title; protected static final Coordinate[] EMPTY_COORDINATE_ARRAY = new Coordinate[0]; protected final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(); protected final SpecialMouseListener mouseInputListener; protected EditableMap2D map2D = null; protected boolean installed = false; protected Cursor CUR_EDIT; protected MapLayer memoryLayer; protected MapLayer edgesLayer; public AbstractEditionHandler() { buildCursors(); mouseInputListener = createMouseListener(); ICON = createIcon(); title = createTitle(); } protected abstract SpecialMouseListener createMouseListener(); protected abstract ImageIcon createIcon(); protected abstract String createTitle(); protected void buildCursors() { Toolkit tk = Toolkit.getDefaultToolkit(); ImageIcon eci_edit = IconBundle.getResource().getIcon("16_edit"); BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); img.getGraphics().drawImage(eci_edit.getImage(), 0, 0, null); CUR_EDIT = tk.createCustomCursor(img, new java.awt.Point(7, 1), "edit"); } private Style createPointStyle() { Style pointSelectionStyle = STYLE_BUILDER.createStyle(); pointSelectionStyle.addFeatureTypeStyle(STYLE_BUILDER.createFeatureTypeStyle(map2D.getPointSymbolizer())); return pointSelectionStyle; } private Style createStyle() { Rule r2 = STYLE_BUILDER.createRule(new Symbolizer[]{map2D.getLineSymbolizer()}); r2.setFilter(new GeometryClassFilter(LineString.class, MultiLineString.class)); Rule r3 = STYLE_BUILDER.createRule(new Symbolizer[]{map2D.getPolygonSymbolizer()}); r3.setFilter(new GeometryClassFilter(Polygon.class, MultiPolygon.class)); Style editionStyle = STYLE_BUILDER.createStyle(); editionStyle.addFeatureTypeStyle(STYLE_BUILDER.createFeatureTypeStyle(null, new Rule[]{r2, r3})); return editionStyle; } public void install(EditableMap2D map) { installed = true; map2D = map; //create the memory layers---------------------------------------------- TempMemoryDataStore mds = new TempMemoryDataStore(); SimpleFeatureType featureType = null; MapLayer layer = null; try { featureType = DataUtilities.createType("memory", "geom:Geometry"); } catch (SchemaException se) { se.printStackTrace(); } if (featureType != null) { try { mds.createSchema(featureType); FeatureSource<SimpleFeatureType, SimpleFeature> fs = ((DataStore) mds).getFeatureSource(((DataStore) mds).getTypeNames()[0]); layer = new DefaultMapLayer(fs, createStyle()); } catch (IOException se) { se.printStackTrace(); } } memoryLayer = layer; mds = new TempMemoryDataStore(); featureType = null; layer = null; try { featureType = DataUtilities.createType("memory", "geom:Point"); } catch (SchemaException se) { se.printStackTrace(); } if (featureType != null) { try { mds.createSchema(featureType); FeatureSource<SimpleFeatureType, SimpleFeature> fs = ((DataStore) mds).getFeatureSource(((DataStore) mds).getTypeNames()[0]); layer = new DefaultMapLayer(fs, createPointStyle()); } catch (IOException se) { se.printStackTrace(); } } edgesLayer = layer; map2D.setMemoryLayers(new MapLayer[]{memoryLayer, edgesLayer}); } public void installListeners(EditableMap2D map2d) { map2D = map2d; map2D.getComponent().addMouseListener(mouseInputListener); map2D.getComponent().addMouseMotionListener(mouseInputListener); } public void uninstallListeners() { map2D.getComponent().removeMouseListener(mouseInputListener); map2D.getComponent().removeMouseMotionListener(mouseInputListener); } public void uninstall() { map2D.setMemoryLayers(new MapLayer[0]); map2D = null; installed = false; } public boolean isInstalled() { return installed; } public void cancelEdition() { clearMemoryLayer(); mouseInputListener.fireStateChange(); map2D.repaintMemoryDecoration(); } public String getTitle() { return title; } public ImageIcon getIcon() { return ICON; } //--------------------Geometry Edition-------------------------------------- /** * transform a mouse coordinate in JTS Geometry using the CRS of the mapcontext * @param mx : x coordinate of the mouse on the map (in pixel) * @param my : y coordinate of the mouse on the map (in pixel) * @return JTS geometry (corresponding to a square of 6x6 pixel around mouse coordinate) */ protected Geometry mousePositionToGeometry(int mx, int my) { Coordinate[] coord = new Coordinate[5]; int taille = 4; StreamingStrategy strategy = map2D.getRenderingStrategy(); coord[0] = strategy.toMapCoord(mx - taille, my - taille); coord[1] = strategy.toMapCoord(mx - taille, my + taille); coord[2] = strategy.toMapCoord(mx + taille, my + taille); coord[3] = strategy.toMapCoord(mx + taille, my - taille); coord[4] = coord[0]; LinearRing lr1 = GEOMETRY_FACTORY.createLinearRing(coord); return GEOMETRY_FACTORY.createPolygon(lr1, null); } protected Point createPoint(Coordinate coord) { return GEOMETRY_FACTORY.createPoint(coord); } protected MultiPoint createMultiPoint(List<Geometry> geoms) { List<Point> lst = new ArrayList<Point>(); for (Geometry go : geoms) { if (go instanceof Point) { lst.add((Point) go); } } return GEOMETRY_FACTORY.createMultiPoint(lst.toArray(new Point[lst.size()])); } protected LineString createLine(List<Coordinate> coords) { return GEOMETRY_FACTORY.createLineString(coords.toArray(EMPTY_COORDINATE_ARRAY)); } protected LinearRing createLinearRing(List<Coordinate> coords) { if (!(coords.get(0).equals2D(coords.get(coords.size() - 1)))) { Coordinate coo = new Coordinate(coords.get(0)); coords.add(coo); } return GEOMETRY_FACTORY.createLinearRing(coords.toArray(EMPTY_COORDINATE_ARRAY)); } protected Polygon createPolygon(List<Coordinate> coords) { LinearRing ring = createLinearRing(coords); return GEOMETRY_FACTORY.createPolygon(ring, null); } protected MultiPolygon createMultiPolygon(List<Geometry> geoms) { List<Polygon> lst = new ArrayList<Polygon>(); for (Geometry go : geoms) { if (go instanceof Polygon) { lst.add((Polygon) go); } } return GEOMETRY_FACTORY.createMultiPolygon(lst.toArray(new Polygon[lst.size()])); } protected MultiLineString createMultiLine(List<Geometry> geoms) { List<LineString> lst = new ArrayList<LineString>(); for (Geometry go : geoms) { if (go instanceof LineString) { lst.add((LineString) go); } } return GEOMETRY_FACTORY.createMultiLineString(lst.toArray(new LineString[lst.size()])); } protected synchronized void editAddGeometry(Geometry[] geoms) { MapLayer editionLayer = map2D.getEditedMapLayer(); if (editionLayer != null) { for (Geometry geom : geoms) { SimpleFeatureType featureType = (SimpleFeatureType) editionLayer.getFeatureSource().getSchema(); FeatureCollection<SimpleFeatureType, SimpleFeature> collection = FeatureCollections.newCollection(); Object[] values = new Object[featureType.getAttributeCount()]; AttributeDescriptor geomAttribut = featureType.getGeometryDescriptor(); geom = FACILITIES_FACTORY.projectGeometry(geom, map2D.getRenderingStrategy().getContext(), editionLayer); List<AttributeDescriptor> lst = featureType.getAttributeDescriptors(); for (int i = 0, n = lst.size(); i < n; i++) { AttributeDescriptor desc = lst.get(i); if (desc.equals(geomAttribut)) { values[i] = geom; } else { values[i] = desc.getDefaultValue(); } } SimpleFeature sf = SimpleFeatureBuilder.build(featureType, values, null); collection.add(sf); //commit in shape DataStore data = (DataStore) editionLayer.getFeatureSource().getDataStore(); DefaultTransaction transaction = null; FeatureStore<SimpleFeatureType, SimpleFeature> store = null; try { // String featureName = data.getTypeNames()[0]; // there is only one in a shapefile // Create the DefaultTransaction Object transaction = new DefaultTransaction(); // String name = editionLayer.getFeatureSource().getName().getLocalPart(); // try { // //GR: question: why not just editionLayer.getFeatureSource()? // FeatureSource<SimpleFeatureType, SimpleFeature> source = ((DataStore) editionLayer.getFeatureSource().getDataStore()).getFeatureSource(name); // store = (FeatureStore<SimpleFeatureType, SimpleFeature>) source; // } catch (IOException e) { // // Tell it the name of the shapefile it should look for in our DataStore // store = (FeatureStore<SimpleFeatureType, SimpleFeature>) data.getFeatureSource(featureName); // } store = (FeatureStore<SimpleFeatureType, SimpleFeature>) editionLayer.getFeatureSource(); // Then set the transaction for that FeatureStore store.setTransaction(transaction); store.addFeatures(collection); transaction.commit(); } catch (Exception eek) { eek.printStackTrace(); try { store.getTransaction().rollback(); } catch (IOException e) { e.printStackTrace(); } } finally { transaction.close(); } } } } protected synchronized void validateModifiedGeometry(final Geometry geo, final String ID) { if (geo == null || ID == null) { throw new NullPointerException(); } MapLayer editionLayer = map2D.getEditedMapLayer(); FeatureStore<SimpleFeatureType, SimpleFeature> store; if (editionLayer.getFeatureSource() instanceof FeatureStore) { // String name = editionLayer.getFeatureSource().getName().getLocalPart(); // try { // //GR question: why not just editionLayer.getFeatureSource()? // FeatureSource<SimpleFeatureType, SimpleFeature> source = ((DataStore) editionLayer.getFeatureSource().getDataStore()).getFeatureSource(name); // store = (FeatureStore<SimpleFeatureType, SimpleFeature>) source; // } catch (IOException e) { // store = (FeatureStore<SimpleFeatureType, SimpleFeature>) editionLayer.getFeatureSource(); // } store = (FeatureStore<SimpleFeatureType, SimpleFeature>) editionLayer.getFeatureSource(); // store.getDataStore().dispose(); DefaultTransaction transaction = new DefaultTransaction("trans_maj"); // Transaction previoustransaction = store.getTransaction(); store.setTransaction(transaction); FilterFactory ff = CommonFactoryFinder.getFilterFactory(GeoTools.getDefaultHints()); Filter filter = ff.id(Collections.singleton(ff.featureId(ID))); SimpleFeatureType featureType = (SimpleFeatureType) editionLayer.getFeatureSource().getSchema(); AttributeDescriptor geomAttribut = featureType.getGeometryDescriptor(); Geometry geom = FACILITIES_FACTORY.projectGeometry(geo, map2D.getRenderingStrategy().getContext(), editionLayer); try { store.modifyFeatures(geomAttribut, geom, filter); transaction.commit(); } catch (IOException ex) { ex.printStackTrace(); try { transaction.rollback(); } catch (IOException e) { e.printStackTrace(); } } finally { transaction.close(); // store.setTransaction(Transaction.AUTO_COMMIT); } } } //---------------------Memory Layer----------------------------------------- protected synchronized void setMemoryLayerGeometry(List<Geometry> geoms) { if (memoryLayer != null) { //memory layer-------------------------- FeatureCollection<SimpleFeatureType, SimpleFeature> collection = FeatureCollections.newCollection(); for (Geometry geom : geoms) { //geom = projectGeometry(geom, memoryLayer); SimpleFeatureType featureType = (SimpleFeatureType) memoryLayer.getFeatureSource().getSchema(); Object[] values = new Object[featureType.getAttributeCount()]; AttributeDescriptor geomAttribut = featureType.getGeometryDescriptor(); List<AttributeDescriptor> lst = featureType.getAttributeDescriptors(); for (int i = 0, n = lst.size(); i < n; i++) { AttributeDescriptor desc = lst.get(i); values[i] = (desc.equals(geomAttribut)) ? geom : desc.getDefaultValue(); } SimpleFeature sf = SimpleFeatureBuilder.build(featureType, values, null); collection.add(sf); } //commit FeatureStore<SimpleFeatureType, SimpleFeature> store = (FeatureStore<SimpleFeatureType, SimpleFeature>) memoryLayer.getFeatureSource(); try { store.addFeatures(collection); } catch (Exception eek) { eek.printStackTrace(); } //edges layer -------------------------------- collection = FeatureCollections.newCollection(); for (Geometry geom : geoms) { Coordinate[] coords = geom.getCoordinates(); for (Coordinate coord : coords) { //geom = projectGeometry(geom, memoryLayer); SimpleFeatureType featureType = (SimpleFeatureType) edgesLayer.getFeatureSource().getSchema(); Object[] values = new Object[featureType.getAttributeCount()]; AttributeDescriptor geomAttribut = featureType.getGeometryDescriptor(); List<AttributeDescriptor> lst = featureType.getAttributeDescriptors(); for (int i = 0, n = lst.size(); i < n; i++) { AttributeDescriptor desc = lst.get(i); if (desc.equals(geomAttribut)) { values[i] = GEOMETRY_FACTORY.createPoint(coord); } else { values[i] = desc.getDefaultValue(); } } //featureType. SimpleFeature sf = SimpleFeatureBuilder.build(featureType, values, null); collection.add(sf); } //commit store = (FeatureStore<SimpleFeatureType, SimpleFeature>) edgesLayer.getFeatureSource(); try { store.addFeatures(collection); } catch (Exception eek) { eek.printStackTrace(); } } } map2D.repaintMemoryDecoration(); } protected synchronized void clearMemoryLayer() { try { FeatureStore<SimpleFeatureType, SimpleFeature> fst = (FeatureStore<SimpleFeatureType, SimpleFeature>) memoryLayer.getFeatureSource(); fst.removeFeatures(Filter.INCLUDE); fst = (FeatureStore<SimpleFeatureType, SimpleFeature>) edgesLayer.getFeatureSource(); fst.removeFeatures(Filter.INCLUDE); } catch (Exception e) { e.printStackTrace(); } map2D.repaintMemoryDecoration(); } protected synchronized void reprojectEditionLayer() { List<Geometry> geoms = new ArrayList<Geometry>(); List<Geometry> geomsOut = new ArrayList<Geometry>(); try { FeatureCollection<SimpleFeatureType, SimpleFeature> col = (FeatureCollection<SimpleFeatureType, SimpleFeature>) memoryLayer.getFeatureSource().getFeatures(); FeatureIterator<SimpleFeature> ite = col.features(); while (ite.hasNext()) { SimpleFeature sf = ite.next(); geoms.add((Geometry) sf.getDefaultGeometry()); } ite.close(); } catch (IOException ex) { ex.printStackTrace(); } for (Geometry geo : geoms) { geomsOut.add(FACILITIES_FACTORY.projectGeometry(geo, map2D.getRenderingStrategy().getContext().getCoordinateReferenceSystem(), map2D.getRenderingStrategy().getContext().getCoordinateReferenceSystem())); //geomsOut.add(map2D.projectGeometry(geo, memoryMapContext.getCoordinateReferenceSystem(), map2D.getRenderingStrategy().getContext().getCoordinateReferenceSystem())); } clearMemoryLayer(); setMemoryLayerGeometry(geomsOut); } }