GPS tracking using SVG - Part 2

本文是2002和2003年SVG开放开发者会议的论文。在之前解决坐标投影问题基础上,为解决地图分辨率问题,提出添加新细节层级并与SVG缩放级别关联。介绍了加载高分辨率地图的两种方式,详细阐述从搭建地图服务器到添加图像、函数等六个步骤实现地图动态加载及相关功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

a paper for the 2002 and 2003 SVG Open Developers Conference.

Continued from part 1

Where we left off:

We solved some interesting issues with regard to coordinate projection, and built an example, that loads in coordinates from an xml file, and plots a vehicle's movement over a map:

The SVG file:
example2.svg (Opens in a new window)

The color-coded source-code:
example2.html

So that's great, our application does exactly what we want it to.
There's just one thing though - the map isn't too great.
If this is to be of any use we'll need higher resolution maps, but without needing a massive download or it will slow the thing down too much.

Take it to the next level:

That's literally what we'll do - add new levels of detail, and tie them in with SVG's zoomlevels.
The way this works, is that we load higher resolution maps, covering a smaller area, as we zoom in, like this:

Fig.1 to 5 - Increasing detail as we zoom-in:

Level 0 (not zoomed)
Increasing zoom levels

Level 1
Increasing zoom levels

Level 2
Increasing zoom levels

Level 3
Increasing zoom levels

Level 4
Increasing zoom levels

There are two ways of loading the higher resolution maps,

  1. Load the map-segments into a grid, usually using bounding-box measurements in feet. As we move close to the grid-border, the next segment is loaded. The sections are cached on the server, or locally on HD/CD.
  2. Load the maps centred on our vehicle-icon. As we move towards the edge of the map-segment, a new map is loaded, again centred on our vehicle-icon. The maps are created dynamically on the server, depending on the Longitude/Latitude we use in the map's URL-string.

In this case I am going to use the second method - although both have their merits, depending on the situation.
Let's put together a to-do list again:

  1. We need a map-server that returns centered maps on Longitude/Latitude requests.
  2. Catch our SVG's onzoom event, and determine what zoomlevel we're at.
  3. Add an <image> to our SVG, to load the map into.
  4. Make a loadMap() function that loads the map into the image, and positions it correctly.
  5. Call this function when the user zooms in or out, to show the correct map resolution.
  6. Add some of the final touches, like panning the window.
Ok, let's see about Step 1:

Naturally setting up a map-server is no small feat, and will require the necessary licenses to be paid and servers to be set-up.
So for the scope of this paper, and purely for educational purposes I'll use an existing, publicly available map server.
We even have a choice:

There are probably many others too, but I'll use mappoint for this exercise.
To start off we need to know what parameters we can pass in the map-server's URL, here's a URL breakdown:

URL:http://msrvmaps.mappoint.net/isapi/MSMap.dll
ID:(probably used for internal access-control)?ID=3XNsF.
Lat/Lon:&C=44.96,-93.22
Country code - could also be EUR0809 for instance.&L=USA0409
Unknown - needs to be set to "1"&CV=1
Zoom level - 1 is very close, 22000 is the whole world (cool!)&A=285
Image size(in pixels)&S=1000,1000
Offset (Used for panning, not needed in this case)&O=-0,0

Try it, Minneapolis up close:

http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.&C=44.96,-93.22&L=USA0409&CV=1&A=1&S=500,500&O=-0,0

or viewed from outer-space:

http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.&C=44.96,-93.22&L=USA0409&CV=1&A=22000&S=500,500&O=-0,0

(Open in new windows)

Disclaimer: Like I said, we use this service for personal,educational, non-commercial use only.
If you are interested in commercial use contact the companies involved.

Update:

Mappoint have changed their service, and attempts to update these URLs result in a message requesting not to link to their servers directly.
So I changed the examples to use the US census maps. These are not very good quality, but are free.
To update the code, replace this line:

 mapLoader.setAttribute("xlink:href","http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.&C="+parseFloat(LATITUDE)+","+parseFloat(LONGITUDE)+"&L=USA0409&CV=1&A="+zoom+"&S="+res+","+res+"&O=-0,0");

With these:

 var myzoom=zoom*0.0056;
 mapLoader.setAttribute("xlink:href","http://tiger.census.gov/cgi-bin/mapper/map.png?lat="+parseFloat(LATITUDE)+"&lon="+parseFloat(LONGITUDE)+"&wid="+myzoom+"&ht="+myzoom+"&iht="+res+"&iwd="+res+"&conf=palette1.con&on=cities&on=counties&on=majroads&on=places&on=shorelin&on=interstate&on=statehwy&on=states&on=ushwy&on=water");

OK, now for Step 2:

Catching the onzoom event, and recognising what zoomlevel we're at isn't that hard:

<svg onzoom="catchZoom()">
<rect x="80px" y="10px" width="40px" height="40px" /> 
<script>
	function catchZoom(){
		if (!window.svgDocument)svgDocument = evt.target.ownerDocument;
		alert("currentScale = "+svgDocument.rootElement.currentScale)
	}
</script>
</svg> 

Open the example, and zoom in or out - an alert will show the currentScale. This ranges from 0.0625 to 16, 1 being original size.

Example 3:

example3.svg (Opens in a new window)

At this point we have to drop Batik support, as Batik doesn't have the onzoom event implemented yet.
It has however been mentioned as a feature request, so it's likely to be added soon.

In Step 3 we add an image to our SVG:

We'll use this image to load our dynamic maps.
I also add a line in init() to get a handle on the image, so we can alter it's "xlink:href" property later.
To keep things simple I'll just use one image for now. Normally we'd use two, to avoid flashing while a map is loading.
for the moment we load a placekeeper image - pk.jpg.
width="200px" height="200px" are temporary values.

<svg onload="init()">
	<image id="detail" width="200px" height="200px" xlink:href="images/pk.jpg" />
	<script type="text/ecmascript">
		function init(){
			if (!window.svgDocument)svgDocument = evt.target.ownerDocument;
			mapLoader=svgDocument.getElementById("detail")	
		}
	</script>
</svg> 
In Step 4 we add a "loadMap()" function:

This loads the map into the image, and positions it correctly.

function loadMap(lonDist,latDist,LONGITUDE,LATITUDE){
	vehicle.lastxfeet=lonDist
	vehicle.lastyfeet=latDist
	//We set some default values. These should always have the same proportion to each other,
	//so we can divide all three, or multiply all three by the same amount.
	//Multiplying times 2 loads large map (large area), dividing by two loads small maps (modem users)
	var startSize=120000
	var startZoom=60
	var startRes=350 
	
	//We use the currentScale to get a usable multiplication coefficient.
	c=(svgDocument.rootElement.currentScale/2)+0.8
	
	var res=Math.round(startRes+((startRes/8)*c))
	var zoom=Math.round(startZoom/c)
	//As we have to pass integers in the URL, we check what the rest was, to adjust the display size accordingly:
	var zoomRest=(zoom/(startZoom/c))
	//Load the map passing the coords and size
	var myzoom=zoom*0.0056;
 	mapLoader.setAttribute("xlink:href","http://tiger.census.gov/cgi-bin/mapper/map.png?lat="+parseFloat(LATITUDE)+"&lon="+parseFloat(LONGITUDE)+"&wid="+myzoom+"&ht="+myzoom+"&iht="+res+"&iwd="+res+"&conf=palette1.con&on=cities&on=counties&on=majroads&on=places&on=shorelin&on=interstate&on=statehwy&on=states&on=ushwy&on=water");
	
	//Calculate what size to display the map at + set size:
	var width=((startSize/c)*zoomRest)+res*2
	var height=((startSize/c)*zoomRest)+res*2
	mapLoader.setAttribute("width",width)
	mapLoader.setAttribute("height",height)
	vehicle.mapLoaderSize=width
	//Calculate what location to display the map at + move:
	var xVal=parseInt(lonDist)-(width/2)
	var yVal=parseInt(latDist)-(height/2)
	var cont="translate("+xVal+" "+yVal+")"
	mapLoader.setAttribute("transform", cont)
	//Set the viewers size:
	vehicle.setSize(c)
}
In Step 5 we call "loadMap()" when the user zooms in or out:

This allows us to show the correct map resolution depending on how close we're zoomed in.
The onzoom event calls "catchZoom()". This basically tests the zoom-level, and loads a new image appropriate to that zoom-level.

In Step 6 we add a few finishing touches:

We keep track of the distance covered from the initial loading coordinate, so we can load the next map segment when our vehicle approaches the map's edge.
We use feet, instead of Lon/Lat for this, as the feet scale 1:1 to pixels in the SVG. So if we know our map's image is 500px wide, then if our vehicle travels more than 200 feet from the initial position, we load the next map (by setting border=true)- again centred on the vehicles position, and reset the lastxVal and lastyVal variables.

Another thing to fix is that we want our browser's viewport to follow the vehicle, so the vehicle remains visible as it moves.
The way I did this works well, despite it's simplicity:

	var difx=(this.xfeet[i-1]-this.xfeet[i])
	var dify=(this.yfeet[i-1]-this.yfeet[i])
	var cof=(200000/Math.min(window.innerHeight,window.innerWidth))/d.currentScale
	d.currentTranslate.y+=(dify/cof)
	d.currentTranslate.x+=(difx/cof)
	

In line 1 and 2 we subtract the previous position from the current one, to find out what amount to pan the viewport by.
In line three we find the ratio our map is being displayed at, as when the map is zoomed, 1px in size is no longer 1px on the screen.
In the remaining lines we pan the window by the equivalent of the amount the vehicle moved.

Let's have a look what we have so far:

In part 1 we solved some issues with regard to coordinate projection, and built an example, that loads in coordinates from an xml file, and plots a vehicle's movement over a map.
In part 2 we added the high-definition maps that load more detailed areas, as the viewer zooms in:

The SVG file:
example4.svg (Opens in a new window)

The color-coded source-code:
example4.html

Well, that's about it for the 2002 paper - I hope you found it interesting, if you have any comments or questions don't hesitate to email me.

For SVG Open 2003, we have added part 3, SVG and Base64.


Cheers,
Richard Bennett.
richard.b@gritechnologies.com

Valid XHTML 1.0!

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值