지도 위에 벡터 표출하기

게시판 IDL Q&A 지도 위에 벡터 표출하기

이 게시글은 3개 답변과 3명 참여가 있으며 마지막으로  ChoiYoun에 의해 1 주, 1 일 전에 업데이트 됐습니다.

  • 글쓴이
  • #5459

    ChoiYoun
    회원

    안녕하세요.

    지도 위에 벡터를 표출하는 도중 막혀서 글 올립니다.

    자료의 형태는 아래와 같습니다. 예제파일 다운로드 링크(10.5MB)

    restore, ‘./EXAMPLE/uu.save’
    restore, ‘./EXAMPLE/vv.save’
    restore, ‘./EXAMPLE/lon_arr.save’
    restore, ‘./EXAMPLE/lat_arr.save’
    help, uu, vv, lon_arr, lat_arr
    ;UU FLOAT = Array[903, 991]
    ;UU FLOAT = Array[903, 991]
    ;LON_ARR FLOAT = Array[903, 991]
    ;LOT_ARR FLOAT = Array[903, 991]

    이를 지도 위에 표출하기 위해 다음과 같이 VECTOR 함수를 이용하려고 했는데,

    sb = 31 &wb = 122 &nb = 41 &eb = 132
    m = MAP(‘Geographic’, LIMIT = [sb,wb,nb,eb], CENTER_LONGITUDE = 128)

    ;Can not work T T..
    v = VECTOR(uu, vv, lon_arr, lat_arr, /OVERPLOT, /AUTO_SUBSAMPLE)
    ;Syntax ;graphic = VECTOR(U, V, [, X, Y ] [, Keywords=value] [, Properties=value])

    VECTOR의 (X, Y)는 1차원만 사용할 수 있더군요. 즉, 정방형 데이터일 때만 사용할 수 있는 듯합니다.

    ARROW 함수를 사용해 하나씩 그리는 방법도 있지만 자료가 크다보니 너무 오래 걸립니다.

    고견 부탁드립니다.

  • #5460

    mwkim
    회원

    안녕하세요.

    질문하신 부분에서 VECTOR 함수의 X, Y에 들어가는 자료의 형태는 1차원 자료이지만 정방형 데이터일 필요는 없습니다.

    간단하게는 X, Y에 들어가는 데이터를 1차원 형태로 변형만 해주어도 됩니다.
    (다만 정방형 데이터가 아니니 U, V도 같이 1차원으로 변형해야 합니다.)

    예를 들어 올려주신 예제 자료를 기준으로

    arrSize = SIZE(uu,/N_ELEMENTS)
    uuRe = REFORM(uu,arrSize)
    vvRe = REFORM(vv,arrSize)
    lonRe = REFORM(lon_arr,arrSize)
    latRe = REFORM(lat_arr,arrSize)

    와 같이 변환한 후에

    v = VECTOR(uuRe, vvRe, lonRe, latRe, /OVERPLOT, /AUTO_SUBSAMPLE)

    로 벡터를 표출하시면 됩니다.

    다만 위와 같이 표출했을 때, 올려주신 자료에서는 격자 수가 많아 벡터(화살표)가 잘 안보이기도 하고,

    일정 구역에서 벡터 크기가 튀는 부분이 있어 표출할 때 옵션을 통해 조정이 필요해 보입니다.

  • #5461

    Sangwoo
    회원

    VECTOR 함수에 투입될 수 있는 데이터의 형태는 두가지 경우가 있습니다.

    <경우 1>
    x : M개의 일정 간격의 X방향 격자점 좌표값들로 구성된 1차원 배열
    y : N개의 일정 간격의 Y방향 격자점 좌표값들로 구성된 1차원 배열
    u : MxN의 형태를 갖는 U성분 값들로 구성된 2차원 배열
    v : MxN의 형태를 갖는 V성분 값들로 구성된 2차원 배열
    vec = VECTOR(u, v, x, y, ~~~~~)

    <경우 2>
    x : N개의 X좌표값들로 구성된 1차원 배열
    y : N개의 Y좌표값들로 구성된 1차원 배열
    u : N개의 U성분 값들로 구성된 1차원 배열
    v : N개의 V성분 값들로 구성된 1차원 배열
    vec = VECTOR(u, v, x, y, ~~~~~)

    다만 여기서 <경우 1>에 해당되려면 모든 데이터 포인트들이 X 및 Y 방향으로 일정한 간격을 갖는 정방형 격자 형태로 분포해야 합니다. 그런데 올려주신 데이터를 보면 배열 구조 자체는 <경우 1>에 해당되는 것처럼 보이긴 하지만, 실제 데이터 포인트들의 공간적 분포를 보면 정방형의 규칙 격자 분포를 하지 않는 경우에 해당됩니다. 이런 경우에는 VECTOR 함수에 데이터를 투입해도 제대로 작동하지 않습니다. 따라서 이런 경우에는 바로 위 댓글에서 언급된 것과 같이 uu, vv, lon_arr, lat_arr 각 배열을 1차원 배열화하여 VECTOR 함수에 투입해야 합니다. 즉 <경우 2>에 해당되도록 배열들을 인위적으로 약간 손을 본 다음에 VECTOR 함수에 투입하는 방식입니다.

    다만 이렇게 했을 경우 각 배열은 903×991=894873개의 원소들을 갖는 1차원 배열이 됩니다. 즉 지도상에 표출될 벡터 화살표들의 총 갯수가 90만개에 육박하는 셈입니다. 이 상태로는 그 갯수가 지나치게 많기 때문에 표출을 하더라도 가독성이 매우 떨어질 수 밖에 없습니다. 물론 VECTOR 함수에는 벡터들이 너무 많을 경우를 위해서 자체적으로 샘플링을 하는 AUTO_SUBSAMPLE, X_SUBSAMPLE, Y_SUBSAMPLE 등의 기능들이 지원됩니다. 하지만 이런 기능들은 <경우 1>에서만 유효하고, <경우 2>에 대해서는 해당되지 않습니다. 따라서 샘플링을 직접 해주는 것이 필요할 것입니다. 예를 들면 90만개는 너무 많으므로 1/1000로 줄여서 약 900여개의 벡터들만 표시하기로 한다고 하면 다음과 같은 처리를 해주는 것도 필요할 수 있습니다.

    mf = 1000
    lonRe_r = CONGRID(lonRe, N_ELEMENTS(lonRe)/mf)
    latRe_r = CONGRID(latRe, N_ELEMENTS(latRe)/mf)
    uuRe_r = CONGRID(uuRe, N_ELEMENTS(uuRe)/mf)
    vvRe_r = CONGRID(vvRe, N_ELEMENTS(vvRe)/mf)

    이렇게 처리한 후에 VECTOR 함수에 투입하면 됩니다.

    v = VECTOR(uuRe_r, vvRe_r, lonRe_r, latRe_r, /OVERPLOT)

    다만 한가지 더 말씀을 드리자면, 실제 데이터 값들을 보니까 uu, vv의 값들 중 -9999인 값들이 있습니다. 이런 값들이 살아있게 되면 벡터의 길이가 비정상적으로 스케일링될 수 밖에 없기 때문에 반드시 걸러줘야 합니다. 따라서 사전에 WHERE 함수를 사용하여 비정상값들을 걸러주는 작업이 필요하다는 점도 염두에 두셔야 할 것 같습니다.

    • 이 답변은  Sangwoo에 의해 1 주, 3 일 전에 수정됐습니다.
  • #5463

    ChoiYoun
    회원

    친절한 설명 감사합니다. 1차원으로 변경할 생각을 못했네요. 항상 배워갑니다.

답변은 로그인 후 가능합니다.