건물 내부에 대한 정확 정보는 해당 건물에 대한 설계 도면입니다. 설계 도면 파일은 아래와 같은 CAD 도면(예시)을 이용하는데요.

위와 같은 도면을 아래처럼 3차원 모델로 제작할 수 있습니다.

위와 같이 제작된 3차원 모델 데이터를 웹에서 시각화하고 사용자 인터렉션을 통해 공간 상에서 원하는 위치로 이동할 수 있습니다.

공간정보시스템 / 3차원 시각화 / 딥러닝 기반 기술 연구소 @지오서비스(GEOSERVICE)
건물 내부에 대한 정확 정보는 해당 건물에 대한 설계 도면입니다. 설계 도면 파일은 아래와 같은 CAD 도면(예시)을 이용하는데요.

위와 같은 도면을 아래처럼 3차원 모델로 제작할 수 있습니다.

위와 같이 제작된 3차원 모델 데이터를 웹에서 시각화하고 사용자 인터렉션을 통해 공간 상에서 원하는 위치로 이동할 수 있습니다.
사용자가 원하는 형식으로 전화를 입력했을때 정해진 형식(xx-xxx-xxxx)으로 변경해주는 함수입니다.
const formatPhoneNumber = (input) => {
const cleanInput = input.replaceAll(/[^0-9]/g, "");
let result = "";
const length = cleanInput.length;
if(length === 8) {
result = cleanInput.replace(/(\d{4})(\d{4})/, '$1-$2');
} else if(cleanInput.startsWith("02") && (length === 9 || length === 10)) {
result = cleanInput.replace(/(\d{2})(\d{3,4})(\d{4})/, '$1-$2-$3');
} else if(!cleanInput.startsWith("02") && (length === 10 || length === 11)) {
result = cleanInput.replace(/(\d{3})(\d{3,4})(\d{4})/, '$1-$2-$3');
} else {
result = undefined;
}
console.log(`${input} -> ${result}`);
return result;
}
테스트를 위해 다음 코드를 실행해 보면..
formatPhoneNumber("08032332333");
formatPhoneNumber("021231234");
formatPhoneNumber("(02)12351234");
formatPhoneNumber("63633221");
formatPhoneNumber("010-9543-3224");
formatPhoneNumber("0625252312");
formatPhoneNumber("03112341234");
결과는 다음과 같습니다.
021231234 -> 02-123-1234
08032332333 -> 080-3233-2333
021231234 -> 02-123-1234
(02)12351234 -> 02-1235-1234
63633221 -> 6363-3221
010-9543-3224 -> 010-9543-3224
0625252312 -> 062-525-2312
03112341234 -> 031-1234-1234
인지하지 못한 전화번호 형식이 있을 수 있으니 개선해서 사용하시면 됩니다.
크기 조절이 가능한 gwc-resizable-panel 태그를 이용한 사이드 패널을 구성하면 이 패널 안에 내용이 많아 수직으로 스크롤해야 할 경우 gwc-vscrollview 태그를 자식으로 두는 경우에 대한 코드를 정리합니다.

위의 화면 중 노란색 영역이 gwc-resizable-panel이고 초록 영역이 자식인 gwc-vscrollview 입니다.
사이드 패널에 대한 JS 코드는 다음과 같습니다.
class SearchResultUI {
constructor() {
const domLayout = document.createElement("div");
domLayout.classList.add("search-result-ui");
domLayout.innerHTML = `
0
0
0
`;
document.body.appendChild(domLayout);
GeoServiceWebComponentManager.instance.update();
}
}
7번의 gwc-resizable-panel의 resizable-left와 min-width는 각각 패널의 왼쪽 모서리를 이용해 크기를 조절할 수 있고, 패널의 가로 크기는 최소 200px를 유지해야 한다는 것입니다. min-width 값의 단위는 px이며 값을 지정할 때는 단위를 지정하지 않습니다./p>
해당되는 CSS는 다음과 같습니다.
.search-result-ui > gwc-resizable-panel {
box-shadow: 0 0 2px rgb(0 0 0 / 50%), 0 0 10px rgb(0 0 0 / 50%);;
left: calc(100% - 20em); /* width 값만큼 빼줘야 함 */
right: 0;
top: 3em;
width: 20em;
height: calc(100vh - 3em); /* 패널 위에 공간이 3em 임 */
_opacity: 0.8;
}
.search-result-ui > gwc-resizable-panel > .search-result-header {
height: 2.6em;
...
}
...
.search-result-ui > gwc-resizable-panel gwc-vscrollview {
width: 100%;
background: rgba(20,20,20,1);
height: calc(100% - 2.6em); /* 스크롤 영역 위의 공간이 2.6em 임 */
}
.search-result-ui > gwc-resizable-panel .search-result-content {
padding: 0.4em;
min-height: 100%;
display: flex;
flex-direction: column;
gap: 0.2em;
}
아래의 영상은 위의 UI가 반영된 실제 구동 영상입니다. 패널에 대한 크기 조절 등의 사용자 인터렉션을 파악할 수 있습니다.
안녕하세요, GIS Developer 김형준입니다.
오는 5월 25일부터 3일간 메타버스 환경 구축 및 인터랙티브 웹 개발이라는 주제를 가지고 강의를 진행합니다. 메타버스 환경 구축은 Blender라는 3차원 모델링 툴을 사용하고 인터렉티브 웹 개발은 three.js 라이브러리를 활용합니다. Javascript을 이미 알고 있다는 가정 하에 Blender나 three.js를 전혀 모르시는 분들도 이해하실 수 있도록 진행할 계획입니다.
아래의 영상은 교육 내용 중 실습 예제 중 하나입니다.
교육장소는 서울 판교에 있는 메타버스 캠퍼스입니다. 교육비는 무료이지만 참여할 수 있는 인원 수에 제한이 있습니다. 참여 신청을 위한 링크는 아래의 이미지를 클릭하시면 됩니다. 많은 참여 바랍니다.
원하는 결과는 다음과 같습니다.

장면에 추가된 모델은 3개입니다. 지구 본체, 지구 주변의 푸른 빛(Blooming Light), 지구 주위의 하얀 작은 무수한 별들.
먼저 지구 본체에 대한 코드입니다.
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(5, 50, 50),
new THREE.ShaderMaterial({
uniforms: {
globeTexture: {
value: new THREE.TextureLoader().load("data/earth.jpg")
}
},
vertexShader: `
varying vec2 vertexUV;
varying vec3 vertexNormal;
void main() {
vertexUV = uv;
vertexNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D globeTexture;
varying vec2 vertexUV;
void main() {
vec4 color = texture2D(globeTexture, vertexUV);
gl_FragColor = vec4(color.xyz, 1.);
}
`
})
);
결과는 다음과 같습니다.

지구 가장자리가 어두워서 가장자리를 밝게 만들기 위해 위의 코드에서 fragmentShader 코드를 다음처럼 변경합니다.
fragmentShader: `
uniform sampler2D globeTexture;
varying vec2 vertexUV;
varying vec3 vertexNormal;
void main() {
float intensity = 1.05 - dot(vertexNormal, vec3(0.,0.,1.));
vec3 atmosphere = vec3(0.3, 0.6, 1.0) * pow(intensity, 1.5);
vec4 color = texture2D(globeTexture, vertexUV);
gl_FragColor = vec4(atmosphere + color.xyz, 1.);
}
`,
결과는 다음과 같습니다.

지구 주변의 푸른 빛(Blooming Light)에 대한 코드입니다.
const atmosphere = new THREE.Mesh(
new THREE.SphereGeometry(5, 50, 50),
new THREE.ShaderMaterial({
vertexShader: `
varying vec3 vertexNormal;
void main() {
vertexNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec3 vertexNormal;
void main() {
float intensity = pow(0.76 - dot(vertexNormal, vec3(0,0,1.)), 2.0);
gl_FragColor = vec4(0.3, 0.6, 1.0, 1) * intensity;
}
`,
transparent: true,
blending: THREE.AdditiveBlending,
side: THREE.BackSide
})
);
atmosphere.scale.set(1.2, 1.2, 1.2);
결과는 다음과 같습니다.

이제 지구 주위의 하얀 작은 무수한 별들에 대한 코드입니다.
const starGeometry = new THREE.BufferGeometry();
const starVertices = [];
for(let i=0; i<10000; i++) {
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute("position", new THREE.Float32BufferAttribute(starVertices, 3));
const starMaterial = new THREE.PointsMaterial({color: 0xffffff});
const stars = new THREE.Points(starGeometry, starMaterial);
this._scene.add(stars);
결과는 이 글의 가장 첫번째 이미지와 같습니다.