기본 콘텐츠로 건너뛰기

2020의 게시물 표시

Bspline Knot의 수정

앞에서 B- spline곡선은 여러 개의 부분 곡선들로 이루어져 있고, 각 부분 곡선들은 매듭 구간에서 정의되고 있다고 했습니다. 그래서 부분 곡선들이 정의되어 있는 이 매듭 구간을 수정을 하면 곡선의 형태도 바뀌게 됩니다. 이 매듭 구간을 결정하는 knot을 수정함으로써 곡선의 형태를 변형시킬 수 있습니다. 하지만 knot을 수정해서 곡선의 형태를 바꾸는 것은 그다지 바람직한 방법이 아닌 것 같습니다. knot을 수정해서 변형되는 곡선의 형태를 미리 예측하기가 힘들기 때문입니다. knot의 추가 knot의 추가는  기존의 곡선의 형태를 변형시키지 않고  새로운 knot을 매듭 벡터에 추가시키는 것입니다. knot이 하나 추가되면 m이 증가되므로 $m=n+p+1$의 식에서 n이나 p가 증가되어야 합니다. p가 증가되면 하나의 부분 곡선을 이루는데 필요한 basis function의 개수가 증가되므로 p가 증가되기 전보다 곡선의 부분적인 편집 기능이 떨어지게 됩니다. 그래서 이것은 고려하지 않고 n을 증가시킵니다. 즉 새로운 제어점을 추가시킨다는 말입니다. 다시 정리하면 n+1개의 제어점 $P_0,P_1,...,P_{n-1},P_n$와 그것과 연관된 양의 값인 $W_i$, $m+1$개의 매듭을 가진 매듭 벡터 $U=\{u_0,u_1,...,u_{m-1},u_m\}$, 차수 p를 가진 B-spline 곡선에 곡선의 형태는 변형시키지 않고 새로운 매듭을 추가시키는 것입니다. 추가시킬 새로운 매듭  u 가 매듭 구간 $[u_k,u_{k-1})$에 속한다고 가정하면, 이 매듭 구간에서 정의되는 곡선은 제어점 $P_{k-p},P_{k-p+1},...,P_{k-1},P_k$에 의해서 형성됩니다. 우리는 새로운 제어점을 찾아야 하기 때문에 $P_{k-p},P_{k-p+1}$상의 $Q_{k-p+1}, P_{k-p+1},P_{k-p+2}$상의 $Q_{k-p+2},…,P_{k-1},P_k$상의 $Q_k$을 찾아야 합니다. 그리고 나서 기존의 $P_{k-p},

Cloud 마크 그리기 개선

하나의 다각형에 대한 Cloud 마크를 그리는 것에 대해 알아봤습니다. 연결된 여러개의 다각형이 있을 경우 각각 개별적으로 다각형을 생성하는 것은 자칫 지저분해 보일 수 있으므로 연결된 다각형을 묶어 Cloud 마크를 생성하는 것에 대해 알아보도록 하겠습니다. 가운데 3개의 다각형(B,C,D)이 겹쳐져 있습니다. 먼저 겹쳐진 다각형을 찾아야 합니다. 다각형의 Bounding Box를 이용하여 서로 겹쳐지는지 여부를 확인할 수 있습니다. # A, B is Bounding Box if A.MinX > B.MaxX or A.MinY > B.MaxY or A.MaxX < B.MinX or A.MaxY < B.MaxY: return false else: return true 따라서 아래와 같이 색깔별로 묶을 수 있습니다. 여러개의 다각형을 Cloud 마크를 그리기위해 하나의 다각형으로 만들어줘야 합니다. (저희들은 하나의 다각형에 대해서 Cloud 마크를 그리는 로직을 가지고 있습니다.) 일단 다각형을 구성하는 정점들을 구합니다. 첫번째 방법 : 정점들을 포함하는 Bounding Box를 구해 다각형을 생성합니다. 두번째 방법 : 정점들을 포함하는 ConvexHull을 구해 다각형을 생성합니다.

컨테이너 박스에 최대로 배관 스풀 적재하기

앞선 글에 이어지는 글입니다. 컨테이너 박스에 최대로 들어갈 수 있는 스풀을 제작했다면 이제는 스풀들을 최대로 많이 컨테이너 박스에 쌓는 문제입니다. 문제를 풀기에 앞서 스풀은 아래와 같이 생겼습니다. 사람이 직접한다면 경험으로 잘 싣을 수 있겠지만 컴퓨를 이용해 문제를 푸는 입장에서는 복잡합니다. 넣을 공간을 찾는 것도 문제지만 넣는 순간도 중요합니다. 안쪽에 빈 공간이 있다고 해도 미리 쌓은 스풀이 장애물이 된다면 안쪽에 넣을 수가 없습니다. 이러한 문제를 좀더 간단히 하기 위해 스풀 패키지 단위로 컨테이너에 적재하는 것으로 문제를 축소하겠습니다. 그럼 하나의 패키지에 최대한 많은 스풀을 배치(X,Y)하면 됩니다. 패키지에는 층으로 스풀을 쌓지 않습니다. 컨테이너 밖에서 패키지에 최대한 스풀을 많이 배치하고 패키지를 컨테이너 박스에 쌓으면 됩니다.(패키지의 폭과 깊이는 컨테이너와 동일) 이제 패키지에 최대로 스풀을 많이 쌓는 방법에 대해서 고민하면 됩니다. 이러한 유사한 문제를 푸는 NESTING 알고리즘이라는게 있습니다. 정확히는 2D NESTING NESTING 알고리즘은 쉽게 말해 주어진 영역에 다각형을 최대한 많이 넣을 수 있도록 배치하는 알고리즘입니다. 스풀은 3D이므로 NESTING 알고리즘을 이용하기 위해 스풀을 2D(다각형)로 변환시킵니다. 이제 NESTING 알고리즘을 이용하여 2D 다각형을 최대한 많이 배치하도록 합니다. 거~의 끝났습니다.(아직 끝난게 아닙다.) 2D NESTING을 이용하여 배치했기 때문에 높이(Z) 방향으로 빈 공간이 생길 수 있습니다. 높이 방향으로 존재하는 빈 공간을 찾기 위해 Cell Decomposition을 이용하도록 하겠습니다. 패키지를 Cell로 구축합니다. Cell에서 스풀이 차지하는 공간을 제거합니다. 스풀이 차지하는 공간 제거 남은 Cell들이 빈 공간이므로 스풀의 Bounding Box를 이용하여 스풀이 들어갈 수 있는지 확인

[AutoCAD.NET] 주어진 폴리곤을 이용하여 Cloud 마크 그리기

아래와 같이 폴리곤이 주어졌을때 폴리곤 외곽선을 따라 Cloud 마크를 그리는 방안입니다. 폴리곤의 외곽선을 따라 아래와 같이 Cloud 마크를 그릴수 있습니다. AutoCAD.NET API를 이용하면 손쉽게 Cloud 마크를 생성할 수 있습니다. 폴리곤을 이루는 Vertex에 bulge값을 주면 arc가 생성됩니다. Polyline polyline = new Polylin(); polyline.AddVertexAt(index, pt, bulge, 0, 0); $(P0,P1,P2)$로 이루어지는 폴리곤에 Cloud 마크를 그리기 위해 정점$(P0,P1,P2)$ 사이에 임시 정점을 arc length만큼 띄워서 추가합니다. arc length는 상황에 맞게 설정해주면 됩니다. (사용자 옵션 혹은 폴리곤을 이루는 가장 작은 선분의 길이에 비례한 값) double dArcLength = 0.1; List<Point2d> lstPoint = new List<Point2d>(); Point2d[] corners = new Point2d[] { P0, P1, P2 }; for(int i = 0; i < corners.Length;++i) { double l = corners[(i + 1) % corners.Length].GetDistanceTo(corners[i]); int count = Convert.ToInt32(l / dArcLength); Vector2d vec = corners[(i + 1) % corners.Length] - corners[i]; Vector2d normal = vec.GetNormal(); for(int j = 0; j < count;++j) { Point2d pt = corners[i] + normal * j * dArcLength; lstPoint.Add(pt); } } 여기서 주의할 것은 폴리

컨테이너 박스에 들어갈 스풀 최대 길이 구하기

배관 자재를 운반하기 위한 컨테이너 박스에 운송비를 줄이기 위해 최대로 많은 배관 자재를 넣기 위한 방안입니다. 컨테이너 박스는 아시다시피 직육면체로 보시면 되고 배관 자재는 분기(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 그렇게 생각하면 안됩니다. 위 코드는 특정 상황에만 제대로 동작하고 예외

[S3D] Cable Tray의 Open 방향 벡터 구하기

현재 수행하고 있는 과제 중에서 기존에 그려진 Cable Way를 이용하여 Cable Way를 지나가는 Cable Tray를 자동으로 그려주는 기능이 있습니다. Cable Way가 X-Y 평면에 놓여 있을 경우에는 문제없이 잘 그려지지만 수직 방향으로 시작하는 경우에는 Cable Tray의 Open 방향이 잘못 선택되는 문제가 있습니다. 그래서 이 경우에 어떻게 Cable Tray의 Open 방향 벡터를 구하는 방법에 대해 알아보도록 하겠습니다. 제시 1) Cable Way가 시작하는 지점에서 Cable Tray의 기본 Open 방향은 아래와 같습니다. 예를 들어 Vertical Cable Way의 경우는 이렇게 생겼습니다. 우선 Vec1과 Vec2의 Cross Product를 수행하여 벡터 O를 구합니다. 그리고 Vec1과 벡터 O의 Cross Product로 벡터 X를 구합니다. 이제 벡터 X방향으로 Cable Tray의 Open 방향을 맞추면 됩니다. 벡터 O와 벡터 X의 사이 각을 구해 구한 각 만큼 Cable Tray의 단면을 회전시켜 Cable Tray를 생성하면 됩니다. 이렇게해서 Vertical일 경우 Angle을 구해 Open 방향을 찾을 수 있습니다. 단 평면을 구성할 수 있어야 하기 때문에 3점 이상이 필요합니다. 2개의 점으로 구성된 Cable Way에서 Cable Tray의 Open 방향을 맞출 수 없으므로(Open 방향을 구할 수는 있지만 맞는 방향인지는 확인할 수 없음) 사용자가 방향을 정해줘야 합니다. S3D에서는 그것이 가능합니다.!!! 확장해서 Vertical Cable Tray의 경우에 사용자 방향성을 정해 줄수 있다는 것이고 그렇게 된다면 위에서 말한 골치 아픈 계산을 하지 않고 프로그램에서 사용자가 입력한 각도만 사용하면 됩니다. 사용자 편의를 위해(각도를 입력하는 노력을 줄이는) 계산을 수행하는 것과 사용자를 잘 설득해 각도를 입력하라고 유

[GCP + CentOS8] Postgresql + Redmine 설치하기

구글 클라우드 플랫폼에 CentOS8 가상 머신을 만들었습니다. 지역으로 서울을 선택가능한데 실제로 가상 머신을 만들때 오류가 발생합니다.(2020년 4월 기준) 몇번 시도 끝에 서울이 아닌 기본으로 설정된 아이오아로 지역을 선택해서 가상 머신을 생성했습니다.(CentOS8, 100GB) 가상 머신에는 몇가지 방법으로 SSH로 접근이 가능한데 저는 Putty로 접근하는 방법을 선택했습니다. - Putty로 접근하는 방법 - Puttygen으로 공개키 생성 Generate 버튼을 누르고 마우스를 움직여줘야 프로그래스가 진행됩니다. Key comment 항목에 사용자 이름을 입력하고 다시 Generate 버튼을 눌러 키를 생생성합니다. Key passphrase를 입력한 후 Save private key 버튼을 눌러 개인키를 저장합니다. 구글 클라우드 플랫폼 콘솔에서 SSH 등록하기 구글 클라우드 플랫폼의 SSH 화면으로 이동합니다. 공개키를 복사해 GCP에 붙여넣습니다. 생성한 공개키를 통해 VM에 접근 저장한 개인키를 선택합니다. 이제 가상 머신에 접근이 가능하니 먼저 Postgresql을 설치해보도록 하겠습니다. 이미 많은 설치 가이드가 있기 때문에 새로 가이드를 작성하기 보단 아래 링크를 따라 설치하면 됩니다. CentOS8에 Postgresql 설치하기   설치한 Postgresql을 바탕으로 redmine을 설치하도록 하겠습니다. 아래 링크를 따라 설치합니다. CentOS8, Postgresql을 바탕으로 redmine 설치하기

ORA-12705: Cannot access NLS data files or invalid environment specified

갑자기 사용자 PC에서 ORA-12705 문제가 발생하여 오라클에 접속이 불가능하다고 연락이 왔습니다. 잘 사용하던 프로그램이 갑자가 안된다고 합니다. 인터넷으로 검색하던 중 환경변수에 설정을 하면 된다고 하는데 한번 해봐야 겠습니다. -- 아래는 펌글(http://guisin.net/96) -- NLS 데이터 파일에 액세스할 수 없거나 부적합한 환경이 지정되었습니다. 기존 라이브러리를 추출하던중 나타난 접속 오류. 해당 노트북에는 Oracle 9i, Toad 10.6, instantclient 10 이 설치되어 있었다. 해결 방법 : [내 컴퓨터] - [시스템 등록 정보] - [고급] - [환경변수] 에 들어가서 아래의 [시스템 변수] 에 추가 ( 변수 : NLS_LANG | 값 : KOREAN_KOREA.KO16MSWIN949 ) 시스템 변수 에 NLS_LANG 을 추가한다.(새로 만들기)

조건에 맞는 아이템들끼리 그룹 만들기

아래 그림에서 주어진 조건으로 grouping하여 두번째와 같은 결과를 만드는 문제입니다. [1,2,3,5], [4,11,7,8,9], [6,10] 각각 같은 조건을 가지고 있음 조건 : Package, Fluid, Material이 같고 연결된 아이템(물리적으로 연결되어 있으나 노즐이나 OPC에서는 끊김) 기능 : 아이템에서 연결된 아이템들은 찾을 수 있음(1번에 연결된 아이템은 2,3임) 알고리즘 [그림 1]을 다음과 같이 간략화 시킬수 있습니다. all = [1,2,3,4,5,6,7,8,9,10,11,12] 조건에 맞게 grouping합니다. packages = [] while all: item = all.pop() package = group(item) packages.append(package) package.consume(all) 위 루프는 무한 루프에 빠지지 않습니다.(최악의 경우 아이템 수만큼 패키지가 생성됨) group 클래스 class group: def __init__(self, item): self.members = [item] def consume(self, all): """group을 구성한다""" stack = self.members while stack: item = stack.pop() connected_items = self.get_connected_items(item, all) for connected in connected_items: if connected is Equipment or connected is OPC: all.remove(connected) continue if self.members[0].package == c