ITS信號控制系統渠化圖自動生成

最近公司在做一套城市交通信號控制系統的產品,由於渠化圖生成都是單獨採用圖片作爲底圖,實現方式不太直觀。公司主要的理念就是可視化,將數據變成可視化的元素展現出來,並和地圖結合展現信號燈的相位狀態。

實現思路:

(1)採用技術爲SVG (可縮放矢量圖形),爲什麼採用svg,主要考慮了瀏覽器的支持方面

瀏覽器支持
Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持內聯 SVG。Internet Explorer 8或更早版本,可通過安裝Adobe SVG Viewer以支持SVG。

進一步的信息可參考百度百科SVG介紹

(2)採用dojo進行了封裝,由於地圖展現採用了arcgis js api , 依賴於dojo,索性就採用dojo對象封裝

 關於dojo,可參考dojo官方文檔

(3)地圖座標聯動,通過地圖的縮放,實現與地圖的聯動,並在不同的Zoom level下,渠化圖相應的進行適當的縮放。 

map.on("extent-change" , function(p1 , p2 , p3 , p4 ){
			sigs.rePosition() ; 
});


dojo封裝實現:

define(["dojo/_base/declare" ,"dojo/dom" , "esri/geometry/Point" , "dojox/timing/_base" ,"dojo/dom-construct","dojo/dom-style" ,"dojox/gfx","dojox/gfx/move","dojox/gfx/fx" ],
  function(declare ,dom, Point ,  timer , domConstruct , domStyle){


	var timer = new timer.Timer();

	var surface = null;
	var surface_size = null ;


	var circle1 , circle2 , circle3 , circle4 ; 
	var selected_circle = null ; 

	var global1 = null ;
	var global2  = null ;
	var global3 = null ;
	var global4 = null ;
	var global5 = null ;
	//var global6 = null ;
	//var global7 = null ;
	var global8 = null ;

	var maxTime = 20 ; 
	var maxStage = 4 ; 

	var _me ; 

	var _road1 ; 
	var _road2 ; 
	var _gismap = null ; 

	return declare(null, {

		constructor: function(gismap ,  divid , road1 , road2 , lng , lat  ) {

			this._divid  = divid ;
			this._lat = lat ; 
			this._lng = lng ; 
			_me = this ; 
			_road1 = road1 ; 
			_road2 = road2 ; 
			_gismap = gismap ; 


			var ptCenter = new Point({ "x": this._lng, "y": this._lat, "spatialReference": { "wkid": 4326} }) ;
			var screenPoint = _gismap.toScreen(ptCenter) ; 

			domConstruct.create(
				"div",
				{
					style:
					{
				        "background-color": "gray",
				        "width" :"0px" ,
						"height":"0px" , 
				        "position": "absolute",
						"filter":"alpha(Opacity=80)",
						"-moz-opacity":"0.8",
						"opacity": "0.8",
						"z-index":"100",
				        "left": ( screenPoint.x - 150) +"px",
				        "top": ( screenPoint.y - 150) + "px",
				        "z-index": "40",
						"pointer-events": "none"
					} , 
					"id" : this._divid
				},
				dojo.body()
			);
		},
		/*     500*500爲基礎範圍    */
		makeRoads : function(p)
		{
			var pathstr1 = "M100 200 200 200 200 100";		
			var groad = p.createGroup();
			/*roads*/
			groad
			.createPath(pathstr1)
			.setStroke({color: "white"})
			
			groad.createPath(pathstr1)
			.setStroke({color: "white"}).
			applyTransform([dojox.gfx.matrix.translate(100,0) ,  dojox.gfx.matrix.rotategAt(90, 200 , 200)]); 	
			
			groad.createPath(pathstr1)
			.setStroke({color: "white"}).
			applyTransform([ dojox.gfx.matrix.rotategAt(180, 250 , 250)]); 	
			
			groad.createPath(pathstr1)
			.setStroke({color: "white"}).
			applyTransform([dojox.gfx.matrix.translate(0,100) ,  dojox.gfx.matrix.rotategAt(-90, 200 , 200)]); 	
			
			groad.createPath("M100 200 200 200 200 100 300 100 300 200 400 200 400 300 300 300 300 400 200 400 200 300 100 300z")
				.setFill("#8a9599") ; 
			
			groad.createText({ x: 250, y: 258, text: "20", align: "middle"  })
			.setFont({ family: "Arial", size: "16pt", weight: "thin" }) //set font
			.setFill("green");		
			
			return groad ;	
		},


		setTimedText : function(groad , txt)
		{
			groad.children[5].setShape({text:txt}) ; 
		},

		makeArrows : function(p)
		{
			var garrow = p.createGroup() ; 
			
			var g1 = garrow.createGroup() ; 	
			g1.createPath("M120 257 130 257 130.0 254.5 135 258 130 261.5 130 259 120 259z")
				.setFill("white")	
			g1.createPath("M120 273 130 273 130.0 271.5 135 274 130 277.5 130 275 120 275z")
				.setFill("white")	
			g1.createPath("M120 289 130 289 130.0 287.5 135 290 130 293.5 130 291 120 291z")
				.setFill("white")			
			
			
			
			var g2 = garrow.createGroup() ; 	
			g2.createPath("M120 257 130 257 130.0 254.5 135 258 130 261.5 130 259 120 259z")
				.setFill("white")	
			g2.createPath("M120 273 130 273 130.0 271.5 135 274 130 277.5 130 275 120 275z")
				.setFill("white")	
			g2.createPath("M120 289 130 289 130.0 287.5 135 290 130 293.5 130 291 120 291z")
				.setFill("white")			
			g2.applyTransform([dojox.gfx.matrix.rotategAt(90, 250 , 250)]);
			
			var g3 = garrow.createGroup() ; 	
			g3.createPath("M120 257 130 257 130.0 254.5 135 258 130 261.5 130 259 120 259z")
				.setFill("white")	
			g3.createPath("M120 273 130 273 130.0 271.5 135 274 130 277.5 130 275 120 275z")
				.setFill("white")	
			g3.createPath("M120 289 130 289 130.0 287.5 135 290 130 293.5 130 291 120 291z")
				.setFill("white")			
			g3.applyTransform([dojox.gfx.matrix.rotategAt(180, 250 , 250)]);
			
			var g4 = garrow.createGroup() ; 	
			g4.createPath("M120 257 130 257 130.0 254.5 135 258 130 261.5 130 259 120 259z")
				.setFill("white")	
			g4.createPath("M120 273 130 273 130.0 271.5 135 274 130 277.5 130 275 120 275z")
				.setFill("white")	
			g4.createPath("M120 289 130 289 130.0 287.5 135 290 130 293.5 130 291 120 291z")
				.setFill("white")			
			g4.applyTransform([dojox.gfx.matrix.rotategAt(270, 250 , 250)]);
			
			
			return garrow ; 
		},

		makeChannels : function(p) {
			
			/*make channel */
			/*
			 * {
				style: "Dash", width: 3, cap: "butt", color: "#00f"
			 * */
			
			var gchannel = p.createGroup() ; 
			
			gchannel
				.createLine({x1: 250, y1: 100, x2: 250, y2: 200})
				.setStroke({style: "Dash", width: 2, cap: "butt", color: "#fff"}) ; 
			
			gchannel
				.createLine({x1: 250, y1: 300, x2: 250, y2: 400})
				.setStroke({style: "Dash", width: 2, cap: "butt", color: "#fff"}) ; 
			
			
			gchannel
				.createLine({x1: 100, y1: 250, x2: 200, y2: 250})
				.setStroke({style: "Dash", width: 2, cap: "butt", color: "#fff"}) ; 
			
			gchannel
				.createLine({x1: 300, y1: 250, x2: 400, y2: 250})
				.setStroke({style: "Dash", width: 2, cap: "butt", color: "#fff"}) ; 	
			
			gchannel.createText({ x: 320, y: 180, text: _road1, align: "start" })
				.setFont({ family: "SimSun", size: "10pt", weight: "thin" }) //set font
				.setFill("red")
				.applyTransform([dojox.gfx.matrix.rotategAt(-90, 320 , 180)]);
			
			gchannel.createText({ x: 350, y: 320, text: _road2, align: "start" })
				.setFont({ family: "SimSun", size: "10pt", weight: "thin" }) //set font
				.setFill("red");
			
			
			
			
			gchannel.createImage({x:0 , y:0,width: 135, height: 66, src: "images/che2.png"})
				.applyTransform([dojox.gfx.matrix.translate(140 , 285) , dojox.gfx.matrix.scaleAt(0.2, 0 , 0)]);
			
			return gchannel ;
			
			
		},

		makeChedaos : function(p) {

			
			var gChedao = p.createGroup() ; 

			for( var i = 1 ; i < 3 ; i ++ )
			{
				gChedao
					.createLine({x1: 100, y1: 250+16.67*i, x2: 180, y2: 250+16.67*i})
					.setStroke({style: "Dash", width: 1, cap: "butt", color: "#fff"}) ; 
				
				
				gChedao
				.createLine({x1: 320, y1: 200+16.67*i, x2: 400, y2: 200+16.67*i})
				.setStroke({style: "Dash", width: 1, cap: "butt", color: "#fff"}) ; 
				
				
				gChedao
				.createLine({x1: 200+16.67*i, y1:100 , x2: 200+16.67*i, y2:180 })
				.setStroke({style: "Dash", width: 1, cap: "butt", color: "#fff"}) ; 
			
			
				gChedao
				.createLine({x1: 250+16.67*i, y1:320 , x2: 250+16.67*i, y2:400 })
				.setStroke({style: "Dash", width: 1, cap: "butt", color: "#fff"}) ; 
			}
			
			/*繪製人行道*/
			for(var i = 0 ; i < 20 ; i ++ )
			{
				gChedao.createRect({x:180  , y:200 + i*5 , width : 20 , height :2.5})
					.setFill("white"); 		
				
				gChedao.createRect({x:300  , y:200 + i*5 , width : 20 , height :2.5})
					.setFill("white"); 		
				
				gChedao.createRect({x:200+i*5  , y:180 , width : 2.5 , height :20})
					.setFill("white"); 		
				
				gChedao.createRect({x:200+i*5  , y:300 , width : 2.5 , height :20})
					.setFill("white"); 		
			}
			
			return gChedao ;
			/*draw 車道*/			
		},


	

		createCircleGroupV : function(p ,x1,y1,r , str)
		{
			var group = p.createGroup() ; 	
			group.createCircle({cx: x1, cy: y1, r: r}).setStroke("white").setFill("red");
			group.createCircle({cx: x1, cy: y1 + 2.5*r, r: r}).setStroke("white").setFill("transparent");
			group.createCircle({cx: x1, cy: y1 + 5*r, r: r}).setStroke("white").setFill("transparent");
			
			group.createText({ x: x1, y: y1-r, text: str, align:"middle"}).setFill("white")
				.setFont({ family: "SimSun", size: "6pt", weight: "thin" });
			return group ; 
		},

		createCircleGroupH :  function(p , x1,y1,r ,str)
		{
			var group = p.createGroup() ; 	
			group.createCircle({cx: x1, cy: y1, r: r}).setStroke("white").setFill("transparent");
			group.createCircle({cx: x1+ 2.5*r, cy: y1 , r: r}).setStroke("white").setFill("transparent");
			group.createCircle({cx: x1+ 5*r, cy: y1 , r: r}).setStroke("white").setFill("green");
			
			group.createText({ x: x1-2*r, y: y1, text: str, align:"middle"}).setFill("white")
				.setFont({ family: "SimSun", size: "3pt", weight: "thin" });
			
			return group ; 
		},


		createLightgroups : function(p)
		{
			var gg = p.createGroup() ; 	  	
			this.createCircleGroupV(gg,270 ,150 , 4 , "0") ; //1
			this.createCircleGroupV(gg,280 ,150 , 4 , "1") ; //2	
			this.createCircleGroupV(gg,220 ,330 , 4 , "2") ; //3
			this.createCircleGroupV(gg,230 ,330 , 4 , "3") ; //4	
			
			this.createCircleGroupH(gg,150 ,220 , 4 , "4") ; //5
			this.createCircleGroupH(gg,150 ,230 , 4 , "5") ; //6
			this.createCircleGroupH(gg,330 ,270 , 4 , "6");  //7
			this.createCircleGroupH(gg,330 ,280 , 4 , "7") ; //8
			return gg ; 
		},


		createNorthArrow  :  function(p , x1, y1 , rotated){
			var gg = p.createGroup() ; 	  	
			
			var npoints1 = [{x: x1, y:y1}, {x:x1, y: y1-50}, {x: x1-25, y: y1+50} , {x: x1, y:y1}];
			var npoints2 = [{x: x1, y:y1}, {x:x1, y: y1-50}, {x: x1+25, y: y1+50} , {x: x1, y:y1}];

			gg.createPolyline(npoints1)
				.setFill([255, 0, 0, 0.5]);
			
			gg.createPolyline(npoints2)
				.setFill([255, 255, 255, 0.5]);
			
			gg.applyTransform([dojox.gfx.matrix.rotategAt(rotated, x1 , y1)]); 	

			return gg ; 
		},



		createTestStage  : function(p ,  x1, y1 , r )
		{
			var group = p.createGroup() ; 	
			
			circle1 = group.createCircle({cx: x1, cy: y1, r: r}).setStroke("white").setFill("gray");
			group.createText({ x: x1, y: y1, text: "1", align:"middle"}).setFill("red")
				.setFont({ family: "SimSun", size: "16pt", weight: "thin" });
			
			circle2 =  group.createCircle({cx: x1+ 2.5*r, cy: y1 , r: r}).setStroke("white").setFill("gray");
			group.createText({ x: x1+ 2.5*r, y: y1, text: "2", align:"middle"}).setFill("red")
				.setFont({ family: "SimSun", size: "16pt", weight: "thin" });
			
			circle3 =  group.createCircle({cx: x1+ 5*r, cy: y1 , r: r}).setStroke("white").setFill("gray");
			group.createText({ x: x1+ 5*r, y: y1, text: "3", align:"middle"}).setFill("red")
				.setFont({ family: "SimSun", size: "16pt", weight: "thin" });
			
			circle4 =  group.createCircle({cx: x1+ 7.5*r, cy: y1 , r: r}).setStroke("white").setFill("green");
			group.createText({ x: x1+ 7.5*r, y: y1, text: "4" , align:"middle"}).setFill("red")
				.setFont({ family: "SimSun", size: "16pt", weight: "thin" });
			
			circle1.connect("onmousedown", this.onMouseDown);
			circle2.connect("onmousedown", this.onMouseDown);
			circle3.connect("onmousedown", this.onMouseDown);
			circle4.connect("onmousedown", this.onMouseDown);
			
			
			return group ; 
		},


		createDirArrow  : function(p , ew){ //ew 東西方向拐彎
			var group = p.createGroup() ; 	
			if( ew )
			{
				group.createPath("M220 250 C240 240 240 240 250 220")
				.setStroke("green"); 	
			
				group.createPath("M220 250 C240 240 240 240 250 220")
					.setStroke("green")
					.applyTransform([dojox.gfx.matrix.rotategAt(180, 250 , 250)]); 
			}
			else
			{
				group.createPath("M220 250 C240 240 240 240 250 220")
				.setStroke("green")
				.applyTransform([dojox.gfx.matrix.rotategAt(-90, 250 , 250)]); 	
			
				group.createPath("M220 250 C240 240 240 240 250 220")
					.setStroke("green")
					.applyTransform([dojox.gfx.matrix.rotategAt(90, 250 , 250)]); 	
			}
			return group ; 
		},


		resetAll : function()
		{
			for( var i = 0 ; i < 8 ; i++ )
			{
				global4.children[i].children[0].setFill("red") ;	
				global4.children[i].children[1].setFill("transparent") ;	
				global4.children[i].children[2].setFill("transparent") ;	
			}

		},

		setStage  :  function(stage)
		{
			this.resetAll();
			switch( stage )
			{
			case 1:     //南北直行
				global4.children[1].children[0].setFill("transparent") ;	
				global4.children[1].children[1].setFill("transparent") ;	
				global4.children[1].children[2].setFill("green") ;	
				
				global4.children[2].children[0].setFill("transparent") ;	
				global4.children[2].children[1].setFill("transparent") ;	
				global4.children[2].children[2].setFill("green") ;
				break;
			case 2:     //南北左拐
				global4.children[0].children[0].setFill("transparent") ;	
				global4.children[0].children[1].setFill("transparent") ;	
				global4.children[0].children[2].setFill("green") ;	
				
				global4.children[3].children[0].setFill("transparent") ;	
				global4.children[3].children[1].setFill("transparent") ;	
				global4.children[3].children[2].setFill("green") ;
				break;  
			case 3:     //東西直行
				global4.children[4].children[0].setFill("transparent") ;	
				global4.children[4].children[1].setFill("transparent") ;	
				global4.children[4].children[2].setFill("green") ;	
				
				global4.children[7].children[0].setFill("transparent") ;	
				global4.children[7].children[1].setFill("transparent") ;	
				global4.children[7].children[2].setFill("green") ;
				break;
			case 4:     //東西左拐
				global4.children[5].children[0].setFill("transparent") ;	
				global4.children[5].children[1].setFill("transparent") ;	
				global4.children[5].children[2].setFill("green") ;	
				
				global4.children[6].children[0].setFill("transparent") ;	
				global4.children[6].children[1].setFill("transparent") ;	
				global4.children[6].children[2].setFill("green") ;
				break;		
			}
		},



		onMouseDown  :  function(evt){
			

			if( evt.target == circle1.getEventSource() ){
				_me.setStage(1) ; 
			}
			if( evt.target == circle2.getEventSource() ){
				_me.setStage(2) ; 
			}

			if( evt.target == circle3.getEventSource() ){
				_me.setStage(3) ; 
			}
			if( evt.target == circle4.getEventSource() ){
				_me.setStage(4) ; 
			}
			
			dojo.stopEvent(evt);
		},

		advanceTime  :  function(){
			maxTime -- ; 
			_me.setTimedText(global1 , maxTime) ; 
			
			if( maxTime == 0  )
			{
				
				maxTime = 21 ; 
				_me.setStage( maxStage);
				maxStage--;
				if( maxStage== 0  )
				{
					maxStage = 4 ; 
				}
			}
		},

		rotate : function(angle)
		{
			global1.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			global2.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250  )]);
			global3.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			global4.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			global5.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			//global6.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			//global7.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
			global8.applyTransform([dojox.gfx.matrix.rotategAt(angle , 250, 250 )]);
		},

		centerIt : function(zlevel){
			if( zlevel == 0 )
				return ; 
			var ptCenter = new Point({ "x": this._lng, "y": this._lat, "spatialReference": { "wkid": 4326} }) ;
			_gismap.centerAndZoom(ptCenter, zlevel);
		},

		rePosition : function() {
			var ptCenter = new Point({ "x": this._lng, "y": this._lat, "spatialReference": { "wkid": 4326} }) ;
			var screenPoint = _gismap.toScreen(ptCenter) ; 
			dojo.query("#"+this._divid).style( {left: ( screenPoint.x - 150) +"px"  , top:( screenPoint.y - 150) + "px"} ) ; 
		},

		zoom : function(zoomFactor)
		{
			global1.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			global2.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			global3.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			global4.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			global5.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			//global6.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
			//global7.applyTransform([dojox.gfx.matrix.scaleAt(0.8, 250 , 250)]);
			global8.applyTransform([dojox.gfx.matrix.scaleAt(zoomFactor, 250 , 250)]);
		},

		init :function() {
			
			surface = dojox.gfx.createSurface(this._divid, 400, 400);
			surface_size = {width: 400, height: 400};			
			global1 = this.makeRoads(surface);
			global2 = this.makeChannels(surface);
			global3 = this.makeChedaos(surface);
			global4 = this.createLightgroups(surface);
			global5 = this.makeArrows(surface) ;
			
			//global6 = this.createTestStage(surface , 200, 450 , 20 ) ; 
			//global7 = this.createNorthArrow(surface , 300 , 180 , 20) ; 
			
			global8 = this.createDirArrow(surface,false) ;			

			global1.applyTransform([dojox.gfx.matrix.translate(-100 , -100 )]);
			global2.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			global3.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			global4.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			global5.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			//global6.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			//global7.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);
			global8.applyTransform([dojox.gfx.matrix.translate(-100 , -100)]);		
			
			timer.setInterval(1000);
			timer.onTick = this.advanceTime;
			timer.start();

			
		}
	}) ; 
});








html中使用demo:

sig = new SignalDraw(map , "div123" , "XX路" , "YY路" , 121.539 ,31.125 ) ; 
		sig.init();
		sig.zoom(0.8) ; 
		sig.rotate(-10) ; 


實現效果:








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章