Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.fmap.control / src / main / java / org / gvsig / fmap / mapcontrol / AreaAndPerimeterCalculator.java @ 46332

History | View | Annotate | Download (7.42 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.fmap.mapcontrol;
7

    
8
import java.awt.geom.PathIterator;
9
import java.awt.geom.Point2D;
10
import java.util.ArrayList;
11
import org.cresques.cts.GeoCalc;
12
import org.cresques.cts.IProjection;
13
import org.gvsig.fmap.geom.Geometry;
14
import org.gvsig.fmap.geom.GeometryLocator;
15
import org.gvsig.fmap.geom.GeometryManager;
16
import org.gvsig.fmap.geom.GeometryUtils;
17
import org.gvsig.fmap.geom.primitive.Line;
18
import org.gvsig.fmap.mapcontext.MapContext;
19

    
20
public class AreaAndPerimeterCalculator {
21

    
22
    public double perimeter(org.gvsig.fmap.geom.Geometry geom, IProjection proj, int distanceUnits) {
23
        ArrayList parts = getXY(geom);
24
        double perimeter = 0;
25
        for (int j = 0; j < parts.size(); j++) {
26
            Double[][] xsys = (Double[][]) parts.get(j);
27
            double dist;
28
            double distAll = 0;
29

    
30
            for (int i = 0; i < (xsys[0].length - 1); i++) {
31
                Point2D p = new Point2D.Double(xsys[0][i], xsys[1][i]);
32
                Point2D p2 = new Point2D.Double(xsys[0][i + 1], xsys[1][i + 1]);
33
                dist = distanceWorld(p, p2,proj,distanceUnits);
34
                distAll += dist;
35
            }
36
            perimeter += distAll / MapContext.getDistanceTrans2Meter()[distanceUnits];
37
        }
38
        return perimeter;        
39
    }
40
    
41
    public double area(org.gvsig.fmap.geom.Geometry geom, IProjection proj, int areaUnits) {
42
        ArrayList parts = getXY(geom);
43
        double area = 0;
44
        for( int i = 0; i < parts.size(); i++ ) {
45
            Double[][] xsys = (Double[][]) parts.get(i);
46
            Double[] xs = xsys[0];
47
            Double[] ys = xsys[1];
48
            if( isCCW(xs, ys) ) {
49
                if( proj.isProjected() ) {
50
                    area -= returnCoordsArea(
51
                        xs,
52
                        ys,
53
                        new Point2D.Double(xs[xs.length - 1], ys[ys.length - 1]),
54
                        areaUnits
55
                    );
56
                } else {
57
                    area -= returnGeoCArea(xs, ys);
58
                }
59
            } else {
60
                if( proj.isProjected() ) {
61
                    area += returnCoordsArea(
62
                        xs,
63
                        ys,
64
                        new Point2D.Double(xs[xs.length - 1], ys[ys.length - 1]),
65
                        areaUnits
66
                    );
67
                } else {
68
                    area += returnGeoCArea(xs, ys);
69
                }
70
            }
71
        }
72
        return area;
73
    }
74

    
75
    public double distanceWorld(Point2D pt1, Point2D pt2, IProjection proj, int distanceUnits) {
76

    
77
      double dist;
78
      if (proj.isProjected()) {
79
        dist = pt1.distance(pt2);
80
        dist = dist * MapContext.getDistanceTrans2Meter()[distanceUnits];
81
      }
82
      else {
83
        GeoCalc geocalc = new GeoCalc(proj);
84
        dist = geocalc.distanceVincenty(pt1, pt2);
85
      }
86
      return dist;
87
    }
88

    
89
    private boolean isCCW(Double[] xs, Double[] ys) {
90
        Line line = GeometryUtils.createLine(Geometry.SUBTYPES.GEOM2D);
91
        for( int i = 0; i < ys.length; i++ ) {
92
            line.addVertex(xs[i], ys[i]);
93
        }
94
        if(line.isEmpty()){
95
            return true;
96
        }
97
        try {
98
            return line.isCCW();
99
            
100
        } catch (Exception ex) {
101
            throw new RuntimeException("Can't calculate isCCW", ex);
102
        }
103
    }
104

    
105
    private double returnGeoCArea(Double[] xs, Double[] ys) {
106
        double[] lat = new double[xs.length];
107
        double[] lon = new double[xs.length];
108
        for( int K = 0; K < xs.length; K++ ) {
109
            lon[K] = xs[K] / org.gvsig.fmap.mapcontrol.tools.geo.Geo.Degree;
110
            lat[K] = ys[K] / org.gvsig.fmap.mapcontrol.tools.geo.Geo.Degree;
111
        }
112
        return (org.gvsig.fmap.mapcontrol.tools.geo.Geo.sphericalPolyArea(lat, lon, xs.length - 1) * org.gvsig.fmap.mapcontrol.tools.geo.Geo.SqM);
113
    }
114

    
115
    /**
116
     * Calcula el ?rea.
117
     *
118
     * @param xs
119
     * @param ys
120
     * @param point
121
     * @param areaUnits
122
     *
123
     * @return ?rea.
124
     */
125
    public double returnCoordsArea(Double[] xs, Double[] ys, Point2D point, int areaUnits) {
126
        Point2D aux = point;
127
        double elArea = 0.0;
128
        Point2D pPixel;
129
        Point2D p;// = new Point2D.Double();
130
        Point2D.Double pAnt = new Point2D.Double();
131
        for( int pos = 0; pos < xs.length - 1; pos++ ) {
132
            pPixel = new Point2D.Double(xs[pos], ys[pos]);
133
            p = pPixel;
134
            if( pos == 0 ) {
135
                pAnt.x = aux.getX();
136
                pAnt.y = aux.getY();
137
            }
138
            elArea = elArea + ((pAnt.x - p.getX()) * (pAnt.y + p.getY()));
139
            pAnt.setLocation(p);
140
        }
141

    
142
        elArea = elArea + ((pAnt.x - aux.getX()) * (pAnt.y + aux.getY()));
143
        elArea = Math.abs(elArea / 2.0);
144
        return (elArea / (Math.pow(MapContext.getAreaTrans2Meter()[areaUnits], 2)));
145
    }
146

    
147
    public ArrayList getXY(org.gvsig.fmap.geom.Geometry geometry) {
148
        ArrayList xs = new ArrayList();
149
        ArrayList ys = new ArrayList();
150
        ArrayList parts = new ArrayList();
151
        double[] theData = new double[6];
152

    
153
        //double[] aux = new double[6];
154
        PathIterator theIterator;
155
        int theType;
156
        int numParts = 0;
157
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
158
        theIterator = geometry.getPathIterator(null, geomManager.getFlatness()); //, flatness);
159
        boolean isClosed = false;
160
        while( !theIterator.isDone() ) {
161
            theType = theIterator.currentSegment(theData);
162

    
163
            switch( theType ) {
164
            case PathIterator.SEG_MOVETO:
165
                if( numParts == 0 ) {
166
                    xs.add(theData[0]);
167
                    ys.add(theData[1]);
168
                } else {
169
                    if( !isClosed ) {
170
                        Double[] x = (Double[]) xs.toArray(new Double[0]);
171
                        Double[] y = (Double[]) ys.toArray(new Double[0]);
172
                        parts.add(new Double[][]{x,
173
                            y});
174
                        xs.clear();
175
                        ys.clear();
176
                    }
177
                    xs.add(theData[0]);
178
                    ys.add(theData[1]);
179
                }
180
                numParts++;
181
                isClosed = false;
182
                break;
183
            case PathIterator.SEG_LINETO:
184
                isClosed = false;
185
                xs.add(theData[0]);
186
                ys.add(theData[1]);
187
                break;
188
            case PathIterator.SEG_CLOSE:
189
                isClosed = true;
190
                xs.add(theData[0]);
191
                ys.add(theData[1]);
192
                Double[] x = (Double[]) xs.toArray(new Double[0]);
193
                Double[] y = (Double[]) ys.toArray(new Double[0]);
194
                parts.add(new Double[][]{x,
195
                    y});
196
                xs.clear();
197
                ys.clear();
198
                break;
199
            } //end switch
200

    
201
            theIterator.next();
202
        } //end while loop
203

    
204
        if( !isClosed ) {
205
//                isClosed=true;
206
            xs.add(theData[0]);
207
            ys.add(theData[1]);
208
            Double[] x = (Double[]) xs.toArray(new Double[0]);
209
            Double[] y = (Double[]) ys.toArray(new Double[0]);
210
            parts.add(new Double[][]{x,
211
                y});
212
            xs.clear();
213
            ys.clear();
214
        }
215
        return parts;
216

    
217
    }
218

    
219
}