배관 자재를 운반하기 위한 컨테이너 박스에 운송비를 줄이기 위해 최대로 많은 배관 자재를 넣기 위한 방안입니다.
컨테이너 박스는 아시다시피 직육면체로 보시면 되고 배관 자재는 분기(TEE)가 없는 선형적인 구조라고 가정하겠습니다.(직관, ELBOW, REDUER, FLANGE로만 구성)
쉽게 생각해보면 "컨테이너 박스에 차례로 배관 자재를 들어갈때 까지 넣으면 될것 같습니다."
이게 끝일까요?
이렇게만 하고 코딩을 시작하면 될까요?
가슴 한 구석에서 "이렇게만 하면 안될 것 같은데..."라고 이야기하는 것 같습니다.
여튼 시작해보겠습니다.
일반적으로 컨테이너 박스는 차량에 실려 운반되기 때문에 한쪽이 긴 직육면체입니다.
다행이 직관이 컨테이너의 길이 방향으로 놓여있다면 쉬울것 같은데 그렇지 않다면 문제가 됩니다.
그래서 직관을 컨테이너 길이 방향(각도 0)으로 회전시켜서 넣습니다.
코딩을 해봅시다.
if angle == 0:
pass
elif angle == 90:
직관을 -90도로 회전
elif angle == 270:
직관을 -270도로 회전
else:
pass
여러분들이 이런 코드를 보면 위험하다는 느낌을 가져야 합니다.
평면(360)을 4분면으로 나누어 처리했는데 일반 배관 라인은 직교하여 생성하기 때문에 큰 무리가 없어 보입니다만
사선으로 이동하는 배관 라인의 경우에 우리가 원하는 결과를 만족시킬수 없습니다.
그럼 45도를 코드에 넣어서 처리하면 되지 않을까 생각하시겠지만
if angle == 0:
pass
elif angle == 45:
직관을 -45도로 회전
elif angle == 90:
직관을 -90도로 회전
elif angle == 270:
직관을 -270도로 회전
else:
pass
그렇게 생각하면 안됩니다.
위 코드는 특정 상황에만 제대로 동작하고 예외의 경우를 처리하지 못합니다.
저의 경험상 사용자는 우리가 고려했던 환경, 예상했던 조건에서만 S/W를 사용하지 않습니다.
개발 시 모든 경우를 테스트하여 코드화시키지 못하기 때문에 실제 사용 시에 발생하는 예외 사항에 대해 처리를 하지 못합니다.
그래서 유지 보수 기간이 있지 않습니까? 라는 소리가 들리는 듯 하군요.
예외 발생 경우는
elif 예외 발생: # 2020.12.19 현업 XXX가 왜 안되냐며 난리침....
으로 코드에 들어가게 되고 우리의 코드는 간결성을 잃어버리고 스파게티가 되며
후임자는 기존 코드를 수정하면 어떤 일이 발생할지 몰라 두려움에 자기 나름의 elif를 추가하게 될겁니다.
다시 본론으로 돌와서 그럼 어떨게 할까요?
문제를 박스에 박스를 넣는 것으로 치환을 시키면 수월하게 문제를 해결할 수 있을것 같습니다.
한 박스가 다른 박스에 들어갈 수 있는 조건은 폭, 너비, 깊이가 모두 작으면 됩니다.
이때 박스의 폭, 너비, 깊이를 서로 바꿔가면서 확인을 해야 합니다.
이제 문제는 배관 자재에서 박스(Bounding Box)를 구하는 문제로 축소(?)됩니다.
하지만 Bounding Box를 구하는게 그리 쉽지는 않습니다.
흔히 생각하게되는 좌표의 최소, 최대값으로 구하는 Bounding Box나 OBB(Oriented Bounding Box)도 이 문제에는 적합하지 않은것 같습니다.
그래서 이 문제를 해결하기 위해 가장 긴 직선 구간을 깊이 방향으로 맞추는 방식으로 문제를 해결하고자 합니다.
배관 자재가 i에서 j까지 있다고 가정해봅시다.
직선 구간이 하나 있으면
Box(폭=파이프 직경,높이=파이프 직경, 깊이=직선 구간의 길이)
가 됩니다.
2개 이상일 경우에는
길이가 가장 긴 직선 구간을 선택해 깊이 방향 벡터를 구합니다.(배관자 k,i<=k<=j)
배관 자재k에 붙어있는 직선 구간을 구해 두 배관의 길이 방향 벡터를 외적하여 폭의 벡터를 구합니다.
폭 벡터를 구했으면 배관 자재k의 길이 방향 벡터와 폭 벡터의 외적을 통해서 너비 벡터를 구합니다.
이제 구할 박스의 폭, 높이, 깊이 방향 벡터를 구했습니다.
이제 모델의 좌표들을 벡터 내적으로 이용하여 구할 박스의 좌표계로 변환해줘야 합니다.
이제 변환된 모델 좌표들에서 Min, Max값을 구해 박스를 만들면 됩니다.
Box(폭 = Max Y - Min Y, 높이 = Max Z - Min Z, 깊이 = Max X - Min X)
추가적으로 파이프나 Component의 중심점을 이용하여 좌표를 계산했기 때문에 파이프의 직경을 이용하여 박스를 보정하면 좀 더 정확해질 것 같습니다.
댓글
댓글 쓰기