001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/SurfaceBoundaryImpl.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.model.spatialschema;
045    
046    import java.io.Serializable;
047    import java.util.Arrays;
048    
049    import org.deegree.framework.log.ILogger;
050    import org.deegree.framework.log.LoggerFactory;
051    
052    /**
053     * default implementation of the SurfaceBoundary interface.
054     * 
055     * ------------------------------------------------------------
056     * 
057     * @version 11.6.2001
058     * @author Andreas Poth href="mailto:poth@lat-lon.de"
059     */
060    
061    class SurfaceBoundaryImpl extends PrimitiveBoundaryImpl implements SurfaceBoundary, Serializable {
062        /** Use serialVersionUID for interoperability. */
063        private final static long serialVersionUID = 1399131144729310956L;
064    
065        private static final ILogger LOG = LoggerFactory.getLogger( SurfaceBoundaryImpl.class );
066    
067        public Ring exterior = null;
068    
069        public Ring[] interior = null;
070    
071        /**
072         * constructor
073         */
074        public SurfaceBoundaryImpl( Ring exterior, Ring[] interior ) {
075            super( exterior.getCoordinateSystem() );
076            this.exterior = exterior;
077            this.interior = interior;
078            setValid( false );
079        }
080    
081        /**
082         * gets the exterior ring
083         */
084        public Ring getExteriorRing() {
085            return exterior;
086        }
087    
088        /**
089         * gets the interior ring(s)
090         */
091        public Ring[] getInteriorRings() {
092            return interior;
093        }
094    
095        /**
096         * returns the boundary of the boundary
097         */
098        public Boundary getBoundary() {
099            return null;
100        }
101    
102        /**
103         * checks if this curve is completly equal to the submitted geometry
104         * 
105         * @param other
106         *            object to compare to
107         */
108        public boolean equals( Object other ) {
109            if ( !super.equals( other ) || !( other instanceof SurfaceBoundaryImpl ) ) {
110                return false;
111            }
112    
113            if ( !exterior.equals( ( (SurfaceBoundary) other ).getExteriorRing() ) ) {
114                return false;
115            }
116    
117            if ( interior != null ) {
118                Ring[] r1 = getInteriorRings();
119                Ring[] r2 = ( (SurfaceBoundary) other ).getInteriorRings();
120    
121                if ( !Arrays.equals( r1, r2 ) ) {
122                    return false;
123                }
124            } else {
125                if ( ( (SurfaceBoundary) other ).getInteriorRings() != null ) {
126                    return false;
127                }
128            }
129    
130            return true;
131        }
132    
133        /**
134         * The operation "dimension" shall return the inherent dimension of this Geometry, which shall
135         * be less than or equal to the coordinate dimension. The dimension of a collection of geometric
136         * objects shall be the largest dimension of any of its pieces. Points are 0-dimensional, curves
137         * are 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional.
138         */
139        public int getDimension() {
140            return 1;
141        }
142    
143        /**
144         * The operation "coordinateDimension" shall return the dimension of the coordinates that define
145         * this Geometry, which must be the same as the coordinate dimension of the coordinate reference
146         * system for this Geometry.
147         */
148        public int getCoordinateDimension() {
149            return exterior.getPositions()[0].getCoordinateDimension();
150        }
151    
152        /**
153         * returns a copy of the geometry
154         */
155        public Object clone() {
156            SurfaceBoundary sb = null;
157    
158            try {
159                Ring ext = (Ring) ( (RingImpl) getExteriorRing() ).clone();
160                Ring[] inn = new Ring[interior.length];
161    
162                for ( int i = 0; i < inn.length; i++ ) {
163                    inn[i] = (Ring) ( (RingImpl) interior[i] ).clone();
164                }
165    
166                sb = new SurfaceBoundaryImpl( ext, inn );
167            } catch ( Exception ex ) {
168                LOG.logError( "SurfaceBoundary_Impl.clone: ", ex );
169            }
170    
171            return sb;
172        }
173    
174        /**
175         * The Boolean valued operation "intersects" shall return TRUE if this Geometry intersects
176         * another Geometry. Within a Complex, the Primitives do not intersect one another. In general,
177         * topologically structured data uses shared geometric objects to capture intersection
178         * information.
179         */
180        public boolean intersects( Geometry gmo ) {
181            boolean inter = exterior.intersects( gmo );
182    
183            if ( !inter ) {
184                if ( interior != null ) {
185                    for ( int i = 0; i < interior.length; i++ ) {
186                        if ( interior[i].intersects( gmo ) ) {
187                            inter = true;
188                            break;
189                        }
190                    }
191                }
192            }
193    
194            return inter;
195        }
196    
197        /**
198         * The Boolean valued operation "contains" shall return TRUE if this Geometry contains another
199         * Geometry.
200         * <p>
201         * </p>
202         * At the moment the operation just works with point geometries
203         */
204        public boolean contains( Geometry gmo ) {
205            boolean con = false;
206    
207            con = exterior.contains( gmo );
208    
209            if ( con ) {
210                if ( interior != null ) {
211                    for ( int i = 0; i < interior.length; i++ ) {
212                        if ( interior[i].intersects( gmo ) ) {
213                            con = false;
214                            break;
215                        }
216                    }
217                }
218            }
219    
220            return con;
221        }
222    
223        /**
224         * The Boolean valued operation "contains" shall return TRUE if this Geometry contains a single
225         * point given by a coordinate.
226         * <p>
227         * </p>
228         * dummy implementation
229         */
230        public boolean contains( Position position ) {
231            return contains( new PointImpl( position, null ) );
232        }
233    
234        /**
235         * calculates the envelope of the surface boundary
236         */
237        private void calculateEnvelope() {
238            envelope = (Envelope) ( (EnvelopeImpl) exterior.getEnvelope() ).clone();
239        }
240    
241        /**
242         * calculates the centroid of the surface boundary
243         */
244        private void calculateCentroid() {
245            try {
246                double[] cen = exterior.getCentroid().getAsArray().clone();
247                double cnt = exterior.getAsCurveSegment().getNumberOfPoints();
248    
249                for ( int i = 0; i < cen.length; i++ ) {
250                    cen[i] *= cnt;
251                }
252    
253                if ( interior != null ) {
254                    for ( int i = 0; i < interior.length; i++ ) {
255                        double[] pos = interior[i].getCentroid().getAsArray();
256                        cnt += interior[i].getAsCurveSegment().getNumberOfPoints();
257    
258                        for ( int j = 0; j < pos.length; j++ ) {
259                            cen[j] += ( pos[j] * interior[i].getAsCurveSegment().getNumberOfPoints() );
260                        }
261                    }
262                }
263    
264                for ( int j = 0; j < cen.length; j++ ) {
265                    cen[j] /= cnt;
266                }
267    
268                centroid = new PointImpl( new PositionImpl( cen ), crs );
269            } catch ( Exception ex ) {
270                LOG.logError( "", ex );
271            }
272        }
273    
274        /**
275         * calculates the centroid and the envelope of the surface boundary
276         */
277        protected void calculateParam() {
278            calculateEnvelope();
279            calculateCentroid();
280            setValid( true );
281        }
282    
283        /**
284         * 
285         * 
286         * @return
287         */
288        public String toString() {
289            String ret = null;
290            ret = "interior = " + interior + "\n";
291            ret += ( "exterior = " + exterior + "\n" );
292            return ret;
293        }
294    }