[DB 생성]
전 게시물에서 작성한 DB를 추가했다.
[SQL]
-- 데이터베이스 생성
-- CREATE 테이블명;
-- 데이터베이스 사용
-- USE 테이블명;
-- 사용자 테이블 생성
CREATE TABLE `user` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NULL,
`password` VARCHAR(255) NULL,
`email` VARCHAR(255) NULL,
`create` DATETIME,
`update` DATETIME
);
-- 차량 동작 로그 테이블 생성
CREATE TABLE `operation` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`date` DATE NULL,
`time` TIME NULL,
`content` TEXT NULL,
`location` VARCHAR(255) NULL
);
-- 음성 테이블 생성
CREATE TABLE `voice` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`text` TEXT NULL,
`voice` TEXT NULL,
`read` VARCHAR(255) NULL
);
-- 경로 테이블 생성
CREATE TABLE `route` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`current_point` VARCHAR(255) NULL,
`start_point` VARCHAR(255) NULL,
`end_point` VARCHAR(255) NULL,
`locations` LONGTEXT NULL,
`distance` VARCHAR(255) NULL,
`route_time` INT NULL,
`all` LONGTEXT NULL
);
-- 교통 정보 테이블 생성
CREATE TABLE `traffic` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`date` DATE NULL,
`time` TIME NULL,
`start_point` VARCHAR(255) NULL,
`end_point` VARCHAR(255) NULL,
`content` TEXT NULL,
`rank` INT NULL
);
-- 설정 테이블 생성
CREATE TABLE `set` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`transport` INT NULL,
`toll` INT NULL,
`highway` INT NULL
);
-- POI 테이블 생성
CREATE TABLE `poi` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`location` VARCHAR(255) NULL,
`name` VARCHAR(255) NULL,
`content` TEXT NULL,
`category` VARCHAR(255) NULL,
`hour` VARCHAR(255) NULL,
`type` INT NULL
);
-- 알림 테이블 생성
CREATE TABLE `alert` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`date` DATE NULL,
`time` TIME NULL,
`content` TEXT NULL,
`read` VARCHAR(255) NULL,
`location` VARCHAR(255) NULL,
`rank` INT NULL
);
-- 목록 테이블 생성
CREATE TABLE `list` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`user` INT NULL,
`question` TEXT NULL,
`result` TEXT NULL
);
-- 마크 테이블 생성
CREATE TABLE `mark` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`start_point` VARCHAR(255) NULL,
`end_point` VARCHAR(255) NULL,
`content` TEXT NULL
);
[수동 노드 확인 코드]
데이터베이스에 경로를 저장하기 위해 경로의 노드를 확인해보자 (길 안내 노드만 추가함)
아래는 모든 경로를 마커로 찍어보는 노드 확인용 코드이다.
노드를 수동으로 추가해서 위치를 확인할 수 있다.
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/db/db.php");
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>노드 확인용</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
#map {
height: 600px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
// 지도 초기화
var map = L.map('map').setView([35.85799, 128.46495], 13); // 중심 좌표 설정
// OpenStreetMap 타일 레이어 추가
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);
// 노드를 추가하는 부분
var nodes = [
[35.85799, 128.46495],
[35.85858, 128.46433],
[35.85266, 128.48114],
[35.85323, 128.47743]
];
// 노드 마커 표시
nodes.forEach(function(node) {
L.marker(node).addTo(map);
});
</script>
</body>
</html>
이동할 경로가 잘 찍혀있는 것을 볼 수 있다!
이제 위 코드에 추가해서 내비게이션 같은 모양새를 좀 내보도록 하자.
일단 내비게이션에 들어가면 보통 길 찾기 기능을 제공한다.
[길찾기 UI 추가, 현 위치 띄워주기]
길찾기를 할 수 있도록 윗부분에 출발지와 도착지를 입력할 수 있는 칸을 두고
출발지와 도착지를 바꾸는 버튼, 현 위치를 넣는 버튼을 추가했다. (이건 나중에 만들자)
초기 위치는 현재 위치로 띄워주고, 출발지에는 현재 위치를 넣어주었다.
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/h/db/db.php");
$user_id = $_SESSION['id'];
$sql = "SELECT * FROM `route` WHERE `id` = " . $user_id . "";
$user_id;
$res = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($res);
($row['current_point'] != null) ? $current_point = $row['current_point'] : $current_point = '1';
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>노드 확인용</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="/h/css/index.css">
</head>
<body>
<div id="popup">
<div class="search_left">
<button class="btn btn_change" onclick="">↑↓</button>
</div>
<div class="search">
<input type="text" id="start" placeholder="출발지 입력" value='<?php echo $current_point; ?>'>
<input type="text" id="end" placeholder="도착지 입력">
</div>
<div class="search_right">
<button class="btn btn_current" onclick="test()">현위치</button>
<button class="btn btn_search" onclick="getRoute()">찾기</button>
</div>
</div>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
//current_value --> 위도, 경도 (문자열 형식)
var current_value = document.getElementById('start').value;
//current_point --> [위도, 경도] (배열로 변환)
var current_point = current_value.split(',').map(Number); // 문자열을 배열로 변환하고 숫자로 변환
// 지도 초기화
var map = L.map('map').setView(current_point, 13); // 지도의 맨 처음 위치 설정
// OpenStreetMap 타일 레이어 추가
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);
// 노드를 추가하는 부분
var nodes = [
[35.85799, 128.46495],
[35.85858, 128.46433],
[35.85266, 128.48114],
[35.85323, 128.47743]
];
// 노드 마커 표시
nodes.forEach(function(node) {
L.marker(node).addTo(map);
});
</script>
</body>
</html>
[길찾기 기능 추가]
다음으로는 사용자가 출발지와 도착지를 입력하면 경로를 찾아주는 기능을 넣어보자.
[HTML 코드] (CSS는 이전 게시물의 CSS와 동일하다)
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/h/db/db.php");
$user_id = $_SESSION['id'];
$sql = "SELECT * FROM `route` WHERE `id` = " . $user_id . "";
$user_id;
$res = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($res);
($row['current_point'] != null) ? $current_point = $row['current_point'] : $current_point = '1';
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>노드 확인용</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.css" />
<link rel="stylesheet" href="/h/css/index.css">
</head>
<body>
<div id="popup">
<div class="search_left">
<button class="btn btn_change" onclick="">↑↓</button>
</div>
<div class="search">
<input type="text" id="start" placeholder="출발지 입력" value='<?php echo $current_point; ?>'>
<input type="text" id="end" placeholder="도착지 입력">
</div>
<div class="search_right">
<button class="btn btn_current" onclick="test()">현위치</button>
<button class="btn btn_search" onclick="getRoute()">찾기</button>
</div>
</div>
<div id="map"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-routing-machine/dist/leaflet-routing-machine.js"></script>
<script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
<script>
//current_value --> 위도, 경도 (문자열 형식)
var current_value = document.getElementById('start').value;
//current_point --> [위도, 경도] (배열로 변환)
var current_point = current_value.split(',').map(Number); // 문자열을 배열로 변환하고 숫자로 변환
// 지도 초기화
var map = L.map('map').setView(current_point, 13); // 지도의 맨 처음 위치를 현위치로 설정
// OpenStreetMap 타일 레이어 추가
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);
// // 노드를 추가
// var nodes = [
// [35.85799, 128.46495],
// [35.85858, 128.46433],
// [35.85266, 128.48114],
// [35.85323, 128.47743]
// ];
// // 노드 마커 표시
// nodes.forEach(function(node) {
// L.marker(node).addTo(map);
// });
map.on('locationfound', function(e) {
marker.setLatLng(e.latlng);
map.setView(e.latlng, 16);
closePopup(); // 위치가 발견되면 팝업 닫기
});
map.on('locationerror', function(e) {
alert(e.message);
});
var control = L.Routing.control({
waypoints: [],
routeWhileDragging: true,
geocoder: L.Control.Geocoder.nominatim(),
createMarker: function() {
return null;
} // 기본 마커 비활성화
}).addTo(map);
//길찾기 팝업 숨기기 !!
control.getContainer().style.display = 'none';
// 경로 찾기 함수
function getRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
if (start && end) {
// Geocoding을 통해 위치를 찾기
L.Control.Geocoder.nominatim().geocode(start, function(results) {
if (results.length > 0) {
var startLatLng = results[0].center;
L.Control.Geocoder.nominatim().geocode(end, function(results) {
if (results.length > 0) {
var endLatLng = results[0].center;
// 출발지와 도착지 설정
control.setWaypoints([
L.latLng(startLatLng.lat, startLatLng.lng),
L.latLng(endLatLng.lat, endLatLng.lng)
]);
// 경로 정보 요청
control.on('routesfound', function(e) {
var routes = e.routes;
// 모든 노드 불러오기 !!
var all = routes[0].coordinates.map(coord => `"${coord.lat}, ${coord.lng}"`).join(',');
var distance = routes[0].summary.totalDistance;
var routeTime = routes[0].summary.totalTime;
// 경로 안내 정보를 필터링하여 인덱스 번호 추출 --> 인덱스를 숫자 배열로 변환
var index = routes[0].instructions.map(instruction => instruction.index);
// 인덱스를 사용해 해당 위도와 경도를 배열로 반환
var locations = index.map(index => {
var coord = routes[0].coordinates[index];
return coord ? `${coord.lat}, ${coord.lng}` : null; // coord가 존재할 경우에만 반환
}).filter(coord => coord !== null); // null 값 제거
});
} else {
alert('도착지를 찾을 수 없습니다.');
}
});
} else {
alert('출발지를 찾을 수 없습니다.');
}
});
} else {
alert('출발지와 도착지를 모두 입력하세요.');
}
}
</script>
</body>
</html>
[결과 화면]
[경로 데이터 DB 저장]
경로 정보를 요청한 후 데이터베이스에 업데이트 해줄 것이므로 경로 정보 요청 마지막에 아래 코드를 넣는다.
// 경로 정보 요청
control.on('routesfound', function(e) {
var routes = e.routes;
// 모든 노드 불러오기 !!
var all = routes[0].coordinates.map(coord => `"${coord.lat}, ${coord.lng}"`).join(',');
var distance = routes[0].summary.totalDistance;
var routeTime = routes[0].summary.totalTime;
// 경로 안내 정보를 필터링하여 인덱스 번호 추출 --> 인덱스를 숫자 배열로 변환
var index = routes[0].instructions.map(instruction => instruction.index);
// 인덱스를 사용해 해당 위도와 경도를 배열로 반환
var locations = index.map(index => {
var coord = routes[0].coordinates[index];
return coord ? `${coord.lat}, ${coord.lng}` : null; // coord가 존재할 경우에만 반환
}).filter(coord => coord !== null); // null 값 제거
// AJAX 요청으로 데이터베이스 업데이트
updateDatabase(routes, start, end, locations, distance, routeTime, index, all);
});
SCRIPT 코드 하단에는 데이터를 PHP파일로 전송하는 코드를 넣어준다.
콘솔에서 들어갈 데이터를 확인할 수 있다.
// 데이터베이스 업데이트 함수
function updateDatabase(routes, start, end, locations, distance, routeTime, index, all) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "update_route.php", true);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log('데이터베이스 업데이트 성공:', xhr.responseText);
} else {
console.error('업데이트 실패:', xhr.status, xhr.statusText);
}
}
};
xhr.send(JSON.stringify({
// current_point: marker.getLatLng().lat + ',' + marker.getLatLng().lng,
start_point: start,
end_point: end,
locations: JSON.stringify(locations).slice(1, -1),
distance: distance,
route_time: routeTime,
all,
all
}));
console.log(routes);
console.log(index);
console.log(all);
console.log(JSON.stringify(locations).slice(1, -1));
}
[update_route.php]
<?php
include($_SERVER['DOCUMENT_ROOT'] . "/h/db/db.php");
// JSON 형식의 POST 데이터 읽기
$data = json_decode(file_get_contents("php://input"), true);
// 로그 파일에 데이터 기록
file_put_contents('log.txt', print_r($data, true), FILE_APPEND);
// POST 데이터 받기
$user_id = $_SESSION['id'];
$current_point = $data['current_point'];
$start_point = $data['start_point'];
$end_point = $data['end_point'];
$locations = $data['locations'];
$distance = $data['distance'];
$route_time = (int)$data['route_time'];
$all = $data['all'];
// 먼저 ID가 1인 레코드가 존재하는지 확인
$sql_check = "SELECT * FROM `route` WHERE `id` = '" . $user_id . "'";
$result = $conn->query($sql_check);
if ($result->num_rows > 0) {
$sql_up = "UPDATE `route` set
`user` = '" . $user_id . "',
`start_point` = '" . $start_point . "',
`end_point` = '" . $end_point . "',
`locations` = '" . $locations . "',
`distance` = '" . $distance . "',
`route_time` = '" . $route_time . "',
`all` = '" . $all . "'
WHERE id= '" . $user_id . "'
";
$res_up = mysqli_query($conn, $sql_up);
if ($res_up) {
echo "업데이트 성공";
} else {
echo "업데이트 실패: " . mysqli_error($conn);
}
} else {
// ID가 1인 레코드가 없을 경우 새 레코드 생성
$sql_in = "INSERT INTO `route`
(
`user`,
`start_point`,
`end_point`,
`locations`,
`distance`,
`route_time`,
`all`
)
VALUES
(
'" . $user_id . "',
'" . $start_point . "',
'" . $end_point . "',
'" . $locations . "',
'" . $distance . "',
'" . $route_time . "',
'" . $all . "'
)
';
";
$res_in = mysqli_query($conn, $sql_in);
if ($res_in) {
echo "생성 성공";
} else {
echo "생성 실패: " . mysqli_error($conn);
}
}
$conn->close();
[결과 화면]
'Project > 내비게이션' 카테고리의 다른 글
[OSM] 내비게이션 어플리케이션 개발 (1) (1) | 2024.09.23 |
---|---|
[OSM]OpenStreetMap을 이용한 내비게이션 만들기 - 4 (1) | 2024.09.20 |
[OSM]OpenStreetMap을 이용한 내비게이션 만들기 - 3 (16) | 2024.09.19 |
[OSM]OpenStreetMap을 이용한 내비게이션 만들기 - 1 (2) | 2024.09.09 |