지오서비스웹(GEOSERVICE-WEB)으로 만든 통계 지도

지오서비스웹으로 만들 수 있는 통계지도입니다. 입력 데이터는 서울시 행정구역도와 인구 데이터입니다.

먼저 색상 단계 구분도입니다. 서울시 행정구역도에 포함되는 포인트 인구 데이터를 집계해서 얻은 결과입니다.

다음은 핵사곤 영역을 이용한 색상 단계 구분도인데요. 핵사곤 영역은 서울시 행정구역도를 이용해 지오서비스웹의 핵사곤 생성 기능을 이용해 만들었습니다.

다음은 밀도도입니다.

지오서비스웹은 웹에서 누구나 사용할 수 있는 서비스이며 자세한 내용은 아래의 URL을 참조하시기 바랍니다.

지오서비스웹(GEOSERVICE-WEB)

Drei 컴포넌트 : RenderTexture

RenderTexture는 재질의 map 속성에 사용할 수 있는 텍스쳐를 별도의 카메라와 광원 그리고 모델로 구성된 씬을 통해 만들어 주는 컴포넌트로 그 활용성이 매우 높습니다.

RenderTexture가 적용된 Cube 컴포넌트입니다.

function Cube() {
  const textRef = useRef()
  useFrame((state) => (textRef.current.position.x = Math.sin(state.clock.elapsedTime) * 2))
  return (
    <mesh>
      <cylinderGeometry />
      <meshStandardMaterial>
        <RenderTexture attach="map" anisotropy={16}>
          <PerspectiveCamera makeDefault manual aspect={1 / 1} position={[0, 0, 5]} />
          <color attach="background" args={['orange']} />
          <ambientLight intensity={0.5} />
          <directionalLight position={[10, 10, 5]} />
          <Text font={suspend(inter).default} ref={textRef} fontSize={4} color="#555">
            hello
          </Text>
          <Dodecahedron />
        </RenderTexture>
      </meshStandardMaterial>
    </mesh>
  )
}

위의 코드에서 Dodecahedron 컴포넌트가 보이는데, 코드는 다음과 같습니다.

function Dodecahedron(props) {
  const meshRef = useRef()
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  useFrame(() => (meshRef.current.rotation.x += 0.01))
  return (
    <group {...props}>
      <mesh
        ref={meshRef}
        scale={clicked ? 1.5 : 1}
        onClick={() => click(!clicked)}
        onPointerOver={() => hover(true)}
        onPointerOut={() => hover(false)}>
        <dodecahedronGeometry args={[0.75]} />
        <meshStandardMaterial color={hovered ? 'hotpink' : '#5de4c7'} />
      </mesh>
    </group>
  )
}

실제 Cube는 다음처럼 렌더링됩니다.

SkinedMesh의 Clone

애니메이션 모델 리소스로부터 가져온 데이터를 여러개 복사해서 사용하고자 할때 필요한 코드입니다.

1개만 사용할때는 문제가 없는 기본적으로 작성된 코드는 다음과 같습니다.

import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import * as THREE from "three"

export function Robot({ color = "gray", ...props }) {
  const group = useRef()
  const { nodes, materials, animations } = useGLTF('/Robot.glb')
  const { actions } = useAnimations(animations, group)
  const [ animation, setAnimation ] = useState("Idle")

  useEffect(() => {
    actions[animation].reset().fadeIn(0.5).play()
    return () => actions[animation].fadeOut(0.5)
  }, [ animation ])

  materials.Alpha_Body_MAT.color = new THREE.Color(color)

  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Scene">
        <group name="Armature" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
          <primitive object={nodes.mixamorigHips} />
          <skinnedMesh name="Alpha_Joints" geometry={nodes.Alpha_Joints.geometry} material={materials.Alpha_Joints_MAT} skeleton={nodes.Alpha_Joints.skeleton} />
          <skinnedMesh name="Alpha_Surface" geometry={nodes.Alpha_Surface.geometry} material={materials.Alpha_Body_MAT} skeleton={nodes.Alpha_Surface.skeleton} />
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/Robot.glb')

위의 코드에 대한 모델 여러개를 장면에 추가하기 위해 다음처럼 코드를 수정해야 합니다.

import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useGLTF, useAnimations } from '@react-three/drei'
import * as THREE from "three"
import { useGraph } from '@react-three/fiber'
import { SkeletonUtils } from "three-stdlib"

export function Robot({ color = "gray", ...props }) {
  const group = useRef()
  const { scene, materials, animations } = useGLTF('/Robot.glb')
  const clone = useMemo(() => SkeletonUtils.clone(scene), [scene])
  const { nodes } = useGraph(clone)
  const { actions } = useAnimations(animations, group)
  const [ animation, setAnimation ] = useState("Idle")

  useEffect(() => {
    actions[animation].reset().fadeIn(0.5).play()
    return () => actions[animation].fadeOut(0.5)
  }, [ animation ])

  const material = materials.Alpha_Body_MAT.clone()
  material.color = new THREE.Color(color)

  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Scene">
        <group name="Armature" rotation={[Math.PI / 2, 0, 0]} scale={0.01}>
          <primitive object={nodes.mixamorigHips} />
          <skinnedMesh name="Alpha_Joints" geometry={nodes.Alpha_Joints.geometry} material={materials.Alpha_Joints_MAT} skeleton={nodes.Alpha_Joints.skeleton} />
          <skinnedMesh name="Alpha_Surface" geometry={nodes.Alpha_Surface.geometry} material={material} skeleton={nodes.Alpha_Surface.skeleton} />
        </group>
      </group>
    </group>
  )
}

useGLTF.preload('/Robot.glb')

위의 코드에서 SkeletonUtils를 사용하고 있는데 이를 위해 아래의 코드를 실행하여 three-stdlib를 설치해야 합니다.

npm i three-stdlib