//$HeadURL$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2008 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.igeo.views.swing.layerlist; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Iterator; import java.util.List; import java.util.Locale; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.GeometryUtils; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.dataadapter.DataAccessAdapter; import org.deegree.igeo.dataadapter.FeatureAdapter; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.Layer; import org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureCollection; import org.deegree.model.spatialschema.Curve; import org.deegree.model.spatialschema.Geometry; import org.deegree.model.spatialschema.GeometryException; import org.deegree.model.spatialschema.MultiCurve; import org.deegree.model.spatialschema.MultiPoint; import org.deegree.model.spatialschema.MultiSurface; import org.deegree.model.spatialschema.Point; import org.deegree.model.spatialschema.Ring; import org.deegree.model.spatialschema.Surface; import org.deegree.model.spatialschema.SurfaceBoundary; /** * Panel for calculating and displaying layer statistics. At the moment following statistical values - depending on * available geometry types - will be calculated/displayed: * <ul> * <li>number of features * <li>mean distance between features * <li>number of vertices * <li>mean number of vertices per feature * <li>number of polygon inner rings * <li>mean number of inner rings per polygon * <li>total area (polygons) * <li>mean area (polygons) * <li>max area (polygons) * <li>min area (polygons) * <li>total linestring length * <li>mean linestring length * <li>min linestring length * <li>max linestring length * <li>total boundary length (polygon) * <li>total inner boundary length (polygon) * <li>mean boundary length (polygon) * <li>mean inner boundary length (polygon) * <li>minimum outter boundary length * <li>maximum outter boundary length * </ul> * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ public class LayerStatisticPanel extends JPanel { private static final long serialVersionUID = 7309786709997995099L; private static final ILogger LOG = LoggerFactory.getLogger( LayerStatisticPanel.class ); @SuppressWarnings("unused") private ApplicationContainer<Container> appCont; /** * * @param appCont */ LayerStatisticPanel( ApplicationContainer<Container> appCont ) { this.appCont = appCont; } /** * * @param layer */ void init( Layer layer ) { String[] tabHeader = new String[] { Messages.getMessage( Locale.getDefault(), "$MD10111" ), Messages.getMessage( Locale.getDefault(), "$MD10112" ) }; Object[][] data = new Object[1][2]; List<DataAccessAdapter> list = layer.getDataAccess(); int cnt = 0; for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter && ( (FeatureAdapter) adapter ).getFeatureCollection() != null ) { cnt += ( (FeatureAdapter) adapter ).getFeatureCollection().size(); } } data[0][0] = Messages.getMessage( Locale.getDefault(), "$MD10113" ); data[0][1] = cnt; // TODO // add futher parameters JTable table = new JTable( new DefaultTableModel( data, tabHeader ) ); table.setAutoResizeMode( JTable.AUTO_RESIZE_ALL_COLUMNS ); JPanel center = new JPanel( new BorderLayout() ); center.add( table.getTableHeader(), BorderLayout.PAGE_START ); center.add( table, BorderLayout.CENTER ); JButton calcbt = new JButton( Messages.getMessage( Locale.getDefault(), "$MD10116" ) ); calcbt.addActionListener( new LSPActionListener( layer, table ) ); JPanel panel = new JPanel( new FlowLayout( FlowLayout.LEFT ) ); panel.add( calcbt ); center.add( panel, BorderLayout.SOUTH ); add( center, BorderLayout.CENTER ); } // /////////////////////////////////////////////////////////////////////////// // inner classes // /////////////////////////////////////////////////////////////////////////// /** * * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version. $Revision$, $Date$ */ private class LSPActionListener implements ActionListener { private JTable table; private Layer layer; /** * * @param layer * @param table * @param noOfFeat */ LSPActionListener( Layer layer, JTable table ) { this.layer = layer; this.table = table; } /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed( ActionEvent evt ) { DefaultTableModel model = (DefaultTableModel) table.getModel(); addDistance( model ); addArea( model ); addLength( model ); try { addBoundary( model ); addVertices( model ); } catch ( Exception e ) { LOG.logWarning( "ignore", e ); } } private void addVertices( DefaultTableModel model ) throws GeometryException { float cnt = 0; float vcnt = 0; List<DataAccessAdapter> list = layer.getDataAccess(); for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter ) { FeatureCollection fc = ( (FeatureAdapter) adapter ).getFeatureCollection(); cnt = fc.size(); Iterator<Feature> iterator = fc.iterator(); while ( iterator.hasNext() ) { Feature feature = iterator.next(); Geometry geom = feature.getDefaultGeometryPropertyValue(); if ( geom instanceof Point ) { vcnt++; } else if ( geom instanceof MultiPoint ) { vcnt += ( (MultiPoint) geom ).getSize(); } else if ( geom instanceof Curve ) { vcnt += ( (Curve) geom ).getAsLineString().getNumberOfPoints(); } else if ( geom instanceof MultiCurve ) { Curve[] curves = ( (MultiCurve) geom ).getAllCurves(); for ( Curve curve : curves ) { vcnt += curve.getAsLineString().getNumberOfPoints(); } } else if ( geom instanceof Surface ) { SurfaceBoundary sb = ( (Surface) geom ).getSurfaceBoundary(); vcnt += sb.getExteriorRing().getPositions().length; Ring[] rings = sb.getInteriorRings(); for ( Ring ring : rings ) { vcnt += ring.getPositions().length; } } else if ( geom instanceof MultiSurface ) { Surface[] surfaces = ( (MultiSurface) geom ).getAllSurfaces(); for ( Surface surface : surfaces ) { SurfaceBoundary sb = surface.getSurfaceBoundary(); vcnt += sb.getExteriorRing().getPositions().length; Ring[] rings = sb.getInteriorRings(); for ( Ring ring : rings ) { vcnt += ring.getPositions().length; } } } } } } Object[] rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10494" ); rowData[1] = (int) vcnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10495" ); rowData[1] = vcnt / cnt; model.addRow( rowData ); } private void addBoundary( DefaultTableModel model ) throws Exception { List<DataAccessAdapter> list = layer.getDataAccess(); // number of surfaces/multisurfaces float cnt = 0; // number of iner rings float icnt = 0; // length of outter boundaries double meanLength = 0; // outter boundaries min length double minLength = Double.MAX_VALUE; // outter boundaries max length double maxLength = Double.MIN_VALUE; // length of inner boundaries double innerLength = Double.MIN_VALUE; float holes = 0; for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter ) { FeatureCollection fc = ( (FeatureAdapter) adapter ).getFeatureCollection(); Iterator<Feature> iterator = fc.iterator(); while ( iterator.hasNext() ) { Feature feature = iterator.next(); Geometry geom = feature.getDefaultGeometryPropertyValue(); double a = 0; double b = 0; if ( geom instanceof Surface ) { SurfaceBoundary sb = ( (Surface) geom ).getSurfaceBoundary(); a = sb.getExteriorRing().getAsCurveSegment().getLength(); Ring[] rings = sb.getInteriorRings(); holes += rings.length; for ( Ring ring : rings ) { b += ring.getAsCurveSegment().getLength(); icnt++; } } if ( geom instanceof MultiSurface ) { Surface[] surfaces = ( (MultiSurface) geom ).getAllSurfaces(); for ( Surface surface : surfaces ) { SurfaceBoundary sb = surface.getSurfaceBoundary(); a = sb.getExteriorRing().getAsCurveSegment().getLength(); Ring[] rings = sb.getInteriorRings(); holes += rings.length; for ( Ring ring : rings ) { b += ring.getAsCurveSegment().getLength(); icnt++; } } } if ( a > 0 ) { meanLength += a; innerLength += b; cnt++; if ( a < minLength ) { minLength = a; } if ( a > maxLength ) { maxLength = a; } } } } } if ( meanLength > 0 ) { Object[] rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10486" ); rowData[1] = ( meanLength + innerLength ) / cnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10487" ); rowData[1] = minLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10488" ); rowData[1] = maxLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10489" ); rowData[1] = meanLength + innerLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10490" ); rowData[1] = (int) icnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10493" ); rowData[1] = icnt / cnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10491" ); rowData[1] = innerLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10492" ); rowData[1] = innerLength / icnt; model.addRow( rowData ); } } private void addLength( DefaultTableModel model ) { List<DataAccessAdapter> list = layer.getDataAccess(); // number of curves/multicurves float cnt = 0; // curves length double meanLength = 0; // curves minimum length double minLength = Double.MAX_VALUE; // curves maximum length double maxLength = Double.MIN_VALUE; for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter ) { FeatureCollection fc = ( (FeatureAdapter) adapter ).getFeatureCollection(); Iterator<Feature> iterator = fc.iterator(); while ( iterator.hasNext() ) { Feature feature = iterator.next(); Geometry geom = feature.getDefaultGeometryPropertyValue(); double a = 0; if ( geom instanceof Curve ) { a = ( (Curve) geom ).getLength(); } if ( geom instanceof MultiCurve ) { Curve[] curves = ( (MultiCurve) geom ).getAllCurves(); for ( Curve curve : curves ) { a += curve.getLength(); } } if ( a > 0 ) { meanLength += a; cnt++; if ( a < minLength ) { minLength = a; } if ( a > maxLength ) { maxLength = a; } } } } } if ( meanLength > 0 ) { Object[] rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10482" ); rowData[1] = meanLength / cnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10483" ); rowData[1] = minLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10484" ); rowData[1] = maxLength; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10485" ); rowData[1] = meanLength; model.addRow( rowData ); } } private void addArea( DefaultTableModel model ) { List<DataAccessAdapter> list = layer.getDataAccess(); // number of surfaces/multisurfaces float cnt = 0; // surfaces area double meanArea = 0; // surfaces minimum area double minArea = Double.MAX_VALUE; // surfaces minimum area double maxArea = Double.MIN_VALUE; for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter ) { FeatureCollection fc = ( (FeatureAdapter) adapter ).getFeatureCollection(); Iterator<Feature> iterator = fc.iterator(); while ( iterator.hasNext() ) { Feature feature = iterator.next(); Geometry geom = feature.getDefaultGeometryPropertyValue(); double a = 0; if ( geom instanceof Surface ) { a = ( (Surface) geom ).getArea(); } if ( geom instanceof MultiSurface ) { a = ( (MultiSurface) geom ).getArea(); } if ( a > 0 ) { meanArea += a; cnt++; if ( a < minArea ) { minArea = a; } if ( a > maxArea ) { maxArea = a; } } } } } if ( meanArea > 0 ) { Object[] rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10478" ); rowData[1] = meanArea / cnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10479" ); rowData[1] = minArea; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10480" ); rowData[1] = maxArea; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10481" ); rowData[1] = meanArea; model.addRow( rowData ); } } private void addDistance( DefaultTableModel model ) { List<DataAccessAdapter> list = layer.getDataAccess(); float cnt = 0; double meanDist = 0; double minDist = Double.MAX_VALUE; double maxDist = Double.MIN_VALUE; for ( DataAccessAdapter adapter : list ) { if ( adapter instanceof FeatureAdapter ) { FeatureCollection fc = ( (FeatureAdapter) adapter ).getFeatureCollection(); Feature[] f1 = fc.toArray(); for ( int i = 0; i < f1.length; i++ ) { Point p1 = f1[i].getDefaultGeometryPropertyValue().getCentroid(); for ( int j = i + 1; j < f1.length; j++ ) { Point p2 = f1[j].getDefaultGeometryPropertyValue().getCentroid(); double d = GeometryUtils.distance( p1.getPosition(), p2.getPosition() ); meanDist += d; if ( d < minDist ) { minDist = d; } if ( d > maxDist ) { maxDist = d; } cnt++; } } } } Object[] rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10475" ); rowData[1] = meanDist / cnt; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10476" ); rowData[1] = minDist; model.addRow( rowData ); rowData = new Object[2]; rowData[0] = Messages.getMessage( Locale.getDefault(), "$MD10477" ); rowData[1] = maxDist; model.addRow( rowData ); } } }