Cesium JS에서 3D 모델 생성하기

오늘은 Cesium JS를 활용하여 3D 모델을 생성해 보도록 하겠습니다.

서비스바로가기


1. 3D 모델을 생성 할 버튼 및 onclick 이벤트 생성


<!DOCTYPE html>
<html lang="en">
<meta charset = "UTF-8">
<head>
    <script src="js/Cesium-1.53/Build/Cesium/Cesium.js"></script>
    <script src="js/jquery/jquery-3.3.1.min.js"></script>
    <link href="js/Cesium-1.53/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer" style="width:auto; height:600px;"></div>
 
<div>
    <h2>3차원 모델 만들기</h2>
    <input type="button" id="boxbutton" value="3D 상자" onclick="makeBox();">
    <input type="button" id="cylinderbutton" value="3D 원기둥" onclick="makeCylinder();">
</div>
 
</body>
</html>
cs


실행 화면은 다음과 같습니다. 


2. body태그 안 script 태그 안에 makeBox 함수 생성


<script type="text/javascript">
    var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
    Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
 
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
    var viewer = new Cesium.Viewer('cesiumContainer',
        {
            timeline : false,
            animation : false,
            selectionIndicator : false,
            navigationHelpButton : false,
            infoBox : false,
            navigationInstructionsInitiallyVisible : false       
        });
    
    // 3D 상자 생성하기
    function makeBox(){
         var box = viewer.entities.add({
                name : 'Box',
                position : Cesium.Cartesian3.fromDegrees(126.92440337.524624255.0), //상자가 생성될 위,경도 및 지면과의 이격(클수록 이격이 큼)
                box : {
                    dimensions : new Cesium.Cartesian3(500.0500.0500.0), // 상자의 크기 설정
                    material : Cesium.Color.WHITE, // 상자의 색 설정
                    outline : false// 외곽선 설정
                    outlinecolor : Cesium.Color.BLACK // 외곽선 색 설정
                }
         }); 
         // 상자 생성 시 확대 함   
         viewer.zoomTo(viewer.entities);
         alert('3D 상자를 생성합니다.');
    }
</script>
</body>
</html>
cs


3D 상자 버튼을 눌렀을 시의 화면 입니다.


3. body태그 안 script 태그 안에 makeCylinder 함수 생성


<script type="text/javascript">
    var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
    Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
 
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
    var viewer = new Cesium.Viewer('cesiumContainer',
        {
            timeline : false,
            animation : false,
            selectionIndicator : false,
            navigationHelpButton : false,
            infoBox : false,
            navigationInstructionsInitiallyVisible : false       
        });
    
     //3D 원기둥 생성하기
    function makeCylinder(){
        var cylinder = viewer.entities.add({
            name : 'Cylinder',
            position : Cesium.Cartesian3.fromDegrees(126.90719537.526650255.0),
            cylinder : {
                length : 490// 원기둥의 길이 설정
                topRadius : 200
                bottomRadius : 200//원기둥의 위,아래 넓이를 설정
                material : Cesium.Color.WHITE,
                outline : false,
                outlinecolor : Cesium.Color.BLACK
            }
        });
        viewer.zoomTo(viewer.entities);
        alert('3D 원기둥을 생성합니다.');
    }
</script>
</body>
</html>
cs


3D 원기둥 버튼을 눌렀을 시의 화면입니다.


전체 소스코드는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<!DOCTYPE html>
<html lang="en">
<meta charset = "UTF-8">
<head>
    <script src="js/Cesium-1.53/Build/Cesium/Cesium.js"></script>
    <script src="js/jquery/jquery-3.3.1.min.js"></script>
    <link href="js/Cesium-1.53/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer" style="width:auto; height:600px;"></div>
<div>
    <h2>3차원 모델 만들기</h2>
    <input type="button" id="boxbutton" value="3D 상자" onclick="makeBox();">
    <input type="button" id="cylinderbutton" value="3D 원기둥" onclick="makeCylinder();">
</div>
<script type="text/javascript">
    var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
    Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
 
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
    var viewer = new Cesium.Viewer('cesiumContainer',
        {
            timeline : false,
            animation : false,
            selectionIndicator : false,
            navigationHelpButton : false,
            infoBox : false,
            navigationInstructionsInitiallyVisible : false       
        });
    
    // 3D 상자 생성하기
    function makeBox(){
         var box = viewer.entities.add({
                name : 'Box',
                position : Cesium.Cartesian3.fromDegrees(126.92440337.524624255.0),
                box : {
                    dimensions : new Cesium.Cartesian3(500.0500.0500.0),
                    material : Cesium.Color.WHITE,
                    outline : false,
                    outlinecolor : Cesium.Color.BLACK
                }
         });     
         viewer.zoomTo(viewer.entities);
         alert('3D 상자를 생성합니다.');
    }
    
    //3D 원기둥 생성하기
    function makeCylinder(){
        var cylinder = viewer.entities.add({
            name : 'Cylinder',
            position : Cesium.Cartesian3.fromDegrees(126.90719537.526650255.0),
            cylinder : {
                length : 490,
                topRadius : 200,
                bottomRadius : 200,
                material : Cesium.Color.WHITE,
                outline : false,
                outlinecolor : Cesium.Color.BLACK
            }
        });
        viewer.zoomTo(viewer.entities);
        alert('3D 원기둥을 생성합니다.');
    }
    
</script>
</body>
</html>
 
cs


완성된 실행화면입니다.

서비스바로가기

CesiumJS에서 OGC Web Service이용하기 

WMS 서비스

서비스바로가기

WFS 서비스

서비스바로가기


CesiumJS 위에 OGC WMS 인터페이스가 제공되는 지도서비스를 Overlay 합니다.

WMS (Web Map Service)는 인터넷을 통해 지도이미지(Raster Image)를 제공하는 서비스 입니다.
WFS (Web Feature Service)는  인터넷을 통해 벡터데이터(Vector Graphics)를 제공하는 서비스 입니다.

참조 : WMS와 WFS의 효율적 사용 (Vector Graphics와 Raster Image의 비교)

                                     

1. WMS 활용하기 

index.html 파일을 생성한 후 아래의 소스코드를 입력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/jquery/jquery-3.3.1.min.js"></script>
    <script src="js/Cesium-1.50/Build/Cesium/Cesium.js"></script>
    <link href="js/Cesium-1.50/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<script type="text/javascript">
    var baseMap, mapViewer;
 
    $(document)
        .ready(
            function() {
                //실행 시 처음 보여질 범위를 설정
                var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
                //처음 보여질 범위 중 거리를 설정
                Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
                Cesium.Camera.DEFAULT_VIEW_FACTOR = 5;
 
                Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
 
                var mapViewer = new Cesium.Viewer(
                    'cesiumContainer',
                    {    // 하단 위젯 제거
                        timeline : false,
                        animation : false,
                        selectionIndicator : false,
                        navigationHelpButton : false,
                        infoBox : false,
                        navigationInstructionsInitiallyVisible : false,
                        vaseLayerPicker : true
                    }
);
 
                var wms = new Cesium.WebMapServiceImageryProvider({
                    // 제작한 국가지점번호 데이터 가져오기
                    url: 'http://***.***.***.***/geoserver/progworks/wms',
                    parameters: {
                        format:'image/png',
                        transparent:'true'
                    },
                    layers : 'progworks:national_point_num_5179_to_4326',
                    maximumLevel : 12
                });
                // 가져온 데이터 올리기 
                var imageryLayers = mapViewer.imageryLayers;
                imageryLayers.addImageryProvider(wms);
 
            })
</script>
<body>
<div id="cesiumContainer" style="width: 100%; height: 710px"></div>
</body>
</html>
cs


geoserver에서 자체 제작한 국가지점번호 레이어를 불러옵니다. 

var wms = new Cesium.WebMapServiceImageryProvider({
                    // 제작한 국가지점번호 레이어 가져오기
                    url: 'http://***.***.***.***/geoserver/progworks/wms',
                    parameters: {
                        format:'image/png',
                        transparent:'true'
                    },
                    layers : 'progworks:national_point_num_5179_to_4326',
                    maximumLevel : 12
                });
                // 가져온 데이터 올리기 
                var imageryLayers = mapViewer.imageryLayers;
                imageryLayers.addImageryProvider(wms);
 


프로젝트를 실행합니다.  

서비스바로가기


2. WFS 활용하기

* GeoServer 에서 자체 제작한 국가지점번호 레이어를 가져옵니다. GeoJson 형식으로 레이어를 사용했습니다.
  line 36을 아래와 같이 변경합니다.

// 제작한 국가지점번호 레이어 가져오기 
mapViewer.dataSources.add(Cesium.GeoJsonDataSource.load('http://*.***.**.***:8180/geoserver/progworks/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=progworks:national_point_num_5179_to_4326&outputFormat=application/json', {
    // 선 색을 설정
    stroke: Cesium.Color.WHITE,
    // 선의 두께 설정
    strokeWidth: 5
}));                         
cs

* 프로젝트를 실행합니다. 



Cesium JS 시작하기

Node JS 환경 

서비스바로가기

ApacheTomcat 환경

서비스바로가기


* CesiumJS 란? 

플러그인없이 웹 브라우저에서 3D지도를 만들기위한 오픈소스 JavaScript 라이브러리 입니다. 


* CesiumJS 시작하기

1. 가입하기

 CesiumJS를 이용하기 위해서는 먼저 Cesium ion에 가입을 하여야 합니다. (AccessToken 발급)

  -> Cesium ion 바로가기


1. Node JS 환경에서 Cesium JS 활용하기

* Express 프레임워크 활용하기

Node JS의 모듈 중 Express 프레임워크를 기반으로 작업을 진행하겠습니다.

Express를 사용하는 이유는 대중적이고 인기가 많을뿐만아니라 소스코드의 간소화로 인해 향후 유지보수를 쉽게 하기 위함입니다.


기본 서버 구성하기

  1. server라는 이름의 js 파일을 생성합니다.

  2. 아래의 소스코드를 입력합니다. (콘솔과 웹상에 Hello Cesium이라는 문구를 표출하여 확인을 해봅니다.) 

1
2
3
4
5
6
7
8
9
10
const express = require('express');
const app = express();
 
app.use('/'function (req, res) {
    res.send("Hello Cesium");
});
 
app.listen(8080function () {
    console.log("Hello Cesium");
});
cs

node 서버를 실행시킨 후 콘솔과 웹상에 아래와 같이 표출된다면 서버구성 성공입니다!

웹상에 표출할 HTML 구성하기

  1. 먼저 html이라는 이름의 폴더를 생성합니다.

  2. html 폴더안에 testmap이라는 이름의 html파일을 생성합니다.

  3. 아래의 소스코드를 입력합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$(function(){
    var baseMap, mapViewer;
 
    var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
    Cesium.Camera.DEFAULT_VIEW_FACTOR =0.7;
 
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
 
    var mapViewer = new Cesium.Viewer(
        'cesiumContainer',
        {
            timeline : false,
            animation : false,
            selectionIndicator : false,
            navigationHelpButton : false,
            infoBox : false,
            navigationInstructionsInitiallyVisible : false,
 
            imageryProvider : Cesium
                .createOpenStreetMapImageryProvider({
                    url : 'https://a.tile.openstreetmap.org/'
                }),
 
            baseLayerPicker :true
        });
});
cs

server.js와 testmap.html 연결하기

1. server.js의 코드를 아래와 같이 변경하여 줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var express = require('express');
var app = express();
var path = require('path');
 
app.use(express.static(path.join(__dirname, 'html')));
 
app.get('/'function (req,res) {
    res.sendFile(path.join(__dirname, 'html''testmap.html'));
});
 
app.use('/'function (req, res) {
    res.send("Hello Cesium");
});
 
app.listen(8081function () {
    console.log("Hello Cesium");
});
cs

html과 같은 정적 파일을 제공하기위한 소스코드

1
app.use(express.static(path.join(__dirname, 'html')));
cs

웹상에 표출할 html파일을 바라보기위한 소스코드 

1
2
3
app.get('/'function (req,res) {
    res.sendFile(path.join(__dirname, 'html''testmap.html'));
});
cs

최초 시작 시 web에 표출될 지역의 범위와 높이를 설정

1
2
3
4
var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
cs


Open Street Map을 불러옵니다.  

1
2
3
imageryProvider : Cesium.createOpenStreetMapImageryProvider({
                    url : 'https://a.tile.openstreetmap.org/'
                }),
cs

* Tip - baseLayerPicker : true 하면 오른쪽 상단 메뉴에 베이스레이어를 선택하는 버튼이 생성됩니다.

* Tip - 세슘 Rectangle document 정보 https://cesiumjs.org/Cesium/Build/Documentation/Rectangle.html

staticCesium.Rectangle.fromDegrees(westsoutheastnorthresult) → Rectangle

Creates a rectangle given the boundary longitude and latitude in degrees.
NameTypeDefaultDescription
westNumber0.0optionalThe westernmost longitude in degrees in the range [-180.0, 180.0].
southNumber0.0optionalThe southernmost latitude in degrees in the range [-90.0, 90.0].
eastNumber0.0optionalThe easternmost longitude in degrees in the range [-180.0, 180.0].
northNumber0.0optionalThe northernmost latitude in degrees in the range [-90.0, 90.0].
resultRectangleoptionalThe object onto which to store the result, or undefined if a new instance should be created.
Returns:

The modified result parameter or a new Rectangle instance if none was provided. 


소스코드 구성을 마쳤으니 실행해보도록 하겠습니다. 

서비스바로가기



2. Apache Tomcat 환경에서 Cesium JS 활용하기

필자는 Eclipse IDE를 활용하여 작업을 진행하였습니다.


Cesium JS 다운받기 

해당 사이트로 접속하여 Cesium JS를 다운받습니다. (https://cesiumjs.org/downloads/)


프로젝트 생성하기

Dynamic Web Projcet를 이용하여 프로젝트를 생성합니다. 


Apache Tomcat 서버 구성하기 (Apache-tomcat Download)

톰캣 사이트에 들어가 본인 운영체제 환경에 맞게 다운로드를 합니다.


서버 구성 순서 ( Window -> Preferences -> Server -> Runtime Enviroments -> Add -> Next -> Finish) 


HTML 구성하기 

기본적인 HTML 구성 후 로컬상에서 서버를 실행하여 제대로 구동되는지 확인해보겠습니다.

start라는 이름의 html파일을 생성 후 아래의 소스코드를 입력합니다.

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<h1>Hello Cesium</h1>
</body>
</html>
cs

사진과 같이 작동되는것을 확인할 수 있습니다.


다운받은 Cesium JS 파일 업로드 하기 

다운받은 Cesium JS 폴더를 압축 해제 후 WebContent 디렉토리 하단 또는 본인 임의의 디렉토리 내부로 이동시킵니다.


Cesium JS 활용하기 

앞서 기본적으로 구성하였던 start.html의 소스코드를 아래와 같이 교체합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<meta charset = "UTF-8">
<head>
    <script src="js/Cesium-1.50/Build/Cesium/Cesium.js"></script>
    <link href="js/Cesium-1.50/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer" style="width:100%; height:710px"></div>
<script type="text/javascript">
    var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
    Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
 
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkOGMxZjMzNy01N2FkLTQ3YTctODU0NS05NGY0MmE3MGJiOWEiLCJpZCI6NjExNywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0NTI3OTE3NH0.6VdcqK6vL7faWx_vYkkOuNNa8dapTn1geCi7qYBhGCw';
    var viewer = new Cesium.Viewer('cesiumContainer',
        {
            timeline : false,
            animation : false,
            selectionIndicator : false,
            navigationHelpButton : false,
            infoBox : false,
            navigationInstructionsInitiallyVisible : false,
            
            imageryProvider : Cesium.createOpenStreetMapImageryProvider({
                url : 'http://a.tile.openstreetmap.org/'
            }),
            
            baseLayerPicker : true
        });
</script>
</body>
</html>
 
cs


서버와 소스코드 구성을 완료 하였으니 실행해보도록 하겠습니다.

서비스바로가기

+ Recent posts