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