FingerEyes-Xr에서 JSTS를 사용한 쓰는 코드 정리

FingerEyes-Xr은 JS 기반의 맵엔진이고 JSTS는 JS 기반의 지오메트리 연산 라이브러리입니다.

웹브라우저에서 공간 데이터에 대한 처리를 수행하는 경우에 JSTS를 사용하면 매우 좋은데요. 오래전부터 1.9버전을 사용하고 있었는데 오늘 보니 JSTS가 2.9.3 버전까지 올라왔군요.

JSTS에 대한 코드만을 뽑아 정리하기가 버겨워…. 대충 언급하여 정리해 봅니다. 아래 코드의 목적은 중첩되는 공간 데이터에 대한 헥사곤 도형을 생성해 주는 것입니다.

#run() {
  const selectLayers = this.#dialog.content.querySelector(".input-layer")
  const radius = parseFloat(this.#dialog.content.querySelector(".radius").value)
  const layerName = selectLayers.value
  const layer = app.map.layers().layer(layerName)
  const mbrLayer = layer.MBR()

  // MBR의 좌표계를 배경지도에 대한 좌표계로 변경함
  const proj = layer.EPSG() === -1 ? null : proj4(layer.proj4Name(), 'EPSG:' + layer.EPSG());
  const [minX, minY] = proj ? proj.forward([mbrLayer.minX, mbrLayer.minY]) : [mbrLayer.minX, mbrLayer.minY];
  let [maxX, maxY] = proj ? proj.forward([mbrLayer.maxX, mbrLayer.maxY]) : [mbrLayer.maxX, mbrLayer.maxY];
  maxX += radius*2
  maxY += radius*2

  const xStep = radius + radius/2
  const yStep = radius * Math.sin(60*(Math.PI/180)) * 2
  const gl = new Xr.layers.GraphicLayer("gl")
  app.map.layers().add(gl)

  const cntRows = layer.totalRowsCount();
  const wktReader = new jsts.io.WKTReader()

  for(let y=minY; y<maxY; y+=yStep) {
    for(let cx=minX; cx<maxX; cx+=xStep) {  
      ...
      const pts = [[ /* Hexagon 도형 구성 좌표 만드는 코드 */ ]]

      const psd = new Xr.data.PolygonShapeData(pts)
      const pgr = new Xr.data.PolygonGraphicRow(count, psd)

      const geomHexa = wktReader.read(psd.toWKT(false))   
      let intersected = false
      for(let i=0; i<cntRows; i++) {
        const shapeRow = layer.getShapeByFID(i)
        const geom = wktReader.read(shapeRow.shapeData().toWKT(true))   
        if(geom.intersects(geomHexa)) {
          intersected = true
          break
        }
      }
  
      if(intersected) gl.rowSet().add(pgr)
    }
  }

  app.map.update()
}

JSTS에 대한 주요 코드는 21번, 31/35번, 36번인데요. 각각 jsts.io.WKTReader 객체 준비, WKT로부터 JSTS를 위한 지오메트리 객체를 생성, 중첩 여부 확인 코드입니다. 참고로 위의 코드는 다음과 같은 결과를 만들어 냅니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다