Self taught HarmonyOS application development (54) - correct positioning deviation

The previous article has introduced the method of obtaining the current location, which has a problem: there is a deviation of about 500 meters from the actual location.

Cause investigation

After some investigation, it is concluded that the gps signal uses WGS-84 coordinate system, while Gaode map uses GCJ-02 Mars coordinate system. Only after coordinate transformation can the correct position be displayed. There are many articles in this field on the Internet. Here we use the code in the following blog posts:

https://www.cnblogs.com/blogger-Li/p/11616835.html

The code is as follows:

// This code is quoted from Hugo_nice blog post below// https://www.cnblogs.com/blogger-Li/p/11616835.htmlpackage  xwg. harmony. stopwatch;
import java.math.BigDecimal;import java.math.RoundingMode;
/** * gps Correction algorithm, applicable to google, Gaode system map */public abstract class GpsUtil {
private final static double a = 6378245.0;    private final static double pi = 3.1415926535897932384626;    private final static double ee = 0.00669342162296594323;
/**     * Calculate the distance between any two points (longitude and latitude) on the earth * * @ param lat1 * latitude of the first point * @ param lng1 * longitude of the first point * @ param lat2 * latitude of the second point * @ param lng2 * longitude of the second point * @ return return return distance unit: meter     */    public static double distance(double lat1, double lng1, double lat2, double lng2) {        double a, b, R;        R = 6378137; // Earth radius LAT1 = LAT1 * math PI / 180.0;         lat2 = lat2 * Math. PI / 180.0;         a = lat1 - lat2;         b = (lng1 - lng2) * Math. PI / 180.0;         double d;         double sa2, sb2;         sa2 = Math. sin(a / 2.0);         sb2 = Math. sin(b / 2.0);         d = 2 * R * Math. asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math. cos(lat2) * sb2 * sb2));         return d;    }
/**     * Description: WGS-84 to GCJ-02 <BR>     *     * @author dsn     * @date 2017 2:09:27 PM, October 24, 2009 * @ param latitude * latitude * @ param longitude * longitude * @ return [latitude, longitude] * @ version 1.0     */    public static double[] toGCJ02Point(double latitude, double longitude) {        double[] dev = calDev(latitude, longitude);        double retLat = latitude + dev;        double retLon = longitude + dev;        return new double[] { retLat, retLon };    }
/**     * Description: WGS-84 to GCJ-02 <BR>     *     * @author dsn     * @date 2017 2:09:27 PM, October 24, 2014 * @ param latitude * latitude * @ param longitude * longitude * @ param scale * longitude and latitude retain decimal places * @ return [latitude, longitude] * @ version 1.0     */    public static double[] toGCJ02Point(double latitude, double longitude, int scale) {        double[] dev = calDev(latitude, longitude);        double retLat = latitude + dev;        double retLon = longitude + dev;        return new double[] { new BigDecimal(retLat).setScale(scale, RoundingMode.DOWN).doubleValue(),                new BigDecimal(retLon).setScale(scale, RoundingMode.DOWN).doubleValue() };    }
/**     * Description:GCJ-02 to WGS-84 <BR>     *     * @author dsn     * @date 2017 October 24, 2014, 2:09:54 PM * @ param latitude * latitude * @ param longitude * longitude * @ return [latitude, longitude] * @ version 1.0     */    public static double[] toWGS84Point(double latitude, double longitude) {        double[] dev = calDev(latitude, longitude);        double retLat = latitude - dev;        double retLon = longitude - dev;        dev = calDev(retLat, retLon);        retLat = latitude - dev;        retLon = longitude - dev;        return new double[] { retLat, retLon };    }
private static double[] calDev(double wgLat, double wgLon) {        if (isOutOfChina(wgLat, wgLon)) {            return new double[] { 0, 0 };        }        double dLat = calLat(wgLon - 105.0, wgLat - 35.0);        double dLon = calLon(wgLon - 105.0, wgLat - 35.0);        double radLat = wgLat / 180.0 * pi;        double magic = Math.sin(radLat);        magic = 1 - ee * magic * magic;        double sqrtMagic = Math.sqrt(magic);        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);        return new double[] { dLat, dLon };    }
private static boolean isOutOfChina(double lat, double lon) {        if (lon < 72.004 || lon > 137.8347)            return true;        if (lat < 0.8293 || lat > 55.8271)            return true;        return false;    }
private static double calLat(double x, double y) {        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;        return ret;    }
private static double calLon(double x, double y) {        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;        return ret;    }}

public void setLocation(double long_deg, double lat_deg){    double ret[] = GpsUtil.toGCJ02Point(lat_deg, long_deg);    latitude = ret;    longitude = ret;    invalidate();}

Before setting the longitude and latitude, the transformation method can be called. The deviation between the converted position and the actual position can be within tens of meters.

Reference code

https://github.com/xueweiguo/Harmony/tree/master/StopWatch

reference material

Transformation relationship between GCJ-02 Mars coordinate system and WGS-84 coordinate system:

https://www.cnblogs.com/blogger-Li/p/11616835.html

Get the location information of the device:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/device-location-info-0000000000031900

Introduction to the author's works

Actual Python design pattern It is a technical book published by the author last March. The book uses Python's standard GUI toolkit tkinter to illustrate 23 design patterns one by one through executable examples. On the one hand, it can make readers understand the application scenarios and problems to be solved of each design pattern in real software development; On the other hand, by explaining the solution process of these problems, readers can understand how to judge the advantages and disadvantages of using design patterns when writing code, and make rational use of design patterns. Readers who are interested in design patterns and hope to use them with learning can quickly cross the threshold from understanding to application through this book; Readers who want to learn Python GUI programming can use the examples in this book as a reference for design and development; Readers who use Python language for image analysis and data processing can quickly build their own system architecture based on the examples in this book. 