시각화/프로세싱

▶함께배우는 프로세싱 :: generative design M6.1 Spring

비주얼라이즈 2015. 3. 1. 15:41






▶함께배우는 프로세싱 :: generative design M6.1 Spring


이번 글에서는 generative design에서 제공하고있는 예제 중 각 노드를 spring으로 연결하는 예제를 살펴보고자 한다.  이 예제를 통해 확인할 수 있는 결과는 아래의 영상과 같다.











SPRINGS AS CONNECTIONS.



연결된 노드들을 연결하는 것은 "Force directed layout'에서 두 번째로 중요한 요소이다.

이러한 연결들(connections)은 일정 길이를 초과하지않도록 스스로 제한 하도록 해야한다. 스프링(SPINRG)의 개념은 이러한 목적을 위해 일반적으로 사용되는 방법중 하나이다.





알고리즘


위에서 설명한 이유로, 스프링의 알고리즘은 멀리떨어져 있다면 각각의 대상이 서로를 향해 이동하도록 하게하고, 각 대상의 거리가 너무 가까워지게 되면 서로를 밀어내도록 한다.






Following step.


1. fromNode와 toNode의 거리차의를 결정한다.

2. 거리 vector를 정규화(Normalize)한다. 

3. 원하는 길이로 Scale th distance와 target point를 확립한다.

4. force vector를 결정한다.

5. 절반 지점에서 force vector를 나누고, 이것을 노드에 적용한다.








SPRING으로 연결된 노드. 간단한 예제






이 예제에서는 'generativedesign'라이브러리를 사용한다. (이것을 로드하지않으면 Node를 새로 구성해야한다.) 이와다르게 'Spring'클래스는 아래에서 직접 구조를 살펴보면서 작성할 것이다.


gerenativedesign 라이브러리가 설치되지않았다면 30초만 투자하자.


라이브러리 설치는 프로세싱 상단 메뉴바에서도 가능하다. 

[Sketch] - [Import Libary] - [Add Library] - generative design을 검색후 우측 install버튼 클릭






setup부분에서는 스프링예제에 필요한 두 개의 노드를 생성한다. 각 노드마다 두 개의 값을 전달하고 있는데, 이것은 화면의 중심지점을 기준으로 랜덤값 ±50을 부여했다. 이것은 시작점이므로 큰 의미는 없다. 그다음은 이렇게 생성한 두 개의노드를 받는 spring을 생성한다.


setup부분은 프로세싱 실행 후 한번만 동작하는 것이기 때문에, setup부분으로는 각 노드의 위치값에 대한 변화없이 한번 그려진다.




 


background(255);로 화면의 배경을 white로 설정해준다.


if(mousePressed == ture) 라는 조건문으로 마우스클릭위치를 바탕으로 nodeA의 x,y값을 변경한다. 여기서 중요한것은 nodeA에 대한 x,y값만 변경한다는 것이다. 이는 nodeA위치변화에 대한 nodeB의 움직임 변화를 보기위함이다. (자세한것은 코드작성 후 실행화면에서 확인할 수 있다.)




스프링과 노드A와 B모두 업데이트해준다.




업데이트를 마쳤다면, 이를 바탕으로 노드와 선을 그린다.

line에서는 노드A의 x,y와 노드B의 x,y를 잇는 선을 그린다. 그리고 아래의 ellipse부분에서는 각노드를 그린다.




Spring 클래스부분




위 사진 속 주석에서 적어 놓은 것 처럼, 스프링은 각 노드를 잇는 선이기 때문에, 항상 두 개 이상의 노드를 필요로 한다.



lengths부분에서 우리가원하는 스프링의 길이를 설정할 수 있다. 이번 예제에서는 이 길이를 임의로 100으로 설정했지만, 네트워크그래프를 그리는 등의 응용작업을 하고자 한다면 이 값에 다른 변수를 지정해볼 수 도 있을 것이다.


그밖에 자세한 lengths와 stiffness, damping등은 아래에서 적용방법에 대해서 확인할 수 있다.




void update()에서는 현제 프레임의 환경속에서 각 변수들의 값을 측정하고 그 값을 기반으로 다시 노드간의 force와 damping등의 기능을 적용한다. 





먼저 PVector diff는 두 노드의 difference를 의미하며, 이는 PVector.sub(A, B)함수를 활용하여 얻는다. 이를 통해 얻게된 값 'diff'는 정규화(normalize)를 거친 뒤, 앞서 우리가 설정한 'legnths'값을 곱해준다.





타겟포인트는 시작노드(fromNode)와 두 노드간의 차이값(diff)의 차로 얻는다.




두 노드간의 힘을 결정하게될 'force'는 앞서 구한 타겟포인트(target)과 도착노드(toNode)의 차로 얻는다. 이를 통해 얻게된 force는 2분의 1로 나누고(절반지점) 거기에 stiffness와 damping값을 곱하여 우리가 알고있는 스프링의 움직임을 구현한다.





마지막으로 위에서 구한 force값들을 각노드의 velocity(속도)값에 더해준다.  이때 한가지 주의할 것은 toNode에는 그대로 더해주지만, fromNode에는 -1을 곱하여 적용해주어야 한다는 점이다. 그렇지 않으면 두 노드는 서로를 끌어당기지 않게되기 때문이다.




[fromNode.velocity.add(force)로 적용하여 실행한 결과]




Generative Gestaltung, ISBN: 978-3-87439-759-9

First Edition, Hermann Schmidt, Mainz, 2009

Hartmut Bohnacker, Benedikt Gross, Julia Laub, Claudius Lazzeroni

Copyright 2009 Hartmut Bohnacker, Benedikt Gross, Julia Laub, Claudius Lazzeroni


http://www.generative-gestaltung.de