Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libGeocoding / src / org / gvsig / geocoding / geommatches / SimpleLineMatcher.java @ 26883

History | View | Annotate | Download (7.34 KB)

1 26845 vsanjaime
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 Prodevelop S.L  main development
26
 */
27
28
package org.gvsig.geocoding.geommatches;
29
30
import java.awt.geom.PathIterator;
31
import java.util.ArrayList;
32
import java.util.HashMap;
33
import java.util.Iterator;
34 26883 vsanjaime
import java.util.List;
35 26845 vsanjaime
import java.util.Map;
36
37 26883 vsanjaime
import org.gvsig.fmap.dal.feature.Feature;
38 26845 vsanjaime
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.primitive.Curve2D;
40
import org.gvsig.fmap.geom.primitive.Point2D;
41
import org.gvsig.fmap.geom.util.UtilFunctions;
42
43
import com.vividsolutions.jts.geom.Coordinate;
44
import com.vividsolutions.jts.linearref.LengthIndexedLine;
45
46
/**
47
 *
48
 * This class searchs positions over lines (ways)
49
 *
50
 * @author <a href="mailto:jsanz@prodevelop.es"> Jorge Gaspar Sanz Salinas</a>
51
 * @author <a href="mailto:vsanjaime@prodevelop.es"> Vicente Sanjaime Calvet</a>
52
 *
53
 */
54
public class SimpleLineMatcher extends GeomMatcher {
55
56
        /**
57
         * This method gets the position over lines (Streets) or next to the lines
58
         *
59
         * @return
60
         */
61
        @SuppressWarnings("unchecked")
62
        public Geometry[] match() {
63
64
                // Group the geometries by one field
65
                HashMap geomstreets1 = groupFeaturesByAttribute(this
66 26883 vsanjaime
                                .getGroupFieldPosition(), (List) this
67 26845 vsanjaime
                                .getFeatures().get(0));
68
                Iterator it = geomstreets1.entrySet().iterator();
69
                Point2D[] points = new Point2D[geomstreets1.size()];
70
                int position = 0;
71
                while (it.hasNext()) {
72
                        Map.Entry e = (Map.Entry) it.next();
73
                        ArrayList geomss = (ArrayList) e.getValue();
74
                        // Insert geometries of one street into array
75
                        Geometry[] arrGeoms = new Geometry[geomss.size()];
76
                        for (int i = 0; i < geomss.size(); i++) {
77
                                arrGeoms[i] = (Geometry) geomss.get(i);
78
                        }
79
                        // Parse geometries to JTS
80
                        com.vividsolutions.jts.geom.Geometry[] geomsjts = parseGeomsToJTS(
81
                                        geomss.get(0).getClass(), arrGeoms);
82
                        // Make the UNION of the all geometries with the same attribute
83
                        com.vividsolutions.jts.geom.Geometry geomstreetjts = unionLinesJTS(geomsjts);
84
85
                        // Get the point of the geometry (LINE)
86
                        Point2D point = getLinesPosition(geomstreetjts, getParams());
87
                        points[position] = point;
88
                        position++;
89
                }
90
91
                return points;
92
93
        }
94
95
        /**
96
         * Calculate the position inside sigle line
97
         *
98
         * @param geometryJts
99
         *            line of street
100
         * @param params
101
         *            Parameters to position the point over the lines
102
         * @return
103
         */
104
        private Point2D getLinesPosition(
105
                        com.vividsolutions.jts.geom.Geometry geometryJts,
106
                        MatchesParams params) {
107
108
                double totaldistance = geometryJts.getLength();
109
                LengthIndexedLine lenline = new LengthIndexedLine(geometryJts);
110
                Long distance = params.getDistance();
111
                Integer relativedist = params.getRelativeDistance();
112
                Double offset = params.getOffset();
113
114
                Coordinate coors = null;
115
116
                // first calculate with the distance
117
                if (distance != null) {
118
119
                        if (lenline.isValidIndex(distance)) {
120
                                coors = lenline.extractPoint(distance);
121
                                // with offset
122
                                if (offset != null && offset.doubleValue() > 0) {
123
                                        return getOffsetPosition(new Point2D(coors.x, coors.y),
124
                                                        offset);
125
                                }
126
                                // Without offset
127
                                else {
128
                                        return new Point2D(coors.x, coors.y);
129
                                }
130
                        }
131
                }
132
                // Calculate percentage of distance
133
                else if (relativedist != null) {
134
                        if (totaldistance > 0) {
135
                                double dist = (relativedist * totaldistance) / 100.0;
136
                                coors = lenline.extractPoint(dist);
137
                                // with offset
138
                                if (offset != null && offset.doubleValue() > 0) {
139
                                        return getOffsetPosition(new Point2D(coors.x, coors.y),
140
                                                        offset);
141
                                }
142
                                // Without offset
143
                                else {
144
                                        return new Point2D(coors.x, coors.y);
145
                                }
146
                        }
147
                }
148
                // Any other case
149
                else {
150
                        if (totaldistance > 0) {
151
                                double dist = totaldistance / 2.0;
152
                                coors = lenline.extractPoint(dist);
153
                                // with offset
154
                                if (offset != null && offset.doubleValue() > 0) {
155
                                        return getOffsetPosition(new Point2D(coors.x, coors.y),
156
                                                        offset);
157
                                }
158
                                // Without offset
159
                                else {
160
                                        return new Point2D(coors.x, coors.y);
161
                                }
162
                        }
163
                }
164
                return null;
165
        }
166
167
        /**
168
         * Calculate the position in the line with offset
169
         *
170
         * @param linePoint
171
         *            middle point over the liner
172
         * @param dist
173
         *            perpendicular distance since the line
174
         * @return
175
         */
176
        @SuppressWarnings("unchecked")
177
        private Point2D getOffsetPosition(Point2D linePoint, double dist) {
178
179 26883 vsanjaime
                List feats = (List) getFeatures().get(0);
180 26845 vsanjaime
                Geometry[] geoms = new Geometry[feats.size()];
181
                Iterator it = feats.iterator();
182
                int cont = 0;
183
                while (it.hasNext()) {
184
                        geoms[cont] = (Geometry) ((Feature) it.next())
185
                                        .getGeometry("GEOMETRY");
186
                        cont++;
187
                }
188
                for (int j = 0; j < geoms.length; j++) {
189
                        double[] coords = new double[6];
190
                        Point2D inicio = null;
191
                        Point2D fin = null;
192
193
                        boolean inter = geoms[j].intersects(linePoint.getBounds2D());
194
                        if (inter) {
195
                                PathIterator iter = ((Curve2D) geoms[j]).getGeneralPathX()
196
                                                .getPathIterator(null);
197
                                iter.currentSegment(coords);
198
                                inicio = new Point2D(coords[0], coords[1]);
199
200
                                iter.next();
201
                                iter.currentSegment(coords);
202
                                fin = new Point2D(coords[0], coords[1]);
203
204
                                log.debug("Return point with offset");
205
                                return getPerpendicularPoint(inicio, fin, linePoint, dist);
206
                        }
207
208
                }
209
                log.debug("Return original point without offset");
210
                return linePoint;
211
212
        }
213
214
        /**
215
         *
216
         * This method calculates a point perpendicular to the line at a distance
217
         *
218
         * @param inicio
219
         *            initial point of the line
220
         * @param fin
221
         *            end point of the line
222
         * @param linePoint
223
         *            middle point over line
224
         * @param dist
225
         *            perpendicular distance to the line
226
         * @return
227
         */
228
        private Point2D getPerpendicularPoint(Point2D inicio, Point2D fin,
229
                        Point2D linePoint, double dist) {
230
231
                java.awt.geom.Point2D p1 = new java.awt.geom.Point2D.Double(inicio
232
                                .getX(), inicio.getY());
233
                java.awt.geom.Point2D p2 = new java.awt.geom.Point2D.Double(fin.getX(),
234
                                fin.getY());
235
                java.awt.geom.Point2D perpPoint = new java.awt.geom.Point2D.Double(
236
                                linePoint.getX(), linePoint.getY());
237
238
                java.awt.geom.Point2D[] p = UtilFunctions.getPerpendicular(p1, p2,
239
                                perpPoint);
240
                java.awt.geom.Point2D unit = UtilFunctions.getUnitVector(p[0], p[1]);
241
242
                java.awt.geom.Point2D res = new java.awt.geom.Point2D.Double(perpPoint
243
                                .getX()
244
                                + (unit.getX() * dist), perpPoint.getY() + (unit.getY() * dist));
245
246
                return new Point2D(res.getX(), res.getY());
247
        }
248
249
}