GPS/轨迹追踪、轨迹回放、围栏控制

折腾一个多月终于弄完了这个项目,起初都未曾接触GPS/轨迹追踪、轨迹回放、圈划围栏...等一些在百度地图或者Googel地图操作的一些业务,后端的业务相对来说简单点

cas单点登录,mongdb灵活的数据存储方式,ActiveMQ消息推送、Redis存储...

这篇的主要篇幅主要来讲述下项目中的一些地图上棘手的问题

接口测试数据:

1.GPS数据接收接口对于日期格式的转化
作为码农都知道Web接口传输的数据都是以Json的数据形式传输,日期格式不同是我们头疼的事情,当然要是我们自己给App端,云平台端...都喜欢直接点java.util.Date类型直接抛给对

方,当然作为接收方很反感这种以毫秒的形式
①org.springframework.web.bind.annotation.ResponseBody 这是我们用SpringMvc常用的一种转JSON的形式,常用业务中完全可以搞定
②com.alibaba.fastjson.annotation.JSONField 阿里巴巴的转JSON形式,起初对它并不有所偏好,后来写接口写多了,就慢慢喜欢上了

@ResponseBody 直接将我们所需要的数据格式封装起来直接转JSON返回
如:

  1 import java.io.Serializable;
  2
  3 @SuppressWarnings("rawtypes")
  4 public class APIContent implements Serializable{
  5     /**
  6      *
  7      */
  8     private static final long serialVersionUID = 2127409162712908650L;
  9
 10     public APIContent(){}
 11
 12     private Page page;
 13
 14     private boolean ok=true;
 15
 16     /**
 17      * 返回的数据包
 18      */
 19     private Object data;
 20
 21     /**
 22      * 错误码,请查globs
 23      */
 24     private int code = ApiGlobals.SUCCESS;
 25     /**
 26      * 消息处理
 27      */
 28     private String msg;
 29
 30
 31     /**
 32      * 返回数据成功,设置数据。
 33      * @param data
 34      */
 35     public APIContent(Object data){
 36         this.data=data;
 37     }
 38
 39     /**
 40      * 返回数据成功,设置数据。
 41      * @param data
 42      */
 43     public APIContent(Page page, Object data){
 44         this.page = page;
 45         this.data=data;
 46     }
 47     public APIContent(int code){
 48         this.code=code;
 49     }
 50     public Object getData() {
 51         return data;
 52     }
 53
 54     public void setData(Object data) {
 55         this.data = data;
 56     }
 57
 58     public int getCode() {
 59         return code;
 60     }
 61
 62     public void setApiCode(int code){
 63         switch(code){
 64         case ApiCode.opt.DATA_REPEAT:
 65             setMsg("data is repeat! ");
 66             break;
 67         case ApiCode.opt.NOT_LOGIN:
 68             setMsg("please login first! ");
 69             break;
 70         case ApiCode.bug.INVAILD_PARAMS:
 71             setMsg("invaild params! ");
 72             break;
 73         case ApiCode.bug.NO_RESOURCE:
 74             setMsg("not exists resource! ");
 75             break;
 76         case ApiCode.bug.OPERATION:
 77             setMsg("operation falied! ");
 78             break;
 79         case ApiCode.bug.UNDEFINE_FUN:
 80             setMsg("unimplements function or version! ");
 81             break;
 82         case ApiCode.fatal.ERR_SERVER:
 83             setMsg("server error! ");
 84             break;
 85         case ApiCode.Login.INVAILD_PWD:
 86             setMsg("password is invalid! ");
 87         case ApiCode.Login.NOT_REGISTER:
 88             setMsg("not register user! ");
 89             break;
 90         case ApiCode.BindDevice.DEVICE_HAS_BIND:
 91             setMsg("device has binded! ");
 92             break;
 93         case ApiCode.BindDevice.INVAILD_PWD:
 94             setMsg("device password is invalid! ");
 95             break;
 96         case ApiCode.BindDevice.NO_DEVICE:
 97             setMsg("device is not exists! ");
 98             break;
 99         }
100         this.code=code;
101     }
102
103     public boolean isOk() {
104         return ok;
105     }
106     public void setOk(boolean ok) {
107         this.ok = ok;
108     }
109     public void setCode(int code) {
110
111         this.code = code;
112     }
113
114     public Page getPage() {
115         return page;
116     }
117     public void setPage(Page page) {
118         this.page = page;
119     }
120     public String getMsg() {
121         return msg;
122     }
123     public void setMsg(String msg) {
124         this.msg = msg;
125     }
126
127 }

将数据封装到date中然后标识状态码,提示信息返回

@JSONField 的处理有所不同的是,对于日期的处理以及返回形式都可改变
如:我们对日期格式的转化

@JSONField(name = "type")
private String mcTypeName; // 设备类型
@JSONField(name = "expireTime", format = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;    //过期时间
@JSONField(name = "createTime", format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;    //接入时间

返回数据处理 :自定义形式..仅作参考

1 Map<Class<?>, String[]> includes = new HashMap<Class<?>, String[]>();
2 includes.put(APIContent.class, new String[] { "code", "msg", "data" });
3 includes.put(HashMap.class, new String[] { "gps", "obd", "hb", "status", "bd", "gg", "geoname"});
4 includes.put(VOrganize.class, new String[] { "organizeName", "vehicles" });
5 includes.put(Vehicle.class, new String[] { "statusMap", "plateNum", "vechleName", "imei", "id", "vechleioc" });
6 includes.put(OBDProtocol.class, new String[] { "engineStatus", "speedAverage" });
7 includes.put(GPSProtocol.class, new String[] { "acc", "gpsTime", "latitude", "longitude" });
8 includes.put(HBProtocol.class, new String[] { "time" });
9 includes.put(Point.class, new String[] { "lat", "lng" });

  1 package com.jimi.commons.utils;
  2
  3 import java.util.ArrayList;
  4 import java.util.Iterator;
  5 import java.util.List;
  6 import java.util.Map;
  7 import java.util.Map.Entry;
  8
  9 import javax.servlet.ServletOutputStream;
 10 import javax.servlet.http.HttpServletResponse;
 11
 12 import org.apache.commons.beanutils.PropertyUtils;
 13 import org.apache.commons.io.IOUtils;
 14 import org.apache.log4j.Logger;
 15
 16 import com.alibaba.fastjson.serializer.JSONSerializer;
 17 import com.alibaba.fastjson.serializer.NameFilter;
 18 import com.alibaba.fastjson.serializer.PropertyFilter;
 19 import com.alibaba.fastjson.serializer.SerializeConfig;
 20 import com.alibaba.fastjson.serializer.SerializeWriter;
 21 import com.alibaba.fastjson.serializer.SerializerFeature;
 22 import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
 23 import com.alibaba.fastjson.serializer.ValueFilter;
 24 import com.jimi.commons.vo.APIContent;
 25
 26
 27 /**
 28  * 转换JSON工具类
 29  *
 30  */
 31 public class JsonUtils {
 32     private static Logger log = Logger.getLogger(JsonUtils.class);
 33     private final static String DATAS_FLAG = "\"data\":[]";
 34     private static boolean loaded = false;
 35
 36     /**
 37      *
 38      * @param object
 39      * @param includes
 40      * @return
 41      * @author chengxuwei
 42      *
 43      */
 44     public static String toJson(Object object,Map<Class<?>,String[]> includes) {
 45         return toJson(object,includes,null,null);
 46     }
 47
 48     /**
 49      *
 50      * @param object
 51      * @param includes
 52      * @param alias
 53      * @return
 54      * @author chengxuwei
 55      */
 56     public static String toJson(Object object,Map<Class<?>,String[]> includes,Map<Class<?>,Map<String,String>> alias) {
 57         return toJson(object,includes,null,alias);
 58     }
 59     /**
 60      * 带包函,排出的序列化
 61      * @param object 被转对象
 62      * @param includes 类包函的属性
 63      * @param excludes 类排出的属性
 64      * @return
 65      * @author chengxuwei
 66      */
 67     public static String toJson(Object object,Map<Class<?>,String[]> includes,Map<Class<?>,String[]> excludes,Map<Class<?>,Map<String,String>> alias ) {
 68         SerializeWriter writer = new SerializeWriter();
 69         try{
 70             JSONSerializer serializer = new JSONSerializer(writer);
 71             //序列化配置
 72 //            serializer.config(SerializerFeature.WriteNullNumberAsZero, true);
 73 //            serializer.config(SerializerFeature.WriteNullStringAsEmpty, true);
 74 //            serializer.config(SerializerFeature.WriteNullBooleanAsFalse, true);
 75 //            serializer.config(SerializerFeature.WriteNullListAsEmpty, true);
 76             //包括
 77             if(null!=includes&&includes.size()>0){
 78                 SimpleSerializerFilter filter = SimpleSerializerFilter.getIncludeFilter();
 79                 Iterator<Entry<Class<?>, String[]>> ite = includes.entrySet().iterator();
 80                 while(ite.hasNext()){
 81                     Entry<Class<?>, String[]> kv = ite.next();
 82                     filter.addFilterFields(kv.getKey(), kv.getValue());
 83                 }
 84                 serializer.getPropertyFilters().add(filter);
 85             }
 86             //排出
 87             if(null!=excludes&&excludes.size()>0){
 88                 SimpleSerializerFilter filter=SimpleSerializerFilter.getExcludesFilter();
 89                 Iterator<Entry<Class<?>, String[]>> ite = excludes.entrySet().iterator();
 90                 while(ite.hasNext()){
 91                     Entry<Class<?>, String[]> kv = ite.next();
 92                     filter.addFilterFields(kv.getKey(), kv.getValue());
 93                 }
 94                 serializer.getPropertyFilters().add(filter);
 95
 96             }
 97             //别名
 98             if(null!=alias&&alias.size()>0){
 99                 SimpleNameFilter filter=new SimpleNameFilter();
100                 filter.addAllAlias(alias);
101                 serializer.getNameFilters().add(filter);
102             }
103             //值过滤,Android,IOS终端需要空字符串为""空数字为0
104             serializer.getValueFilters().add(new ValueFilter(){
105                 public Object process(Object source, String name, Object value) {
106                     if(null==value){
107                         try {
108                             Class clazz = PropertyUtils.getPropertyType(source, name);
109                             if(clazz.isAssignableFrom(String.class)){
110                                 value="";
111                             }else if(clazz.isAssignableFrom(Integer.class)){
112                                 value=0;
113                             }
114                         } catch (Exception e) {
115                             e.printStackTrace();
116                         }
117                     }
118
119                     return value;
120                 }
121
122             });
123             //write
124             serializer.write(object);
125             return     writer.toString();
126         }catch(Exception e){
127             log.error("to json string error", e);
128         }finally{
129             writer.close();
130         }
131         return null;
132     }
133
134     /**
135      * 转为Json字串
136      *
137      * @param object   转换数据对象
138      * @return Json字串
139      */
140     public static String toJson(Object object) {
141         return toJson(object, new String[0]);
142     }
143
144     /**
145      * 转为Json字串
146      *
147      * @param object   转换数据对象
148      * @param includes 包含属性数组
149      * @return Json字串
150      */
151     public static String toJson(Object object, String... includes) {
152         return toJson(object, includes, new String[0]);
153     }
154
155     /**
156      * 转为Json字串
157      *
158      * @param object   转换数据对象
159      * @param includes 包含属性数组
160      * @param excludes 不包含属性数组
161      * @return Json字串
162      */
163     public static String toJson(Object object, String[] includes, String[] excludes) {
164         return toJson(object, includes, excludes, null);
165     }
166
167     /**
168      * 转为Json字串
169      *
170      *
171      * 属性名称转换
172      *
173      * 对象A有两个属性:id和name
174      * 正常转换为Json字串为:{"id": 1001, "name":"测试数据"}
175      *
176      * 定义属性名称转换:
177      * nameMap.put("id", "cid");
178      * 转换为Json字串为:{"cid": 1001, "name":"测试数据"}
179      *
180      * @param object   转换数据对象
181      * @param includes 包含属性数组
182      * @param excludes 不包含属性数组
183      * @param aliasMap 属性别名map
184      * @return Json字串
185      */
186     @SuppressWarnings("rawtypes")
187     public static String toJson(Object object, String[] includes, String[] excludes, final Map<String, String> aliasMap) {
188         //属性过滤
189         PropertyFilter propertyFilter = null;
190         if ((includes != null && includes.length > 0) || (excludes != null && excludes.length > 0)) {
191             propertyFilter = new CustomPropertyFilter(includes, excludes);
192         }
193
194         /**
195          * 属性名称转换
196          *
197          * 对象A有两个属性:id和name
198          * 正常转换为Json字串为:{"id": 1001, "name":"测试数据"}
199          *
200          * 定义属性名称转换:
201          * nameMap.put("id", "cid");
202          * 转换为Json字串为:{"cid": 1001, "name":"测试数据"}
203          */
204         NameFilter nameFilter = null;
205
206         if (aliasMap != null && aliasMap.size() > 0) {
207             nameFilter = new NameFilter() {
208                 public String process(Object source, String name, Object value) {
209                     if (aliasMap.containsKey(name)) {
210                         return aliasMap.get(name);
211                     }
212                     return name;
213                 }
214             };
215         }
216
217         StringBuffer sb = new StringBuffer(2048);
218
219         try {
220             if (object instanceof APIContent) {
221                 APIContent apiContent = (APIContent) object;
222                 List list = null;
223                 if(apiContent.getData() instanceof List){
224                     list =(List)apiContent.getData();
225                     List nullList=new ArrayList();
226                     apiContent.setData(nullList);
227                 }
228                 sb.append(toJson4Detail(DATAS_FLAG, apiContent, list, propertyFilter, nameFilter));
229                 list = null;
230             }else {
231                 sb.append(toJSONString(object, propertyFilter, nameFilter));
232             }
233         } catch (Exception e) {
234             log.error("toJson错误:", e);
235         }
236
237         return sb.toString();
238     }
239
240     public static String escapeXml(String input) {
241         if (input != null) {
242             input = input.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
243         }
244         return input;
245     }
246
247     private static String toJSONString(Object object, SerializerFeature... features) {
248         return toJSONString(object, null, features);
249     }
250
251     private static String toJSONString(Object object, PropertyFilter propertyFilter, SerializerFeature... features) {
252         return toJSONString(object, propertyFilter, null, features);
253     }
254
255     private static String toJSONString(Object object, PropertyFilter propertyFilter, NameFilter nameFilter, SerializerFeature... features) {
256         SerializeWriter out = new SerializeWriter();
257
258         try {
259             JSONSerializer serializer = new JSONSerializer(out);
260             for (SerializerFeature feature : features) {
261                 serializer.config(feature, true);
262             }
263
264             serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
265             //serializer.config(SerializerFeature.WriteTabAsSpecial, true);
266             serializer.config(SerializerFeature.DisableCircularReferenceDetect, true);
267
268             if (propertyFilter != null) {
269                 serializer.getPropertyFilters().add(propertyFilter);
270             }
271             if (nameFilter != null) {
272                 serializer.getNameFilters().add(nameFilter);
273             }
274
275             setSerializeConfig(serializer.getMapping());
276
277             serializer.write(object);
278
279             return out.toString();
280         } finally {
281             out.close();
282         }
283     }
284
285     private static String toJson4Detail(String flag, Object data, Object list, PropertyFilter propertyFilter, NameFilter nameFilter) {
286         StringBuffer sb = new StringBuffer(2048);
287
288         if (list == null) {
289             sb.append(toJSONString(data,propertyFilter, nameFilter));
290         } else {
291             sb.append(toJSONString(data));
292             int pos = sb.indexOf(flag);
293             if (pos != -1) {
294                 int end = pos + flag.length();
295                 int start = end - 2;
296                 sb.delete(start , end);
297                 sb.insert(start, toJSONString(list, propertyFilter, nameFilter));
298             }
299         }
300
301         return sb.toString();
302     }
303
304     private static void setSerializeConfig(SerializeConfig serializeConfig) {
305         if (!loaded) {
306             serializeConfig.put(java.sql.Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd"));
307             loaded = true;
308         }
309     }
310
311
312
313 }

 1 /*
 2      * public void returnJson2(HttpServletResponse response, Object object, String... includes) { returnJson2(response, getJson(object, includes)); }
 3      *
 4      * public void returnJson2(HttpServletResponse response, Object object, String[] includes, String[] excludes) { returnJson2(response, getJson(object, includes, excludes)); }
 5      *
 6      * public void returnJson2(HttpServletResponse response, String json) { returnJson(response, (HttpServletRequest) null, json); }
 7      */
 8     public void returnJson(HttpServletResponse response, HttpServletRequest request, String json) {
 9         try {
10             String contentType = "application/json; charset=UTF-8";
11             if (request != null) {
12                 String accept = request.getHeader("accept");
13                 if (accept != null && !accept.contains("json")) {
14                     contentType = "text/html; charset=UTF-8";
15                 }
16             }
17             response.setContentType(contentType);
18             response.getWriter().write(json);
19             response.getWriter().flush();
20         } catch (IOException e) {
21             if (logger.isErrorEnabled()) {
22                 logger.error("returnJson is error!", e);
23             }
24         }
25     }

 2.分段轨迹/轨迹追踪

(注:每次选取不同轨迹的时候先清除原先画的轨迹)

百度地图

谷歌地图

代码实现:

①值得注意的是GPS经纬度转化为百度经纬度和谷歌经纬度是不一样的
这里我做的算法处理
获取百度经纬度:通过GPS/(lat,lng)得到百度地图经纬度
获取谷歌地图经纬度:通过GPS/(lat,lng)得到百度地图经纬度,在将百度经纬度转化为谷歌地图经纬度
源码:(获取上诉接口数据...然后在做坐标处理)

Point.java

 1 public class Point {
 2
 3     private double lat;// 纬度
 4     private double lng;// 经度
 5
 6     public Point() {
 7     }
 8
 9     public Point(double lng, double lat) {
10         this.lng = lng;
11         this.lat = lat;
12     }
13
14     @Override
15     public boolean equals(Object obj) {
16         if (obj instanceof Point) {
17             Point bmapPoint = (Point) obj;
18             return (bmapPoint.getLng() == lng && bmapPoint.getLat() == lat) ? true
19                     : false;
20         } else {
21             return false;
22         }
23     }
24
25     public double getLat() {
26         return lat;
27     }
28
29     public void setLat(double lat) {
30         this.lat = lat;
31     }
32
33     public double getLng() {
34         return lng;
35     }
36
37     public void setLng(double lng) {
38         this.lng = lng;
39     }
40
41     @Override
42     public String toString() {
43         return "Point [lat=" + lat + ", lng=" + lng + "]";
44     }
45
46 }

经纬度转化算法

  1 public class CoordinateConversion {
  2     private static final double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
  3
  4     private static final double pi = 3.14159265358979324;  //元周率
  5     private static final double a = 6378245.0; //卫星椭球坐标投影到平面地图坐标系的投影因子。
  6     private static final double ee = 0.00669342162296594323; //ee: 椭球的偏心率。
  7
  8     /**
  9      * gg_lat 纬度
 10      * gg_lon 经度
 11      * GCJ-02转换BD-09 Google地图经纬度转百度地图经纬度
 12      * */
 13     public static Point google_bd_encrypt(double gg_lat, double gg_lon) {
 14         Point point = new Point();
 15         double x = gg_lon, y = gg_lat;
 16         double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
 17         double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
 18         double bd_lon = z * Math.cos(theta) + 0.0065;
 19         double bd_lat = z * Math.sin(theta) + 0.006;
 20         point.setLat(bd_lat);
 21         point.setLng(bd_lon);
 22         return point;
 23     }
 24
 25     /**
 26      * wgLat 纬度
 27      * wgLon 经度
 28      * BD-09转换GCJ-02 百度转google
 29      * */
 30     public static Point bd_google_encrypt(double bd_lat, double bd_lon) {
 31         Point point = new Point();
 32         double x = bd_lon - 0.0065, y = bd_lat - 0.006;
 33         double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
 34         double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
 35         double gg_lon = z * Math.cos(theta);
 36         double gg_lat = z * Math.sin(theta);
 37         point.setLat(gg_lat);
 38         point.setLng(gg_lon);
 39         return point;
 40     }
 41
 42
 43     /**
 44      * wgLat 纬度
 45      * wgLon 经度
 46      * BD-09转换GCJ-02 百度转
 47      * */
 48     public static Point bd_google_baidu_encrypt(double bd_lat, double bd_lon) {
 49         Point point = new Point();
 50         point=wgs_gcj_encrypts(bd_lat,bd_lon);
 51         point=google_bd_encrypt(point.getLat(),point.getLng());
 52         return point;
 53     }
 54
 55
 56     /**
 57      * wgLat 纬度
 58      * wgLon 经度
 59      * WGS-84 到 GCJ-02 的转换(即 GPS 加偏)
 60      * */
 61     public static Point wgs_gcj_encrypts(double wgLat, double wgLon) {
 62         Point point = new Point();
 63         if (outOfChina(wgLat, wgLon)) {
 64             point.setLat(wgLat);
 65             point.setLng(wgLon);
 66             return point;
 67         }
 68         double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
 69         double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
 70         double radLat = wgLat / 180.0 * pi;
 71         double magic = Math.sin(radLat);
 72         magic = 1 - ee * magic * magic;
 73         double sqrtMagic = Math.sqrt(magic);
 74         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
 75         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
 76         double lat = wgLat + dLat;
 77         double lon = wgLon + dLon;
 78         point.setLat(lat);
 79         point.setLng(lon);
 80         return point;
 81     }
 82
 83     public static void transform(double wgLat, double wgLon, double[] latlng) {
 84         if (outOfChina(wgLat, wgLon)) {
 85             latlng[0] = wgLat;
 86             latlng[1] = wgLon;
 87             return;
 88         }
 89         double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
 90         double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
 91         double radLat = wgLat / 180.0 * pi;
 92         double magic = Math.sin(radLat);
 93         magic = 1 - ee * magic * magic;
 94         double sqrtMagic = Math.sqrt(magic);
 95         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
 96         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
 97         latlng[0] = wgLat + dLat;
 98         latlng[1] = wgLon + dLon;
 99     }
100
101     private static boolean outOfChina(double lat, double lon) {
102         if (lon < 72.004 || lon > 137.8347)
103             return true;
104         if (lat < 0.8293 || lat > 55.8271)
105             return true;
106         return false;
107     }
108
109     private static double transformLat(double x, double y) {
110         double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
111                 + 0.2 * Math.sqrt(Math.abs(x));
112         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
113         ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
114         ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
115         return ret;
116     }
117
118     private static double transformLon(double x, double y) {
119         double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
120                 * Math.sqrt(Math.abs(x));
121         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
122         ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
123         ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
124                 * pi)) * 2.0 / 3.0;
125         return ret;
126     }
127 }

初始化原型地图通用模块

  1 <script type="text/javascript">
  2 var allMap;//公共的默认加载百度google地图
  3 var allMapType=$("#selectMap").val();
  4 if(allMapType==‘googleMap‘){
  5     initGoogleMap();
  6
  7 }else{
  8     initBaiDuMap();//默认自动加载百度地图
  9
 10 }
 11
 12 //普通
 13 $("#selectMap").change(function(){
 14     var mapType=$(this).children(‘option:selected‘).val();//这就是selected的值
 15     if(mapType==‘googleMap‘){
 16         initGoogleMap();
 17
 18     }else{
 19         initBaiDuMap();
 20
 21     }
 22     allMapType=mapType;
 23 });
 24
 25 /***
 26 电子围栏切换
 27 $("#selectGeozoneMap").change(function(){
 28     var mapType=$(this).children(‘option:selected‘).val();//这就是selected的值
 29     if(mapType==‘googleMap‘){
 30         initGoogleMap();//初始化google地图
 31         intoGoogleTools();//初始化google地图绘制工具
 32     }else{
 33         initBaiDuMap();//初始化百度地图
 34         intoBaiDuMapTools();//初始化百度地图绘制工具
 35     }
 36 });
 37 **/
 38
 39 function initBaiDuMaps(){
 40     var myCity = new BMap.LocalCity();
 41     myCity.get(myCenterAndZoom);
 42     function myCenterAndZoom(result){
 43         var cityName = result.name;
 44         //initBaiDuMaps(cityName);
 45     }
 46 }
 47 function initBaiDuMap(){
 48     // 百度地图API功能
 49     allMap= new BMap.Map("allmap"); // 创建Map实例 divID必须为allmap
 50     allMap.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地图,设置中心点坐标和地图级别
 51     allMap.addControl(new BMap.MapTypeControl()); //添加地图类型控件
 52     allMap.addControl(new BMap.NavigationControl());//设置导航条 (左上角,添加默认缩放平移控件)
 53     allMap.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
 54     allMap.clearOverlays();
 55 }
 56
 57
 58 function initGoogleMap(){
 59     //Google地图API功能
 60     //纬度&经度
 61     var myCenter=new google.maps.LatLng(39.915,116.404);
 62     var mapProp = {
 63             center:myCenter,
 64             zoom:10,
 65             mapTypeId:google.maps.MapTypeId.ROADMAP
 66     };
 67     allMap = new google.maps.Map(document.getElementById("allmap"),mapProp);
 68 }
 69
 70
 71 //地图自动高度
 72 function  mapAutoHeight(){
 73     $("#allmap").height($(window).height() - $(".header").outerHeight() - $(".breadcrumb-func").outerHeight() - $(".footer").outerHeight());
 74 }
 75 mapAutoHeight();
 76 $(window).resize(function(){
 77     mapAutoHeight();
 78 });
 79
 80 //状态
 81 var icon_end                 = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/end.png"              ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 82 var icon_start               = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/start.png"            ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 83 var icon_gray_automobile     = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/gray_automobile.png"  ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 84 var icon_gray_bus            = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/gray_bus.png"         ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 85 var icon_gray_truck          = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/gray_truck.png"       ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 86 var icon_green_automobile    = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/green_automobile.png" ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 87 var icon_green_bus           = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/green_bus.png"        ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 88 var icon_green_truck         = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/green_truck.png"      ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 89 var icon_red_automobile      = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/red_automobile.png"   ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 90 var icon_red_bus             = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/red_bus.png"          ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 91 var icon_red_truck           = {icon:new BMap.Icon(_ctx+"/resource/images/36x43/red_truck.png"        ,new BMap.Size(36,44)),offset:new BMap.Size(0,-22),imageOffset:new BMap.Size(0,-22)};
 92 //0,离线; 1,在线静止; 2,在线运动.
 93 var vechleIconMap=
 94 {
 95     ‘0_bus‘        :icon_gray_bus           ,
 96     ‘1_bus‘        :icon_red_bus            ,
 97     ‘2_bus‘        :icon_green_bus          ,
 98     ‘0_automobile‘ :icon_gray_automobile    ,
 99     ‘1_automobile‘ :icon_red_automobile     ,
100     ‘2_automobile‘ :icon_green_automobile   ,
101     ‘0_truck‘      :icon_gray_truck         ,
102     ‘1_truck‘      :icon_red_truck          ,
103     ‘2_truck‘      :icon_green_truck
104 };
105
106 var gicon_end                 = {url:_ctx+"/resource/images/36x43/end.png"              ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
107 var gicon_start               = {url:_ctx+"/resource/images/36x43/start.png"            ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
108 var gicon_gray_automobile     = {url:_ctx+"/resource/images/36x43/gray_automobile.png"  ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
109 var gicon_gray_bus            = {url:_ctx+"/resource/images/36x43/gray_bus.png"         ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
110 var gicon_gray_truck          = {url:_ctx+"/resource/images/36x43/gray_truck.png"       ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
111 var gicon_green_automobile    = {url:_ctx+"/resource/images/36x43/green_automobile.png" ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
112 var gicon_green_bus           = {url:_ctx+"/resource/images/36x43/green_bus.png"        ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
113 var gicon_green_truck         = {url:_ctx+"/resource/images/36x43/green_truck.png"      ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
114 var gicon_red_automobile      = {url:_ctx+"/resource/images/36x43/red_automobile.png"   ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
115 var gicon_red_bus             = {url:_ctx+"/resource/images/36x43/red_bus.png"          ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
116 var gicon_red_truck           = {url:_ctx+"/resource/images/36x43/red_truck.png"        ,size:new google.maps.Size(36,44),origin:new google.maps.Point(0,0),anchor:new google.maps.Point(18,44)};
117
118 //0,离线; 1,在线静止; 2,在线运动.
119 var gvechleIconMap=
120 {
121     ‘0_bus‘        :gicon_gray_bus           ,
122     ‘1_bus‘        :gicon_red_bus            ,
123     ‘2_bus‘        :gicon_green_bus          ,
124     ‘0_automobile‘ :gicon_gray_automobile    ,
125     ‘1_automobile‘ :gicon_red_automobile     ,
126     ‘2_automobile‘ :gicon_green_automobile   ,
127     ‘0_truck‘      :gicon_gray_truck         ,
128     ‘1_truck‘      :gicon_red_truck          ,
129     ‘2_truck‘      :gicon_green_truck
130 };
131
132 </script>

轨迹分段Map.js

  1 //获取所有点的坐标
  2
  3 var label; //信息标签
  4 var centerPoint;
  5 var selfAll;
  6
  7 var startIcon=_ctx+"/resource/images/36x43//start.png";//
  8 var startMaker;//起点
  9 var startLable;
 10 var startPoint;
 11
 12 var endIcon=_ctx+"/resource/images/36x43/end.png";//
 13 var endLable;//终点
 14 var endMaker;
 15 var endPoint;
 16
 17 var points=[];
 18 //Googel
 19 var map;
 20
 21 //选择加载
 22 $("#selectMap").change(function(){
 23     var mapType=$(this).children(‘option:selected‘).val();//这就是selected的值
 24     if(mapType==‘googleMap‘){
 25         initGoogleMap();
 26     }else{
 27         initBaiDuMap();
 28     }
 29     allMapType=mapType;
 30     getPointAtMap();
 31 });
 32
 33
 34 //选择路段信息
 35 function getPointAtMap(startTime,endTime,imei){
 36     points.splice(0, points.length);   //清除记录
 37     $.ajax({
 38         type:"post",
 39         url:_ctx+"/drivingrecord/getPonitAtMap",
 40         async: false,
 41         cache: false,
 42         data:{"startTime":startTime,"endTime":endTime,"imei":imei,"selectMap":allMapType},
 43         dataType: ‘json‘,
 44         success:function(returnData){
 45             if(returnData.code==0){
 46                 if(allMapType == ‘googleMap‘){
 47                     $.each(returnData.data,function(n,value){
 48                         points.push(new google.maps.LatLng(value.lat, value.lng));
 49                     });
 50                     initgoogel();
 51                 }else{
 52                     allMap.clearOverlays();
 53                     $.each(returnData.data,function(n,value){
 54                         points.push(new BMap.Point(value.lng, value.lat));
 55                     });
 56                     initbaidu();
 57                 }
 58             }else{
 59                 layer.msg("该时间段无行驶记录");
 60                 allMap.clearOverlays();
 61                 initbaidu();
 62             }
 63         }
 64     });
 65 }
 66
 67 function initbaidu() {
 68     //初始化地图,选取第一个点为起始点
 69     allMap.centerAndZoom(points[0], 15);
 70
 71     centerPoint = new BMap.Point((points[0].lng + points[points.length - 1].lng) / 2, (points[0].lat + points[points.length - 1].lat) / 2);
 72     allMap.panTo(centerPoint);
 73     //连接所有点
 74     allMap.addOverlay(new BMap.Polyline(points, {strokeColor: "#00cc00", strokeWeight: 5, strokeOpacity: 1}));
 75
 76     //显示起点
 77     startLable = new BMap.Label("", {offset: new BMap.Size(-35,-35)});
 78     //car = new BMap.Marker(points[0], {icon: new BMap.Icon(iconImg, new BMap.Size(48, 48), {imageOffset: new BMap.Size(0, 0)})});
 79     startPoint=points[0];
 80     startMaker = new BMap.Marker(startPoint, {icon: new BMap.Icon(startIcon, new BMap.Size(48,48)),offset: new BMap.Size(2,-20),imageOffset: new BMap.Size(0,-20)});
 81     //startMaker.setLabel(startLable);
 82     allMap.addOverlay(startMaker);
 83     //显示终点
 84     endLable = new BMap.Label("", {offset: new BMap.Size(-35,-35)});
 85     //car = new BMap.Marker(points[0], {icon: new BMap.Icon(iconImg, new BMap.Size(48, 48), {imageOffset: new BMap.Size(0, 0)})});
 86     endPoint=points[points.length-1];
 87     endMaker = new BMap.Marker(endPoint, {icon: new BMap.Icon(endIcon, new BMap.Size(48,48)),offset: new BMap.Size(2,-20),imageOffset: new BMap.Size(0,-20)});
 88     //endMaker.setLabel(endLable);
 89     allMap.addOverlay(endMaker);
 90 }
 91
 92 //初始化谷歌地图
 93 function initgoogel(){
 94     var indexCenter=points.length/2;
 95     indexCenter=indexCenter>>0;
 96
 97     var mapOptions = {
 98             zoom: 14,             //缩放级别
 99             center: points[indexCenter],
100             panControl: true,
101             zoomControl: true,
102             mapTypeControl: true,
103             scaleControl: true,
104             overviewMapControl: true,
105             mapTypeId: google.maps.MapTypeId.ROADMAP
106     };
107     map = new google.maps.Map(document.getElementById(‘allmap‘),mapOptions);
108     var lineSymbol = {
109             //travelMode: google.maps.DirectionsTravelMode.DRIVING,
110             path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
111             scale: 2,
112             strokeColor: ‘#0000‘,
113             strokeOpacity: 1.0,    // 透明度
114             strokeWeight: 2,    // 宽度
115             strokeOpacity : 0.8,
116             fillColor : "#0000",
117             fillOpacity : 0.4
118     };
119     line = new google.maps.Polyline({
120         path: points,
121         icons: [{
122             icon: lineSymbol,
123             offset: ‘1%‘
124         }],
125         strokeColor: ‘#418f02‘,
126         //travelMode: google.maps.DirectionsTravelMode.DRIVING,
127         map: map
128     });
129     linePath=line.getPath();
130     new google.maps.Marker(
131             {
132                 position: points[0],
133                 icon:startIcon,
134                 map: map
135             }
136
137     );
138     new google.maps.Marker(
139             {
140                 position: points[points.length - 1],
141                 icon:endIcon,
142                 map: map
143             }
144     );
145
146 }

注:

① 我们都知道纬度的范围是南北纬0-90°,经度的范围是东西经0-180°

百度地图:对应点经纬度先填纬度,后天经度(开始没有仔细看百度API被坑了许久)

points.push(new BMap.Point(value.lng, value.lat));

谷歌地图:经纬度正常

points.push(new google.maps.LatLng(value.lat, value.lng));

②对起始位置,终点位置的修饰以及轨迹的修饰

其实原理都相通,我们描画地图上的坐标,都是通过逐个坐标点来控制,确定起始,终点坐标,自定义类型

如:

百度地图~

//初始化地图,选取第一个点为起始点
allMap.centerAndZoom(points[0], 15);
//连接所有点
allMap.addOverlay(new BMap.Polyline(points, {strokeColor: "#00cc00", strokeWeight: 5, strokeOpacity: 1}));
//显示起点
startLable = new BMap.Label("", {offset: new BMap.Size(-35,-35)});
//car = new BMap.Marker(points[0], {icon: new BMap.Icon(iconImg, new BMap.Size(48, 48), {imageOffset: new BMap.Size(0, 0)})});
startPoint=points[0];
startMaker = new BMap.Marker(startPoint, {icon: new BMap.Icon(startIcon, new BMap.Size(48,48)),offset: new BMap.Size(2,-20),imageOffset: new BMap.Size(0,-20)});
//显示终点
endLable = new BMap.Label("", {offset: new BMap.Size(-35,-35)});
//car = new BMap.Marker(points[0], {icon: new BMap.Icon(iconImg, new BMap.Size(48, 48), {imageOffset: new BMap.Size(0, 0)})});
endPoint=points[points.length-1];
endMaker = new BMap.Marker(endPoint, {icon: new BMap.Icon(endIcon, new BMap.Size(48,48)),offset: new BMap.Size(2,-20),imageOffset: new BMap.Size(0,-20)});
//endMaker.setLabel(endLable);
allMap.addOverlay(endMaker);

(当然这里值得一提的中点位置,不是终点是中点,当时围栏显示轨迹中心位置所取的一个点,每种地图都要设置一个中心点)

即取起始位置和终点位置的中点就OK了~有点逻辑头脑的都可以接收

开始做百度地图的时候有点棘手,毕竟先前没有接触过,后来做谷歌地图的时候,就灵活点了~

起点,终点 (确定坐标位置就OK了,我们是把所有坐标放到数组上的,当前后面的操作就SO easy啦)

new google.maps.Marker(
            {
                position: points[0],
                icon:startIcon,
                map: map
            }

    );
new google.maps.Marker(
            {
                position: points[points.length - 1],
                icon:endIcon,
                map: map
            }
    );

③百度经纬度,谷歌经纬度转当前地理位置

百度地图:

谷歌地图:

  1 /** 假数据测试 * */
  2 var label; // 信息标签
  3 var centerPoint;
  4 var selfAll;
  5
  6 var cars; // 汽车图标
  7 var cariconImg = _ctx + "/resource/images/36x43/green_automobile.png";//
  8 //var cariconImg=icon_green_automobile;//
  9 var carlabel; // 信息标签
 10 var carcenterPoint;
 11
 12 var startIcon = _ctx + "/resource/images/36x43//start.png";//
 13 var startMaker;// 起点
 14 var startLable;
 15 var startPoint;
 16
 17 var endIcon = _ctx + "/resource/images/36x43/end.png";//
 18 var endLable;// 终点
 19 var endMaker;
 20 var endPoint;
 21
 22 var timer; // 定时器
 23 var index = 0; // 记录播放到第几个point
 24
 25 var points = []; // 坐标
 26 var gpsSpeeds = []; // 时速
 27 var gpsTimes = []; // 时间
 28
 29 //Googel
 30 var map;
 31 var linePath;
 32
 33 //默认加载
 34 var allMapType = $("#selectMap").val();
 35 if (allMapType == ‘googleMap‘) {
 36     initGoogleMap(); // 加载Googel地图
 37 }else{
 38     initBaiDuMap(); // 默认自动加载百度地图
 39     initPiont();
 40 }
 41
 42 //选择加载
 43 $("#selectMap").change(function(){
 44     var mapType=$(this).children(‘option:selected‘).val();//这就是selected的值
 45     if(mapType==‘googleMap‘){
 46         initGoogleMap();
 47         initPiont();
 48     }else{
 49         initBaiDuMap();
 50         initPiont();
 51     }
 52     allMapType=mapType;
 53 });
 54
 55
 56 //加载百度地图上的点
 57 function initPiont() {
 58     points.splice(0, points.length);   //清除记录
 59     var startTime = $("#startTime").val();
 60     var endTime = $("#endTime").val();
 61     var imei = $("#imei").val();
 62     if (startTime != "" && startTime != "" && imei != "") {
 63         $.ajax({
 64             type : "post",
 65             url : _ctx + "/trackreplay/initPiont",
 66             async : false,
 67             cache : false,
 68             data : {"startTime":startTime,"endTime":endTime,"imei":imei,"selectMap":allMapType},
 69             dataType : ‘json‘,
 70             success : function(returnData){
 71                 if (returnData.code == 0){
 72                     if (returnData.data != null){
 73                         if(allMapType == ‘googleMap‘){
 74                             $.each(returnData.data,function(n,value){
 75                                 points.push(new google.maps.LatLng(value.lat, value.lng));
 76                                 gpsSpeeds.push(value.gpsSpeed);
 77                                 gpsTimes.push(value.CurrentTime);
 78                             });
 79                             initGoogel();
 80                         }else{
 81                             $.each(returnData.data,function(n,value){
 82                                 points.push(new BMap.Point(value.lng, value.lat));
 83                                 gpsSpeeds.push(value.gpsSpeed);
 84                                 gpsTimes.push(value.CurrentTime);
 85                             });
 86                             initBaiDuMap();// 默认自动加载百度地图
 87                             initBaidu();
 88                         }
 89                         $("#gpsTime").text(gpsTimes[0]);
 90                         $("#gpsSpeed").text(gpsSpeeds[0]);
 91                     }else{
 92                         layer.msg("该时间段无行驶记录");
 93                         initBaiDuMap();// 默认自动加载百度地图
 94                         initBaidu();
 95                     }
 96                 }
 97             }
 98         });
 99     }
100 }
101 //初始化百度地图
102 function initBaidu() {
103     // 初始化地图,选取第一个点为起始点
104     allMap.centerAndZoom(points[0], 15);
105
106     var driving = new BMap.DrivingRoute(allMap);
107
108     centerPoint = new BMap.Point(
109             (points[0].lng + points[points.length - 1].lng) / 2,
110             (points[0].lat + points[points.length - 1].lat) / 2
111     );
112     allMap.panTo(centerPoint);
113     // 连接所有点
114     allMap.addOverlay(
115             new BMap.Polyline(
116                     points,
117                     {
118                         strokeColor : "#00cc00",
119                         strokeWeight : 5,
120                         strokeOpacity : 1
121                     }
122             )
123     );
124
125     //Start
126     startLable = new BMap.Label(
127             "",
128             {
129                 offset : new BMap.Size(-35, -35)
130             }
131     );
132     startPoint = points[0];
133     startMaker = new BMap.Marker(
134             startPoint,
135             {
136                 icon : new BMap.Icon(startIcon, new BMap.Size(48, 48)),
137                 offset : new BMap.Size(2, -20),
138                 imageOffset : new BMap.Size(0, -20)
139             }
140     );
141     // startMaker.setLabel(startLable);
142     allMap.addOverlay(startMaker);
143     //Car
144     carlabel = new BMap.Label(
145             "",
146             {
147                 offset : new BMap.Size(-35, -35)
148             }
149     );
150     carcenterPoint = points[0];
151     cars = new BMap.Marker(
152             carcenterPoint,
153             {
154                 icon : new BMap.Icon(cariconImg, new BMap.Size(48, 48)),
155                 offset : new BMap.Size(2, -20),
156                 imageOffset : new BMap.Size(0, -20)
157             }
158     );
159     allMap.addOverlay(cars);
160     //End
161     endLable = new BMap.Label("", {offset : new BMap.Size(-35, -35)});
162     endPoint = points[points.length - 1];
163     endMaker = new BMap.Marker(
164             endPoint,
165             {
166                 icon : new BMap.Icon(endIcon, new BMap.Size(48, 48)),
167                 offset : new BMap.Size(2, -20),
168                 imageOffset : new BMap.Size(0, -20)
169             }
170     );
171     allMap.addOverlay(endMaker);
172 }
173
174 //初始化谷歌地图
175 function initGoogel(){
176     var indexCenter=points.length/2;
177     indexCenter=indexCenter>>0;
178     var mapOptions = {
179             zoom: 14,             //缩放级别
180             center: points[indexCenter],
181             panControl: true,
182             zoomControl: true,
183             mapTypeControl: true,
184             scaleControl: true,
185             overviewMapControl: true,
186             mapTypeId: google.maps.MapTypeId.ROADMAP
187     };
188     map = new google.maps.Map(document.getElementById(‘allmap‘),mapOptions);
189     var lineSymbol = {
190             //travelMode: google.maps.DirectionsTravelMode.DRIVING,
191             path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
192             scale: 2,
193             strokeColor: ‘#0000‘,
194             strokeOpacity: 1.0,    // 透明度
195             strokeWeight: 2,    // 宽度
196             strokeOpacity : 0.8,
197             fillColor : "#0000",
198             fillOpacity : 0.4
199     };
200     line = new google.maps.Polyline({
201         path: points,
202         icons: [{
203             icon: lineSymbol,
204             offset: ‘1%‘
205         }],
206         strokeColor: ‘#418f02‘,
207         //travelMode: google.maps.DirectionsTravelMode.DRIVING,
208         map: map
209     });
210     linePath=line.getPath();
211     new google.maps.Marker(
212             {
213                 position: points[0],
214                 icon:startIcon,
215                 map: map
216             }
217
218     );
219     new google.maps.Marker(
220             {
221                 position: points[points.length - 1],
222                 icon:endIcon,
223                 map: map
224             }
225     );
226 }
227
228
229 var timer; // 定时器
230 var index = 0; // 记录播放到第几个point
231 var statue = true; // 默认停止
232
233 var count = 0;
234
235 function Operate() {
236     $("#paly").parent().toggleClass("pause");
237     if (statue) {
238         statue = false;
239         play();
240     } else {
241         statue = true;
242         pause();
243     }
244 }
245 var marker = null;
246
247 function play() {
248     var timeat = $("#palyTime").val();
249     var point = points[index];
250     var speed = gpsSpeeds[index];
251     var time = gpsTimes[index];
252     timeat = 1000 - timeat;
253     if(allMapType == ‘googleMap‘){   //Googel
254         var geocoder = new google.maps.Geocoder();
255         geocoder.geocode({‘latLng‘: point}, function(results, status) {
256             if (status == google.maps.GeocoderStatus.OK) {
257                 if (results[0]) {
258                     var address=results[0].formatted_address;
259                     var sindex=address.indexOf("邮政编码");
260                     if(sindex>0){
261                         $("#address").text(address.substring(0,sindex));
262                     }else{
263                         $("#address").text(address);
264                     }
265
266                 }
267             }});
268         map.panTo(point);
269         if(index < points.length){
270             index++;
271             if (!marker){
272                 marker = new google.maps.Marker(
273                         {
274                             position: points[index],
275                             icon:cariconImg,
276                             map: map
277                         });
278             }else{
279                 if(index < points.length){
280                     marker.setPosition(points[index]);
281                 }else{
282                     map.panTo(point);
283                 }
284             }
285             timer = window.setTimeout("play(" + index + ")", timeat);
286         }
287     }else{   //baidu
288         if (index > 0) {
289             allMap.addOverlay(
290                     new BMap.Polyline(
291                             [ points[index - 1], point ],
292                             {
293                                 strokeColor : "red",
294                                 strokeWeight : 1,
295                                 strokeOpacity : 1
296                             }
297                     )
298             );
299         }
300         // 通过当前经纬度获取当前位置
301         var geoc = new BMap.Geocoder();
302         geoc.getLocation(point, function(rs) {
303             if (rs && rs.address)
304                 $("#address").text(rs.address);
305         });
306         cars.setPosition(point);
307         index++;
308         allMap.panTo(point);
309         if (index < points.length) {
310             timer = window.setTimeout("play(" + index + ")", timeat);
311         } else {
312             allMap.panTo(point);
313         }
314     }
315     $("#gpsTime").text(time);
316     $("#gpsSpeed").text(speed);
317 }
318
319 function pause() {
320     if (timer) {
321         window.clearTimeout(timer);
322     }
323 }
324
325 function reset() {
326     if (timer) {
327         window.clearTimeout(timer);
328     }
329     index = 0;
330     cars.setPosition(points[0]);
331     allMap.panTo(centerPoint);
332
333     Operate();
334
335 }

 围栏设置与控制

百度:

谷歌:

百度 JS

  1 //0:电子围栏,1:地标
  2 var flag = $("#flag").val();
  3 $(document).ready(function(){
  4     var allMapType=$("#selectGeozoneMap").val();
  5     if(allMapType==‘googleMap‘){
  6         $("#map-pin").hide();
  7         initGoogleMap();
  8         intoGoogleTools();//初始化google地图绘制工具
  9     }else{
 10         $("#map-pin").show();
 11         initBaiDuMap();//默认自动加载百度地图
 12         intoBaiDuMapTools();
 13         searchAddrTip();
 14     }
 15
 16 });
 17
 18 $("#selectGeozoneMap").change(function(){
 19     var mapType=$(this).children(‘option:selected‘).val();//这就是selected的值
 20     if(mapType==‘googleMap‘){
 21         $("#map-pin").hide();
 22         initGoogleMap();//初始化google地图
 23         intoGoogleTools();//初始化google地图绘制工具
 24     }else{
 25         $("#map-pin").show();
 26         initBaiDuMap();//初始化百度地图
 27         intoBaiDuMapTools();//初始化百度地图绘制工具
 28     }
 29 });
 30
 31 //多边形清除
 32 function initToDrawing(){
 33     //drawingManagerBaidu.setDrawingMode(BMAP_DRAWING_POLYGON);//默认进入地图开启画多边形
 34     clearAll();
 35     intoBaiDuMapTools();
 36 }
 37
 38
 39 /**
 40  * 百度绘制工具加载
 41  * */
 42
 43 var baiduoverlays = [];
 44 function intoBaiDuMapTools(){
 45     allMap.removeEventListener("click", initToDrawing);
 46     //实例化鼠标绘制工具
 47     var drawingManagerBaidu = new BMapLib.DrawingManager(allMap, {
 48         isOpen: false, //是否开启绘制模式
 49         enableDrawingTool: true, //是否显示工具栏
 50         drawingToolOptions: {
 51             anchor: BMAP_ANCHOR_TOP_RIGHT, //位置
 52             //drawingModes: [BMAP_DRAWING_POLYGON,BMAP_DRAWING_CIRCLE],
 53             drawingModes: [BMAP_DRAWING_POLYGON],
 54             offset: new BMap.Size(150, 5), //偏离值
 55             scale: 0.8 //工具栏缩放比例
 56         },
 57         polygonOptions: {
 58             strokeColor : "#0000FF",
 59                strokeOpacity : 0.8,
 60                strokeWeight : 2,
 61                fillColor : "#FF0000",
 62             fillOpacity : 0.4,
 63                editable:false, //是否可以编辑
 64                draggable:false //是否可拖动
 65         } //多边形的样式
 66     });
 67     drawingManagerBaidu.setDrawingMode(BMAP_DRAWING_POLYGON);//默认进入地图开启画多边形
 68     //添加鼠标绘制工具监听事件,用于获取绘制结果
 69     drawingManagerBaidu.addEventListener(‘overlaycomplete‘, overlaycomplete);
 70     var htmlcontent = ‘‘;
 71     var opts = ‘‘;
 72     var strName="围栏";
 73     if(flag != 0){
 74         strName="地标";
 75     }
 76
 77     htmlcontent += ‘<div class="p-tb10">‘;
 78     htmlcontent += ‘<div>‘;
 79     htmlcontent += ‘<table>‘;
 80     htmlcontent += ‘<tr>‘;
 81     htmlcontent += ‘<td class="ta-r"><label><font color="#ff0000">*</font>&nbsp;名称:&nbsp;&nbsp;</label></td>‘;
 82     htmlcontent += ‘<td><input type="text" id="geoname" name="geoname" size="20"  placeholder="请输入‘+strName+‘标题" class="form-control" style="width:160px;" /></td>‘;
 83     htmlcontent += ‘</tr>‘;
 84     htmlcontent += ‘<tr>‘;
 85     htmlcontent += ‘<td class="ta-r p-t7"><label>描述:&nbsp;</label></td>‘;
 86     htmlcontent += ‘<td class="p-t7"><input type="text" id="description" name="description"  placeholder="请输入‘+strName+‘描述信息" class="form-control" size="50" style="width:160px;" /></td>‘;
 87     htmlcontent += ‘</tr>‘;
 88     htmlcontent += ‘<tr>‘;
 89     htmlcontent += ‘<td>&nbsp;</td>‘;
 90     htmlcontent += ‘<td  class="p-t7"><input type="submit" value="提交"  class="btn btn-primary btn-block" onclick="saveGoogleGeozoneInfo();"  /></td>‘;
 91     htmlcontent += ‘</tr>‘;
 92     htmlcontent += ‘</table>‘;
 93     htmlcontent += ‘</div>‘;
 94     htmlcontent += ‘</div>‘;
 95     opts = {
 96             width : 200,     // 信息窗口宽度
 97             height: 156,     // 信息窗口高度
 98             title : "创建"+strName , // 信息窗口标题
 99             enableMessage:false,//设置允许信息窗发送短息
100             message:htmlcontent
101     };
102
103
104     var infoWindow = new BMap.InfoWindow(htmlcontent,opts);  // 创建信息窗口对象
105
106     //回调获得覆盖物信息
107     function overlaycomplete(e){
108         drawingManagerBaidu.setDrawingMode(BMAP_DRAWING_POLYGON);//默认进入地图开启画多边形
109         baiduoverlays.push(e.overlay);
110         try{
111             var array= e.overlay.getPath();
112               showLonLat(array);
113         }catch(e){
114         }
115         //添加单击事件
116            allMap.addEventListener("click",initToDrawing);
117      }
118     //获取所画围栏点经纬度
119     function showLonLat(arr){
120           var info="";
121           for(var i=0; i<arr.length;i++){
122                //纬度&经度
123               info+="|("+arr[i].lat+","+arr[i].lng+")";
124           }
125           var coors=info.substring(1);
126           var str="多边形节点数:" + (arr.length) + "&nbsp;节点坐标:"+info;
127           //document.getElementById(‘mapinfo‘).innerHTML = "手动绘制多边形节点数:" + arr.length + "<br>节点坐标:"+info;
128           console.log("overlaycomplete:"+str);
129           var falgs=false;
130           var len=arr.length;
131           len=Number(len);
132           if(len>=3){
133               falgs=true;
134           }else{
135               intoBaiDuMapTools();
136               if(flag == 0){
137                   layer.msg(‘围栏为封闭的多边形!‘);
138               }else{
139                   layer.msg(‘地标为封闭的多边形!‘);
140               }
141              }
142           if(falgs){
143               $("#maptype").val("baidu");
144               $("#coors").val(coors);
145               var point = new BMap.Point(arr[0].lng,arr[0].lat);
146               allMap.openInfoWindow(infoWindow,point); //开启信息窗口
147           }
148       }
149 }
150
151 //清除围栏
152 function clearAll() {
153     for(var i = 0; i < baiduoverlays.length; i++){
154         allMap.removeOverlay(baiduoverlays[i]);
155         allMap.clearOverlays();
156    }
157     baiduoverlays.length = 0;
158  }

谷歌:

  1 //0:电子围栏,1:地标
  2 var flag = $("#flag").val();
  3 /**
  4  * Google绘制工具加载
  5  * */
  6 function intoGoogleTools(){
  7     //图形绘制工具控加载此AIP链接后面加上&libraries=drawing
  8     var drawingManager = new google.maps.drawing.DrawingManager({
  9             drawingMode: google.maps.drawing.OverlayType.POLYGON,
 10             drawingControl: true,
 11             drawingControlOptions: {
 12             position: google.maps.ControlPosition.TOP_CENTER,
 13             drawingModes: [
 14               //google.maps.drawing.OverlayType.MARKER,
 15               //google.maps.drawing.OverlayType.CIRCLE,
 16               google.maps.drawing.OverlayType.POLYGON, //仅使用多边形绘制工具
 17               //google.maps.drawing.OverlayType.POLYLINE,
 18              // google.maps.drawing.OverlayType.RECTANGLE
 19             ]
 20           },
 21           circleOptions: {
 22             strokeColor : "#0000FF",
 23             strokeOpacity : 0.8,
 24             strokeWeight : 2,
 25             fillColor : "#FF0000",
 26             fillOpacity : 0.4,
 27             editable:false, //是否可以编辑
 28             draggable:false //是否可拖动
 29             },
 30             polygonOptions: {//设置画线样式
 31               strokeColor: "#0000FF",
 32               strokeOpacity: 0.8,
 33               strokeWeight: 3,
 34               fillColor: "#FF0000",
 35               fillOpacity: 0.35,
 36               editable: false
 37               }
 38         });
 39     drawingManager.setMap(allMap);
 40
 41     //注册 多边形 绘制完成事件
 42     var geozonePolygon = null;
 43     google.maps.event.addListener(drawingManager, ‘polygoncomplete‘, function(polygon) {
 44         drawingManager.setDrawingMode(null); //切换为选择模式
 45         geozonePolygon=polygon;
 46         showLonLat(polygon);
 47     });
 48     var htmlcontent = ‘‘;
 49     var strName="围栏";
 50     if(flag != 0){
 51         strName="地标";
 52     }
 53
 54     htmlcontent += ‘<div class="p-t10 p-b5">‘;
 55     htmlcontent += ‘<div>‘;
 56     htmlcontent += ‘<table>‘;
 57     htmlcontent += ‘<tr>‘;
 58     htmlcontent += ‘<td class="ta-r"><label><font color="#ff0000">*</font>&nbsp;名称:&nbsp;&nbsp;</label></td>‘;
 59     htmlcontent += ‘<td><input type="text" id="geoname" name="geoname" size="20"  placeholder="请输入‘+strName+‘标题" class="form-control" style="width:160px;" /></td>‘;
 60     htmlcontent += ‘</tr>‘;
 61     htmlcontent += ‘<tr>‘;
 62     htmlcontent += ‘<td class="ta-r p-t7"><label>描述:&nbsp;</label></td>‘;
 63     htmlcontent += ‘<td class="p-t7"><input type="text" id="description" name="description"  placeholder="请输入‘+strName+‘描述信息" class="form-control" size="50" style="width:160px;" /></td>‘;
 64     htmlcontent += ‘</tr>‘;
 65     htmlcontent += ‘<tr>‘;
 66     htmlcontent += ‘<td>&nbsp;</td>‘;
 67     htmlcontent += ‘<td  class="p-t7"><input type="submit" value="提交"  class="btn btn-primary btn-block" onclick="saveGoogleGeozoneInfo();"  /></td>‘;
 68     htmlcontent += ‘</tr>‘;
 69     htmlcontent += ‘</table>‘;
 70     htmlcontent += ‘</div>‘;
 71     htmlcontent += ‘</div>‘;
 72
 73     var infowindow = new google.maps.InfoWindow({
 74         content: htmlcontent,
 75         zIndex: 1000
 76     });
 77     //循环显示 经纬度
 78     function showLonLat(polygon){
 79         var array= polygon.getPath().getArray();
 80         var paths = polygon.getPath();
 81         var geozone="";
 82         for(var i=0; i<array.length;i++){
 83             geozone+="|"+array[i];
 84         };
 85         geozone=geozone.substring(1);
 86         //document.getElementById(‘mapinfo‘).innerHTML = "手动绘制多边形节点数:" + arr.length + "<br>节点坐标:"+info;
 87         var falg=false;
 88         var len=array.length;
 89         len=Number(len);
 90         if(len>=3){
 91             falg=true;
 92         }else{
 93             infowindow.setMap(null);
 94             geozonePolygon.setMap(null);
 95             drawingManager.setDrawingMode(google.maps.drawing.OverlayType.POLYGON);
 96             if(flag == 0){
 97                 layer.msg(‘围栏为封闭的多边形!‘);
 98             }else{
 99                 layer.msg(‘地标为封闭的多边形!‘);
100             }
101          }
102         if(falg){
103             $("#maptype").val("google");
104                 $("#coors").val(geozone);
105                 infowindow.setPosition(paths.getAt(0));
106                 infowindow.open(allMap);
107         }
108     }
109
110     //信息框弹出关闭
111     google.maps.event.addListener(infowindow,‘closeclick‘, function() {
112         geozonePolygon.setMap(null);
113         drawingManager.setDrawingMode(google.maps.drawing.OverlayType.POLYGON);
114     });
115
116     //点击地图页面
117     google.maps.event.addListener(allMap, ‘click‘, function(event) {
118          infowindow.setMap(null);
119          geozonePolygon.setMap(null);
120          drawingManager.setDrawingMode(google.maps.drawing.OverlayType.POLYGON);
121     });
122 }
123
124
125
126
127 //弹框后输入围栏信息保存
128 function saveGoogleGeozoneInfo(){
129     var mapType=$("#maptype").val();
130     var coors=$("#coors").val();
131     var geoname=$("#geoname").val();
132     var description=$("#description").val();
133     ajaxMapFencingSave(mapType,coors,geoname,description);
134 }
135
136 //围栏保存到后台  flag:0为电子围栏
137 var postSaveUrl=_ctx+"/geozone/editGeozone";
138 function ajaxMapFencingSave(mapType,coors,geoname,description){
139     if(geoname!=‘‘){
140         $.ajax({
141             type:‘POST‘,
142             url:postSaveUrl,
143             data:{"geom":coors,
144                 "mapType":mapType,
145                 "type":"polygon",
146                 "geoname":geoname,
147                 "description":description,
148                 "flag":flag},
149             dataType:‘json‘,
150             success: function(rest){
151                 if(rest.ok){
152                     if(flag == 0){
153                         layer.msg(‘围栏设置成功!‘);
154                         window.location.href=_ctx+"/geozone/giveanalarm?id="+rest.data.id+"&geonames="+rest.data.geoname;
155                     }else{
156                         layer.msg(‘地标设置成功!‘);
157                         window.location.href=_ctx+"/geozone/landMarkList";
158                     }
159                     //$("#id").val(rest.data.id);
160                     //$("#geonames").val(rest.data.geoname);
161                     //$("#giveanalarmForm").submit();
162                 }else{
163                     if(flag == 0){
164                         layer.msg(‘围栏设置失败!‘);
165                     }else{
166                         layer.msg(‘地标设置失败!‘);
167                     }
168                 }
169             }
170         });
171     }else{
172         document.getElementById(‘geoname‘).focus();
173         if(flag == 0){
174             layer.msg(‘围栏名称必须填写!‘);
175         }else{
176             layer.msg(‘地标名称必须填写!‘);
177         }
178     }
179 }
180
181
182 /**
183  * 地址查询
184  * 自动提示功能
185  * @param inputId
186  */
187 function initSeachBaidu(inputId){
188     //建立一个自动完成的对象
189     var autoComplete= new BMap.Autocomplete({"input" : inputId    ,"location" :allMap});
190     //鼠标点击下拉列表后的事件
191     //查询输入 TODO 是否去掉查询按钮
192 //    autoComplete.addEventListener("onconfirm", function(e) {
193 //        var _value = e.item.value;
194 //        var searchValue = _value.province +  _value.city +  _value.district +  _value.street +  _value.business;
195 //    });
196 }
197
198
199 function searchAddrTip(){
200     var allMapType=$("#selectGeozoneMap").val();
201     if(allMapType==‘baiduMap‘){
202         baiduInit();
203     }else{
204         //googleSeach(inputId);
205     }
206 }
207 /**
208  * 地址查询
209  * 自动提示功能
210  * @param inputId
211  */
212 function baiduInit(){
213     // 百度地图API功能
214     function G(id) {
215         return document.getElementById(id);
216     }
217
218     var ac = new BMap.Autocomplete(    //建立一个自动完成的对象
219         {"input" : "mapSearchText"
220         ,"location" : allMap
221     });
222
223     ac.addEventListener("onhighlight", function(e) {  //鼠标放在下拉列表上的事件
224     var str = "";
225         var _value = e.fromitem.value;
226         var value = "";
227         if (e.fromitem.index > -1) {
228             value = _value.province +  _value.city +  _value.district +  _value.street +  _value.business;
229         }
230         str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value;
231
232         value = "";
233         if (e.toitem.index > -1) {
234             _value = e.toitem.value;
235             value = _value.province +  _value.city +  _value.district +  _value.street +  _value.business;
236         }
237         str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value;
238         G("searchResultPanel").innerHTML = str;
239     });
240
241     var myValue;
242     ac.addEventListener("onconfirm", function(e) {    //鼠标点击下拉列表后的事件
243     var _value = e.item.value;
244         myValue = _value.province +  _value.city +  _value.district +  _value.street +  _value.business;
245         G("searchResultPanel").innerHTML ="onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue;
246         setPlace();
247     });
248
249     function setPlace(){
250         allMap.clearOverlays();    //清除地图上所有覆盖物
251         function myFun(){
252             var pp = local.getResults().getPoi(0).point;    //获取第一个智能搜索的结果
253             allMap.centerAndZoom(pp, 18);
254             allMap.addOverlay(new BMap.Marker(pp));    //添加标注
255         }
256         var local = new BMap.LocalSearch(allMap, { //智能搜索
257           onSearchComplete: myFun
258         });
259         local.search(myValue);
260     }
261 }
262
263 /**
264  * Google搜索
265  * */
266 function googleSeach(inputId){
267     var options = {
268               bounds: defaultBounds,
269               types: [‘establishment‘]
270     };
271     autocomplete = new google.maps.places.Autocomplete(inputId, options);
272 }

先这样了.........了解详细讨论 ,欢迎加群讨论! QQ群:131874993

时间: 2024-10-24 08:31:39

GPS/轨迹追踪、轨迹回放、围栏控制的相关文章

OpenLayers 3 之 实时追踪轨迹-获取最后添加的要素

问题描述 有时,往往有这样的需求:每隔一段时间查询一个物体的位置,然后将这个位置绘制在地图上,中间的点用普通的样式标识,当前位置(也就是最新的点位置)使用一个特殊的样式.我们可以这样实现,查询到一个新位置,将改点添加到地图上的同时,赋予其特殊的样式,当再查询到有新的位置时,获取最后添加的要素,删除其特殊样式,然后添加新的要素点位置. 那么,问题来了:怎么获取最后添加的要素呢? 方法一: getFeatures 首先,我们知道,ol.source.Vector,提供了 getFeatures 方法

《TableStore最佳实践:轻松实现轨迹管理与地理围栏》

一.方案背景轨迹管理系统日常生活中使用非常普遍,如外卖派送轨迹.快递物流流转.车辆定位轨迹等.该场景与地理位置管理类似,核心点与瓶颈都在数据库的存储性能与查询能力,同时需要时间字段正序排列,保证轨迹点顺序:一方面,存储服务需要应对海量数据的低延迟存.读,另一方面,存储服务也要提供高效的多维度数据检索与排序.表格存储(TableStore)对于轨迹管理场景,依然可以胜任,完全具备实现轨迹管理系统的能力.不妨来体验一下基于TableStore打造的[亿量级摩托车管理系统]样例: 需求场景某城市市区出

轨迹追踪

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type

使用GMap.NET类库,实现地图轨迹回放。(WPF版)

前言 实现轨迹回放,GMap.NET有对应的类GMapRoute.这个类函数很少,功能有限,只能实现简单的轨迹回放.要实现更复杂的轨迹回放,就需要自己动手了. 本文介绍一种方法,可以实现复杂的轨迹回放.有句话"功夫在诗外",GMap.NET给你提供了基本地图处理功能:但是不要让CMap.NET束缚了手脚.你需要有深刻理解地图实现原理,深入理解WPF动画的原理,才能到达随心所欲.最终的效果如下: GMap.NET 显示原理 地图就是由许多方格"瓦片"组合而来.当你移动

Android 百度鹰眼轨迹SDK(v2.1.6)

闲聊 看过<鹰眼追击>这部电影的读者一定对"鹰眼"这台巨无霸计算机印象深刻,如今我们能够实现自己的鹰眼. 效果图 本篇为百度地图SDK第三篇博文 第一篇实现:Android 百度地图周边雷达(v6.1.3)及覆盖物 第二篇实现:Android 百度定位SDK(v6.1.3)结合方向传感器 本博文为第三篇 使用百度鹰眼轨迹SDK能够实现的功能 轨迹追踪 借助GPS.基站.Wi-Fi和传感器信息,实现室内.外高精度的连续轨迹追踪.总体定位精度50m: GPS:10m(取决于芯片

Android百度鹰眼轨迹

作者:短工邦技术部 - 陈文超 百度地图之百度鹰眼轨迹使用 拿外卖配送为例,配送员从接单开始上传行驶轨迹,用户端可以实时查看配送员的行驶轨迹,对于点外卖的用户来说可以更直接地观察到自己的订单是否在配送过程中,不再需要一遍一遍地拨打商户电话催促. 在思考相关解决方案的时候第一个想到的是在后台不断地获取配送员的经纬度,上传到服务器,然后在用户端实时地刷新这些经纬度数据显示到地图上.这种方法虽说思路很简单,只是数据的上传与刷新,但是轨迹的准确度与定位的精准度有很大关系,如果遇到网络环境较弱等的情况,定

使用python进行运动轨迹合并:多次骑行跑步轨迹叠加显示

现有各种各样的运动app.运动手表手环以及gps码表等可以用于记录日常骑行或跑步等运动轨迹;但轨迹显示多数只限于显示一天的轨迹,经过搜索只发现一篇文章介绍跑步轨迹叠加方法(查看),根据教程尝试了下还因为perl语言的一些插件没搞定,果断放弃决定自己动手丰衣足食. 先上效果图: ps:那条长线不是绘制的有问题,的确是单日骑行距离最远的一次,260多公里(开始30多公里由于码表磁铁位置问题只记录了几公里,码表记录233公里). 济南市附近轨迹,缺个环泰: 卫星地图轨迹: 轨迹绘制方法: 作为一位骑行

运动App后台持续定位生成轨迹

1. 连续定位采集点 1.定位LocationService,另起进程同时创建守卫进程Service, LocationHelperService,Service挂掉时守卫进程唤起LocationService. package com.yxc.barchart.map.location.service; import android.app.Service; import android.content.ComponentName; import android.content.Intent;

基于公共子序列的轨迹聚类(c#)

前言 如今的世界中,想要研究人们的出行活动,可以利用智能手机或智能手环等个人设备生成的 GPS 数据进行研究.而在众多的研究方向中,出行的热点路线或者说经常出行的路线也比较受欢迎.采用热力图的方式对其进行研究具有许多优点.热力图给使用者的感觉就是特别直观,一眼便看出来哪些路径属于热迹(我们把热点路线,也就是重复度高的路线称为热迹).如下图所示: (图片来自网上,侵删) 从图中我们一眼便能够找出两条粗壮的热迹.这表示有某种物体经常沿着两条路线运动.但对于计算机来说,要从图中找出这两条热迹,并加以区