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