[OSRM] Chat GPT와 함께하는 TSP - 4

2024. 12. 4. 21:59프로그래밍/GIS

728x90

저번 글에서 TSP 를 이용해서 순번을 만들었습니다.

https://tobee.tistory.com/entry/OSRM-vroom%EA%B3%BC-OSRM%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-TSP

이제 만들어진 이 순번을 이용해서 각각 지점별 경로를 생성해 보는 것을 해봐야 겠습니다.

위와 같이 TSP 가 나왔습니다.

nodejs 를 이용해서 만들어 보는 것으로 가닥을 잡아 보겠습니다.

 

1.경로 생성하기

우선 만들어진 output.json 파일을 이용해서 경로를 생성해야 합니다. 이를 route.json 으로 하겠습니다.

const axios = require('axios');
const fs = require('fs');

// OSRM 서버 URL
const osrmUrl = 'http://localhost:5000/route/v1/driving';

// VROOM output.json 경로
const outputJsonPath = 'output.json'; // 실제 경로로 변경
const routeJsonPath = 'route.json'; // 저장할 경로 설정

// OSRM 경로 요청 함수
async function getRouteFromOSRM(coords) {
  const url = `${osrmUrl}/${coords.join(';')}?overview=full&geometries=geojson`;
  try {
    const response = await axios.get(url);
    if (!response.data || !response.data.routes || response.data.routes.length === 0) {
      console.error('OSRM 응답 데이터가 비어 있습니다.');
      return null;
    }
    return response.data.routes[0]; // 첫 번째 경로 반환
  } catch (error) {
    console.error('OSRM 요청 실패:', error.message);
    return null;
  }
}

// VROOM output.json 처리 및 route.json 저장
async function processVroomOutput() {
  try {
    const data = JSON.parse(fs.readFileSync(outputJsonPath, 'utf8'));

    if (!data.routes || data.routes.length === 0) {
      console.error('VROOM output에 경로 정보가 없습니다.');
      return;
    }

    const steps = data.routes[0].steps; // 첫 번째 경로의 steps 가져오기
    const sequence = steps.map(step => step.location); // 좌표 추출

    console.log('경로 계산 및 저장을 시작합니다...');
    const routeData = [];

    for (let i = 0; i < sequence.length - 1; i++) {
      const coords = [sequence[i], sequence[i + 1]].map(loc => loc.join(','));
      const route = await getRouteFromOSRM(coords);
      if (route) {
        routeData.push({
          from: sequence[i],
          to: sequence[i + 1],
          distance: route.legs[0].distance,
          duration: route.legs[0].duration,
          geometry: route.geometry
        });
      }
    }

    // route.json 파일로 저장
    fs.writeFileSync(routeJsonPath, JSON.stringify(routeData, null, 2));
    console.log(`경로 데이터가 ${routeJsonPath}에 저장되었습니다.`);
  } catch (error) {
    console.error('Error processing VROOM output:', error.message);
  }
}

// 실행
processVroomOutput();

 

위 자바스크립트 코드를 실행하기 위해서는 nodejs가 필요 합니다.

다음 파일을 이용해서 nodejs 를 만들었습니다.

node-v22.11.0-win-x64

 

그런 다음, 모듈을 하나 설치해 줍니다.

▶ 이때 주의 할 점은 아래 설치는 위 스크립크가 위치한 곳에 설치해야 한다는 것을 명심하십시오

npm install axios

 

그런 다음 경로 파일을 생성해 보겠습니다.

C:\DEV\GIS\OSRM_exec\TSP>node tsp_route_out_with_step.js
경로 계산 및 저장을 시작합니다...
경로 데이터가 route_step.json에 저장되었습니다.

 

2. 지도 위에 표시 result.json

그럼 leaflet 을 이용해서 지도 상에 표시하는 코드를 작성해 봅니다.

물론 Chat gpt 교수님이 하실 겁니다.

<!DOCTYPE html>
<html>
<head>
  <title>OSRM Routes on Map</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
  <style>
    #map {
      height: 100vh;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
  <script>
    // Leaflet 지도 초기화
    const map = L.map('map').setView([37.497942, 127.027621], 13); // 강남구 중심 좌표

    // OpenStreetMap 타일 레이어 추가
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 19,
    }).addTo(map);

    // route.json 파일 로드
    fetch('route.json')
      .then(response => response.json())
      .then(routeData => {
        routeData.forEach(route => {
          // GeoJSON 경로 추가
          const geoJson = L.geoJSON(route.geometry, {
            style: {
              color: 'blue',
              weight: 3,
              opacity: 0.7
            }
          }).addTo(map);

          // 출발점 마커 추가
          L.marker([route.from[1], route.from[0]]).addTo(map);

          // 도착점 마커 추가
          L.marker([route.to[1], route.to[0]]).addTo(map);
        });

        // 지도 영역 설정
        const bounds = L.latLngBounds(
          routeData.flatMap(route => [
            [route.from[1], route.from[0]],
            [route.to[1], route.to[0]]
          ])
        );
        map.fitBounds(bounds);
      })
      .catch(err => console.error('Error loading route.json:', err));
  </script>
</body>
</html>

 

3. 결과 확인

결과를 확인해 보겠습니다.

728x90