Changeset 5715 in josm for trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
- Timestamp:
- 2013-02-13T19:12:38+01:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
r5681 r5715 7 7 import java.util.LinkedList; 8 8 import java.util.Map; 9 import org.openstreetmap.josm.Main; 9 10 10 11 import org.openstreetmap.josm.data.Bounds; 12 import org.openstreetmap.josm.data.coor.EastNorth; 11 13 12 14 /** … … 122 124 return result; 123 125 } 126 127 /** 128 * Makes a WayPoint at the projection of point P onto the track providing P is less than 129 * tolerance away from the track 130 * 131 * @param P : the point to determine the projection for 132 * @param tolerance : must be no further than this from the track 133 * @return the closest point on the track to P, which may be the first or last point if off the 134 * end of a segment, or may be null if nothing close enough 135 */ 136 public WayPoint nearestPointOnTrack(EastNorth P, double tolerance) { 137 /* 138 * assume the coordinates of P are xp,yp, and those of a section of track between two 139 * trackpoints are R=xr,yr and S=xs,ys. Let N be the projected point. 140 * 141 * The equation of RS is Ax + By + C = 0 where A = ys - yr B = xr - xs C = - Axr - Byr 142 * 143 * Also, note that the distance RS^2 is A^2 + B^2 144 * 145 * If RS^2 == 0.0 ignore the degenerate section of track 146 * 147 * PN^2 = (Axp + Byp + C)^2 / RS^2 that is the distance from P to the line 148 * 149 * so if PN^2 is less than PNmin^2 (initialized to tolerance) we can reject the line; 150 * otherwise... determine if the projected poijnt lies within the bounds of the line: PR^2 - 151 * PN^2 <= RS^2 and PS^2 - PN^2 <= RS^2 152 * 153 * where PR^2 = (xp - xr)^2 + (yp-yr)^2 and PS^2 = (xp - xs)^2 + (yp-ys)^2 154 * 155 * If so, calculate N as xn = xr + (RN/RS) B yn = y1 + (RN/RS) A 156 * 157 * where RN = sqrt(PR^2 - PN^2) 158 */ 159 160 double PNminsq = tolerance * tolerance; 161 EastNorth bestEN = null; 162 double bestTime = 0.0; 163 double px = P.east(); 164 double py = P.north(); 165 double rx = 0.0, ry = 0.0, sx, sy, x, y; 166 if (tracks == null) 167 return null; 168 for (GpxTrack track : tracks) { 169 for (GpxTrackSegment seg : track.getSegments()) { 170 WayPoint R = null; 171 for (WayPoint S : seg.getWayPoints()) { 172 EastNorth c = S.getEastNorth(); 173 if (R == null) { 174 R = S; 175 rx = c.east(); 176 ry = c.north(); 177 x = px - rx; 178 y = py - ry; 179 double PRsq = x * x + y * y; 180 if (PRsq < PNminsq) { 181 PNminsq = PRsq; 182 bestEN = c; 183 bestTime = R.time; 184 } 185 } else { 186 sx = c.east(); 187 sy = c.north(); 188 double A = sy - ry; 189 double B = rx - sx; 190 double C = -A * rx - B * ry; 191 double RSsq = A * A + B * B; 192 if (RSsq == 0.0) { 193 continue; 194 } 195 double PNsq = A * px + B * py + C; 196 PNsq = PNsq * PNsq / RSsq; 197 if (PNsq < PNminsq) { 198 x = px - rx; 199 y = py - ry; 200 double PRsq = x * x + y * y; 201 x = px - sx; 202 y = py - sy; 203 double PSsq = x * x + y * y; 204 if (PRsq - PNsq <= RSsq && PSsq - PNsq <= RSsq) { 205 double RNoverRS = Math.sqrt((PRsq - PNsq) / RSsq); 206 double nx = rx - RNoverRS * B; 207 double ny = ry + RNoverRS * A; 208 bestEN = new EastNorth(nx, ny); 209 bestTime = R.time + RNoverRS * (S.time - R.time); 210 PNminsq = PNsq; 211 } 212 } 213 R = S; 214 rx = sx; 215 ry = sy; 216 } 217 } 218 if (R != null) { 219 EastNorth c = R.getEastNorth(); 220 /* if there is only one point in the seg, it will do this twice, but no matter */ 221 rx = c.east(); 222 ry = c.north(); 223 x = px - rx; 224 y = py - ry; 225 double PRsq = x * x + y * y; 226 if (PRsq < PNminsq) { 227 PNminsq = PRsq; 228 bestEN = c; 229 bestTime = R.time; 230 } 231 } 232 } 233 } 234 if (bestEN == null) 235 return null; 236 WayPoint best = new WayPoint(Main.getProjection().eastNorth2latlon(bestEN)); 237 best.time = bestTime; 238 return best; 239 } 124 240 }
Note:
See TracChangeset
for help on using the changeset viewer.