🤷🏻‍♀️ 문제가 발생했다.

Exif2geojson 해당 예제를 사용하여 작동하는것을 확인했다.
하지만 설마 하는마음에 5장의 사진을 넣어보니 위치가 상이했다.

K-001

이제 이것을 어떠한 방식으로 해야할지 고민을 해봐야 한다…..
저 사진은 같은장소에서 좌우로만 찍은 사진들 뿐인데 위치가 다 상이했다.

🤷🏻‍♀️ 해결 방안을 찾았다. (대안)

고민을 하게됬다 이걸 어떠한 방식으로 해결하면 슬기로울까… 고민하던중!
openlayers 기능중에 Box Selection이 있었다. 이걸 활용하자 생각했다.
해당 기능 DragBox 안에는 getGeometry()가 포함되어있다.
즉 DragBox 선택을 할경우 폴리곤을 생성을 하고 해당 폴리곤의 geometry를 포함하는지 비교분석하는 함수가 ol.source.Vector 의 getFeaturesInExtent 부분에 교차하는 부분이 있으면 Features를 리턴을 한다.

그러면

  const extent = dragBox.getGeometry().getExtent(); 
    //드래그한 박스의 범위
  const boxFeatures = vectorSource
    .getFeaturesInExtent(extent) 
    //vector의 소스에 해당범위를 범위를 지정하고
    .filter((feature) => feature.getGeometry().intersectsExtent(extent));
    //지정된 범위에 포함하는 Feature만 걸러낸다.

이러면 boxFeatures 에는 해당범위의 Feature가 들어있으니 interaction.select에 선택한것에 대한 값만 전달하면 끝이다. 예제의 코드가 너무 깔끔하다.

이렇게되면 이제 해당범위의 파일만 다운받을 방법만 찾으면된다.

🤷🏻‍♀️ 다운로드 부분

먼저 사진들의 위경도를 변환된게 EPSG:3857 좌표계였다. 허나 사진을 정리할때 동단위로 사진을 정리하기 위함이다. 그렇기에 GeoCodeing 이 필요로했다.
Vworld 에서도 openAPI를 재공을 해주지만
SGIS 통계지리정보서비스 를 이용하려한다.
개발자센터에 들어가보면 여러정보를 openAPI로 받을수있다. 통계청에서 만든 서비스이다.
서비스키를 발급받고 해당키는 문서 시작시 Access Token이 매번 다르게 갱신된다.
input hidden 으로 문서시작시 받아둬야했다.

<input type="hidden" name="SGIS_AccessToken" value="">
function sgis_authkey() {
  var cunsumer_key = "서비스키~~";
  var consumer_secret = "보안키~~~~";
  var param = {
    consumer_key: cunsumer_key,
    consumer_secret: consumer_secret,
  };

  $.ajax({
    type: "GET",
    url: "https://sgisapi.kostat.go.kr/OpenAPI3/auth/authentication.json",
    data: param,
    dataType: "json",
    success: function (getResult) { //getResult에 Access Token이 담겨온다
      console.log(getResult);
      $("input[name=SGIS_AccessToken]").val(getResult.result.accessToken);
    },
  });
}

이제 문서시작시 SGIS_AccessToken 이것만 있으면 openAPI를 사용이 가능하다.

Feature에 담겨있는 좌표를 SGIS에서 변환해주는 좌표계는 EPSG:5179이다.
그렇기에 좌표를 변환해줘야한다. proj4.js를 사용해야한다.
허나 우리나라의 좌표는 이슈가좀 있다.
2003년 12월에 “국가좌표변환계수고시” 가있엇다.
proj4.js에 해당좌표를 보정해줘야한다.

      //[오래된 지리원 표준]
      //*보정된 서부원점(Bessel) - KLIS에서 서부지역에 사용중
      defs('EPSG:5173', "+proj=tmerc +lat_0=38 +lon_0=125.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");
      //*보정된 중부원점(Bessel): KLIS에서 중부지역에 사용중
      defs('EPSG:5174', "+proj=tmerc +lat_0=38 +lon_0=127.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");
      //*보정된 제주원점(Bessel): KLIS에서 제주지역에 사용중
      defs('EPSG:5175', "+proj=tmerc +lat_0=38 +lon_0=127.0028902777778 +k=1 +x_0=200000 +y_0=550000 +ellps=bessel +units=m +no_defs  +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");
      //*보정된 동부원점(Bessel): KLIS에서 동부지역에 사용중
      defs('EPSG:5176', "+proj=tmerc +lat_0=38 +lon_0=129.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");
      //*보정된 동해(울릉)원점(Bessel): KLIS에서 울릉지역에 사용중
      defs('EPSG:5177', "+proj=tmerc +lat_0=38 +lon_0=131.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs  +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");
      //[KATEC 계열]한반도 전체를 하나의 좌표계로 나타낼 때 많이 사용하는 좌표계입니다
      //*UTM-K (Bessel): 새주소지도에서 사용 중
      defs('EPSG:5178', "+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43");      
      //*UTM-K (GRS80): 네이버지도에서 사용중인 좌표계
      defs('EPSG:5179', "+proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs ");      
      //[타원체 바꾼 지리원 표준]
      //*서부원점(GRS80)-falseY:50000
      defs('EPSG:5180', "+proj=tmerc +lat_0=38 +lon_0=125 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs");      
      //*중부원점(GRS80)-falseY:50000: 다음지도에서 사용중인 좌표계
      defs('EPSG:5181', "+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs");      
      //*제주원점(GRS80)-falseY:55000
      defs('EPSG:5182', "+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=550000 +ellps=GRS80 +units=m +no_defs");      
      //*동부원점(GRS80)-falseY:50000
      defs('EPSG:5183', "+proj=tmerc +lat_0=38 +lon_0=129 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs");      
      //*동해(울릉)원점(GRS80)-falseY:50000
      defs('EPSG:5184', "+proj=tmerc +lat_0=38 +lon_0=131 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs");      
      //[현재 국토지리정보원 표준] 2002년 이후에 국토지리정보원 지형도에서 사용중인 좌표계입니다.
      //*서부원점(GRS80)-falseY:60000
      defs('EPSG:5185', "+proj=tmerc +lat_0=38 +lon_0=125 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs");  
      //*중부원점(GRS80)-falseY:60000
      defs('EPSG:5186', "+proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs");  
      //*동부원점(GRS80)-falseY:60000
      defs('EPSG:5187', "+proj=tmerc +lat_0=38 +lon_0=129 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs");  
      //*동해(울릉)원점(GRS80)-falseY:60000
      defs('EPSG:5188', "+proj=tmerc +lat_0=38 +lon_0=131 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs");        

네이버는 3857 좌표로 변경했다.
이렇게 보정값을 넣어주고

var corrdinates = selectedFeatures.R[0].A.geometry.flatCoordinates
// 첫번째 선택된 Feature의 좌표값을 받아오고 X,Y 의 좌표값을 proj4.js를 통해 
var p_5179 = proj4('EPSG:3857','EPSG:5179',[corrdinates[0],corrdinates[1]]);

이렇게 좌표를 변환을 하고
해당 좌표를 openAPI로 리턴값을 받자.

// 행정동
var param = {
  x_coor: loc_x,
  y_coor: loc_y,
  addr_type: "20", // doc 문서에 타입별 정보가있다.
  accessToken: $("input[name=SGIS_AccessToken]").val(),
};

function geocode_promise_function(param) {
  return new Promise((resolve, reject) => {
    $.ajax({
      type: "GET",
      url: "https://sgisapi.kostat.go.kr/OpenAPI3/addr/rgeocode.json",
      data: param,
      dataType: "json",
      success: function (data) {
        if (data.errMsg == "Success") {
          $("input[name=bunji_address]").val(data.result[0].full_addr);
          createZipFile();
        } else {
          $("input[name=bunji_address]").val("알수없는주소");
        }
      },
    });
  });
}

리턴되는 값에는 주소가 담겨서 온다 이제 폴더를 만들고 압축해서 다운받으면 완성이다.!

function createZipFile(){
  var addr = $("#bunji_address").val();
  var zip = new JSZip();
  var zipFolder = zip.folder(addr);
  
  for(var i = 0; i < selectedFeatures.R.length; i++){
    var fileName = selectedFeatures.R[i].A.url
    zipFolder.file(fileName, srch_file_Data(fileName));
  }

  zip.generateAsync({ type: "blob" }).then(function (blob) {
    saveAs(blob, String(addr));
  });
}

function srch_file_Data(param_FileName){
  var files = $("#dropfile_input")[0].files;
  for(var z = 0; z < files.length; z++ ){
    if(files[z].name == param_FileName){
      return files[z];
    }
  }
}

srch_file_Data 파일명이 같은 파일을 내보내는 함수이고
createZipFile는 변환한 주소로 폴더를 만들고 해당 폴더에 Feature에 담긴 파일명과
같은 파일들을 내뱉어주면 완성이다.

🤷🏻‍♀️ 중간완성!

post3-4

post3-5

짝짝짝 실제 구동은 Amso Mad에서 볼 수 있다.

남은 작업은 Exif의 데이터가 없는 이미지는 첨부가 안되게 하는 기능을 추가를 해야하고 확장할만한 기능이 있나 찾아봐야 겠다.

참고) OpenLayers, ol-ext, FileSavers, exif.js, JSZip, SGIS통계지리정보서비스


Note: 만들고나니 내것이 아니었다.

Leave a comment