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 / aggregate / MultiSurface2D.java @ 41612

History | View | Annotate | Download (10.1 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.aggregate;
25

    
26
import java.util.ArrayList;
27
import java.util.List;
28

    
29
import com.vividsolutions.jts.geom.GeometryFactory;
30
import com.vividsolutions.jts.geom.LineString;
31
import com.vividsolutions.jts.geom.LinearRing;
32
import com.vividsolutions.jts.geom.PrecisionModel;
33
import com.vividsolutions.jts.geom.TopologyException;
34
import com.vividsolutions.jts.precision.GeometryPrecisionReducer;
35

    
36
import org.cresques.cts.IProjection;
37
import org.gvsig.fmap.geom.Geometry;
38
import org.gvsig.fmap.geom.GeometryException;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.fmap.geom.aggregate.MultiCurve;
41
import org.gvsig.fmap.geom.aggregate.MultiLine;
42
import org.gvsig.fmap.geom.aggregate.MultiPoint;
43
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
44
import org.gvsig.fmap.geom.aggregate.MultiSurface;
45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
46
import org.gvsig.fmap.geom.generalpath.DefaultGeometryManager;
47
import org.gvsig.fmap.geom.operation.GeometryOperationException;
48
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
49
import org.gvsig.fmap.geom.primitive.Primitive;
50
import org.gvsig.fmap.geom.primitive.Surface;
51
import org.gvsig.fmap.geom.generalpath.primitive.surface.polygon.Polygon2D;
52
import org.gvsig.fmap.geom.type.GeometryType;
53
import org.gvsig.fmap.geom.generalpath.util.Converter;
54
import org.gvsig.fmap.geom.primitive.Curve;
55
import org.gvsig.fmap.geom.primitive.Polygon;
56

    
57
/**
58
 * @author Jorge Piera Llodr? (jorge.piera@iver.es)
59
 */
60
public class MultiSurface2D extends BaseMultiPrimitive implements MultiSurface, MultiPolygon {
61
        private static final long serialVersionUID = 625054010696136925L;
62

    
63
        /**
64
         * The constructor with the GeometryType like and argument 
65
         * is used by the {@link GeometryType}{@link #create()}
66
         * to create the geometry
67
         * @param type
68
         * The geometry type
69
         */
70
        public MultiSurface2D(GeometryType geomType) {
71
                super(geomType);                
72
        }
73
        
74
        MultiSurface2D(GeometryType geomType, String id, IProjection projection) {
75
                super(geomType, id, projection);
76
        }
77

    
78
        MultiSurface2D(GeometryType geomType, String id, IProjection projection,
79
                        Polygon2D[] polygons) {
80
                super(geomType, id, projection, polygons);
81
        }
82

    
83
        /*
84
         * (non-Javadoc)
85
         * 
86
         * @see com.iver.cit.gvsig.fmap.core.FGeometryCollection#cloneGeometry()
87
         */
88
        public Geometry cloneGeometry() {
89
                MultiSurface2D auxSurface = new MultiSurface2D(geometryType, id, projection);
90
                for (int i = 0; i < getPrimitivesNumber(); i++) {
91
                        auxSurface.addSurface((Surface)((Surface) geometries.get(i)).cloneGeometry());
92
                }
93
                return auxSurface;
94
        }        
95

    
96
        /* (non-Javadoc)
97
         * @see org.gvsig.fmap.geom.aggregate.MultiSurface#addSurface(org.gvsig.fmap.geom.primitive.Surface)
98
         */
99
        public void addSurface(Surface surface) {
100
                geometries.add(surface);
101
        }
102

    
103
        public void addPrimitive(Primitive primitive) {
104
                addSurface((Surface)primitive);
105
        }
106
        /* (non-Javadoc)
107
         * @see org.gvsig.fmap.geom.aggregate.MultiSurface#getSurfaceAt(int)
108
         */
109
        public Surface getSurfaceAt(int index) {
110
                return (Surface)getPrimitiveAt(index);
111
        }
112
        
113
        
114
    public Geometry union(Geometry other)
115
        throws GeometryOperationNotSupportedException,
116
        GeometryOperationException {
117

    
118
        com.vividsolutions.jts.geom.Geometry this_jts, other_jts, union_jts;
119
        Geometry resp = null;
120

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

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

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

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

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

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

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

    
228
    public MultiPolygon toPolygons() throws GeometryException {
229
        return this;
230
    }
231

    
232
    public MultiPoint toPoints() throws GeometryException {
233
        if( this.getPrimitivesNumber() < 1 ) {
234
            return null;
235
        }
236
        int numPoints = 0;
237
        for( int i=0; i<this.getPrimitivesNumber(); i++ ) {
238
            numPoints += ((Curve)(this.getPrimitiveAt(i))).getNumVertices();
239
        }
240
        DefaultGeometryManager manager = (DefaultGeometryManager) GeometryLocator.getGeometryManager();
241
        MultiPoint multipoint = manager.createMultiPoint(this.getGeometryType().getSubType());
242
        multipoint.ensureCapacity(numPoints);
243
        for( int i=0; i<this.getPrimitivesNumber(); i++ ) {
244
            Curve curve = (Curve)(this.getPrimitiveAt(i));
245
            for( int n=0; n<curve.getNumVertices(); n++ ) {
246
                multipoint.addPrimitive(curve.getVertex(n));
247
            }
248
        }        
249
        return multipoint;
250
    }
251

    
252
    public MultiLine toLines() throws GeometryException {
253
        if( this.getPrimitivesNumber() < 1 ) {
254
            return null;
255
        }
256
        DefaultGeometryManager manager = (DefaultGeometryManager) GeometryLocator.getGeometryManager();
257
        MultiLine multi = manager.createMultiLine(this.getGeometryType().getSubType());
258
        multi.ensureCapacity(this.getPrimitivesNumber());
259
        for( int i=0; i<this.getPrimitivesNumber(); i++ ) {
260
            Polygon polygon = (Polygon)(this.getPrimitiveAt(i));
261
            MultiLine lines = polygon.toLines();
262
            for( int n=0; n<lines.getPrimitivesNumber(); n++ ) {
263
                multi.addPrimitive(lines.getPrimitiveAt(n));
264
            }
265
        }        
266
        return multi;
267
    }
268
}