001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/spatialschema/SurfaceBoundaryImpl.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004    This file is part of deegree.
005    Copyright (C) 2001-2006 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     * @version 11.6.2001
057     * @author Andreas Poth href="mailto:poth@lat-lon.de"
058     */
059    
060    class SurfaceBoundaryImpl extends PrimitiveBoundaryImpl implements SurfaceBoundary,
061                                                                               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        public Ring[] interior = null;
069    
070        /**
071         * constructor
072         */
073        public SurfaceBoundaryImpl( Ring exterior, Ring[] interior ) {
074            super( exterior.getCoordinateSystem() );
075            this.exterior = exterior;
076            this.interior = interior;
077            setValid( false );
078        }
079    
080        /**
081         * gets the exterior ring
082         */
083        public Ring getExteriorRing() {
084            return exterior;
085        }
086    
087        /**
088         * gets the interior ring(s)
089         */
090        public Ring[] getInteriorRings() {
091            return interior;
092        }
093    
094        /**
095         * returns the boundary of the boundary
096         */
097        public Boundary getBoundary() {
098            return null;
099        }
100    
101        /**
102         * checks if this curve is completly equal to the submitted geometry
103         * @param other object to compare to
104         */
105        public boolean equals( Object other ) {
106            if ( !super.equals( other ) || !( other instanceof SurfaceBoundaryImpl ) ) {
107                return false;
108            }
109    
110            if ( !exterior.equals( ( (SurfaceBoundary)other ).getExteriorRing() ) ) {
111                return false;
112            }
113    
114            if ( interior != null ) {
115                Ring[] r1 = getInteriorRings();
116                Ring[] r2 = ( (SurfaceBoundary)other ).getInteriorRings();
117    
118                if ( !Arrays.equals( r1, r2 ) ) {
119                    return false;
120                }
121            } else {
122                if ( ( (SurfaceBoundary)other ).getInteriorRings() != null ) {
123                    return false;
124                }
125            }
126    
127            return true;
128        }
129    
130        /**
131         * The operation "dimension" shall return the inherent dimension of this
132         * Geometry, which shall be less than or equal to the coordinate dimension.
133         * The dimension of a collection of geometric objects shall be the largest
134         * dimension of any of its pieces. Points are 0-dimensional, curves are
135         * 1-dimensional, surfaces are 2-dimensional, and solids are 3-dimensional.
136         */
137        public int getDimension() {
138            return 1;
139        }
140    
141        /**
142         * The operation "coordinateDimension" shall return the dimension of the
143         * coordinates that define this Geometry, which must be the same as the
144         * coordinate dimension of the coordinate reference system for this Geometry.
145         */
146        public int getCoordinateDimension() {
147            return exterior.getPositions()[0].getCoordinateDimension();
148        }
149    
150        /**
151         * returns a copy of the geometry
152         */
153        public Object clone() {
154            SurfaceBoundary sb = null;
155    
156            try {
157                Ring ext = (Ring)( (RingImpl)getExteriorRing() ).clone();
158                Ring[] inn = new Ring[interior.length];
159    
160                for ( int i = 0; i < inn.length; i++ ) {
161                    inn[i] = (Ring)( (RingImpl)interior[i] ).clone();
162                }
163    
164                sb = new SurfaceBoundaryImpl( ext, inn );
165            } catch ( Exception ex ) {
166                LOG.logError( "SurfaceBoundary_Impl.clone: ", ex );
167            }
168    
169            return sb;
170        }
171    
172        /**
173         * The Boolean valued operation "intersects" shall return TRUE if this Geometry
174         * intersects another Geometry. Within a Complex, the Primitives do not
175         * intersect one another. In general, topologically structured data uses shared
176         * geometric objects to capture intersection information.
177         */
178        public boolean intersects( Geometry gmo ) {
179            boolean inter = exterior.intersects( gmo );
180    
181            if ( !inter ) {
182                if ( interior != null ) {
183                    for ( int i = 0; i < interior.length; i++ ) {
184                        if ( interior[i].intersects( gmo ) ) {
185                            inter = true;
186                            break;
187                        }
188                    }
189                }
190            }
191    
192            return inter;
193        }
194    
195        /**
196         * The Boolean valued operation "contains" shall return TRUE if this Geometry
197         * contains another Geometry.<p></p>
198         * At the moment the operation just works with point geometries
199         */
200        public boolean contains( Geometry gmo ) {
201            boolean con = false;
202    
203            con = exterior.contains( gmo );
204    
205            if ( con ) {
206                if ( interior != null ) {
207                    for ( int i = 0; i < interior.length; i++ ) {
208                        if ( interior[i].intersects( gmo ) ) {
209                            con = false;
210                            break;
211                        }
212                    }
213                }
214            }
215    
216            return con;
217        }
218    
219        /**
220         * The Boolean valued operation "contains" shall return TRUE if this Geometry
221         * contains a single point given by a coordinate.<p></p>
222         * dummy implementation
223         */
224        public boolean contains( Position position ) {
225            return contains( new PointImpl( position, null ) );
226        }
227    
228        /**
229         * calculates the envelope of the surface boundary
230         */
231        private void calculateEnvelope() {
232            envelope = (Envelope)( (EnvelopeImpl)exterior.getEnvelope() ).clone();
233        }
234    
235        /**
236         * calculates the centroid of the surface boundary
237         */
238        private void calculateCentroid() {
239            try {
240                double[] cen = exterior.getCentroid().getAsArray().clone();
241                double cnt = exterior.getAsCurveSegment().getNumberOfPoints();
242    
243                for ( int i = 0; i < cen.length; i++ ) {
244                    cen[i] *= cnt;
245                }
246    
247                if ( interior != null ) {
248                    for ( int i = 0; i < interior.length; i++ ) {
249                        double[] pos = interior[i].getCentroid().getAsArray();
250                        cnt += interior[i].getAsCurveSegment().getNumberOfPoints();
251    
252                        for ( int j = 0; j < pos.length; j++ ) {
253                            cen[j] += ( pos[j] * interior[i].getAsCurveSegment().getNumberOfPoints() );
254                        }
255                    }
256                }
257    
258                for ( int j = 0; j < cen.length; j++ ) {
259                    cen[j] /= cnt;
260                }
261    
262                centroid = new PointImpl( new PositionImpl( cen ), crs );
263            } catch ( Exception ex ) {
264                LOG.logError( "", ex );
265            }
266        }
267    
268        /**
269         * calculates the centroid and the envelope of the surface boundary
270         */
271        protected void calculateParam() {
272            calculateEnvelope();
273            calculateCentroid();
274            setValid( true );
275        }
276    
277        /**
278         *
279         *
280         * @return 
281         */
282        public String toString() {
283            String ret = null;
284            ret = "interior = " + interior + "\n";
285            ret += ( "exterior = " + exterior + "\n" );
286            return ret;
287        }
288    } /* ********************************************************************
289    Changes to this class. What the people have been up to:
290    $Log$
291    Revision 1.11  2006/07/12 14:46:15  poth
292    comment footer added
293    
294    ********************************************************************** */