diff --git a/_posts/2023-05-26-Arcgis_map.md b/_posts/2023-05-26-Arcgis_map.md
new file mode 100644
index 0000000000..ef5203a878
--- /dev/null
+++ b/_posts/2023-05-26-Arcgis_map.md
@@ -0,0 +1,513 @@
+---
+layout: post
+title: "Arcgis를 개발에 활용하는 법"
+authors: [Camsul]
+tags: ["Mobile", "Flutter", "Arcgis", "UOScheduler"]
+image: ../assets/images/post-Arcgis-map/post_cover.png
+featured: true
+---
+
+***
+
+## INTRO
+
+안녕하세요! 저는 공간정보공학과 18학번 한진형입니다. 이번에 저의 졸업작품 팀에서 만든 어플에 대해 글을 써보려고 합니다. 그중 문제가 생겼던 부분에서, 새롭게 구현한 부분에 대해 그 해결과정에 대해 글을 써보려 합니다.
+
+중간중간 코드들이 있는데, 실제로 어플 로직에 활용되는 코드이며, 자유로운 사용이 가능함을 미리 밝힙니다.
+
+## UOScheduler 어플에 관하여
+
+UOScheduler는 2023-1 공간정보종합설계2 16조 산출물로 대학 시간표 어플과 공간정보 요소를 융합한 어플입니다.
+
+기존의 위치 정보를 고려하여 시간표를 만들지 못하였는데, 이 어플만으로 위치 정보를 고려하며 시간표를 만들 수 있는 어플입니다.
+
+현재(23.05.26 기준) 1.0.1버젼이 배포되어 있으며, 플레이스토어, 앱스토어에서 찾아보실 수 있습니다.
+> 다운링크
+[UOScheduler Google Play Store](https://play.google.com/store/apps/details?id=com.mycompany.uoscheduler&pli=1)
+[UOScheduler App Store](https://apps.apple.com/kr/app/uoscheduler/id6448325141)
+
+### 어플 제작 배경
+
+어플 제작 배경은 다음과 같습니다.
+기존 시간표 어플에서 위치 정보를 고려하지 못하며, 흩어져있는 학사 관련 정보들을 직접 찾아서 확인해야합니다.
+
+이때 저희는 위치 정보를 고려한 시간표 계획과 캠퍼스 포트폴리오 관리를 동시에 할 수 있는 종합 학사관리 어플을 만들게 되었습니다.
+
+현재는 시간표 기능만 지원하고 있지만, 팀원과들의 협의를 통해 다양한 기능 추가 고려 중에 있습니다.
+
+## 구현 중 문제 발생
+
+문제 내용: Flutter 환경에서 지원하는 도보 경로 api가 없음
+
+건물간 유저의 경로와 소요시간을 구하기 위해 꼭 필요한 내용인데 api로 구현할 수 없음을 확인했습니다. 그래서 다양한 방법을 고려하다가 직접 구현하기로 결정하였습니다.
+
+### Flutter 지원 지도 api 불가한 이유
+
+> - Google
+ 유일하게 공식적으로 도보 api 지원
+ 한국 - 도보 길찾기 기능 비활성화
+> - Apple
+ 공식적으로 지원
+ 도보 길찾기 구현 불가
+> - Naver, Kakao, Tmap
+ Flutter를 공식적으로 지원하지 않음
+ dependency로 제한된 기능만 구현 가능
+
+다양한 이유로 도보 경로 길찾기 api를 찾을 수 없었습니다.
+
+### 해결 과정
+
+다음과 같은 순서를 통해 구현하여 해결 하였습니다.
+추가적으로 `Arcgis`라는 툴을 사용하였습니다.
+
+### 0. ArcGIS에 관하여
+
+ArcGIS는 지리 공간 정보 시스템(`GIS`) 소프트웨어로, 지리적 위치 데이터의 수집, 저장, 관리, 분석 및 시각화를 위한 도구를 제공하는 프로그램입니다.
+
+공간정보공학과 학부생이라면 모두가 다룰 수 있는 Tool이며 IT help desk에 접속하여 교내에서 무료로 사용가능 합니다.
+
+### 1. Arcgis를 통해 교내 노드, 링크 생성
+
+
+
+Arcgis를 통해 교내의 노드들을 먼저 만듭니다.
+노드는 갈림길, 건물 통로, 꺾이는 길을 모두 이어질 수 있는 중간 기지 역할을 합니다.
+그다음에는 모든 이웃한 노드들 사이의 링크를 연결해 줍니다.
+그렇게 하여 교내 길들에 대하여 노드 링크들을 완성합니다.
+
+### 2. 교내의 노드 링크 데이터를 위경도 좌표와 함께 DB로 저장
+
+이렇게 만든 노드, 링크 데이터들을 엑셀파일로 정리합니다.
+위경도 좌표는 WGS84 좌표계로 구현하였습니다. - 네이버 api에 적용할 수 있는 좌표계
+
+노드 DB의 속성(Attribute)은 다음과 같습니다.
+ > 노드번호 (int not null)
+ 건물번호 (int)
+ 건물이름 (string)
+ 위도 (double not null)
+ 경도 (double not null)
+ (건물번호, 이름 - 노드가 건물 입구에 해당하지 않는 경우 null값)
+
+```dart
+//노드 클래스 선언
+class Node {
+ final int nodeId; //노드 id
+ final int? buildingId; //건물 id - 건물이 아닌 노드는 null
+ final String? buildingName; //건물 이름 - 건물이 아닌 노드는 null
+ final double latitude; //위도
+ final double longitude; //경도
+ Node(this.nodeId, this.buildingId, this.buildingName,
+ this.latitude, this.longitude);
+
+ factory Node.fromCsv(List csv) {
+ return Node(
+ csv[0] as int,
+ csv[1] == '' ? null : csv[1] as int,
+ csv[2] == '' ? null : csv[2] as String,
+ csv[3] as double,
+ csv[4] as double,
+ );
+ }
+}
+```
+
+링크 DB의 속성(Attribute)은 다음과 같습니다.
+또한 양방향 링크가 필요하기 때문에 관련 함수도 같이 구현합니다.
+ > 링크번호 (int not null)
+ 출발 노드 번호 (int not null)
+ 도착 노드 번호 (int not null)
+ 출발 위도 (double not null)
+ 출발 경도 (double not null)
+ 도착 위도 (double not null)
+ 도착 경도 (double not null)
+ 링크 길이 (double not null)
+
+```dart
+//링크 클래스 선언
+class Link {
+ final int linkId; //링크 id
+ final int fromNode; //출발 노드 id
+ final int toNode; //도착 노드 id
+ final double fromLongitude; //출발 노드 경도
+ final double fromLatitude; //출발 노드 위도
+ final double toLongitude; //도착 노드 경도
+ final double toLatitude; //도착 노드 위도
+ final double distance; //링크 길이
+ Link(this.linkId, this.fromNode, this.toNode, this.fromLongitude,
+ this.fromLatitude, this.toLongitude, this.toLatitude, this.distance);
+
+ factory Link.fromCsv(List csv) {
+ return Link(
+ csv[0] as int,
+ csv[1] as int,
+ csv[2] as int,
+ csv[3] as double,
+ csv[4] as double,
+ csv[5] as double,
+ csv[6] as double,
+ csv[7] as double,
+ );
+ }
+
+ List getBidirectionalLinks() {
+ //양방향 링크를 만들어주는 함수
+ return [
+ Link(
+ this.linkId,
+ this.toNode,
+ this.fromNode,
+ this.toLongitude,
+ this.toLatitude,
+ this.fromLongitude,
+ this.fromLatitude,
+ this.distance,
+ ),
+ Link(
+ this.linkId,
+ this.fromNode,
+ this.toNode,
+ this.fromLongitude,
+ this.fromLatitude,
+ this.toLongitude,
+ this.toLatitude,
+ this.distance,
+ ),
+ ];
+ }
+}
+```
+
+이렇게 구성된 교내 노드, 링크가 다 합쳐서 250여 개 됩니다.
+이제 이렇게 구성된 DB들을 가지고 길 찾기 알고리즘을 구현하면 됩니다.
+
+저는 DB의 크기가 크지 않아, 각 노드, 링크를 csv파일로 변환하여 어플 내에 내장하였습니다.
+
+### 3. 다익스트라 알고리즘을 우선순위큐로 구현
+
+이 글을 보시는 분이라면 우선순위 큐가 무엇인지는 대부분 아실 거로 생각합니다.
+다음과 같이 구현하였고 코드에 대한 리뷰는 언제나 환영입니다!
+
+```dart
+//그래프 클래스 선언
+class Graph {
+ final List nodes;
+ final List links;
+ Graph(this.nodes, this.links);
+
+ Map dijkstra(int sourceBuildingId) {
+ //초기 거리 값을 무제한으로 초기화
+ final Map distances = Map.fromIterable(
+ nodes.where((node) => node.buildingId == sourceBuildingId),
+ key: (node) => node.nodeId,
+ value: (node) => double.infinity.toStringAsFixed(1),
+ );
+ distances[sourceBuildingId] = '0.0';
+
+ // 우선순위 큐를 사용하여 가장 가까운 노드를 찾는다
+ final PriorityQueue> queue =
+ HeapPriorityQueue((a, b) => a.value.compareTo(b.value));
+ queue.add(MapEntry(sourceBuildingId, 0.0));
+
+ while (queue.isNotEmpty) {
+ //큐가 비어있지 않다면
+ final int nodeId = queue.removeFirst().key; //큐에서 가장 가까운 노드를 꺼낸다
+ final Node node = nodes.firstWhere(
+ (node) => node.nodeId == nodeId, //노드를 찾는다
+ orElse: () => throw Exception('Node $nodeId not found.')); //노드가 없다면 에러를 띄운다
+ final double currentDistance =
+ double.parse(distances[nodeId]!); //현재 노드까지의 거리를 저장한다
+
+ // 이웃한 노드들에 대해 거리를 업데이트
+ for (final Link link in links.where((link) => link.fromNode == nodeId)) {
+ final int neighborId = link.toNode; //이웃 노드의 id를 저장한다
+ final Node neighbor = nodes.firstWhere(
+ (node) => node.nodeId == neighborId, //이웃 노드를 찾는다
+ orElse: () => throw Exception('Node $neighborId not found.')); //이웃 노드가 없다면 에러를 띄운다
+ final double newDistance =
+ currentDistance + link.distance; //현재 노드까지의 거리와 링크 길이를 더한다
+ final String newDistanceStr =
+ newDistance.toStringAsFixed(1); //소수점 첫째자리까지만 저장한다
+ if (distances[neighborId] == null ||
+ double.parse(distances[neighborId]!) > newDistance) {
+ //이웃 노드까지의 거리가 null이거나 현재 노드까지의 거리와 링크 길이를 더한 값이 이웃 노드까지의 거리보다 작다면
+ distances[neighborId] = newDistanceStr; //이웃 노드까지의 거리를 업데이트한다
+ queue.add(MapEntry(neighborId, newDistance)); //큐에 이웃 노드를 추가한다
+ }
+ }
+ // 이거 주석 해제해서보면 어떻게 그래프가 만들어지는지 알 수 있음 - 디버그 콘솔 폭탄 주의
+ // print('Distances: $distances');
+ }
+ return distances;
+ }
+}
+```
+
+자세히 보신 분은 아시겠지만, 사실상 BFS 알고리즘과 다를 바가 없습니다.
+추후 가중치 or 우선순위가 있는 구현을 위해서, 먼저 다음과 같이 구현하였습니다.
+
+### 4. 출발, 도착 건물 번호를 입력하면 그 경로 사이에 경로 노드 리스트 및 전체 거리 리턴하는 함수 구현
+
+출발, 도착 건물 번호를 입력하면, 해당하는 노드번호를 찾아야 경로탐색을 시작할 수 있을 것 입니다.
+그래서 먼저 다음과 같은 함수를 구현합니다.
+
+```dart
+//건물 id를 노드 id로 변환하는 함수
+int buildingIdToNodeId(int buildingId, List nodes) {
+ final Node node = nodes.firstWhere(
+ (node) => node.buildingId == buildingId, //노드를 찾는다
+ orElse: () => throw Exception(
+ 'Building number $buildingId not found.')); //해당하는 노드가 없다면 에러를 띄운다
+ return node.nodeId;
+}
+```
+
+그런 다음 지금까지 구성된 DB를 불러와서, 최단경로 알고리즘을 돌릴 수 있는 함수를 구현합니다.
+
+```dart
+Future printShortestPath(int startBuildingId, int endBuildingId) async {
+ final nodesData = await rootBundle.loadString('assets/uos_node.csv'); //노드 데이터를 불러온다
+ final nodesCsv = CsvToListConverter(
+ fieldDelimiter: ',',
+ eol: "\n",
+ shouldParseNumbers: true,
+ ).convert(nodesData).sublist(1);
+
+
+ final linksData = await rootBundle.loadString('assets/uos_edge.csv'); //링크 데이터를 불러온다
+ final linksCsv = CsvToListConverter(
+ //csv파일을 리스트로 변환
+ fieldDelimiter: ',',
+ eol: "\n",
+ shouldParseNumbers: true,
+ ).convert(linksData).sublist(1);
+ final nodes = nodesCsv.map((node) => Node.fromCsv(node)).toList(); //노드 리스트를 만든다
+
+ // 양방향 링크로 수정해준다
+ final List links = [];
+ for (final linkCsv in linksCsv) {
+ final Link link = Link.fromCsv(linkCsv);
+ links.addAll(link.getBidirectionalLinks());
+ }
+ final graph = Graph(nodes, links); //노드, 링크 정보를 넣어서 그래프를 만든다
+
+ final int startNodeId =
+ buildingIdToNodeId(startBuildingId, nodes); //출발 건물 id를 노드 id로 변환
+ final int endNodeId =
+ buildingIdToNodeId(endBuildingId, nodes); //도착 건물 id를 노드 id로 변환
+ print("출발건물: $startBuildingId, 도착건물: $endBuildingId");
+ print("출발node: $startNodeId, 도착node: $endNodeId");
+ final distances =
+ graph.dijkstra(startNodeId); //다익스트라 알고리즘을 사용하여 출발 노드에서 각 노드까지의 거리를 구한다
+
+ //도착 노드까지의 거리가 null이거나 무한대라면 - 해당하는 경로가 없는 것 (우리의 학교 노드, 링크에서는 발생하지 않음, 모든 그래프는 연결되었으니!)
+ if (!distances.containsKey(endNodeId) ||
+ double.parse(distances[endNodeId]!) == double.infinity) {
+ print(
+ 'start id: $startBuildingId - end id: $endBuildingId 경로 없음'); //경로가 없다고 출력
+ return [];
+ }
+
+ List shortestPath = []; //최단 경로를 저장할 리스트
+ double totalDistance = 0.0; //총 거리를 저장할 변수
+ int currentNode = endNodeId; //현재 노드를 도착 노드로 초기화
+ while (currentNode != startNodeId) {
+ //현재 노드가 출발 노드가 될 때까지 반복
+ final List linksFromCurrentNode = links
+ .where((link) => link.toNode == currentNode)
+ .toList(); //현재 노드에서 나가는 링크들을 찾는다
+ final List nodesFromCurrentNode = linksFromCurrentNode
+ .map((link) => link.fromNode)
+ .toList(); //현재 노드에서 나가는 링크들의 출발 노드를 찾는다
+ final List distancesFromCurrentNode =
+ nodesFromCurrentNode //현재 노드에서 나가는 링크들의 출발 노드까지의 거리를 찾는다
+ .map((nodeId) => double.parse(distances[nodeId] ?? '0.0'))
+ .toList();
+ if (distancesFromCurrentNode.isEmpty) {
+ //현재 노드에서 나가는 링크가 없다면 에러를 띄운다
+ break;
+ }
+ final int shortestNodeIdIndex = distancesFromCurrentNode
+ .indexWhere(//현재 노드에서 나가는 링크들의 출발 노드 중에서 가장 가까운 노드를 찾는다
+ (distance) => distance == distancesFromCurrentNode.reduce(min));
+ final int shortestNodeId =
+ nodesFromCurrentNode[shortestNodeIdIndex]; //가장 가까운 노드의 id를 저장한다
+ final Link shortestLink =
+ linksFromCurrentNode[shortestNodeIdIndex]; //가장 가까운 노드로 가는 링크를 저장한다
+
+ shortestPath.add(shortestLink); //최단 경로에 링크를 추가한다
+ totalDistance += shortestLink.distance; //총 거리에 링크의 거리를 더한다
+
+ currentNode = shortestNodeId; //현재 노드를 가장 가까운 노드로 변경한다
+
+ if (currentNode == endNodeId) break; //현재 노드가 도착 노드라면(도착점을 찾았으면!) 반복문을 빠져나간다
+ }
+
+ shortestPath = shortestPath.reversed.toList(); //최단 경로를 거꾸로 뒤집는다 - 역순이었기 때문
+
+ for (final link in shortestPath) {
+ print('pathId: ${link.linkId} / from ${link.fromNode} -> to ${link.toNode} / dis: ${link.distance}');
+ }
+ print('Total distance: $totalDistance');
+
+ final List result = [
+ totalDistance.toStringAsFixed(1), //총 거리를 소수점 첫째자리까지 문자열로 변환
+ shortestPath //최단 경로를 반환
+ ];
+ return result; //총 거리 [0]double, 최단 경로 [1]List를 반환
+}
+```
+
+최종적으로 링크들의 총 거리와, 경로 리스트들을 반환합니다.
+
+### 5. 프론트에 연결하여 DB로 가져오기
+
+이 데이터들을 네이버 지도 api 코드에 전달합니다.
+
+네이버 지도 api코드를 StatefulWidget로 선언하여 해당 지도 구현 코드에 전달해 줍니다.
+
+네이버 지도 api를 구현하기 위한 dependency는 다음의 것을 사용하였습니다.
+[flutter_naver_map](https://pub.dev/packages/flutter_naver_map)
+
+```dart
+//네이버 지도 api 클래스
+class NaverMapApi extends StatefulWidget {
+ final NLatLng startPointPosition;
+ final NLatLng endPointPosition;
+ final List? naverMapPathData; //네이버 지도에 출력할 경로 데이터
+ final double distance;
+
+ const NaverMapApi({
+ Key? key,
+ required this.startPointPosition,
+ required this.endPointPosition,
+ this.naverMapPathData,
+ required this.distance,
+ }) : super(key: key);
+
+ @override
+ _NaverMapApiState createState() => _NaverMapApiState();
+}
+```
+
+다음은 강의 사이의 경로를 구현하기 위한, 실제로 DB가 넘어가는 코드 부분입니다.
+
+```dart
+//...
+Container(
+ width: MediaQuery.of(context).size.width * 0.9,
+ height: MediaQuery.of(context).size.height* 0.23,
+ child: NaverMapApi(
+ key: ValueKey(pathData),
+ startPointPosition: _model.startPointPosition,
+ endPointPosition:_model.endPointPosition,
+ naverMapPathData: pathData,
+ distance: distance,
+ ),
+),
+//...
+```
+
+네이버지도를 띄우기 위한 container를 만들고, 그곳에 제가 구현한 NaverMapApi 위젯을 구현하였습니다.
+
+### 6. 두 건물 사이의 경로를 네이버 지도 api를 활용하여 표시하기
+
+이렇게 넘어온 DB를 바탕으로 네이버 지도 위에 경로를 그려줍니다.
+이때 출발,도착점의 중간 지점을 지도의 초기 위치로 두었습니다.
+또한 전체 링크 길이에 따라서 Zoom이 결정되도록 하였습니다.
+
+```dart
+//...
+Scaffold(
+ body: NaverMap(
+ options: NaverMapViewOptions(
+ tiltGesturesEnable: false, //지도 기울어짐 false
+ rotationGesturesEnable : false, //지도 회전 false
+ initialCameraPosition: NCameraPosition( // 지도 초기 위치
+ target: NLatLng(midLat, midLng), //출발점과 도착점의 중간지점
+ zoom: zoomNum, //경로 길이에 따라 산출된 zoomNum이 들어감
+ ),
+ ),
+ onMapReady: (controller) async {
+ // 네이버 지도가 로딩되면 마커를 추가함
+ NaverMapController naverMapController = controller;
+ await naverMapController.addOverlay(startMarker);
+ await naverMapController.addOverlay(endMarker);
+ await naverMapController.addOverlay(roads); // 경로를 지도에 추가
+ },
+ ),
+);
+//...
+```
+
+이 코드로 네이버 지도에 출발, 도착 마커 및 경로를 추가하였습니다
+
+### 7. 예상 소요시간을 계산하여 표시
+
+또한 이 코드에는 전체 링크 길이가 전달되는데요.
+이때 예상소요시간을 계산하기 위해, 성인 도보 4km/h 기준으로 예상소요시간을 구하였습니다.
+
+```dart
+// 두 건물 사이의 경로를 구하는 함수
+ Future dijkstra(int startBuildingNum, int endBuildingNum) async {
+
+ final shortestPath = await printShortestPath(startBuildingNum, endBuildingNum);
+ if (shortestPath.isEmpty) {
+ print('해당 건물 간에 경로가 존재하지 않습니다.');
+ return;
+ }
+ print("shortestPath[0] (전체 경로 길이) -> ${shortestPath[0]}"); // 거리
+ print("shortestPath[1] (경로 구성 개수) -> ${shortestPath[1].length}"); // 경로
+ pathData = shortestPath[1];
+
+ final double dijkstraEstimatedTime = double.parse(shortestPath[0]) / 67; // 예상 소요시간을 계산합니다.
+ final int dijkstraEstimatedroundedTime = dijkstraEstimatedTime.round(); // 반올림
+ print('건물 $startBuildingNum번 -> 건물 $endBuildingNum번 - 예상 소요시간: $dijkstraEstimatedroundedTime 분');
+
+
+ setState(() {
+ showEstimatedTime = dijkstraEstimatedroundedTime; // 예상 소요시간을 업데이트합니다.
+ distance = double.parse(shortestPath[0]); // 거리를 표시합니다.
+ pathData = shortestPath[1]; // 경로 정보를 업데이트합니다.
+ }); // 경로가 업데이트됐으므로 화면을 다시 그려줍니다.
+
+ }
+```
+
+위 코드로 예상 소요 시간을 계산하여, 분 단위로 표시하였습니다.
+
+### 8. 마무리
+
+그래서 다음과 같은 화면을 구성하였습니다.
+
+
+
+두 건물 (또는 문) 사이의 경로가 그려지며 예상 소요시간이 정상적으로 출력됨을 확인 할 수 있습니다.
+
+### 마치며
+
+
+
+이렇게 Flutter에서 도보 경로 구현을 완료하였습니다.
+일주일 만에 급하게 구현한 것이라 여러모로 부족한 점들이 있습니다.
+물론 교내에서는 이상 없이 모두 작동이 잘됩니다.
+
+현재 노드, 링크의 수가 많지 않아 지역을 커버하는 해상도가 낮은 편입니다.
+이 부분을 보완하기 위해 DB의 해상도를 올릴 필요가 있습니다.
+
+교내 외로 확장이 필요할 경우 이를 대비한 효율적인 구현이 되어있지는 않습니다.
+저는 데이터 수가 적어서, 어플 자체에 교내 노드, 링크 정보를 csv로 저장하여 그것을 불러오는 방식으로 구현하였습니다.
+
+노드, 링크들이 많아지거나, 추가적인 확장이 경우 이를 필요한 지역별로 구분하는 알고리즘을 추가하여, 불필요한 패킷 통신이나, 메모리 낭비를 줄일 수 있을 것입니다.
+
+또한 서버에 DB를 저장하여 시기에 맞춰 필요한 부분만 전송할 수 있도록 구현이 필요합니다.
+
+적절한 DB를 고르는 로직도 구현해야 해고, 개선해야 할 게 많지만, 앱의 발전에 맞춰서 조금씩 진행해 보려 합니다.
+
+긴 글 읽어주셔서 감사합니다!
+
+#### 관련 링크
+
+[UOScheduler Google Play Store](https://play.google.com/store/apps/details?id=com.mycompany.uoscheduler&pli=1)
+[UOScheduler App Store](https://apps.apple.com/kr/app/uoscheduler/id6448325141)
+[ArcGIS 공식 홈페이지 - Esri Korea](https://www.esrikr.com/products/arcgis/)
+[서울시립대학교 IT help desk](https://cis.uos.ac.kr/ithelpdesk/html/hw-sw/sw-install.do?menuid=1089003003000000000)
diff --git a/assets/images/post-Arcgis-map/8mamuri_cap.jpeg b/assets/images/post-Arcgis-map/8mamuri_cap.jpeg
new file mode 100644
index 0000000000..602f0af107
Binary files /dev/null and b/assets/images/post-Arcgis-map/8mamuri_cap.jpeg differ
diff --git a/assets/images/post-Arcgis-map/navi.png b/assets/images/post-Arcgis-map/navi.png
new file mode 100644
index 0000000000..3efede9c99
Binary files /dev/null and b/assets/images/post-Arcgis-map/navi.png differ
diff --git a/assets/images/post-Arcgis-map/post_cover.png b/assets/images/post-Arcgis-map/post_cover.png
new file mode 100644
index 0000000000..80733a9e1b
Binary files /dev/null and b/assets/images/post-Arcgis-map/post_cover.png differ
diff --git a/assets/images/post-Arcgis-map/uos_arcgis.png b/assets/images/post-Arcgis-map/uos_arcgis.png
new file mode 100644
index 0000000000..63eef43c67
Binary files /dev/null and b/assets/images/post-Arcgis-map/uos_arcgis.png differ