001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/PolygonImpl.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    
048    import org.deegree.framework.log.ILogger;
049    import org.deegree.framework.log.LoggerFactory;
050    import org.deegree.model.crs.CoordinateSystem;
051    
052    /**
053     * 
054     * 
055     * 
056     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
057     * @author last edited by: $Author: apoth $
058     * 
059     * @version. $Revision: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $
060     */
061    class PolygonImpl extends SurfacePatchImpl implements Polygon, Serializable {
062        /** Use serialVersionUID for interoperability. */
063        private final static long serialVersionUID = -1293845886457211088L;
064    
065        private static final ILogger LOG = LoggerFactory.getLogger( PolygonImpl.class );
066    
067        private SurfaceBoundary boundary = null;
068    
069        /**
070         * 
071         * @param exteriorRing
072         * @param interiorRings
073         * @param crs
074         */
075        PolygonImpl( Ring exteriorRing, Ring[] interiorRings, CoordinateSystem crs ) {
076            super( exteriorRing, interiorRings, crs );
077        }
078    
079        /**
080         * Creates a new PolygonImpl object.
081         * 
082         * @param interpolation
083         * @param exteriorRing
084         * @param interiorRings
085         * @param crs
086         * 
087         * @throws GeometryException
088         */
089        PolygonImpl( SurfaceInterpolation interpolation, Position[] exteriorRing, Position[][] interiorRings,
090                     CoordinateSystem crs ) throws GeometryException {
091            super( interpolation, exteriorRing, interiorRings, crs );
092            // TODO
093            // implementation based on segments
094    
095            Ring outer = new RingImpl( exteriorRing, crs );
096            Ring[] inner = null;
097    
098            if ( interiorRings != null ) {
099                inner = new Ring[interiorRings.length];
100    
101                for ( int i = 0; i < inner.length; i++ ) {
102                    inner[i] = new RingImpl( interiorRings[i], crs );
103                }
104            }
105    
106            boundary = new SurfaceBoundaryImpl( outer, inner );
107        }
108    
109        /**
110         * The operation "boundary" shall return the boundary of this SurfacePatch represented as a
111         * collection of Curves organized as a SurfaceBoundary, consisting of Curve instances along the
112         * boundary of the aggregate Surface, and interior to the Surface where SurfacePatches are
113         * adjacent.
114         * 
115         */
116        public SurfaceBoundary getBoundary() {
117            return boundary;
118        }
119    
120        /**
121         * checks if this curve is completly equal to the submitted geometry
122         * 
123         * @param other
124         *            object to compare to
125         */
126        public boolean equals( Object other ) {
127            if ( !super.equals( other ) || !( other instanceof PolygonImpl ) ) {
128                return false;
129            }
130    
131            return true;
132        }
133    
134        /**
135         * 
136         * 
137         * @return
138         */
139        public String toString() {
140            String ret = "SurfacePatch: ";
141            ret = "interpolation = " + interpolation + "\n";
142            ret += "exteriorRing = \n";
143            ret += ( exteriorRing + "\n" );
144            ret += ( "interiorRings = " + interiorRings + "\n" );
145            ret += ( "envelope = " + getEnvelope() + "\n" );
146            return ret;
147        }
148    
149        /**
150         * returns a shallow copy of the geometry
151         */
152        public Object clone() {
153            Polygon p = null;
154    
155            try {
156                p = new PolygonImpl( new SurfaceInterpolationImpl( getInterpolation().getValue() ), getExteriorRing(),
157                                     getInteriorRings(), this.crs );
158            } catch ( Exception e ) {
159                LOG.logError( e.getMessage(), e );
160            }
161    
162            return p;
163        }
164    
165        /**
166         * The Boolean valued operation "intersects" shall return TRUE if this Geometry intersects
167         * another Geometry. Within a Complex, the Primitives do not intersect one another. In general,
168         * topologically structured data uses shared geometric objects to capture intersection
169         * information.
170         */
171        public boolean intersects( Geometry gmo ) {
172            boolean inter = false;
173    
174            try {
175                if ( gmo instanceof Point ) {
176                    double tolerance = ( (Point) gmo ).getTolerance();
177                    inter = LinearIntersects.intersects( ( (Point) gmo ).getPosition(), this, tolerance );
178                } else if ( gmo instanceof Curve ) {
179                    inter = LinearIntersects.intersects( (Curve) gmo, new SurfaceImpl( this ) );
180                } else if ( gmo instanceof Surface ) {
181                    inter = LinearIntersects.intersects( (Surface) gmo, new SurfaceImpl( this ) );
182                } else if ( gmo instanceof Aggregate ) {
183                    inter = intersectsMultiObject( (Aggregate) gmo );
184                }
185            } catch ( Exception e ) {
186                LOG.logError( e.getMessage(), e );
187            }
188    
189            return inter;
190        }
191    
192        /**
193         * the operations returns true if the submitted multi primitive intersects with the curve
194         * segment
195         */
196        private boolean intersectsMultiObject( Aggregate mprim )
197                                throws Exception {
198            boolean inter = false;
199    
200            int cnt = mprim.getSize();
201    
202            for ( int i = 0; i < cnt; i++ ) {
203                if ( intersects( mprim.getObjectAt( i ) ) ) {
204                    inter = true;
205                    break;
206                }
207            }
208    
209            return inter;
210        }
211    
212        /**
213         * The Boolean valued operation "contains" shall return TRUE if this Geometry contains another
214         * Geometry.
215         * <p>
216         * </p>
217         */
218        public boolean contains( Geometry gmo ) {
219            boolean contain = false;
220    
221            try {
222                if ( gmo instanceof Point ) {
223                    contain = LinearContains.contains( this, ( (Point) gmo ).getPosition(), gmo.getTolerance() );
224                } else if ( gmo instanceof Curve ) {
225                    contain = LinearContains.contains( this, ( (Curve) gmo ).getAsLineString(), gmo.getTolerance() );
226                } else if ( gmo instanceof Surface ) {
227                    contain = LinearContains.contains( new SurfaceImpl( this ), (Surface) gmo );
228                } else if ( gmo instanceof Aggregate ) {
229                    contain = containsMultiObject( (Aggregate) gmo );
230                }
231            } catch ( Exception e ) {
232                LOG.logError( e.getMessage(), e );
233            }
234    
235            return contain;
236        }
237    
238        /**
239         * 
240         * 
241         * @param gmo
242         * 
243         * @return
244         */
245        private boolean containsMultiObject( Aggregate gmo ) {
246            try {
247                for ( int i = 0; i < gmo.getSize(); i++ ) {
248                    if ( !contains( gmo.getObjectAt( i ) ) ) {
249                        return false;
250                    }
251                }
252            } catch ( Exception e ) {
253                LOG.logError( e.getMessage(), e );
254            }
255    
256            return true;
257        }
258    }