/* Spatial Operations & Editing Tools for uDig * * Axios Engineering under a funding contract with: * Diputación Foral de Gipuzkoa, Ordenación Territorial * * http://b5m.gipuzkoa.net * http://www.axios.es * * (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT). * DFG-OT agrees to licence under Lesser General Public License (LGPL). * * 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 es.axios.udig.ui.editingtools.precisiontools.commons.internal; import java.io.IOException; import net.refractions.udig.project.ILayer; import net.refractions.udig.project.internal.ProjectPlugin; import net.refractions.udig.project.ui.render.displayAdapter.MapMouseEvent; import net.refractions.udig.tools.edit.EditToolHandler; import net.refractions.udig.tools.edit.preferences.PreferenceUtil; import net.refractions.udig.tools.edit.support.SnapBehaviour; 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.FeatureIterator; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.feature.type.Name; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; import org.opengis.filter.spatial.BBOX; import org.opengis.referencing.FactoryException; import org.opengis.referencing.operation.TransformException; /** * Utility class. * * @author Aritz Davila (www.axios.es) * @author Mauricio Pazos (www.axios.es) */ public class PrecisionToolsUtil { private PrecisionToolsUtil() { // utility class pattern } /** * Search if there is a feature under cursor position. If snap is off, * search on a little bbox around cursor, if it's on, search around an * accurate bbox similar to the snap area. * * @return True if its a feature under the cursor position, false otherwise. */ public static boolean isFeatureUnderCursor(EditToolHandler handler, MapMouseEvent e) { int snapRadious = 5; // if snap is on, set an accurate snapRadious to use later for // getting // its area. if (PreferenceUtil.instance().getSnapBehaviour() != SnapBehaviour.OFF) { snapRadious = PreferenceUtil.instance().getSnappingRadius() + (PreferenceUtil.instance().getSnappingRadius() / 2); } // transforms the bbox to the layer crs ReferencedEnvelope bbox = handler.getContext().getBoundingBox(e.getPoint(), snapRadious); try { bbox = bbox.transform(handler.getEditLayer().getCRS(), true); } catch (TransformException te) { te.printStackTrace(); } catch (FactoryException fe) { fe.printStackTrace(); } FeatureCollection<SimpleFeatureType, SimpleFeature> collection = null; FeatureIterator<SimpleFeature> iterator = null; try { Class<? extends Filter> filterType = BBOX.class; FeatureStore<SimpleFeatureType, SimpleFeature> store = handler.getEditLayer().getResource( FeatureStore.class, null); Filter createBBoxFilter = createBBoxFilter(bbox, handler.getEditLayer(), filterType); collection = store.getFeatures(createBBoxFilter); iterator = collection.features(); if (iterator.hasNext()) { return true; } } catch (IOException e1) { e1.printStackTrace(); } finally { if (iterator != null) { collection.close(iterator); } } return false; } /** * Creates A geometry filter for the given layer. * * @param boundingBox * in the same crs as the viewport model. * @return a Geometry filter in the correct CRS or null if an exception * occurs. */ private static Filter createBBoxFilter( ReferencedEnvelope boundingBox, ILayer layer, Class<? extends Filter> filterType) { FilterFactory2 factory = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); if (!layer.hasResource(FeatureSource.class)) return Filter.EXCLUDE; try { SimpleFeatureType schema = layer.getSchema(); Name geom = getGeometryAttDescriptor(schema).getName(); Filter bboxFilter = factory.bbox(factory.property(geom), boundingBox); return bboxFilter; } catch (Exception e) { ProjectPlugin.getPlugin().log(e); return Filter.EXCLUDE; } } private static GeometryDescriptor getGeometryAttDescriptor(SimpleFeatureType schema) { return schema.getGeometryDescriptor(); } /** * Get the feature under the cursor, the first one if there are more than * one. Return null if there isn't feature under the cursor. TODO improve * the case when there are more than 1 feature under the cursor. * * @param handler * @param e * @return */ public static SimpleFeature getFeatureUnderCursor(EditToolHandler handler, MapMouseEvent e) { int snapRadious = 5; // if snap is on, set an accurate snapRadious to use later for // getting // its area. if (PreferenceUtil.instance().getSnapBehaviour() != SnapBehaviour.OFF) { snapRadious = PreferenceUtil.instance().getSnappingRadius() + (PreferenceUtil.instance().getSnappingRadius() / 2); } // transforms the bbox to the layer crs ReferencedEnvelope bbox = handler.getContext().getBoundingBox(e.getPoint(), snapRadious); try { bbox = bbox.transform(handler.getEditLayer().getCRS(), true); } catch (TransformException te) { te.printStackTrace(); } catch (FactoryException fe) { fe.printStackTrace(); } FeatureCollection<SimpleFeatureType, SimpleFeature> collection = null; FeatureIterator<SimpleFeature> iterator = null; try { Class<? extends Filter> filterType = BBOX.class; FeatureStore<SimpleFeatureType, SimpleFeature> store = handler.getEditLayer().getResource( FeatureStore.class, null); Filter createBBoxFilter = createBBoxFilter(bbox, handler.getEditLayer(), filterType); collection = store.getFeatures(createBBoxFilter); iterator = collection.features(); if (iterator.hasNext()) { return iterator.next(); } } catch (IOException e1) { e1.printStackTrace(); } finally { if (iterator != null) { collection.close(iterator); } } return null; } }