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 / primitive / impl / Surface2D.java @ 41160

History | View | Annotate | Download (7.56 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.primitive.impl;
25

    
26
import java.awt.geom.Rectangle2D;
27
import java.util.ArrayList;
28
import java.util.List;
29

    
30
import com.vividsolutions.jts.geom.GeometryFactory;
31
import com.vividsolutions.jts.geom.LineString;
32
import com.vividsolutions.jts.geom.LinearRing;
33
import com.vividsolutions.jts.geom.MultiPolygon;
34
import com.vividsolutions.jts.geom.Polygon;
35
import com.vividsolutions.jts.geom.PrecisionModel;
36
import com.vividsolutions.jts.geom.TopologyException;
37
import com.vividsolutions.jts.precision.GeometryPrecisionReducer;
38

    
39
import org.cresques.cts.IProjection;
40

    
41
import org.gvsig.fmap.geom.Geometry;
42
import org.gvsig.fmap.geom.exception.CreateGeometryException;
43
import org.gvsig.fmap.geom.operation.GeometryOperationException;
44
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
45
import org.gvsig.fmap.geom.primitive.FShape;
46
import org.gvsig.fmap.geom.primitive.GeneralPathX;
47
import org.gvsig.fmap.geom.primitive.Surface;
48
import org.gvsig.fmap.geom.primitive.SurfaceAppearance;
49
import org.gvsig.fmap.geom.type.GeometryType;
50
import org.gvsig.fmap.geom.util.Converter;
51

    
52
/**
53
 * Pol�gono 2D.
54
 *
55
 * @author Vicente Caballero Navarro
56
 */
57
public class Surface2D extends OrientableSurface2D implements Surface {
58
        private static final long serialVersionUID = -8448256617197415743L;
59

    
60
        /**
61
         * The constructor with the GeometryType like and argument 
62
         * is used by the {@link GeometryType}{@link #create()}
63
         * to create the geometry
64
         * @param type
65
         * The geometry type
66
         */
67
        public Surface2D(GeometryType geomType) {
68
                super(geomType);
69
        }
70

    
71
        /**
72
         * Constructor used in the {@link Geometry#cloneGeometry()} method.
73
         * @param geomType
74
         * @param id
75
         * @param projection
76
         * @param gpx
77
         */
78
        Surface2D(GeometryType geomType, String id, IProjection projection, GeneralPathX gpx) {
79
                super(geomType, id, projection, gpx);
80
        }        
81

    
82
        /*
83
         * (non-Javadoc)
84
         * @see org.gvsig.fmap.geom.Geometry#getShapeType()
85
         */
86
        public int getShapeType() {
87
                return TYPES.SURFACE;
88
        }
89

    
90
        /*
91
         * (non-Javadoc)
92
         * @see org.gvsig.fmap.geom.primitive.FShape#cloneFShape()
93
         */
94
        public FShape cloneFShape() {
95
                return new Surface2D(getGeometryType(), id, projection, (GeneralPathX) gp.clone());
96
        }
97

    
98
        /*
99
         * (non-Javadoc)
100
         * @see org.gvsig.fmap.geom.primitive.impl.OrientablePrimitive2D#intersects(java.awt.geom.Rectangle2D)
101
         */
102
        public boolean intersects(Rectangle2D r) {
103
                return gp.intersects(r);
104
        }
105

    
106
        public SurfaceAppearance getSurfaceAppearance() {
107
                // TODO Auto-generated method stub
108
                return null;
109
        }
110

    
111
        public void setSurfaceAppearance(SurfaceAppearance app) {
112
                // TODO Auto-generated method stub
113
                
114
        }
115
        
116
    public Geometry union(Geometry other)
117
        throws GeometryOperationNotSupportedException,
118
        GeometryOperationException {
119

    
120
        com.vividsolutions.jts.geom.Geometry this_jts, other_jts, union_jts;
121
        Geometry resp = null;
122

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

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

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

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

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

    
221
    private double getLinearRingArea(LinearRing lr, GeometryFactory gf) {
222
        Polygon po = gf.createPolygon(lr);
223
        double resp = po.getArea(); 
224
        return resp;
225
    }
226

    
227
    private LinearRing toLinearRing(LineString ls, GeometryFactory gf) {
228
        return gf.createLinearRing(ls.getCoordinateSequence());
229
    }
230
    
231
    
232
    
233
        
234
}