2016 가을학기연구참여보고서 Visualizing tool of Route Optimization with Google Maps API 2016. 09 ~ 12 (15주) Logistics Lab. 지도교수님김병인멘토김현준참여학생조혜민
1. 서론 1.1. 연구배경및목적본연구는 Logistics Lab에서수행하는경로최적화문제를보조하는목적으로수행되었다. 현재 Logistics Lab에서는택배차량상하차문제, 물류차량경로최적화문제등여러경로최적화과제를해결하고있다. 하지만, solution을도출했을때그경로를시각적으로표시할수없기때문에, 과제수행도중직관적으로현재 solution이최적인지확인하는과정이쉽지않았다. 따라서본연구는 google maps api를활용하여 Logistics Lab에서도출한 solution을지도에시각화해, 보다직관적인의사결정과정을돕는것을목표로한다. csv 형식으로도출된 solution 을 C++ 코드로읽고, Javascript 형태로변환하여 Internet Explorer나 Chrome와같은 web에서확인할수있도록하는것이궁극적인목적이다. 이때, solution에서각각의경로를따로, 혹은동시에지도위에표시할수있게하였고, 각각의경로정보, Node 정보를확인할수있도록했다. 1.2. 연구문제 1.2.1. 입력데이터 [Figure 1. 입력데이터예시 ] 사용자가입력하는데이터를이용하여지도상에데이터를표시한다. 표시하는데이터의종류는총세가지이다. 첫번째, Node의좌표를표시할때사용하는데이터, 두번째, Node의아이콘을클릭했을때팝업되는정보창에표시되는데이터, 마지막으로 turnover rate인데, turnover rate 는경로를표시할때그값이 1이면실선, 2이면점선으로표시되도록하는데이터이다. 출력예시에서그이용을확인할수있다. 모든입력데이터가지도에표시되지는않는다. 사용자는 C++ 코드상에서이를자유롭게조절할수있다. Figure 1에서 latitude와 longitude는첫번째유형의데이터로, 좌표를표시하는데사용된다. i-th vehicle, order of n, node_index는두번째유형의데이터이며, Node의아이콘을클릭했을때팝업창에데이터가표시된다. 마지막으로 turnover rate는그값에따라경로를실선, 혹은점선으로표시하게한다. 예시에서 capacity, ton 수, node_name, arriving time, departing time, demand distance, travel time, address는사용하지않는다.
1.2.2. 출력파일 [Figure 2. 출력파일예시 ] 입력데이터를바탕으로지도에 Node와경로를표시한다. 이때사용자가원하는경로를선별적으로시각화할수있으며, Select All 버튼을누르면모든경로를지도상에표시할수있다. 각각의경로는다른색으로표시된다. 2. 연구방법 2.1. 연구과정본연구는 Javascript와 C++ 를이용하여진행되었다. Javascript는 google maps api에데이터를표시하는역할이며, C++ 은사용자가제공하는데이터를읽는역할을한다. 2.1.1. Google maps api Google maps api는 Google에서제공하는 Javascript & HTML 기반지도웹어플리케이션이다. 최소거리길찾기, 장소표시하기등의기능을가지며, Google Developer의튜토리얼을통해사용방법을익힐수있다. 하지만한국에서는법률상길찾기기능이제한되어있어, 이번과제에서는부득이하게주어진데이터를표시하는데사용이그쳤다. 2.1.2. Javascript 코드
[Figure 3. Javascript 코드 : 지도기본설정 ] 위코드는사용자에게표시되는지도의기본설정을의미한다. 예를들어 <title>directions service</title> 은웹페이지창상단에나타나는이름이 Directions service 임을의미하고, #floating-panel 부분은지도위에뜨는 floating panel의설정값을나타낸다.
[Figure 4. Javascript 코드 : 경로선택메뉴 ] 위코드는페이지상단의경로선택메뉴를나타낸다. 경로숫자를이름으로가진 checkbox 타 입의항목들을표시하고있다. [Figure 5. Javascript 코드 : 핵심네개변수 ] 변수는다음과같이두종류로나눌수있다. 1. path: 지도에서선을표시하기위한변수. 2. marker: 지도에서아이콘을표시하기위한변수.
vehiclepath는 path를구현하기위한변수이고, marker는지도에서 node 부분에아이콘을띄우기위한변수이다. 아이콘을띄우는이유는아이콘을클릭했을때그 node에대한정보를 pop-up하기위함이다. vehiclepath는 route의개수 +1만큼, marker도 route의개수 +1만큼선언한다. +1만큼더선언한이유는코드를짤때 Route 1이 vehiclepath[1] 을가리키게, 즉 route의번호와배열순서의번호를동일하게사용하여직관적으로코드를짤수있도록하기위해서이다. 예시로사용한 input 데이터가 28개였기때문에예시에서는배열형식으로각각 29개씩선언하였다. 이때 vehiclepath, marker 둘다각각번호에맞는 route의정보를저장시키는변수이다. vehiclepath는그 path에포함되는좌표, path의두께, 색등을저장하고, marker는사용하는 icon, marker를띄울좌표등을저장한다. vehiclepath, marker 외에도 vehiclepath_turn, marker_turn이라는변수가있는데, 이는각각의변수를 turnover rate에따라분류하기위하여만든것이다. Turnover rate가 1이면실선, Turnover rate가 2이면점선으로경로가표시된다. 다음은좌표를저장하는변수들이다. vehiclepathcoordinates은 path를위한 route별좌표모음, vehiclepathlocation은 marker를위한 route별좌표모음이다. 둘의차이는다음과같다. vehiclepathcoordinates는지도상에선을표시하기위해, 다시말해선을나타내기위한좌표의모음이고, vehiclepathlocation는지도위의아이콘을나타내기위한좌표모음이기때문에아이콘을클릭했을때팝업되는정보창에들어갈데이터를포함한다.
[Figure 6. Javascript 코드 : vehiclepathcoordination, vehiclepathlocation 데이터삽입예시 ] [Figure 7. Javascript 코드 : initmap()] initmap() 함수는프로그램을켰을때실행되는함수. C++ 의 main 함수와비슷하다. 각코드가의미하는바는다음과같다. map = new google.maps.map(document.getelementbyid('map'), //map을실행하는부분 zoom: 7,//map의확대정도 center: new google.maps.latlng(36, 127.1), // 위도 36, 경도 127.1을중심으로지도를띄운다는의미 maptypeid: google.maps.maptypeid.roadmap// 위성사진이아닌로드맵형식의지도를띄운다는의미
[Figure 7. Javascript 코드 : addline(chkbox)] addline(chkbox) 함수는페이지상단의체크박스가선택되면선택된체크박스의 route에맞게그정보를지도에표시하는함수이다. 체크가되면그 route가전에초기화되었는지, 안되었는지확인한후초기화되지않았다면 route를표시하는선의색, 굵기, route를구성하는좌표, 아이콘등의정보를초기화시켜준다. 만약이전에초기화가된상태라면이미완성된초기화정보를표시한다. 체크가해제되면지도상에나타난 route의시각화된정보를제거한다.
[Figure 8. Javascript 코드 : 그외코드 ] attachsecretmessage는 route의아이콘을클릭했을때정보가뜰수있게하는함수이다. getrandomcolor는 route에따라다른색을사용할수있도록랜덤으로색을정해주는함수이다. linesymbol은점선을표시할수있도록돕는함수이다.
[Figure 9. Javascript 코드 : selectall(chkbox)] selectall(chkbox) 은사용자가입력한데이터에존재하는모든 route의정보를한꺼번에지도에표시할때사용하는함수이다. 이는 addline(chkbox) 와비슷한구조이다. 모든 route를초기화됐는지아닌지검사하고, 초기화되지않은 route는초기값을설정해이미초기화된 route는이전에설정된값을가져와모든 route를지도에표시한다. 2.1.3. C++ 코드 Google maps api에데이터를표시하는것은 Javascript이지만, 데이터를읽는것은 C++ 을이용한다. C++ 로읽은데이터를 Javascript로변환하는과정은 C++ 에저장된데이터를이용해 fout으로 Javascript 코드를출력하는직관적인방식으로진행됐다. C++ 파일의구성은다음과같다. Tokenizer.h : csv 파일을읽고줄마다그요소를 vector에할당해주는코드., 을제거하고요소를 vector에순서대로넣어준다. ReadFile.h : Input file 데이터를읽고 vector에저장하는코드 Show.h : javascript 용법으로데이터를삽입하여코드를출력 test.cpp : main 파일.
[Figure 10. C++ 코드 : Tokenizer.h]
[Figure 11. C++ 코드 : ReadFile.h]
[Figure 12. C++ 코드 : test.cpp] 다른코드들은보통데이터를읽을때사용하는코드와차이가없으나, show.h 코드는저장된데이터를 Javascript 형식으로변환하는코드이기때문에표현의차이가있다. Appendix에원본코드와주석을첨부하였다. 3. 프로그램실행예시 3.1. 첫화면
3.2. 경로다중선택 3.3. 경로선택취소
3.4. 아이콘클릭 3.5. Select All
3.6. Select All 취소 4. 보완점 Google maps api가대한민국에서길찾기과정을지원하지않아사용할수있는기능에한계가있었다. 만약 Google maps api가아닌 T map, Naver 길찾기서비스등을적절하게활용했다면각 Node 사이를이동하는데걸리는시간, 직선거리가아닌실제차량이이동하는경로등을표시할수있었을것이다. 대한민국이아닌다른나라를배경으로한경로최적화문제는이와같은기능을이용하여표시할수있게개선할가능성이남아있다. 또한 Google maps api의가장큰문제점은확대와축소에관계없이아이콘의크기가동일하다는것인데, 이는변경할수없다. 그렇기때문에대한민국지도를전체적으로볼때아이콘들이겹쳐경로가잘보이지않는문제가발생했다. 아주작은아이콘을이용해보았으나이때는아이콘을클릭해정보를표시하는데무리가있었다. 비록시간이없어구현하지못했지만 route마다다른아이콘을사용하도록하고, 아이콘을사라지게할수있는기능을넣었다면보다 route를파악하기쉬웠을것이다. 5. 후기 학기중연구참여이기때문에학업과병행하느라열심히하지않았던것같아후회가된다. 교수님께서계획하셨던과제는두개였는데, 페이스조절을하지못해하나만완성하여아쉽다. Javascript 를모르는상태에서코딩했는데아직까지 Javascript에대해아는내용이하나도없다. 교수님께서그냥하면된다고용기를주셔서도전했더니, 정말 Javascript에대해아무것도모르는상태에서결과물을냈다. 이사실이감개무량하지만, 차라리그시간에하루를잡고 Javascript를공부했으면더빠른시간에과제를끝내고두번째과제도할수있지않았을까하는후회가든다.
학부생이라랩에큰도움은될수없다는사실은알고있지만유난히도움이안됐던것같다. 특 히멘토현준오빠가시킨일을항상기한을넘겨서했던것이마음에걸린다. 과제후반부까지메 모장으로코딩을했던것이패인이었다. 이때문에중괄호를하나빠트린것을눈치채지못하고마 지막까지고생을했었다. Visual Studio 를사용했으면더빠른수정이가능했을것이다. 지면을빌어 사과드린다. 이래저래아쉬운점이많은연구참여였지만예전부터가고싶었던랩에조금이나마발을담근것 같아기쁘다. 이번연구참여를통해자신의부족한점을많이깨닫게되었고, 남은학부과정동안 연구참여때느꼈던문제점을잘보완하고싶다. 6. Appendix #pragma once #include "ReadFile.h" int countnode(int a, vector<route> route_list)// 각각의 Route 에 node 가몇개있는지세는함수입니다 int n = 0; vector<route>::iterator iter = route_list.begin(); while (route_list.end()!= iter) if (iter->veh_no == a) n++; iter++; return n; vector<route>::iterator finditer(int a, vector<route> *route_list)//end 의 iterator 를반환하는함수인데지금보니까왜만들었나싶네요 ^^; 반성중입니다. vector<route>::iterator iter = route_list->begin(); while (iter!= route_list->end()) if (iter->veh_no == a) return iter; iter++; void showfile(const string filename, vector<route> route_list) ofstream fout(filename.c_str()); if (fout.is_open()) <!DOCTYPE html>" << endl; <html>" << endl; <head>" << endl; <meta name=\"viewport\" content=\"initial-scale=1.0, userscalable=no\">" << endl;
<meta charset=\"utf-8\">" << endl; <title>directions service</title>" << endl;// 윈도우창에적히는이름 <style>" << endl;// 이아래는윈도우창설정입니다. html, body " << endl; height: 100%;" << endl; margin: 0;" << endl; padding: 0;" << endl; #map height: 100%;" << endl; #floating-panel " << endl; position: absolute;" << endl; top: 10px;" << endl; left: 25%;" << endl; z-index: 5;" << endl; background-color: #fff;" << endl; padding: 5px;" << endl; border: 1px solid #999;" << endl; text-align: center;" << endl; font-family: 'Roboto','sans-serif';" << endl; line-height: 30px;" << endl; padding-left: 10px;" << endl; " << endl<<endl; </style>" << endl; </head>" << endl; <body>" << endl; <div id=\"floating - panel\" onchange=\"calcroute(); \">" << endl; <b>start: </b>" << endl; // 여기서부터보시면돼요 for (int i = 1; i < ((route_list.back().veh_no) + 1); i++)// 이부분이체크박스를지정하는부분입니다. <input onclick=\"addline(this); \" type=\"checkbox\" value=0 id=\"" << i << "\" />" << endl;// 아이디를 i로지정해줍니다 <label for=\"" << i << "\">" << i << "</label>" << endl;//i가숫자부분이에요 << endl; <input onclick=\"selectall(this); \" type=\"checkbox\" id=\"all\"/>" <label for=\"all\">select All</label> " << endl; </select>" << endl; </div>" << endl; <div id=\"map\"></div>" << endl; <script>" << endl<<endl; /* 아래는변수들을선언하고있습니다. 변수는크게두종류로나눌수있습니다. 1. path: 지도에서선을표시하기위한변수. 2. marker: 지도에서아이콘을표시하기위한변수. path 와 marker 둘다좌표정보가필요합니다. 둘이필요한좌표표현방식이달라서따로저장해줘야해요.*/ 위한변수. /*vehiclepath 는 path 를구현하기위한변수, marker 는 icon 을지도에표시하기
vehiclepath 는 route 의개수 +1 만큼, marker 도 route 의개수 +1 만큼선언해줍니다. 둘다 route 마다의정보를저장시키는변수에요. vehiclepath 는그 path 에포함되는좌표, path 의두께색등을저장하구요, marker 는사용하는 icon, marker 를띄울좌표등을저장합니다. 하나씩더선언한건코드짤때직관적으로짜고싶어서배열의 [0] 부분을비워두고그다음부터시작해서그래요. 그래서 route 의번호랑배열순서번호랑똑같이쓸수있습니다.*/ var vehiclepath = new Array("<< ((route_list.back().veh_no) + 1) <<");" << endl; var vehiclepath_turn = new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl; // 뒤에 turn 붙은건회전수다른 route 따로정의한거에요 var i;" << endl; // 그냥 for문돌릴때쓰는 i var marker= new Array("<< ((route_list.back().veh_no) + 1) <<");" << endl; var marker_turn= new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl; for(i=0;i<"<< ((route_list.back().veh_no) + 1) <<";i++)" << endl; marker[i] = new Array();" << endl; marker_turn[i] = new Array();" << endl; " << endl<<endl; /*vehiclepathcoordinates 은 path 를위한루트별좌표모음 vehiclepathlocation 은 marker 를위한루트별좌표모음차이는 marker 를위한좌표에는그좌표에대한정보가들어있습니다. 클릭했을때나와야되니까요 */ var vehiclepathcoordinates = new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl; var vehiclepathlocation = new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl; var vehiclepathcoordinates_turn = new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl; var vehiclepathlocation_turn = new Array(" << ((route_list.back().veh_no) + 1) << ");" << endl << endl; int n = 0; vector<route>::iterator iter = route_list.begin(); for (int i = 1; i < ((route_list.back().veh_no) + 1); i++)//vehiclepathcoordinates 선언중 vehiclepathcoordinates[" << i << "]= [" << endl; n = countnode(i, route_list); iter = finditer(i, &route_list); for (int j = 0; j < n-1; j++) if (iter->turnover_rate!= (iter + 1)->turnover_rate) lat: " << iter->lattitude << ", lng: " << iter->longitude << "" << endl; else lat: " << iter->lattitude << ", lng: " << iter->longitude << "," << endl; iter++; if (iter->turnover_rate!= (iter-1)->turnover_rate)
];" << endl << endl; vehiclepathcoordinates_turn[" << i << "]= [" << endl; lat: " << iter->lattitude << ", lng: " << iter- >longitude << "" << endl; ];" << endl<<endl; n = 0; iter = route_list.begin(); for (int i = 1; i < ((route_list.back().veh_no) + 1); i++) //vehiclepathlocation 선언중. 여기서 ''< 이안에들어가는게클릭했을때나오는정보입니다. //' 정보 ', lattitude, longitude 순서로적어줍니다 vehiclepathlocation[" << i << "]= [" << endl; n = countnode(i, route_list); iter = finditer(i, &route_list); for (int j = 0; j < n - 1; j++) if (iter->turnover_rate!= (iter + 1)->turnover_rate) ['Route:("<<iter->veh_no<<")Order:[" << iter->order_of_node_in_vehicle << "]Index:(" << iter->node_index<< ")', " << iter->lattitude << ", " << iter->longitude << " ]" << endl; else ['Route:(" << iter->veh_no << ")Order:[" << iter->order_of_node_in_vehicle << "]Index:(" << iter->node_index << ")', " << iter->lattitude << ", " << iter->longitude << " ]," << endl; iter++; if (iter->turnover_rate!= (iter - 1)->turnover_rate) ];" << endl << endl; vehiclepathlocation_turn[" << i << "]= [" << endl; ['Route:(" << iter->veh_no << ")Order:[" << iter- >order_of_node_in_vehicle << "Index:(" << iter->node_index << ")', " << iter->lattitude << ", " << iter->longitude << " ]" << endl; ];" << endl << endl; // 초기화. 이게 main 함수라고보시면될것같아요창을켰을때실행되는함수입니다. function initmap() " << endl; map = new google.maps.map(document.getelementbyid('map'), " << endl;// 이부분은 map을켜는부분이라고생각하면될것같아요 zoom: 7," << endl;// 이정도로확대한 map을띄우겠다 center: new google.maps.latlng(36, 127.1)," << endl;// 이곳을센터로지도를띄우겠다 maptypeid: google.maps.maptypeid.roadmap" << endl;// 위성사진말고로드맵형식의지도를띄우겠다 );" << endl;
" << endl<<endl; function addline(chkbox) " << endl;// 체크가되면체크가된 route의선을지도에그어주고 marker도표시해주는함수입니다. 변수를 check 유무로받아요 if ( chkbox.checked == true )" << endl;// 만약체크가됐다면 " << endl; var color_t = getrandomcolor();" << endl;// 랜덤으로 color pick if(chkbox.value == 0)" << endl;// 만약아무것도체크가안되어있다가체크가됐다면 ( 초기화를해줘야함 ) vehiclepath[chkbox.id] = new google.maps.polyline(" << endl;//vehiclepath라는변수에 path: vehiclepathcoordinates[chkbox.id]," << endl;//vehiclepathcoordinates에저장된좌표들을이어줍니다 strokecolor: color_t," << endl;// 아까랜덤으로뽑은색 strokeopacity: 1.0," << endl; strokeweight: 4" << endl; );" << endl; vehiclepath[chkbox.id].setmap(map);" << endl<<endl;//setmap(somathing) 쓰면 map 위에 something을표시한다는거에요 for (i = 0; i < vehiclepathlocation[chkbox.id].length; i++) " << endl;// 마커표시 marker[chkbox.id][i] = new google.maps.marker(" << endl;//marker 변수에정보를넣어줍니다 position: new google.maps.latlng(vehiclepathlocation[chkbox.id][i][1], vehiclepathlocation[chkbox.id][i][2])," << endl;// 좌표위경도 map: map," << endl; icon: 'red.png'" << endl;// 아이콘모양설정. );" << endl; attachsecretmessage(marker[chkbox.id][i], vehiclepathlocation[chkbox.id][i][0]);" << endl;//vehiclepathlocation[chkbox.id][i][0] 은정보부분이에요. 그걸정보창에띄우겠다는소리 " << endl<<endl; if(vehiclepathlocation_turn[chkbox.id]!= null)" << endl;// 만약 회전수다른 route가있다면걔는점선으로표시 vehiclepath_turn[chkbox.id] = new google.maps.polyline(" << endl; path: vehiclepathcoordinates_turn[chkbox.id]," << endl; strokecolor: color_t," << endl; strokeopacity: 0," << endl; icons: [" << endl; icon: linesymbol," << endl;// 점선으로표시하려면얘를 포함해줘야해요. 밑에정의돼있습니다 linesymbol offset: '0'," << endl; repeat: '20px'" << endl; ]" << endl; );" << endl; vehiclepath_turn[chkbox.id].setmap(map);" << endl<<endl;// 점선 표시 for (i = 0; i < vehiclepathlocation_turn[chkbox.id].length; i++) " << endl;// 회전수다른 route의 marker 표시 marker_turn[chkbox.id][i] = new google.maps.marker(" << endl;
position: new google.maps.latlng(vehiclepathlocation_turn[chkbox.id][i][1], vehiclepathlocation_turn[chkbox.id][i][2])," << endl; map: map," << endl; icon: 'red.png'" << endl; );" << endl; attachsecretmessage(marker_turn[chkbox.id][i], vehiclepathlocation_turn[chkbox.id][i][0]);" << endl; " << endl; " << endl; chkbox.value = 1;" << endl;// 한번이상체크가됐었다면 chkbox.value를 1로바꿔줍니다 " << endl<<endl; endl; i++)" << endl; endl; i++)" << endl; vehiclepath[chkbox.id].setmap(map);" << endl; for (i = 0; i <vehiclepathlocation[chkbox.id].length; i++)" << marker[chkbox.id][i].setmap(map);" << endl; " << endl; if(vehiclepathlocation_turn[chkbox.id]!= null)" << endl; vehiclepath_turn[chkbox.id].setmap(map);" << endl; for (i = 0; i < vehiclepathlocation_turn[chkbox.id].length; marker_turn[chkbox.id][i].setmap(map);" << endl; " << endl; " << endl; " << endl; else" << endl;// 체크해제되면 map에서 path와 marker 삭제 " << endl; vehiclepath[chkbox.id].setmap(null);" << endl; for (i = 0; i < vehiclepathlocation[chkbox.id].length; i++)" << marker[chkbox.id][i].setmap(null);" << endl; " << endl; if(vehiclepathlocation_turn[chkbox.id]!= null)" << endl; vehiclepath_turn[chkbox.id].setmap(null);" << endl; for (i = 0; i < vehiclepathlocation_turn[chkbox.id].length; marker_turn[chkbox.id][i].setmap(null);" << endl; " << endl; " << endl; " << endl; " << endl<<endl; function attachsecretmessage(marker, secretmessage) " << endl;// 이름이 secretmessage인건신경쓰실필요없어요소스긁어와서그렇습니다. var infowindow = new google.maps.infowindow(" << endl;// 마커를클릭했을때뜨는 info창을정의한변수입니다. content: secretmessage" << endl; );" << endl<<endl; marker.addlistener('click', function() " << endl;// 클릭했을때정보창이뜨도록하는함수 infowindow.open(marker.get('map'), marker);" << endl; );" << endl;
" << endl<<endl; 함수 function getrandomcolor() " << endl;// 색랜덤으로골라서반환하는 var letters = '0123456789ABCDEF';" << endl; var color = '#';" << endl; for (var i = 0; i < 6; i++ ) " << endl; color += letters[math.floor(math.random() * 16)];" << endl; " << endl; return color;" << endl; " << endl<<endl; var linesymbol = " << endl;// 점선을만들게도와주는변수입니다. path: 'M 0,-1 0,1'," << endl; strokeopacity: 1," << endl; scale: 4" << endl; ;" << endl <<endl; function selectall(chkbox)" << endl; " << endl; if (chkbox.checked == true)" << endl; " << endl; for (var k = 1; k < 29; k++)" << endl; " << endl; var color_t = getrandomcolor();" << endl; if (document.getelementbyid(k).value == 0)" << endl; " << endl; vehiclepath[k] = new google.maps.polyline(" << endl; path: vehiclepathcoordinates[k]," << endl; strokecolor : color_t," << endl; strokeopacity : 1.0," << endl; strokeweight : 4" << endl; );" << endl; for (var i = 0; i < vehiclepathlocation[k].length; i++)" << endl; " << endl; marker[k][i] = new google.maps.marker(" << endl; position: new google.maps.latlng(vehiclepathlocation[k][i][1], vehiclepathlocation[k][i][2])," << endl; map : map," << endl; icon : 'red.png'" << endl; );" << endl; attachsecretmessage(marker[k][i], vehiclepathlocation[k][i][0]);" << endl; " << endl; if (vehiclepathlocation_turn[k]!= null) " << endl; vehiclepath_turn[k] = new google.maps.polyline(" << endl; path: vehiclepathcoordinates_turn[k]," << endl; strokecolor : color_t," << endl; strokeopacity : 0," << endl; icons : [" << endl; icon: linesymbol," << endl; offset : '0'," << endl;
repeat : '20px'" << endl; ]" << endl; );" << endl; for (i = 0; i < vehiclepathlocation_turn[k].length; i++) " << endl; marker_turn[k][i] = new google.maps.marker(" << endl; position: new google.maps.latlng(vehiclepathlocation_turn[k][i][1], vehiclepathlocation_turn[k][i][2])," << endl; map : map," << endl; icon : 'red.png'" << endl; );" << endl; attachsecretmessage(marker_turn[k][i], vehiclepathlocation_turn[k][i][0]);" << endl; " << endl; " << endl; document.getelementbyid(k).value = 1;" << endl; " << endl; " << endl; i++) " << endl; << endl; i++)" << endl; vehiclepath[k].setmap(map);" << endl; for (i = 0; i < vehiclepathlocation[k].length; i++) marker[k][i].setmap(map);" << endl; " << endl; if (vehiclepathlocation_turn[k]!= null) " << endl; vehiclepath_turn[k].setmap(map);" << endl; for (i = 0; i < vehiclepathlocation_turn[k].length; marker_turn[k][i].setmap(map);" << endl; " << endl; " << endl; " << endl; " << endl; else" << endl; " << endl; for (var l = 1; l < 29; l++)" << endl; " << endl; " << endl; vehiclepath[l].setmap(null);" << endl; for (i = 0; i < vehiclepathlocation[l].length; i++)" " << endl; marker[l][i].setmap(null);" << endl; " << endl; if (vehiclepathlocation_turn[l]!= null)" << endl; " << endl; vehiclepath_turn[l].setmap(null);" << endl; for (i = 0; i < vehiclepathlocation_turn[l].length; " << endl; marker_turn[l][i].setmap(null);" << endl; " << endl; " << endl;
" << endl; " << endl; " << endl; " << endl; </script>" << endl; <script async defer" << endl; src=\"https://maps.googleapis.com/maps/api/js?key=aizasybox23iao8xft_bnm4dnpimbswisjoukgg&signe d_in=true&callback=initmap\"></script>" << endl; </body>" << endl; </html>" << endl;