问题
I want to draw a curve (Beizer curve) between two lat-long points. Currently i am referring this post (code is in javascript).
Code to get curve points using cubic bezier equation
private void drawElementsOnMap(LatLng init, LatLng end) {
mMap.addMarker(new MarkerOptions().position(init));
mMap.addMarker(new MarkerOptions().position(end));
LatLngBounds.Builder bc = new LatLngBounds.Builder();
bc.include(init);
bc.include(end);
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bc.build(), 100));
PolylineOptions line = new PolylineOptions();
line.add(init);
line.add(end);
mMap.addPolyline(line);
double distanceBetween = SphericalUtil.computeDistanceBetween(init, end);
double lineHeadingInit = SphericalUtil.computeHeading(init, end);
double lineHeadingEnd = bearing(end, init);*/
double lineHeading1, lineHeading2;
if (lineHeadingInit < 0) {
lineHeading1 = lineHeadingInit + 45;
lineHeading2 = lineHeadingInit + 135;
} else {
lineHeading1 = lineHeadingInit + -45;
lineHeading2 = lineHeadingInit + -135;
}
LatLng pA = SphericalUtil.computeOffset(init, distanceBetween / 2.5, lineHeading1);
LatLng pB = SphericalUtil.computeOffset(end, distanceBetween / 2.5, lineHeading2);
// Beizer curves with 4 points
gmapsCubicBezier(init, end, pA, pB);
}
private void gmapsCubicBezier(LatLng p1, LatLng p2, LatLng pA, LatLng pB) {
//Polyline options
PolylineOptions options = new PolylineOptions();
LatLng curveLatLng = null;
for (double t = 0.0; t < 1.01; t += 0.01) {
// P = (1−t)3P1 + 3(1−t)2tP2 +3(1−t)t2P3 + t3P4; for 4 points
double arcX = (1 - t) * (1 - t) * (1 - t) * p1.latitude
+ 3 * (1 - t) * (1 - t) * t * pA.latitude
+ 3 * (1 - t) * t * t * pB.latitude
+ t * t * t * p2.latitude;
double arcY = (1 - t) * (1 - t) * (1 - t) * p1.longitude
+ 3 * (1 - t) * (1 - t) * t * pA.longitude
+ 3 * (1 - t) * t * t * pB.longitude
+ t * t * t * p2.longitude;
curveLatLng = new LatLng(arcX, arcY);
options.add(curveLatLng);
//Draw polyline
mMap.addPolyline(options.width(5).color(Color.DKGRAY).geodesic(false));
}
mMap.addMarker(new MarkerOptions().position(curveLatLng));
}
Following are the pictures show different test cases I tried.
case 1: P1 - Mumbai, P2 - Chennai
case 2: P1 - France, P2 - Singapore
case 3: P1 - USA, P2 - Bangalore
case 4: P1 - USA, P2 - Singapore
Questions:
1) Why is algorithm able to draw fairly decent curve only in case 1?
2) Why bezier curve bents on one side in case 2?
3) Why bezier curve looks different in case 3 and 4 (strange cusp at P1 (case 3) and at P2 (case 4)). Is there anyway to avoid it?
4) Why polyline is drawn differently (the direction?) in case 4?
I am unable to understand the pattern in which curve is drawn. Please let me know if I am doing anything wrong.
回答1:
This answer is somewhat specative, but I suggest that nothing you are seeing is actually wrong or even unexpected. As you know, the Earth is round, but Google Maps (and computer screens) are inherently flat and two dimensional. The way we begin creating a flat 2D map of the Earth is by carving up a globe like this:
Things get somewhat warped and skewed in the process of creating the 2D map of the world to which we are all accustomed to see. I don't have the maths to back it up, but it seems obvious that 3D curves connecting two cities across most of the globe would also get warped and skewed after projecting them onto a 2D map. And I would expect the distortions to get more pronounced the longer the curves are.
This also would explain why the curve from Mumbai to Chennai looks normal to you. It is over a relatively short distance, where distortions due to the curvature of the Earth are minimal.
来源:https://stackoverflow.com/questions/47950659/draw-a-curve-bezier-curve-between-two-lat-long-points-on-google-maps-android