본문 바로가기
Researches/Rhino(라이노) | Grasshopper

[Rhino | Grasshopper] 원하는 객체의 바운딩 박스(bounding box) - 그래스호퍼 활용

by DevKev 2023. 3. 27.

 

To Do

Grasshopper를 활용한 bounding box 만들기

- 해당하는 객체 인덱싱

- origin point, normal을 이용한 평면 구성

 

Grasshopper 활용

아마 이 포스트를 보고 있다면 그래스호퍼(Grasshopper)가 라이노(Rhino)에서 어떤 플러그인(Plugin)인지 알고 있을 것이다. 간단하게 그래스호퍼가 무엇인지 요약하자면, 파라메트릭 모델링(Parametric modeling)을 할 수 있도록 도와주는 라이노의 강력한 툴이라고 할 수 있겠다. 여러 파라미터를 조작해서 모델링을 하려고 하면 그냥 단순하게 라이노에서 모델링을 하는 것이 아닌 그래스호퍼를 이용해서 모델을 만들면 굉장히 편하다.

 

나 같은 경우에는 모델링 뿐만 아니라 모델링 이후에 예를 들면 이 모델이 어떤 배치를 가지고 있고, 어떤 평면을 어떤 객체가 교차(intersection)하고 있는지 등등을 분석하기 위해서 그래스호퍼를 활용해 왔다. 플러그인 내에서 C#, python, Visual Basic을 활용할 수 있어서 좀 더 복잡하게 할 것이 있다면 프로그래밍도 이용할 수 있다. 내가 완전 고수라고 할 수는 없지만 그냥 나에게 주어진 문제를 해결하기 위해서 가끔 사용해 왔고, 관련 커뮤니티가 생각보다 친절하지는 않은 것 같아서 조금 정리를 할 필요가 있다고 생각했다.

 

[ 문제 정의 ]

추후에도 몇 가지 공유를 하겠지만, 이번에는 다음의 문제를 풀어보려고 한다:

  • 랜덤하게 배치된 객체가 있다.
  • 그냥 Bounding Box 컴포넌트만 이용하면 제대로된 객체의 sizing이 불가능하다.
  • 각 local 좌표계에서 Bounding Box가 만들어져야 한다. 

[ 원주 방향으로 다양한 크기로 배치된 surface. (좌) front view (우) perspective view]
[ 문제가 되는 상황: Global 좌표계를 기반으로 Bounding Box가 형성되는 상황 ]

 

일단 그냥 Bounding Box 메소드를 이용하면 위와 같은 문제가 발생한다. 원주 방향의 사이즈, 원통 중심방향으로의 깊이 등 각 객체의 사이징을 하려면 해당하는 local 좌표계에서 바운딩 박스가 형성되어야 한다. 문제를 조금 단순화해보기 위해서 다음과 같이 두 개만 골라서 테스트 해보고, 전체적으로 적용해보고자 한다.

 

 

 

 

 

 

[ 소 단위 적용 테스트 ]

그래스호퍼에서 이용한 component를 보면 다음과 같이 정리가 가능하다.

Component
아이콘
Component
이름
Component
기능
Point (Pt) 점 하나(One point) 혹은 여러 점(Multiple points)을 저장
 
Line (Ln) A와 B의 점을 연결하여 선(Line)을 생성 
Plane Normal
(Pl)
O: 평면(plane)의 origin 점(평면의 중점이라고 생각하면 됌)
Z: 평면을 만들 수 있는 법선벡터(Normal)

Brep Boundary REPresentations
Bounding Box
(BBox)
C: Bounding Box를 생성하고자 하는 geometry
P: Bounding Box를 생성하기 위한 base가 되는 평면
    (default: XY plane)

 

[ 그래스 호퍼 component 연결 ]

 

위의 컴포넌트만 쓰면 되는 것이니 굉장히 간단한 문제처럼 보였다. 하지만, 서피스(Surface) 2개 정의한 평면(Plane) 2개가 대응돼서 각 서피스에 대한 2개의 총 4개의 바운딩 박스(bounding box)가 생성이 되었는데, 서피스와 정의한 평면 간의 1대 1 매칭이 될 수 있도록 수정을 해줘야 했다. 지금은 코딩으로 따지면 i, j 루프가 다 돌아서 2*2=4가 되고 있는 상황이다. 그럼 어떻게 문제를 해결할 수 있을까?

 

[ 많은 객체 중 두 개만 뽑아 테스트 ]

 

이런 문제를 해결하고자 할 때는 포럼을 참고하는데 내가 원하는 정보를 찾기 어려운 경우는 결국 혼자 해결하거나 직접 질문을 올려서 고수들한테 조언을 얻는 것이 가장 좋다. 일단 비슷한 사례가 있는지 나도 검색을 해봤다. Graft를 써줘야지 1대 1 대응이 가능할 것이라는 솔루션을 찾을 수 있었고 적용했을 때 그 변화를 보자.

 

[ Graft 적용 전: 개체 당 바운딩 박스 2개 ]
[ Graft 적용 후: 개체당 바운딩 박스 각 1개 ]

 

보다시피, 내가 원하던대로 1대 1 매칭이 된 것을 알 수가 있다. 추후 Graft에 대해서는 조금 더 자세하게 다루겠지만, 계층을 만들어 준다고 생각하면 된다. 바운딩박스 컴포넌트에서 위 화살표가 생긴 걸 볼 수 있는데, 그게 Graft를 적용한 것이고 input과 output 모두에서 적용이 가능하다. 이제 실제로 내가 원해는 100개 개체에 대해서 적용해 봤을 때 잘 되는지 확인하는 작업을 보도록 하겠다.

 

[ 전체 적용 ]

위에 소 단위 적용의 경우, 내가 일일이 순서에 맞춰서 선택해서 해당 컴포넌트에 입력해줬기 때문에 평면과 surface의 순서가 맞을 수 밖에 없었다. 하지만 여러개의 object를 블록으로 지정해서 한번에 선택해서 입력하는 경우, 그 순서(order)가 맞을 수가 없다. 따라서, 전체 적용을 할 때는 평면과 surface의 순서(index 혹은 order)를 맞춰주는 추가적인 작업을 요구한다. 일단 하는 과정에 대해서 정리를 해보면 다음과 같다.

  • Plane 정의 - origin point, normal vector 필요
  • Plane과 Surface object 순서 일치시키기 - 인덱싱(indexing)
  • Bounding Box 만들기

Plane 정의하는 경우 앞에서 다뤘고, 인덱싱을 나는 다음과 같이 진행했다.

  • origin point와 각 개체의 centroid 간에 가장 가까운 점을 따져보고 그 index 획득
  • 그 index를 List item 컴포넌트를 이용해 재구성

 

[ 인덱싱을 위한 컴포넌트 구성 ]

 

그럼 인덱싱을 하기 전과 후에 어떻게 달라졌는지를 다음과 같이 볼 수 있다.

 

[ 인덱싱 전(좌)과 후(우) ]

 

그럼 바운딩 박스는 각 object에 대해서 만들어 봤다. 다음 포스트에서는 하나 더 나아가서 grasshopper python을 이용해서 마지막 과정을 진행해보면서 GHpython의 기본적인 내용에 대해서 다뤄보도록 하겠다.

 

 

Tistory 첫번째 pip 블로거로서,

도움이 되셨다면? 아래 pip button을 통해 후원해 주시면 감사합니다.


 
 
 

 

 

 

 

 

 

https://pip.me/pipmoonbien

 

toss | PIP ME

Life, degen mode on.

www.pip.me