Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / aggregate / impl / MultiSurface2D.java @ 41590

History | View | Annotate | Download (7.62 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.aggregate.impl;
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.MultiPolygon;
33
import com.vividsolutions.jts.geom.Polygon;
34
import com.vividsolutions.jts.geom.PrecisionModel;
35
import com.vividsolutions.jts.geom.TopologyException;
36
import com.vividsolutions.jts.precision.GeometryPrecisionReducer;
37

    
38
import org.cresques.cts.IProjection;
39
import org.gvsig.fmap.geom.Geometry;
40
import org.gvsig.fmap.geom.aggregate.MultiSurface;
41
import org.gvsig.fmap.geom.exception.CreateGeometryException;
42
import org.gvsig.fmap.geom.operation.GeometryOperationException;
43
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
44
import org.gvsig.fmap.geom.primitive.Primitive;
45
import org.gvsig.fmap.geom.primitive.Surface;
46
import org.gvsig.fmap.geom.primitive.impl.surface.polygon.Polygon2D;
47
import org.gvsig.fmap.geom.type.GeometryType;
48
import org.gvsig.fmap.geom.util.Converter;
49

    
50
/**
51
 * @author Jorge Piera Llodr? (jorge.piera@iver.es)
52
 */
53
public class MultiSurface2D extends BaseMultiPrimitive implements MultiSurface {
54
        private static final long serialVersionUID = 625054010696136925L;
55

    
56
        /**
57
         * The constructor with the GeometryType like and argument 
58
         * is used by the {@link GeometryType}{@link #create()}
59
         * to create the geometry
60
         * @param type
61
         * The geometry type
62
         */
63
        public MultiSurface2D(GeometryType geomType) {
64
                super(geomType);                
65
        }
66
        
67
        MultiSurface2D(GeometryType geomType, String id, IProjection projection) {
68
                super(geomType, id, projection);
69
        }
70

    
71
        MultiSurface2D(GeometryType geomType, String id, IProjection projection,
72
                        Polygon2D[] polygons) {
73
                super(geomType, id, projection, polygons);
74
        }
75

    
76
        /*
77
         * (non-Javadoc)
78
         * 
79
         * @see com.iver.cit.gvsig.fmap.core.FGeometryCollection#cloneGeometry()
80
         */
81
        public Geometry cloneGeometry() {
82
                MultiSurface2D auxSurface = new MultiSurface2D(geometryType, id, projection);
83
                for (int i = 0; i < getPrimitivesNumber(); i++) {
84
                        auxSurface.addSurface((Surface)((Surface) geometries.get(i)).cloneGeometry());
85
                }
86
                return auxSurface;
87
        }        
88

    
89
        /* (non-Javadoc)
90
         * @see org.gvsig.fmap.geom.aggregate.MultiSurface#addSurface(org.gvsig.fmap.geom.primitive.Surface)
91
         */
92
        public void addSurface(Surface surface) {
93
                geometries.add(surface);
94
        }
95

    
96
        public void addPrimitive(Primitive primitive) {
97
                addSurface((Surface)primitive);
98
        }
99
        /* (non-Javadoc)
100
         * @see org.gvsig.fmap.geom.aggregate.MultiSurface#getSurfaceAt(int)
101
         */
102
        public Surface getSurfaceAt(int index) {
103
                return (Surface)getPrimitiveAt(index);
104
        }
105
        
106
        
107
    public Geometry union(Geometry other)
108
        throws GeometryOperationNotSupportedException,
109
        GeometryOperationException {
110

    
111
        com.vividsolutions.jts.geom.Geometry this_jts, other_jts, union_jts;
112
        Geometry resp = null;
113

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

    
142
                PrecisionModel pm = new PrecisionModel(1000000);
143
                GeometryPrecisionReducer gpr = new GeometryPrecisionReducer(pm);
144
                this_jts = gpr.reduce(this_jts);
145
                other_jts = gpr.reduce(other_jts);
146
                union_jts = this_jts.union(other_jts);
147

    
148
                if (union_jts instanceof Polygon) {
149
                    double tole = union_jts.getArea();
150
                    tole = tole * 1e-12;
151
                    union_jts = removeInvalidHoles((Polygon) union_jts, tole);
152
                } else {
153
                    if (union_jts instanceof MultiPolygon) {
154
                        double tole = union_jts.getArea();
155
                        tole = tole * 1e-12;
156
                        union_jts =
157
                            removeInvalidHoles((MultiPolygon) union_jts, tole);
158
                    }
159
                }
160

    
161
                resp = Converter.jtsToGeometry(union_jts);
162
                return resp;
163
            } catch (Exception exc) {
164
                throw new GeometryOperationException(exc);
165
            }
166
        }
167
    }
168
    
169
    private com.vividsolutions.jts.geom.Geometry getJTS() {
170
        return Converter.geometryToJts(this);
171
    }
172
    
173
    private MultiPolygon removeInvalidHoles(MultiPolygon mpo, double tol) {
174

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

    
211
    private double getLinearRingArea(LinearRing lr, GeometryFactory gf) {
212
        Polygon po = gf.createPolygon(lr);
213
        double resp = po.getArea(); 
214
        return resp;
215
    }
216

    
217
    private LinearRing toLinearRing(LineString ls, GeometryFactory gf) {
218
        return gf.createLinearRing(ls.getCoordinateSequence());
219
    }
220

    
221
    
222
    
223
}