Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.generalpath / src / main / java / org / gvsig / fmap / geom / generalpath / primitive / surface / polygon / Polygon2D.java @ 41612

History | View | Annotate | Download (9.63 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.geom.generalpath.primitive.surface.polygon;
25

    
26
import com.vividsolutions.jts.geom.Coordinate;
27
import com.vividsolutions.jts.geom.GeometryFactory;
28
import com.vividsolutions.jts.geom.LineString;
29
import com.vividsolutions.jts.geom.LinearRing;
30
import com.vividsolutions.jts.geom.PrecisionModel;
31
import com.vividsolutions.jts.geom.TopologyException;
32
import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory;
33
import com.vividsolutions.jts.precision.GeometryPrecisionReducer;
34
import java.awt.geom.Rectangle2D;
35
import java.util.ArrayList;
36
import java.util.List;
37
import org.cresques.cts.IProjection;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryException;
40
import org.gvsig.fmap.geom.GeometryLocator;
41
import org.gvsig.fmap.geom.aggregate.MultiCurve;
42
import org.gvsig.fmap.geom.aggregate.MultiLine;
43
import org.gvsig.fmap.geom.aggregate.MultiPoint;
44
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
46
import org.gvsig.fmap.geom.generalpath.DefaultGeometryManager;
47
import org.gvsig.fmap.geom.generalpath.gputils.FShape;
48
import org.gvsig.fmap.geom.generalpath.primitive.surface.OrientableSurface2D;
49
import org.gvsig.fmap.geom.generalpath.util.Converter;
50
import org.gvsig.fmap.geom.operation.GeometryOperationException;
51
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
52
import org.gvsig.fmap.geom.primitive.GeneralPathX;
53
import org.gvsig.fmap.geom.primitive.Polygon;
54
import org.gvsig.fmap.geom.primitive.Primitive;
55
import org.gvsig.fmap.geom.type.GeometryType;
56

    
57
/**
58
 * Pol�gono 2D.
59
 *
60
 * @author Vicente Caballero Navarro
61
 */
62
public class Polygon2D extends OrientableSurface2D implements Polygon {
63
        private static final long serialVersionUID = -8448256617197415743L;
64

    
65
        /**
66
         * The constructor with the GeometryType like and argument 
67
         * is used by the {@link GeometryType}{@link #create()}
68
         * to create the geometry
69
         * @param type
70
         * The geometry type
71
         */
72
        public Polygon2D(GeometryType geomType) {
73
                super(geomType);
74
        }
75

    
76
        /**
77
         * Constructor used in the {@link Geometry#cloneGeometry()} method.
78
         * @param geomType
79
         * @param id
80
         * @param projection
81
         * @param gpx
82
         */
83
        protected Polygon2D(GeometryType geomType, String id, IProjection projection, GeneralPathX gpx) {
84
                super(geomType, id, projection, gpx);
85
        }        
86

    
87
        /*
88
         * (non-Javadoc)
89
         * @see org.gvsig.fmap.geom.Geometry#getShapeType()
90
         */
91
        public int getShapeType() {
92
                return TYPES.SURFACE;
93
        }
94

    
95
        /*
96
         * (non-Javadoc)
97
         * @see org.gvsig.fmap.geom.primitive.FShape#cloneFShape()
98
         */
99
        public FShape cloneFShape() {
100
                return new Polygon2D(getGeometryType(), id, projection, (GeneralPathX) gp.clone());
101
        }
102

    
103
        /*
104
         * (non-Javadoc)
105
         * @see org.gvsig.fmap.geom.primitive.impl.OrientablePrimitive2D#intersects(java.awt.geom.Rectangle2D)
106
         */
107
        public boolean intersects(Rectangle2D r) {
108
                return gp.intersects(r);
109
        }
110

    
111
        
112
    public Geometry union(Geometry other)
113
        throws GeometryOperationNotSupportedException,
114
        GeometryOperationException {
115

    
116
        com.vividsolutions.jts.geom.Geometry this_jts, other_jts, union_jts;
117
        Geometry resp = null;
118

    
119
        try {
120
            this_jts = getJTS();
121
            other_jts = Converter.geometryToJts(other);
122
            union_jts = this_jts.union(other_jts);
123
            if (union_jts instanceof com.vividsolutions.jts.geom.Polygon) {
124
                double tole = union_jts.getArea();
125
                tole = tole * 1e-12;
126
                union_jts = removeInvalidHoles((com.vividsolutions.jts.geom.Polygon) union_jts, tole);
127
            } else {
128
                if (union_jts instanceof com.vividsolutions.jts.geom.MultiPolygon) {
129
                    double tole = union_jts.getArea();
130
                    tole = tole * 1e-12;
131
                    union_jts =
132
                        removeInvalidHoles((com.vividsolutions.jts.geom.MultiPolygon) union_jts, tole);
133
                }
134
            }
135
            resp = Converter.jtsToGeometry(union_jts);
136
            return resp;
137
        } catch (CreateGeometryException e) {
138
            throw new GeometryOperationException(e);
139
        } catch (TopologyException e) {
140
            /*
141
             * If JTS throws this, we'll try to simplify them
142
             */
143
            try {
144
                this_jts = getJTS();
145
                other_jts = Converter.geometryToJts(other);
146

    
147
                PrecisionModel pm = new PrecisionModel(1000000);
148
                GeometryPrecisionReducer gpr = new GeometryPrecisionReducer(pm);
149
                this_jts = gpr.reduce(this_jts);
150
                other_jts = gpr.reduce(other_jts);
151
                union_jts = this_jts.union(other_jts);
152

    
153
                if (union_jts instanceof com.vividsolutions.jts.geom.Polygon) {
154
                    double tole = union_jts.getArea();
155
                    tole = tole * 1e-12;
156
                    union_jts = removeInvalidHoles((com.vividsolutions.jts.geom.Polygon) union_jts, tole);
157
                } else {
158
                    if (union_jts instanceof com.vividsolutions.jts.geom.MultiPolygon) {
159
                        double tole = union_jts.getArea();
160
                        tole = tole * 1e-12;
161
                        union_jts =
162
                            removeInvalidHoles((com.vividsolutions.jts.geom.MultiPolygon) union_jts, tole);
163
                    }
164
                }
165

    
166
                resp = Converter.jtsToGeometry(union_jts);
167
                return resp;
168
            } catch (Exception exc) {
169
                throw new GeometryOperationException(exc);
170
            }
171
        }
172
    }
173
    
174
    
175
    private com.vividsolutions.jts.geom.Geometry getJTS() {
176
        return Converter.geometryToJts(this);
177
    }
178
    
179
    private com.vividsolutions.jts.geom.MultiPolygon removeInvalidHoles(com.vividsolutions.jts.geom.MultiPolygon mpo, double tol) {
180

    
181
        GeometryFactory gf = new GeometryFactory(mpo.getPrecisionModel());
182
        
183
        int npo = mpo.getNumGeometries();
184
        com.vividsolutions.jts.geom.Polygon[] pos = new com.vividsolutions.jts.geom.Polygon[npo];
185
        for (int i=0; i<npo; i++) {
186
            pos[i] = removeInvalidHoles((com.vividsolutions.jts.geom.Polygon) mpo.getGeometryN(i), tol);
187
        }
188
        return gf.createMultiPolygon(pos);
189
    }
190
    
191
    private com.vividsolutions.jts.geom.Polygon removeInvalidHoles(com.vividsolutions.jts.geom.Polygon po, double tol) {
192
        
193
        GeometryFactory gf = new GeometryFactory(po.getPrecisionModel());
194
        
195
        int nholes = po.getNumInteriorRing();
196
        List validholes = new ArrayList();
197
        for (int i=0; i<nholes; i++) {
198
            LineString ls = po.getInteriorRingN(i);
199
            LinearRing lr = toLinearRing(ls, gf);
200
            if (getLinearRingArea(lr, gf) > tol) {
201
                validholes.add(lr);
202
            }
203
            
204
        }
205
        
206
        if (validholes.size() < nholes) {
207
            
208
            LinearRing[] holes = (LinearRing[]) validholes.toArray(new LinearRing[0]);
209
            return gf.createPolygon(
210
                toLinearRing(po.getExteriorRing(), gf), holes);
211
        } else {
212
            return po;
213
        }
214
        
215
    }
216

    
217
    private double getLinearRingArea(LinearRing lr, GeometryFactory gf) {
218
        com.vividsolutions.jts.geom.Polygon po = gf.createPolygon(lr);
219
        double resp = po.getArea(); 
220
        return resp;
221
    }
222

    
223
    private LinearRing toLinearRing(LineString ls, GeometryFactory gf) {
224
        return gf.createLinearRing(ls.getCoordinateSequence());
225
    }
226

    
227
    public MultiPoint toPoints() throws GeometryException {
228
        DefaultGeometryManager manager = (DefaultGeometryManager) GeometryLocator.getGeometryManager();
229
        MultiPoint multipoint = manager.createMultiPoint(this.getGeometryType().getSubType());
230
        multipoint.ensureCapacity(this.getNumVertices());
231
        for( int n=0; n<this.getNumVertices(); n++ ) {
232
            multipoint.addPrimitive(this.getVertex(n));
233
        }
234
        return multipoint;    
235
    }
236

    
237
    public MultiLine toLines() throws GeometryException {
238
        GeometryFactory fact = new GeometryFactory();
239
        Coordinate[] coordinates = this.toJTS().getCoordinates();
240
        LineString jts_line = fact.createLineString(coordinates);
241
        
242
        DefaultGeometryManager manager = (DefaultGeometryManager) GeometryLocator.getGeometryManager();
243
        Geometry line = manager.createFrom(jts_line);
244
        MultiCurve multi = manager.createMultiCurve(this.getGeometryType().getSubType());
245
        multi.addPrimitive((Primitive) line);
246
        return (MultiLine) multi;
247
    }
248

    
249
    public MultiPolygon toPolygons() throws GeometryException {
250
        DefaultGeometryManager manager = (DefaultGeometryManager) GeometryLocator.getGeometryManager();
251
        MultiPolygon multi = manager.createMultiPolygon(this.getGeometryType().getSubType());
252
        multi.addPrimitive(this);
253
        return multi;    
254
    }
255
        
256
}