Need a sector based on bearing, geopoint, distance

2019-09-10 05:29发布

问题:

I have a problem. I am trying to write a JAVA code were in given bearing, (lat,lon) , speed I need to get all points which form a sector (like in the diagram (x1,y1) , (x2,y2) and list of points which form an Arc in the direction which is given by bearing (I have very limited knowledge on bearing).

My first thing is to achieve sector based on the direction with hard-coded distance and angle. (i.e fixed values say d = 5km and angle = 60 deg.)

Next Step is based on the speed I want distance d and angle to be calculated like d = func(speed) and angle = func(speed) but this will be later.

Since bearing is given in terms of degree I don't know how to calculate direction. What i was thinking like If i am able to convert the bearing to a unit vector on the same direction. then i think we can draw the sector.

Correct me if i am wrong in my theory/explanation. Please I need help guys.....

More details:

I am working on a small project were in while tracking through google maps on phone I can get (lat,lon) - current position of user, bearing - in the direction in which I am headed and speed - what speed i am travelling.

Distance and angle relation with speed :

If i am travelling with more speed the d should be more and angle should be less (arc will be more narrower)

If i am travelling with less speed then d should be less and `angle should be more (arc will be wider)

If i am stationary the speed is 0 , then i will draw a circle around my current (lat,lon) and find my POI around me.

Once i get this sector i will use Elastic search ( It provide some func() like nearby search and polygon search) to get all the Point Of Interest along my way while i am tracking

Ultimately, while i am driving i want to show user what are the POI he gets along his way. ( we don't know user's destination)

UPDATE

public class Test {

    // N is the number of points on the arc
    // e.g. const int N = 15;
    private static final int N = 10;

    public static void main(String[] args){

        final double deg2Rad = Math.PI / 180.0; //degree to Radian
        final double Rad2deg = 180.0 / Math.PI; //Radian to degree
        double bearing =  90; //direction
        double angle = 60; //sector angle   
        double R = 6371.0; //Radius of earth

        double lat = 12.926428 * deg2Rad;
        double lon = 77.677705 * deg2Rad;

        double d = 5; 

        Geopoint[] array = new Geopoint[N];

        double A = bearing - angle * 0.5;    // starting angle / bearing
        double dA = angle / (double)(N - 1); // angle step between adjacent points

        /* convert lat, lon to cartesian here! */
        double  x = R * Math.cos(lat) * Math.cos(lon);
        System.out.println(x);
        double  y = R * Math.cos(lat) * Math.sin(lon);
        System.out.println(y);
        double  z = R * Math.sin(lat);
        System.out.println(z);


        for (int i = 0; i < N; i++, A += dA)
        {
          double c = Math.cos(A * deg2Rad), 
                 s = Math.sin(A * deg2Rad);

          System.out.println( "C : " + c);
          System.out.println( "S : " + s);

          double x1 = (x + d * c) ;

          double y1 = (y + d * s) ;

          //Convert back to Geopoint
          lat = Math.asin(z / R) * Rad2deg;
          lon = Math.atan2(y1, x1) * Rad2deg;

          array[i] = new Geopoint(lon , lat );
        }

        // return array 
        for ( int i = 0; i < array.length; i++ )
            System.out.println("points," + i + "," + array[i]); 
    }

}

For the above code i am getting below output

Output

points,0,{ "lon":130.56759538189806, "lat":20.62976857973366, "geoadress":"null" }
points,1,{ "lon":130.56753333442796, "lat":20.62976857973366, "geoadress":"null" }
points,2,{ "lon":130.56747144031073, "lat":20.62976857973366, "geoadress":"null" }
points,3,{ "lon":130.56740969980146, "lat":20.62976857973366, "geoadress":"null" }
points,4,{ "lon":130.5673481131545, "lat":20.62976857973366, "geoadress":"null" }
points,5,{ "lon":130.5672866806237, "lat":20.62976857973366, "geoadress":"null" }
points,6,{ "lon":130.5672254024622, "lat":20.62976857973366, "geoadress":"null" }
points,7,{ "lon":130.5671642789225, "lat":20.62976857973366, "geoadress":"null" }
points,8,{ "lon":130.5671033102564, "lat":20.62976857973366, "geoadress":"null" }
points,9,{ "lon":130.56704249671517, "lat":20.62976857973366, "geoadress":"null" }

But this output is wrong. I don't know where i am going wrong.

Output

After changing lat and lon to radians this is my result.

points,0,12.926428,77.677705
points,1,12.926428,77.6917252889466
points,2,12.926428,77.68652371253442
points,3,12.926428,77.68120259629767
points,4,12.926428,77.67583406750569
points,5,12.926428,77.67049090073982
points,6,12.926428,77.6652455243131
points,7,12.926428,77.6601690315512
points,8,12.926428,77.65533021080672
points,9,12.926428,77.65079460778875
points,10,12.926428,77.64662363329005

Since I am dong this lat = Math.asin(z / R) * Rad2deg; to convert from cartesian i am getting all lat same. I don't know how to solve this.

Resut

Based on iant code

Result_1#

I have computed the distance btw (lat,lon) to every point on the arc. It should result in same distance. iant check the result there is slight variation in the distance.

type,id,lat,lon points,1,12.926428,77.677705 Distance in mtrs : 0.0 points,2,12.92657150782396,77.67778916970093 Distance in mtrs : 9.971162660481445 points,3,12.926578367173896,77.67778862221844 Distance in mtrs : 9.971162660481445 points,4,12.926585180719618,77.67778804926368 Distance in mtrs : 9.971162660481445 points,5,12.926591946385617,77.67778745101116 Distance in mtrs : 9.97070966260917 points,6,12.92659866211097,77.67778682764309 Distance in mtrs : 9.971162660481445 points,7,12.926605325849975,77.6777861793494 Distance in mtrs : 9.971162660481445 points,8,12.926611935572756,77.67778550632754 Distance in mtrs : 9.97070966260917 points,9,12.926618489265902,77.67778480878253 Distance in mtrs : 9.97070966260917 points,10,12.92662498493306,77.67778408692685 Distance in mtrs : 9.971162660481445 points,11,12.926631420595564,77.67778334098041 Distance in mtrs : 9.97070966260917 points,12,12.926637794293018,77.67778257117044 Distance in mtrs : 9.97070966260917 points,13,12.926644104083913,77.67778177773138 Distance in mtrs : 9.97070966260917 points,14,12.9266503480462,77.67778096090498 Distance in mtrs : 9.97070966260917 points,15,12.926656524277885,77.67778012094006 Distance in mtrs : 9.970256644154967 points,16,12.926662630897608,77.67777925809244 Distance in mtrs : 9.970256644154967 points,17,12.926668666045215,77.67777837262499 Distance in mtrs : 9.97070966260917 points,18,12.926674627882324,77.67777746480742 Distance in mtrs : 9.97070966260917 points,19,12.92668051459289,77.67777653491626 Distance in mtrs : 9.970256644154967 points,20,12.926686324383741,77.6777755832348 Distance in mtrs : 9.970256644154967 points,21,12.926692055485155,77.67777461005294 Distance in mtrs : 9.970256644154967 points,22,12.926428,77.677705 Distance in mtrs : 0.0

Distance Calculation

public static double distanceOf(Geopoint a, Geopoint b) {
    if (a.isValid() && b.isValid()) {
      double distFactor = Math.acos(Math.sin(Math.toRadians(a.getLat())) * Math.sin(Math.toRadians(b.getLat()))
          + Math.cos(Math.toRadians(a.getLat())) * Math.cos(Math.toRadians(b.getLat()))
              * Math.cos(Math.toRadians(b.getLon()) - Math.toRadians(a.getLon())));
      return 6378.388 * distFactor;
    }
    return -1;
  }

回答1:

When you say that you want to draw the arc I assume you mean using Java Swing. If that's the case then the API already does a lot of the work for you. For example, the Arc2D.Float class has a constructor (see javadoc for details) that lets you define the position and extent of the arc to draw. The x, y, w, h arguments would be set according to the position of the origin and the distance/radius. The start and extent arguments would be set as bearing - angle / 2 and angle respectively. The type argument would be Arc2D.PIE if you want it to look like the diagram in your question.

Once you have created the Arc2D you can draw it using Graphics2D.draw.

I don't understand what you mean by calculating distance and angle as a function of speed. I would think you would need a time argument as well to calculate distance and it's impossible to tell from your question what the relationship between speed and angle should be.



回答2:

const double deg2Rad = Math.PI / 180.0;

// N is the number of points you want on the arc
// If you don't want to pass this, then set it to constant
// e.g. const int N = 15;

Point[] array = new Point[N];
double A = bearing - angle * 0.5;    // starting angle / bearing
double dA = angle / (double)(N - 1); // angle step between adjacent points

double x, y = /* convert lat, lon to cartesian here! */

for (int i = 0; i < N; i++, A += dA)
{
  double c = Math.cos(A * deg2Rad), 
         s = Math.sin(A * deg2Rad);
  array[i] = new Point(x + d * c, y + d * s);
}

// return array


回答3:

I answered a very similar question earlier this week - GeoTools provides all the tools you need to create an arc which fulfils these requirements - GeodeticCalculator allows you to specify a start point, azimuth and distance and will return you the destination point. Using this it is easy to create an arc of any distance and width.

The full code is here that solved the other problem. You would need to parameterize the width (and may be the number of steps in the arc) for your needs.

EDIT

This does produce an arc:

POLYGON ((12.926428 77.677705, 12.926571507823445 77.67778916970063, 12.926578367173352 77.67778862221815, 12.926585180719048 77.67778804926338, 12.926591946385022 77.67778745101086, 12.926598662110349 77.67778682764279, 12.926605325849323 77.6777861793491, 12.926611935572092 77.67778550632724, 12.926618489265206 77.67778480878223, 12.926624984932337 77.67778408692658, 12.926631420594818 77.67778334098014, 12.926637794292239 77.67778257117014, 12.926644104083113 77.67778177773111, 12.926650348045378 77.67778096090471, 12.926656524277035 77.67778012093977, 12.926662630896734 77.67777925809216, 12.926668666044314 77.67777837262472, 12.926674627881402 77.67777746480715, 12.926680514591945 77.67777653491602, 12.92668632438278 77.67777558323456, 12.926692055484166 77.67777461005268, 12.926428 77.677705))

It just depends on how you look at it - that far north (you are working in Svalbard?) things look weird due to the curvature of the earth, so in a flat projection like Plate Carree (WGS84) it doesn't look like an arc.

But in an equidistant projection (designed to keep distances looking correct) it is an arc.

Of course if you are in India then it looks fine in EPSG:4326.