本文介绍了地图,测试当前位置是否在折线上或附近的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用google路线api为路线绘制多段线。有没有人有任何检查当前位置是否在多段线上/附近的例子?试图确定用户当前位置是否在该线的x米范围内,如果不是,我会提出新请求并重新绘制新路线。



干杯!

解决方案

以下是我的解决方案:只需将我创建的 bdccGeoDistanceAlgorithm 类添加到您的项目并使用 bdccGeoDistanceCheckWithRadius 方法检查您的当前位置是否在折线上(折线等于点的纬度列表)
您也可以获得距离从方法

bdccGeoDistanceAlgorithm

  import com.google.android.gms.maps.model.LatLng; 

import java.util.List;

public class bdccGeoDistanceAlgorithm {

//从GLatLng指向GPolyline或GPolygon的距离(以米为单位)poly
public static boolean bdccGeoDistanceCheckWithRadius(List< LatLng> poly,LatLng point ,int radius)
{
int i;
bdccGeo p = new bdccGeo(point.latitude,point.longitude); (i = 0; i<(poly.size() - 1); i ++)
{
LatLng p1 = poly.get(i);


bdccGeo l1 = new bdccGeo(p1.latitude,p1.longitude);

LatLng p2 = poly.get(i + 1);
bdccGeo l2 = new bdccGeo(p2.latitude,p2.longitude);

double distance = p.function_distanceToLineSegMtrs(l1,l2);

if(距离< radius)
返回true;
}
返回false;
}


// object

public static class bdccGeo
{
public double lat;
public double lng;

public double x;
public double y;
public double z;


public bdccGeo(double lat,double lon){
this.lat = lat;
this.lng = lng;

double theta =(lon * Math.PI / 180.0);
double rlat = function_bdccGeoGeocentricLatitude(lat * Math.PI / 180.0);
double c = Math.cos(rlat);
this.x = c * Math.cos(theta);
this.y = c * Math.sin(theta);
this.z = Math.sin(rlat);
}

//以米为单位返回此点与线段geo1-geo2
//的垂直距离的最小值,以及此点到线段的距离在geo1和geo2中结束
public double function_distanceToLineSegMtrs(bdccGeo geo1,bdccGeo geo2)
{

//指向单位球体上方原点和法线到geo1平面,geo2
//可以是飞机的任一侧
bdccGeo p2 = geo1.function_crossNormalize(geo2);

//使用GC geo1 / geo2通过p传递给geo1 / geo2的GC法线的交点
bdccGeo ip = function_bdccGeoGetIntersection(geo1,geo2,this,p2);

//需要检查ip或其反对象在p1和p2之间
double d = geo1.function_distance(geo2);
double d1p = geo1.function_distance(ip);
double d2p = geo2.function_distance(ip);
//window.status = d +,+ d1p +,+ d2p; ((d> = d1p)&(d> = d2p))
返回function bbdccGeoRadiansToMeters(this.function_distance(ip));
else
{
ip = ip.function_antipode();
d1p = geo1.function_distance(ip);
d2p = geo2.function_distance(ip); ((d> = d1p)&(d> = d2p))
返回function_bdccGeoRadiansToMeters(this.function_distance(ip));
}

else
return function_bdccGeoRadiansToMeters(Math.min(geo1.function_distance(this),geo2.function_distance(this)));


//更多数学
public bdccGeo function_crossNormalize(bdccGeo b)
{
double x =(this.y * bz) - (this .z * by);
double y =(this.z * b.x) - (this.x * b.z);
double z =(this.x * b.y) - (this.y * b.x);
double L = Math.sqrt((x * x)+(y * y)+(z * z));
bdccGeo r = new bdccGeo(0,0);
r.x = x / L;
r.y = y / L;
r.z = z / L;

return r;
}

//返回由圆弧geo1到geo2和
// geo3到geo4定义的两个很好的
//圆圈的两个对极点。返回一个点作为Geo,使用.antipode获取另一个点
public bdccGeo function_bdccGeoGetIntersection(bdccGeo geo1,bdccGeo geo2,bdccGeo geo3,bdccGeo geo4)
{
bdccGeo geoCross1 = geo1.function_crossNormalize (GEO2);
bdccGeo geoCross2 = geo3.function_crossNormalize(geo4);
返回geoCross1.function_crossNormalize(geoCross2);
}

public double function_distance(bdccGeo v2)
{
return Math.atan2(v2.function_crossLength(this),v2.function_dot(this));


//更多数学
public double function_crossLength(bdccGeo b)
{
double x =(this.y * bz) - (this .z * by);
double y =(this.z * b.x) - (this.x * b.z);
double z =(this.x * b.y) - (this.y * b.x);
return Math.sqrt((x * x)+(y * y)+(z * z));
}

//数学
public double function_dot(bdccGeo b)
{
return((this.x * bx)+(this.y * by)+(this.z * bz));
}

//从Radians到Meters
public double function_bdccGeoRadiansToMeters(double rad)
{
return rad * 6378137.0; // WGS84赤道半径(以米为单位)
}

//指向这个点的世界另一端
public bdccGeo function_antipode()
{
return this.function_scale(-1.0);
}

//更多数学
public bdccGeo function_scale(double s)
{
bdccGeo r = new bdccGeo(0,0);
r.x = this.x * s;
r.y = this.y * s;
r.z = this.z * s;
return r;
}

//将地理转换为以地心为中心的纬度(弧度)。
public double function_bdccGeoGeocentricLatitude(double geographicLatitude)
{
double flattening = 1.0 / 298.257223563; // WGS84
double f =(1.0 - flattening)*(1.0 - flattening);
return Math.atan((Math.tan(geographicLatitude)* f));
}
}

}


I'm using google directions api to draw a polyline for a route. Does anyone have any examples of checking if current location is on/near a polyline? Trying to determine if users current location is within x meters of that line and if not i'll make a new request and redraw a new route.

Cheers!

解决方案

Here is my solution: just add the bdccGeoDistanceAlgorithm class I have created to your project and use bdccGeoDistanceCheckWithRadius method to check if your current location is on or near polyline (polyline equals to a list of LatLng of points)Your can also get the distance from the method

Class bdccGeoDistanceAlgorithm

import com.google.android.gms.maps.model.LatLng;

import java.util.List;

public class bdccGeoDistanceAlgorithm {

// distance in meters from GLatLng point to GPolyline or GPolygon poly
public static boolean bdccGeoDistanceCheckWithRadius(List<LatLng> poly, LatLng point, int radius)
{
    int i;
    bdccGeo p = new bdccGeo(point.latitude,point.longitude);

    for(i=0; i < (poly.size()-1) ; i++)
    {
        LatLng p1 = poly.get(i);
        bdccGeo l1 = new bdccGeo(p1.latitude,p1.longitude);

        LatLng p2 = poly.get(i+1);
        bdccGeo l2 = new bdccGeo(p2.latitude,p2.longitude);

        double distance = p.function_distanceToLineSegMtrs(l1, l2);

        if(distance < radius)
            return true;
    }
    return false;
}


// object

public static class bdccGeo
{
    public double lat;
    public double lng;

    public double x;
    public double y;
    public double z;


    public bdccGeo(double lat, double lon) {
        this.lat = lat;
        this.lng = lng;

        double theta = (lon * Math.PI / 180.0);
        double rlat = function_bdccGeoGeocentricLatitude(lat * Math.PI / 180.0);
        double c = Math.cos(rlat);
        this.x = c * Math.cos(theta);
        this.y = c * Math.sin(theta);
        this.z = Math.sin(rlat);
    }

    //returns in meters the minimum of the perpendicular distance of this point from the line segment geo1-geo2
    //and the distance from this point to the line segment ends in geo1 and geo2
    public double function_distanceToLineSegMtrs(bdccGeo geo1,bdccGeo geo2)
    {

        //point on unit sphere above origin and normal to plane of geo1,geo2
        //could be either side of the plane
        bdccGeo p2 = geo1.function_crossNormalize(geo2);

        // intersection of GC normal to geo1/geo2 passing through p with GC geo1/geo2
        bdccGeo ip = function_bdccGeoGetIntersection(geo1,geo2,this,p2);

        //need to check that ip or its antipode is between p1 and p2
        double d = geo1.function_distance(geo2);
        double d1p = geo1.function_distance(ip);
        double d2p = geo2.function_distance(ip);
        //window.status = d + ", " + d1p + ", " + d2p;
        if ((d >= d1p) && (d >= d2p))
            return function_bdccGeoRadiansToMeters(this.function_distance(ip));
        else
        {
            ip = ip.function_antipode();
            d1p = geo1.function_distance(ip);
            d2p = geo2.function_distance(ip);
        }
        if ((d >= d1p) && (d >= d2p))
            return function_bdccGeoRadiansToMeters(this.function_distance(ip));
        else
            return function_bdccGeoRadiansToMeters(Math.min(geo1.function_distance(this),geo2.function_distance(this)));
    }

    // More Maths
    public bdccGeo function_crossNormalize(bdccGeo b)
    {
        double x = (this.y * b.z) - (this.z * b.y);
        double y = (this.z * b.x) - (this.x * b.z);
        double z = (this.x * b.y) - (this.y * b.x);
        double L = Math.sqrt((x * x) + (y * y) + (z * z));
        bdccGeo r = new bdccGeo(0,0);
        r.x = x / L;
        r.y = y / L;
        r.z = z / L;

        return r;
    }

    // Returns the two antipodal points of intersection of two great
    // circles defined by the arcs geo1 to geo2 and
    // geo3 to geo4. Returns a point as a Geo, use .antipode to get the other point
    public bdccGeo function_bdccGeoGetIntersection(bdccGeo geo1,bdccGeo  geo2, bdccGeo geo3,bdccGeo geo4)
    {
        bdccGeo geoCross1 = geo1.function_crossNormalize(geo2);
        bdccGeo geoCross2 = geo3.function_crossNormalize(geo4);
        return geoCross1.function_crossNormalize(geoCross2);
    }

    public double function_distance(bdccGeo v2)
    {
        return Math.atan2(v2.function_crossLength(this), v2.function_dot(this));
    }

    //More Maths
    public double function_crossLength(bdccGeo b)
    {
        double x = (this.y * b.z) - (this.z * b.y);
        double y = (this.z * b.x) - (this.x * b.z);
        double z = (this.x * b.y) - (this.y * b.x);
        return Math.sqrt((x * x) + (y * y) + (z * z));
    }

    //Maths
    public double function_dot(bdccGeo b)
    {
        return ((this.x * b.x) + (this.y * b.y) + (this.z * b.z));
    }

    //from Radians to Meters
    public double function_bdccGeoRadiansToMeters(double rad)
    {
        return rad * 6378137.0; // WGS84 Equatorial Radius in Meters
    }

    // point on opposite side of the world to this point
    public bdccGeo function_antipode()
    {
        return this.function_scale(-1.0);
    }

    //More Maths
    public bdccGeo function_scale(double s)
    {
        bdccGeo r = new bdccGeo(0,0);
        r.x = this.x * s;
        r.y = this.y * s;
        r.z = this.z * s;
        return r;
    }

    // Convert from geographic to geocentric latitude (radians).
    public double function_bdccGeoGeocentricLatitude(double geographicLatitude)
    {
        double flattening = 1.0 / 298.257223563;//WGS84
        double f = (1.0 - flattening) * (1.0 - flattening);
        return Math.atan((Math.tan(geographicLatitude) * f));
    }
}

}

这篇关于地图,测试当前位置是否在折线上或附近的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 06:02