Cesium JS에서 User Control 구현하기

이번시간에는 Cesium JS에서 User Controll을 구현하는 시간을 가져보도록 하겠습니다.

기능을 구현하여 라인과 폴리곤을 생성해보도록 하겠습니다.

 

먼저 결과 화면부터 확인하세요.

서비스바로가기

 

* 구현을 위해 작성한 소스코드입니다.

 
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
 
handler.setInputAction(function(event) {
    var earthPosition = viewer.scene.pickPosition(event.position);
        
        if (Cesium.defined(earthPosition)) {
            if (activeShapePoints.length === 0) {
                floatingPoint = createPoint(earthPosition);
                activeShapePoints.push(earthPosition);
                var dynamicPositions = new Cesium.CallbackProperty(function () {
                    return activeShapePoints;
                }, false);
                activeShape = drawShape(dynamicPositions);
            }
            activeShapePoints.push(earthPosition);
            createPoint(earthPosition);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
cs

EventHandler를 위한 handler 변수를 지정하였습니다.

마우스 좌클릭 이벤트를 통해 shape를 그릴 position을 지정합니다. 

 

 
handler.setInputAction(function(event) {
        if (Cesium.defined(floatingPoint)) {
            var newPosition = viewer.scene.pickPosition(event.endPosition);
            if (Cesium.defined(newPosition)) {
                floatingPoint.position.setValue(newPosition);
                activeShapePoints.pop();
                activeShapePoints.push(newPosition);
            }
        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
cs

mouse move 이벤트로 포인트와 포인트 간 shape이 생성될 수 있게끔 하였습니다.

 

 
handler.setInputAction(function(event) {
        terminateShape();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
cs

마우스 우클릭 이벤트를 통해 shape 그리기를 종료하고 새로운 shape를 생성할 수 있게끔 하였습니다. 

 

shape 그리기를 종료하고 새로운 shape를 그리기 위해 아래와 같은 function을 구현하였습니다.

 
function terminateShape() {
        activeShapePoints.pop();
        drawShape(activeShapePoints);
        viewer.entities.remove(floatingPoint);
        viewer.entities.remove(activeShape);
        floatingPoint = undefined;
        activeShape = undefined;
        activeShapePoints = [];
    }
cs

생성되고있던 shape와 찍혀있던 point를 remove함수로 삭제하였습니다. 

 

아래는 포인트와 포인트를 통해 생성되는 Line과 Polygon에 대한 function 입니다.

 
// 포인트 생성 
    function createPoint(worldPosition) {
        var point = viewer.entities.add({
            position : worldPosition,
            point : {
                color : Cesium.Color.RED,
                pixelSize : 10,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
            }
        });
        return point;
    }
 
// 라인과 폴리곤 생성
    function drawShape(positionData) {
        var shape;
        if (drawingMode === 'line') {
            shape = viewer.entities.add({
                polyline : {
                    positions : positionData,
                    clampToGround : true,
                    width : 3
                }
            });
        }
        else if (drawingMode === 'polygon') {
            shape = viewer.entities.add({
                polygon: {
                    hierarchy: positionData,
                    material: new Cesium.ColorMaterialProperty(Cesium.Color.AQUA.withAlpha(0.15))
                }
            });
        }
        return shape;
    }
cs

포인트 생성을 위한 function 내에 point 옵션값 중 heightReference: Cesium.HeightReference.CLAMP_TO_GROUND 옵션은

포인트가 TerrainMap(지형형상 지도)를 인식하여 평면이 아닌 Terrain에 맞게 움직일 수 있게끔 하는 옵션입니다.

물론 라인과 폴리곤도 Terrain에 맞추어 그려집니다.

 

다음은 실행화면 입니다.

처음 실행화면 입니다. 서울 지역 중 평지와 산지가 공존하는 지역을 선정하였습니다.

 

라인과 폴리곤을 선택할 수 있는 select Box를 구현하였습니다.

각 option을 통해 라인과 폴리곤을 생성할 수 있습니다.

 

먼저 라인 그리기를 통해 라인을 그리는 모습입니다.

일직선으로 라인을 생성했지만 사진과 같이 선이 울퉁불퉁한 것을 느끼실 수 있을겁니다.

 

라인이 생성될 때 Terrain에 맞춰 생성되었기 때문이죠

 

폴리곤 또한 마찬가지 입니다.

폴리곤도 각 면이 울퉁불퉁하게 보입니다.

 

폴리곤도 Terrain에 맞춰 생성되었습니다.

 

shape를 만들었으니 삭제하는 기능도 있어야겠죠?

라인 그리기와 폴리곤 그리기로 shape를 생성한 후 화면정리를 선택하면 생성하였던 shape가 삭제됩니다.

select Box 안에 화면정리 기능도 넣어두었습니다.

 

화면정리를 선택하여 shape들을 삭제한 모습입니다.

 

Cesium JS에서 Camera FlyTo 기능 활용하기

이번 시간에는 FlyTo기능을 활용하여 대한민국 곳곳을 탐방하는 시뮬레이션을 구현해보도록 하겠습니다.

 * 본 게시물은 3D 모델들이 적용되어있습니다. 독자분들이 이와 같은 개발을 진행하시거나 둘러보실때에는 고사양의 PC를 활용하심이 훨씬 좋습니다.

   특히 그래픽카드가 고사양일 록 원활한 진행이 가능합니다.

 

먼저 결과 화면부터 확인하세요.

서비스바로가기

 

* Camera FlyTo에 대한 설명은 아래와 같습니다. (CesiumDocument 바로가기)

카메라가 기존 위치에서 새로운 위치로 비행한다 라는 설명을 하고있습니다. 

 

* 위 설명을 토대로 구현된 예제 소스코드 입니다.

* 첫번째 예제는 해당 위치로 비행하여 내려다 보겠다는 의미입니다. 

* 두번째 예제는 해당 위치를 정하지 않고 범위를 지정하여 그 범위를 내려다 보겠다는 의미입니다.

* 세번째 예제는 카메라가 지정 위치로 비행하기 위해 orientation을 활용하게 되고 direction과 up 옵션을 사용합니다.

   - 간략히 설명해 두 옵션을 이용해 카메라의 방향과 위치를 지정하는 것입니다.

* 네번째 예제는 orientation에 heading, pitch, roll 값을 지정하여 카메라의 각도와 방향을 지정하는 것입니다. 

 

=> 필자는 본 게시물(시뮬레이션)을 구현하기 위해 1번과 4번 예제를 참조하였습니다.

 

* 구현을 위해 사용한 소스코드

필자는 시뮬레이션 구현을 위해 아래와 같은 소스코드를 적용시켰습니다. 간단합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function tour(){
    setTimeout(function(){
        viewer.scene.camera.flyTo({
            destination : Cesium.Cartesian3.fromDegrees(127.78675436.643957600000.0)
        });
    },2000);
    
    setTimeout(function(){
        viewer.scene.camera.flyTo({
            destination : Cesium.Cartesian3.fromDegrees(128.07592933.014948500000.0),
            orientation : {
                heading : Cesium.Math.toRadians(0),
                pitch : Cesium.Math.toRadians(-420),
                roll : Cesium.Math.toRadians(0)
            }
        }); 
    },7000);
}
cs

setTimeout함수 내에 위에 설명하였던 flyTo 함수를 사용하였습니다. 

setTimeout은 시간지연함수로써 지정된 시간이 되었을 때, 실행이되게끔 하는 함수입니다. 

 

* 시뮬레이션 구현을 위한 사전준비

시뮬레이션 전, 필자는 시뮬레이션의 View를 위해 3D건물 모델과 DEM모델을 제작하였습니다. 

(각 모델들을 구현하기 위해 사용한 원천 데이터는 전부 "국가공간정보포털"에서 취득하였음을 알립니다.)

3D건물은 여의도와 성남시에, DEM모델은 제주도에 배치하였습니다.

아래 게시물 바로가기를 통해 각 제작방법을 살펴보시길 바랍니다.

1. Cesium Js와 Qgis를 활용한 3D 건물 구현하기

   > 바로가기

2. DEM - 국가공간정보포털 DEM 자료 활용하기 

   > 바로가기

 

* 구현된 시뮬레이션 확인

시작 화면의 모습입니다. 하단 둘러보기 버튼을 클릭하여 시뮬레이션을 시작할 수 있습니다.

 

시뮬레이션의 순서는 대한민국에서 출발하여 성남시, 여의도, 제주도, 마지막으로 최초 위치로 돌아오게 됩니다.

* 대한민국 전체를 살펴보는 모습입니다.

 


* 성남시를 살펴보는 모습입니다. 사진과 같이 3D 모델로 구현된 건물들을 볼 수 있습니다.

 

* 여의도를 살펴보는 모습입니다.

 

* 제주도를 살펴보는 모습입니다. 제주도에는 필자가 직접 제작한 DEM모델을 적용시켰습니다.

Cesium JS를 활용한 운석 낙하 시뮬레이션 

이번 시간에는 Cesium JS를 활용하여 운석 낙하 시 피해 반경을 시뮬레이션 하겠습니다.

운석 낙하는 전 세계에서 가끔 일어나는 자연현상 입니다.  과거 2013년 러시아 첼랴빈스크 지역에 운석이 낙하하여 1600여명이 부상당하고 원화 기준으로 약 350억 원의 피해가 발생 했습니다.  떨어진 운석의 크기는 직경17m, 무게 1만 톤으로 추정되었고 대기권 돌입시 추정 속도는 초속 32.5km이었습니다. 

또한 2014년 03월 경상남도 진주시에 운석이 낙하 중 폭발하였고 그 조각들이 다음날로부터 발견된 사례가 있었습니다. 

<러시아 첼랴빈스크 지역에 운석이 낙하 중인 모습과 발견된 운석의 일부 (출처-Google image검색)>

<경남 진주시에 운석 조각이 낙하중인 모습과 발견된 운석 조각 (출처-Google image검색)>

이러한 사례와 참고자료를 발판삼아 가상으로 운석이 낙하하여 충돌할 시 피해 반경을 가늠하여 보았습니다.  

샘플 프로그램 제작 당시 여의도 지역을 운석 낙하 지점으로 설정했습니다. 막상 만들고 보니 저희 나라에 운석이 떨어지는 것이 별로 좋지 않더라구요. 그래서 일본의 모 지역으로 낙하 지점을 변경했습니다. 정확한 시뮬레이션도 아니고 그저 CesiumJS를 활용하는 한 가지 사례로써 어떤 의도가 존재하지도 않습니다.

먼저 결과화면 보겠습니다.

서비스바로가기

운석은 50m급, 100m급 두 등급으로 정했습니다. 각 등급에 근접한 피해 반경을 구하기 위해 여러가지 공식과 참고자료를 활용했습니다. 하지만 참고자료 또한 추정치여서 실제와는 차이가 있습니다.
우주환경 감시기관(한국천문연구원)에서 참고한 운석의 크기와 그에 따른 충돌에너지에 대한 자료입니다.


(출처 - 우주환경 감시기관)

운석 시작 높이는 지상 100km로 설정했습니다. 대부분의 유성 및 운석이 고도 80~100km 부분 열권에서 연소가 되며 연소되지못한 운석들이 지구로 추락합니다. 

낙하속도 산출은 자유낙하 속도 공식을 활용했습니다. (v: 속도 / g: 중력가속도 / t: 시간 / s: 높이) 

 

 

시뮬레이션

시뮬레이션은 총 3단계로 진행 됩니다. 

단계1. 운석 시뮬레이션 버튼을 클릭하여 시뮬레이션 시작
단계2. 운석이 지면에 추락한 후 피해반경 표출
단계3. 피해반경 전체를 가시화

먼저 시뮬레이션 동작을 위한 버튼입니다. 50m, 100m급 시뮬레이션 버튼으로 시뮬레이션을 진행 할 수 있으며 RESET버튼으로 각 시뮬레이션을 마친 후 맵을 초기화 할 수있습니다. (하나의 시뮬레이션 진행 후 RESET기능을 통해 맵을 초기화 하세요.)

 

50m급 시뮬레이션 장면입니다. (50m급의 피해 반경은 약 11km 입니다.)

 

운석이 낙하 지점을 향해 추락하는 모습입니다.

 

 

운석이 낙하지점에 추락 후 피해반경이 표출 된 모습입니다. (50m급 운석)

 

운석 피해 반경 전체를 볼 수 있게 가시화 된 모습입니다. 100m급 시뮬레이션 장면입니다. (100m급의 피해 반경은 약 1.100km입니다.) 

 

 

프로그램 소스

시작점과 도착점을 지정하여 운석이 움직일 수 있도록 하였습니다. 이번 시뮬레이션의 기초 및 핵심이 되는 부분입니다.

 
/*  
 pos1 - 출발점 지정
 pos2 - 도착점 지정
 */
var pos1 = Cesium.Cartesian3.fromDegrees(126.50874937.369581100000.0);
var pos2 = Cesium.Cartesian3.fromDegrees(126.91362037.5192960.0);
var position = new Cesium.SampledPositionProperty();
 
position.addSample(start, pos1);
position.addSample(stop, pos2);
cs

setTimeout 콜백함수를 활용하여 시간에따른 시뮬레이션을 진행하는 부분입니다.

 
// 운석이 도착점에 도달할 시 피해반경 표출
setTimeout(function(){
    viewer.entities.add({
        position : meteorPosition,
        ellipse : {
            semiMinorAxis : 11000.0
            semiMajorAxis : 11000.0
            material : Cesium.Color.RED.withAlpha(0.5)
        }
    });
},23000); 
// 피해반경 가시화 
setTimeout(function(){
    if(particleSystem != null){
        scene.primitives.remove(particleSystem);
    };
    var staticPosition = Cesium.Cartesian3.fromDegrees(139.74390335.69436360000);
    var orientation = new Cesium.HeadingPitchRange(0,300,0); 
    viewer.scene.camera.setView({
        destination : staticPosition,
        orientation : orientation,
        endTransform : Cesium.Matrix4.IDENTITY
    });
},26000);
cs

semiMinorAxis 와 semiMajorAxis는 지름을 지정하는 파라미터입니다. 단위는 m입니다.

 

마치며

본 시뮬레이션을 구현하는 작업은 흥미로웠습니다. 하지만 운석낙하에 대한 자료가 한참 부족하고 대부분 추정치만 존재하다보니 실제의 값에 근접한 값을 도출하는데 수 일의 노력을 기울였습니다.

하지만 프로그웍스와 독자분들을 위한 유령개구리의 노력은 멈추지 않을것입니다. 감사합니다~!

 

 

 

 

 

 

 

* 전체 소스코드 내용은 다음과 같습니다.

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
<!DOCTYPE html>
<html lang='en'>
<meta charset="UTF-8">
<head>
<script src="js/Cesium-1.54/Build/Cesium/Cesium.js"></script>
<link href="js/Cesium-1.54/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
    @import url(js/Cesium-1.54/Apps/Sandcastle/templates/bucket.css);
</style>
<div id="cesiumContainer" style="width:auto; height:700px"></div>
<script>
var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.7;
 
var viewer = new Cesium.Viewer('cesiumContainer',{
    timeline : false,
    animation : false,
    selectionIndicator : false,
    navigationHelpButton : false,
    infoBox : false,
    navigationInstructionsInitiallyVisible : false
});
 
var scene = viewer.scene;
// 위,경도 표출될 라벨의 옵션을 파라미터로 지정
var entity = viewer.entities.add({
    label : {
        show : true,
        showBackground : true,
        backgroundColor : Cesium.Color.BLACK,
        font : '25px sans-serif',
        horizontalOrigin : Cesium.HorizontalOrigin.LEFT,
        //verticalOrigin을 top으로 지정 
        verticalOrigin : Cesium.VerticalOrigin.TOP,
        //pixelOffset을 통해 label의 상세 위치를 지정 / Cartesian2 사용(x,y)
        pixelOffset : new Cesium.Cartesian2(150)
    }
});
// eventhandler 변수에 screenspacehandler를 담음
var eventhandler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
// movement가 발생하면 위,경도 값을 표출 
eventhandler.setInputAction(function(movement){
    var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, scene.globe.ellipsoid);
    if(cartesian){
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        var longitude = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);
        var latitude = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);
        
        entity.position = cartesian;
        entity.label.show = true;
        entity.label.text = '경도 : '+('' + longitude).slice(-7+ '\u00B0' + '\n위도 : '+('' + latitude).slice(-7+ '\u00B0';
    }else{
        entity.label.show = false;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
</script>
</head>
<body>
</body>
</html>
cs

 

* 28 ~ 40행은 위,경도를 표출할 라벨의 옵션을 key : value 값, 파라미터로 지정한 부분입니다.

 
var entity = viewer.entities.add({
    label : {
        show : true,
        showBackground : true,
        backgroundColor : Cesium.Color.BLACK,
        font : '25px sans-serif',
        horizontalOrigin : Cesium.HorizontalOrigin.LEFT,
        //verticalOrigin을 top으로 지정 
        verticalOrigin : Cesium.VerticalOrigin.TOP,
        //pixelOffset을 통해 label의 상세 위치를 지정 / Cartesian2 사용(x,y)
        pixelOffset : new Cesium.Cartesian2(150)
    }
});
cs

 

* VerticalOrigin에 대한 설명입니다. (자세한 내용은 CesiumDocument를 참고하세요.)

각 포지션을 통해 라벨이 표출되는 위치를 조정할 수 있습니다.

 

* Cartesian2에 대한 설명입니다. (자세한 내용은 CesiumDocument를 참고하세요.)

Cartesian2는 2차원적 개념으로 x, y 값을 갖게됩니다.

 

* 44 ~ 57행은 MouseMove 이벤트를 활용하여 movement가 발생함에 따라 위,경도 값이 표출되게끔 하는 부분입니다.

 
eventhandler.setInputAction(function(movement){
    var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, scene.globe.ellipsoid);
    if(cartesian){
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        var longitude = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);
        var latitude = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);
        
        entity.position = cartesian;
        entity.label.show = true;
        entity.label.text = '경도 : '+('' + longitude).slice(-7+ '\u00B0' + '\n위도 : '+('' + latitude).slice(-7+ '\u00B0';
    }else{
        entity.label.show = false;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
cs

cartographic변수에 cartesian을 활용한 위,경도 값을 담아줍니다.

 

* Cartographic에 대한 설명입니다. (자세한 내용은 CesiumDocument를 참고하세요.)

기본적으로 Cartesian3(x,y,z)값을 갖게되며 기본 투영체 및 좌표계로 WGS84를 사용한다는 것을 알 수 있습니다.

 

결과 화면 보겠습니다.

 

라벨이 마우스를 따라다니며 위,경도를 알려주는 것을 볼 수 있습니다. 제주 한라산의 위,경도는 사진과 같군요 

Cesium JS Feature Picking 활용하기

이번 시간에는 CesiumJS에서 glTF 형식의 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html>
<html lang='en'>
<meta charset="UTF-8">
<head>
<script src="js/Cesium-1.54/Build/Cesium/Cesium.js"></script>
<link href="js/Cesium-1.54/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
    @import url(js/Cesium-1.54/Apps/Sandcastle/templates/bucket.css);
</style>
<div id="cesiumContainer" style="width:auto; height:700px;"></div>
<script>
var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
 
var viewer = new Cesium.Viewer('cesiumContainer', {
     timeline : false,
     animation : false,
     selectionIndicator : false,
     navigationHelpButton : false,
     infoBox : false,
     navigationInstructionsInitiallyVisible : false   
});
 
// Gltf포맷 활용가능하게함.
var scene = viewer.scene;
var position = Cesium.Cartesian3.fromDegrees(126.93451137.5210040);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
// fromGltf 함수를 사용하여 key : value 값으로 요소를 지정
var name = '프로그APT'
var model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
    url : 'js/image/cesium.gltf',
    modelMatrix : modelMatrix,
    scale : 5000.0,
    name : name
}));
viewer.scene.primitives.add(model);
 
// nameoverlay를 위한 설정
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'= 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'black';
 
// feature select 
var selected = {
    feature : undefined,
    originalColor : new Cesium.Color()
};
 
// 모델을 select하기위한 부분
var selectedEntity = new Cesium.Entity(model);
 
// 클릭핸들러 변수선언
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
 
if(Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)){
    // 블루, 그린 실루엣 지원
    var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
    silhouetteBlue.uniforms.length = 0.01;
    silhouetteBlue.selected = [];
    
    var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteGreen.uniforms.color = Cesium.Color.LIME;
    silhouetteGreen.uniforms.length = 0.01;
    silhouetteGreen.selected = [];
    
    viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));
    // mousemove function을 이용하여 모델을 select 후 배열에 담음
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement){
        silhouetteBlue.selected = [];
    // 모델에 마우스가 move될 시 nameoverlay 출현    
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if(!Cesium.defined(pickedFeature)){
        nameOverlay.style.display = 'none';
        return;
    }
    // nameOverlay 설정
    nameOverlay.style.display = 'block';
    nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
    nameOverlay.style.left = movement.endPosition.x +'px';
    
    nameOverlay.textContent = name;
    
    if(pickedFeature !== selected.feature){
        silhouetteBlue.selected = [model];
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    
    // 모델을 클릭하여 알럿창을 띄우기위한 부분 / function onLeftClick
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement){
        // silhouetteGreen 변수에 담을것
        silhouetteGreen.selected = [];
        
        // 새로운 모델 선택
        var pickedFeature = viewer.scene.pick(movement.position);
        if(!Cesium.defined(model)){
            clickHandler(movement);
            return;
        }
        
        // 선택된 모델이 없으면 새로운 모델 선택 가능
         if(silhouetteGreen.selected[model] === pickedFeature){
             return;
        } 
         alert("이곳은" +name+ "입니다." +'\n'+ "높이 : "+"68.7"+"m" +'\n'+ "넓이 : "+"30.2"+"m" +'\n'+ "가구 수 : " +"1000"+ "세대");
         
        // 샌택된 모델의 기존색상 저장(파란색)
        var highlightedFeature = silhouetteBlue.selected[model];
        if(model === highlightedFeature){
            silhouetteBlue.selected = [];
        }
        
        // 새로 선택된 모델 highlight
        silhouetteGreen.selected = [model];
        
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    
}
</script>
</head>
<body>
</body>
</html>
cs

 

40 ~ 50 행 : 모델로 마우스가 이동했을 시 모델의 이름을 표출할 nameOverlay에 대한 설정입니다.

 
// nameoverlay를 위한 설정
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'= 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'black';
cs

 

65 ~ 96행 : 블루, 그린 실루엣을 사용하기위한 변수를 선언하고 onMouseMove function을 활용하기위한 부분입니다. 

 
// 블루, 그린 실루엣 지원
    var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
    silhouetteBlue.uniforms.length = 0.01;
    silhouetteBlue.selected = [];
    
    var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteGreen.uniforms.color = Cesium.Color.LIME;
    silhouetteGreen.uniforms.length = 0.01;
    silhouetteGreen.selected = [];
    
    viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));
    // mousemove function을 이용하여 모델을 select 후 배열에 담음
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement){
        silhouetteBlue.selected = [];
    // 모델에 마우스가 move될 시 nameoverlay 출현    
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if(!Cesium.defined(pickedFeature)){
        nameOverlay.style.display = 'none';
        return;
    }
    // nameOverlay 설정
    nameOverlay.style.display = 'block';
    nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
    nameOverlay.style.left = movement.endPosition.x +'px';
    
    nameOverlay.textContent = name;
    
    if(pickedFeature !== selected.feature){
        silhouetteBlue.selected = [model];
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
cs

* MouseMove 이벤트에 대한 설명 (Cesium Document를 통해 자세한 내용을 살펴보세요.)

마우스의 움직임으로 이벤트를 구현할 수 있습니다.

 

98 ~ 125행 : onLeftClick 함수를 사용하여 새로운 모델 선택 및 모델 실루엣 색상을 변경하기위한 부분입니다. 

 
// 모델을 클릭하여 알럿창을 띄우기위한 부분 / function onLeftClick
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement){
        // silhouetteGreen 변수에 담을것
        silhouetteGreen.selected = [];
        
        // 새로운 모델 선택
        var pickedFeature = viewer.scene.pick(movement.position);
        if(!Cesium.defined(model)){
            clickHandler(movement);
            return;
        }
        
        // 선택된 모델이 없으면 새로운 모델 선택 가능
         if(silhouetteGreen.selected[model] === pickedFeature){
             return;
        } 
         alert("이곳은" +name+ "입니다." +'\n'+ "높이 : "+"68.7"+"m" +'\n'+ "넓이 : "+"30.2"+"m" +'\n'+ "가구 수 : " +"1000"+ "세대");
         
        // 샌택된 모델의 기존색상 저장(파란색)
        var highlightedFeature = silhouetteBlue.selected[model];
        if(model === highlightedFeature){
            silhouetteBlue.selected = [];
        }
        
        // 새로 선택된 모델 highlight
        silhouetteGreen.selected = [model];
        
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
cs

* LeftClick 이벤트에 대한 설명 (Cesium Document를 통해 자세한 내용을 살펴보세요.)

마우스 좌클릭을 통해 선택, 드래그 등의 이벤트를 구현할 수 있습니다.

 

결과 화면을 보겠습니다. 

마우스를 모델에 올렸을 시 모델의 테두리 색상이 파란색으로 변경되고 nameoverlay가 활성화 된 것을 볼 수 있습니다.

 

 

모델을 클릭했을 시 Alert창에 모델의 이름과 임의로 지정한 값을 알립니다.

 

모델을 클릭 후 테두리 색상에 변경된것을 확인할 수 있습니다. 선택했던 모델에 재차 마우스를 올려도 nameOverlay가 활성화됩니다.

 

이번 시간에는 3D Builder를 통한 GLTF포맷 데이터 생성 및 이를 Cesium JS에 활용하는 방법을 공유하겠습니다.
먼저 결과를 확인해보세요. (여의도로 가세요.)

서비스바로가기

 

* glTF 포맷이란?

JSON 표준을 사용하는 3D장면 및 모델의 파일 형식이며 3D장면의 크기를 축소하고 런타임 처리를 최소화하는 

효율적이고 상호 운용 가능한 자산 전달 형식입니다. 

> 바로가기 : glTF Overview (https://www.khronos.org/gltf/)

 

* 3D Builder 사용하기

1. Window '검색'을 통해 3D Builder를 검색하세요. 

Tip. Window에 3D Builder가 기본 제공 되어있지 않은 경우 "MicroSoft Stroe"를 통해 다운로드 받으시길 바랍니다.

2. 3D Builder를 실행한 후 새 장면을 클릭합니다.

Tip. 각 기능에 대한 설명은 "3D Builder 사용자 가이드"를 참고하세요.

3. 3D 모델 생성 및 텍스쳐 입히기

우선, 정육면체 1개를 추가해봅시다. 

 

 

그리고 그리기 메뉴에서 텍스쳐 탭을 클릭 후 임의의 텍스쳐를 입혀봅니다.

 

 

저장을 합니다.

Tip. 저장시에는 파일형식을 "glTF format"형식으로 해야합니다. 

사진과 같이 gltf, bin 형식의 파일 그리고 설정한 텍스쳐 파일이 저장되었습니다.

 

필자는 아래 사진과 같은 3D Model을 생성하였습니다.

 

 

* 소스코드 작성하기 

glTF 포맷을 사용하기 위한 소스코드

 
// Gltf포맷 사용을 위한 변수들 선언
var scene = viewer.scene;
var position = Cesium.Cartesian3.fromDegrees(126.93451137.5210040);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
 
// fromGltf 함수를 사용하여 key : value 값으로 요소를 지정
scene.primitives.add(Cesium.Model.fromGltf({
    url : 'js/image/cesium.gltf'// gltf포맷의 위치 
    modelMatrix : modelMatrix,
    scale : 5000.0
}));
cs

 

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

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
<!DOCTYPE html>
<html lang='en'>
<meta charset="UTF-8">
<head>
<script src="js/Cesium-1.54/Build/Cesium/Cesium.js"></script>
<link href="js/Cesium-1.54/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<title>Make Building</title>
<div id="cesiumContainer" style="width:auto; height:925px;"></div>
<script>
var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
 
var viewer = new Cesium.Viewer('cesiumContainer', {
     timeline : false,
     animation : false,
     selectionIndicator : false,
     navigationHelpButton : false,
     infoBox : false,
     navigationInstructionsInitiallyVisible : false   
});
 
// Gltf포맷 사용을 위한 변수들 선언
var scene = viewer.scene;
var position = Cesium.Cartesian3.fromDegrees(126.93451137.5210040);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
// fromGltf 함수를 사용하여 key : value 값으로 요소를 지정
scene.primitives.add(Cesium.Model.fromGltf({
    url : 'js/image/cesium.gltf'// Gltf포맷의 위치
    modelMatrix : modelMatrix,
    scale : 5000.0
}));
</script>
</head>
<body>
</body>
</html>
cs

 

결과 화면은 다음과 같습니다. 

필자는 여의도 지역의 일부를 생성하였습니다.

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