Changeset 5226 in osm


Ignore:
Timestamp:
2007-10-29T15:02:21+01:00 (17 years ago)
Author:
gabriel
Message:

UtilsPlugin: Simplify math in SimplifyWayAction.

Location:
applications/editors/josm/plugins
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/utilsplugin/src/UtilsPlugin/SimplifyWayAction.java

    r5142 r5226  
    103103                for (int i = from+1; i < to; i++) {
    104104                        Node n = wnew.nodes.get(i);
    105                         double xte = radtometers(linedist(
     105                        double xte = Math.abs(EARTH_RAD * xtd(
    106106                                fromN.coor.lat(), fromN.coor.lon(),
    107                                 n.coor.lat(), n.coor.lon(),
    108                                 toN.coor.lat(), toN.coor.lon()));
     107                                toN.coor.lat(), toN.coor.lon(),
     108                                n.coor.lat(), n.coor.lon()));
    109109                        if (xte > xtemax) {
    110110                                xtemax = xte;
     
    120120        }
    121121
    122         /* ----------------------------------------------------------------------
    123          * Everything below this comment was converted from C to Java by Frederik
    124          * Ramm. The original sources are the files grtcirc.c and smplrout.c from
    125          * the gpsbabel source code (www.gpsbabel.org), which is under GPL. The
    126          * relevant code portions have been written by Robert Lipe.
    127          *
    128          * Method names have been left unchanged where possible.
     122        public static double EARTH_RAD = 6378137.0;
     123
     124        /* From Aviaton Formulary v1.3
     125         * http://williams.best.vwh.net/avform.htm
    129126         */
    130        
    131         public static double EARTH_RAD = 6378137.0;
    132         public static double radmiles = EARTH_RAD*100.0/2.54/12.0/5280.0;
    133 
    134         public static double[] crossproduct(double[] v1, double[] v2) {
    135                 double[] rv = new double[3];
    136                 rv[0] = v1[1]*v2[2]-v2[1]*v1[2];
    137                 rv[1] = v1[2]*v2[0]-v2[2]*v1[0];
    138                 rv[2] = v1[0]*v2[1]-v1[1]*v2[0];
    139                 return rv;
     127        public static double dist(double lat1, double lon1, double lat2, double lon2) {
     128                return 2*Math.asin(Math.sqrt(Math.pow(Math.sin((lat1-lat2)/2), 2) +
     129                        Math.cos(lat1)*Math.cos(lat2)*Math.pow(Math.sin((lon1-lon2)/2), 2)));
    140130        }
    141131
    142         public static double dotproduct(double[] v1, double[] v2) {
    143                 return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
     132        public static double course(double lat1, double lon1, double lat2, double lon2) {
     133                return Math.atan2(Math.sin(lon1-lon2)*Math.cos(lat2),
     134                    Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2)) % (2*Math.PI);
    144135        }
    145136
    146         public static double radtomiles(double rads) {
    147                 return (rads*radmiles);
    148         }
    149 
    150         public static double radtometers(double rads) {
    151                 return (rads * EARTH_RAD);
    152         }
    153        
    154         public static double veclen(double[] vec) {
    155                 return Math.sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
    156         }
    157 
    158         public static double gcdist(double lat1, double lon1, double lat2, double lon2)
    159         {
    160                 double res;
    161                 double sdlat, sdlon;
    162 
    163                 sdlat = Math.sin((lat1 - lat2) / 2.0);
    164                 sdlon = Math.sin((lon1 - lon2) / 2.0);
    165 
    166                 res = Math.sqrt(sdlat * sdlat + Math.cos(lat1) * Math.cos(lat2) * sdlon * sdlon);
    167 
    168                 if (res > 1.0) {
    169                         res = 1.0;
    170                 } else if (res < -1.0) {
    171                         res = -1.0;
    172                 }
    173 
    174                 res = Math.asin(res);
    175                 return 2.0 * res;
    176         }
    177 
    178         static double linedist(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3) {
    179 
    180                 double dot;
    181 
    182                 /* degrees to radians */
    183                 lat1 = Math.toRadians(lat1);  lon1 = Math.toRadians(lon1);
    184                 lat2 = Math.toRadians(lat2);  lon2 = Math.toRadians(lon2);
    185                 lat3 = Math.toRadians(lat3);  lon3 = Math.toRadians(lon3);
    186 
    187                 /* polar to ECEF rectangular */
    188                 double[] v1 = new double[3];
    189                 double[] v2 = new double[3];
    190                 double[] v3 = new double[3];
    191                 v1[0] = Math.cos(lon1)*Math.cos(lat1); v1[1] = Math.sin(lat1); v1[2] = Math.sin(lon1)*Math.cos(lat1);
    192                 v2[0] = Math.cos(lon2)*Math.cos(lat2); v2[1] = Math.sin(lat2); v2[2] = Math.sin(lon2)*Math.cos(lat2);
    193                 v3[0] = Math.cos(lon3)*Math.cos(lat3); v3[1] = Math.sin(lat3); v3[2] = Math.sin(lon3)*Math.cos(lat3);
    194 
    195                 /* 'va' is the axis; the line that passes through the center of the earth
    196                  * and is perpendicular to the great circle through point 1 and point 2
    197                  * It is computed by taking the cross product of the '1' and '2' vectors.*/
    198                 double[] va = crossproduct(v1, v2);
    199                 double la = veclen(va);
    200 
    201                 if (la != 0) {
    202                         va[0] /= la;
    203                         va[1] /= la;
    204                         va[2] /= la;
    205 
    206                         /* dot is the component of the length of '3' that is along the axis.
    207                          * What's left is a non-normalized vector that lies in the plane of
    208                          * 1 and 2. */
    209 
    210                         dot = dotproduct(v3, va);
    211 
    212                         double[] vp = new double[3];
    213                         vp[0]=v3[0]-dot*va[0];
    214                         vp[1]=v3[1]-dot*va[1];
    215                         vp[2]=v3[2]-dot*va[2];
    216 
    217                         double lp = veclen(vp);
    218 
    219                         if (lp != 0) {
    220 
    221                                 /* After this, 'p' is normalized */
    222                                 vp[0] /= lp;
    223                                 vp[1] /= lp;
    224                                 vp[2] /= lp;
    225 
    226                                 double[] cp1 = crossproduct(v1, vp);
    227                                 double dp1 = dotproduct(cp1, va);
    228 
    229                                 double[] cp2 = crossproduct(v2, vp);
    230                                 double dp2 = dotproduct(cp2, va);
    231 
    232                                 if ( dp1 >= 0 && dp2 >= 0 ) {
    233                                         /* rather than call gcdist and all its sines and cosines and
    234                                          * worse, we can get the angle directly.  It's the arctangent
    235                                          * of the length of the component of vector 3 along the axis
    236                                          * divided by the length of the component of vector 3 in the
    237                                          * plane.  We already have both of those numbers.
    238                                          *
    239                                          * atan2 would be overkill because lp and Math.abs are both
    240                                          * known to be positive. */
    241                                         return Math.atan(Math.abs(dot)/lp);
    242                                 }
    243 
    244                                 /* otherwise, get the distance from the closest endpoint */
    245                                 double c1 = dotproduct(v1, vp);
    246                                 double c2 = dotproduct(v2, vp);
    247                                 dp1 = Math.abs(dp1);
    248                                 dp2 = Math.abs(dp2);
    249 
    250                                 /* This is a hack.  d$n$ is proportional to the sine of the angle
    251                                  * between point $n$ and point p.  That preserves orderedness up
    252                                  * to an angle of 90 degrees.  c$n$ is proportional to the cosine
    253                                  * of the same angle; if the angle is over 90 degrees, c$n$ is
    254                                  * negative.  In that case, we flop the sine across the y=1 axis
    255                                  * so that the resulting value increases as the angle increases.
    256                                  *
    257                                  * This only works because all of the points are on a unit sphere. */
    258 
    259                                 if (c1 < 0) {
    260                                         dp1 = 2 - dp1;
    261                                 }
    262                                 if (c2 < 0) {
    263                                         dp2 = 2 - dp2;
    264                                 }
    265 
    266                                 if (Math.abs(dp1) < Math.abs(dp2)) {
    267                                         return gcdist(lat1,lon1,lat3,lon3); 
    268                                 } else {
    269                                         return gcdist(lat2,lon2,lat3,lon3);
    270                                 }
    271                         } else {
    272                                 /* lp is 0 when 3 is 90 degrees from the great circle */
    273                                 return Math.PI/2;
    274                         }   
    275                 } else {
    276                         /* la is 0 when 1 and 2 are either the same point or 180 degrees apart */
    277                         dot = dotproduct(v1, v2);
    278                         if (dot >= 0) {
    279                                 return gcdist(lat1,lon1,lat3,lon3);
    280                         } else {
    281                                 return 0;
    282                         }
    283                 }
     137        public static double xtd(double lat1, double lon1, double lat2, double lon2, double lat3, double lon3) {
     138                double dist_AD = dist(lat1, lon1, lat3, lon3);
     139                double crs_AD = course(lat1, lon1, lat3, lon3);
     140                double crs_AB = course(lat1, lon1, lat2, lon2);
     141                return Math.asin(Math.sin(dist_AD)*Math.sin(crs_AD-crs_AB));
    284142        }
    285143}
Note: See TracChangeset for help on using the changeset viewer.