dat.GUI의 API 정리

dat.GUI는 값을 GUI를 통해 직관적으로 변경하여 기능을 테스트해 볼 수 있는 javascript 기반의 매우 직관적인 라이브러리입니다.

dat.gui를 js에서 사용하기 위해 간단히 CDN을 통해 아래처럼 페이지에 스크립트를 포함할 수 있습니다.


아래는 dat.GUI의 가장 간단한 예제입니다.

var MyData = function() {
    this.dataString = "Dip2K";
    this.dataNumber = 0.7;
    this.dataBoolean = false;
    this.dataFunction = function() {
        alert(
            "dataString: " + this.dataString + "\n" +
            "dataNumber: " + this.dataNumber + "\n" +
            "dataBoolean: " + this.dataBoolean
        );
    };
};

window.onload = function() {
    var myData = new MyData();
        
    var gui = new dat.GUI();
   
    gui.add(myData, "dataString");
    gui.add(myData, "dataNumber");
    gui.add(myData, "dataBoolean");
    gui.add(myData, "dataFunction");
}

관리하고자 하는 데이터는 함수에 대한 new 호출을 통한 this에 바인딩되어져야 합니다. 위의 코드를 실행해 보면 아래와 UI가 페이지의 우측 상단에 표시됩니다.



위의 UI에서 보는 것처럼 함수의 new 호출로 this에 바인딩된 dataString, dataNumber, dataBoolean, dataFunction은 각각의 데이터 타입에 따라 적절한 UI로 표시되며 사용자가 쉽게 변경할 수 있습니다. function 타입의 데이터는 버튼 UI로 표시되며 버튼 클릭시에 해당 함수가 호출됩니다.

이 정도만 되어도 dat.gui를 적절하게 활용할 수 있지만, 여기에 덧붙여 변수값에 대한 제약 조건의 지정 등 다양한 활용이 가능합니다.

예를 들어, dataString 변수에 대해서 입력받을 수 있는 문자열을 Dip2K, James, Anold로 제한하고 싶다면 다음처럼 코드를 작성하면 됩니다.

gui.add(myData, "dataString", ["Dip2K", "James", "Anold"]);

dataNumber에 대해서 0~100 사이의 값만을 입력받으며 0.1 단위로 값의 증가, 감소하고자 한다면 아래처럼 코드를 작성하면 되구요.

gui.add(myData, "dataNumber", 0, 100).step(0.1);

dataNumber가 비록 수치 타입이지만, 항목으로써 선택 받도록 하고 각 항목에 대한 수치값을 지정하는 방식도 가능한데, 아래와 같습니다.

gui.add(myData, "dataNumber", { A: 0, B:50, C:100 });

색상값에 대한 직관적인 입력도 가능합니다. 그 예는 아래와 같습니다.

var MyData = function() {
    this.dataString = "Dip2K";
    this.dataNumber = 50;
    this.dataBoolean = false;

    this.dataColor1 = "#ff0000";
    this.dataColor2 = [ 0, 255, 0 ];
    this.dataColor3 = { h: 350, s: 0.5, v: 0.7 };

    this.dataFunction = function() {
        alert(
            "dataString: " + this.dataString + "\n" +
            "dataNumber: " + this.dataNumber + "\n" +
            "dataBoolean: " + this.dataBoolean + "\n" +
            "dataColor1: " + this.dataColor1 + "\n" +
            "dataColor2: " + this.dataColor2 + "\n" +
            "dataColor3: " + this.dataColor3
        );
    };
};

window.onload = function() {
    var myData = new MyData();

    var gui = new dat.GUI();

    gui.add(myData, "dataString", ["Dip2K", "James", "Anold"]);
    gui.add(myData, "dataNumber", 0, 100).step(0.1);
    gui.add(myData, "dataBoolean");

    gui.addColor(myData, "dataColor1");
    gui.addColor(myData, "dataColor2");
    gui.addColor(myData, "dataColor3");
            
    gui.add(myData, "dataFunction");
}

그런데 만약, 값의 변경이 dat.gui가 아닌 다른 곳에서 이루어진 다면, 변경된 값을 dat.gui에서 반영해 줘야 할 것입니다. 이는 매우 간단합니다. 즉, 아래처럼 listen을 호출해 주면 됩니다. 이 listen 함수는 타이머를 생성하고 이 타이머에서 값의 변경 여부를 검사하여 dat.gui에 반영해주게 됩니다.

gui.add(myData, "dataNumber").listen();

끝으로 dat.gui를 통한 값의 변경이 발생하면, 이에 대한 이벤트가 호출되도록 할 수 있는데, 그 예는 아래와 같습니다.

gui.add(myData, "dataNumber").onChange(
    function(v) {
        //alert(v);
    }).onFinishChange(
    function(v) {
        alert(v);
    });

onChange는 값 변경 중의 매 순간 발생하는 이벤트이고, onFinishChange는 최종적인 값의 변경이 발생할 때 호출되는 이벤트입니다.

이외에도 dat.gui는 설정된 값을 localStorage에 저장할 수 있는 기능도 있다는 것도 알아두시면 유용할듯합니다.

FingerEyes-Xr의 Hotspot 기능

지도 상에 특정한 지점을 시각적으로 두드러지게 표현하고 싶을 경우 FignerEyes-Xr에서는 Hotspot 기능을 활용할 수 있습니다. 아래는 이러한 Hotspot 기능을 활용하여 원하는 위치를 강조하는 기능에 대한 동영상입니다.

코드는 아래와 같이 간단합니다.

var pt = new Xr.PointD(102033, 231233);
var hotSpot = new Xr.ui.HotSpotControl(id, map, pt);
map.userControls().add(hotSpot);

위의 코드에 덧붙여 만약 사용자가 hotSpot을 클릭하면 지도에서 사라지도록 하는 추가 코드는 아래와 같습니다.

hotSpot.addEventListener("click", 
    function() {
        map.userControls().remove(id);
    }
);

FingerEyes-Xr의 소스코드는 GitHub에서 다운로드 받으실 수 있습니다.

git 명령어 정리

참고 url : https://rogerdudler.github.io/git-guide/index.ko.html

// 현재 디릭토리를 빈 local repo 만들고 github에 연결하기
git init
git remote add origin https://github.com/GEOSERVICE/test.git

// github로부터 local repo 만들기
git clone https://github.com/GEOSERVIC/test.git

// 추가, 삭제, 변경된 파일에 대한 반영 및 커밋
git add -A // WORKING TREE -> INDEX TREE
git commit -m “add all” // INDEX TREE -> HEAD TREE

// file1.txt의 추가 및 커밋
git add file1.txt
git commit -m “add file1.txt”

// file1의 삭제 및 커밋
git rm file1.txt
git commit -m “remove file1.txt”

// commit하기전의 지운 파일
git ls-files –deleted

// commit하기전의 지운 파일을 복원
git checkout — plugin/density.js

// commit하기전의 지운 전체 파일 복원
git checkout — *

// github로 반영
git push -u origin master // master는 가지의 이름임, master는 최초의 기본 가지임

// 원격 repo의 변경 사항을 local repo에 반영하기
git pull

// 내가 작업한 것 버리고 원격 repo에 맞추기
git fetch origin
git reset –hard origin/master

[Java] 고유값 만들기

고유한 값으로 사용할 만한 것은 UUID이다. UUID는 그 의미가 가지는 것 그대로 고유한 값이다. 그러나 저장소의 공간은 128 bits이며 문자열로 표현될 때 550e8400-e29b-41d4-a716-446655440000 처럼 그 길이가 상당히 길다. 물론 UUID는 이 기종의 하드웨어나, 시간 또는 공간적으로 다른 환경 모두에서 고유한 값을 제공해 주는 장점이 있다. 그런데, 만약 하나의 서버 내부에서 고유한 값이 필요하다면 어떨까? 한계는 있겠으나, 필자에게는 적합한 방법 중에 하나는 서버 측의 시간을 활용하는 것이다. Java에서 서버의 시간을 얻는 함수는 System.currentTimeMillis, 서버가 기동 된 후의 경과된 시간은 System.nanoTime를 통해 얻을 수 있다. 그 결과는 long형이므로 64 Bits이며, 문자열로 표현하면 대부분 21220887433392와 같이 14개면 표현이 가능하다. 그러나 나에게 고유값이 필요한 목적은 저장소에 저장할 필요는 없고 문자열로 표현했을때, 최대한 짧아야 한다는 것이다. 그런데 이 long 타입을 문자열로 표현하면 14개의 자리를 차지하는 것은 너무 길다. 짧게 표현하는 방법은 없을까? 이 long 값은 10진수이다. 이를 좀 더 높은 진수로 표현한다면 그 길이는 줄어들 것이다. 16진수, 32진수, 64진수, 128진수 등이 가능한데.. 표현 가능한 문자여야 하므로 64진수가 최적이다.

이러한 상황에서 아래의 코드 중 longToBase64라는 함수는 long 타입의 값을 받아 64진수로 진수 변환 방식을 통해 문자열로 변환해 주는 함수이다.

public static String longToBase64(long v) {
    final char[] digits = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 
        'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
        'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
        'Y', 'Z', '#', '$'
    };

    int shift = 6;
    char[] buf = new char[64];
    int charPos = 64;
    int radix = 1 << shift;
    long mask = radix - 1;
    long number = v;

    do {
        buf[--charPos] = digits[(int) (number & mask)];
        number >>>= shift;
    } while (number != 0);

    return new String(buf, charPos, (64 - charPos));
}

아래의 코드는 위의 함수를 테스트한 것으로, 1000개의 고유한 값을 얻는 기능을 수행한다.

for(int i=0; i<1000; i++) {
    long time =  System.nanoTime();
    System.out.println(time + " -> " + longToBase64(time));
}

위의 코드의 결과는 아래와 같은데, 실행하는 매 순간마다 다르게 표시될 것이다.

...

21767297606161 -> 4YMo2G8h
21767297618803 -> 4YMo2JdP
21767297627494 -> 4YMo2LlC
21767297634210 -> 4YMo2M#y
21767297647642 -> 4YMo2Qgq
21767297654358 -> 4YMo2RVm
21767297661469 -> 4YMo2TEt
21767297668185 -> 4YMo2Vhp
21767297676877 -> 4YMo2Xpd
21767297683593 -> 4YMo2Z29
21767297690704 -> 4YMo2#Ng
21767297697420 -> 4YMo30qc
21767297704531 -> 4YMo329j
21767297718753 -> 4YMo35Dx
21767297727445 -> 4YMo37Ll
21767297741272 -> 4YMo3b7o
21767297748383 -> 4YMo3cSv
21767297755099 -> 4YMo3evr
21767297762210 -> 4YMo3gey
21767297776037 -> 4YMo3jCB
21767297783148 -> 4YMo3llI

...