본문 바로가기
STL/stl - cutting하기

[파이썬] STL을 평면으로 자르기 #1. 교점구하기

by 만다린망고 2021. 10. 26.
반응형

STL과 내가 지정한 평면 사이의 교점을 얻는 코드를 짜보았다. 고양이 모델을 사용했다. 먼저 사용한 고양이 모델을 공유한다. 

 

CAT.stl
3.37MB

 

 

 

평면을 하나 만들고 교점을 구했다. 평면은 skspatial 패키지를 사용했다. STL을 불러와 교점을 구하는데는 numpy-stl 패키지를 사용했고, 시각화에는 pyvista 패키지를 사용했다. 

 

평면,선 등 정의 및 계산 : skspatial 패키지

STL 불러와 계산 : numpy-stl 패키지

시각화 : pyvista 패키지

 

결과는 아래와 같다. 

 

 

코드는 아래와 같다. 설명은 주석에 써놓았다. 

 

import os
import numpy as np
import pyvista as pv

from skspatial.objects import Plane
from skspatial.objects import Point
from skspatial.objects import Line


#STL 가져오기
ctl = pv.read('python_stl\CAT.stl') #STL 불러오기

#교점 찾기
inter_point=np.zeros(3) #교점이 저장될 변수

pl=Plane([0,-160,0],[0,1,0]) #원하는 평면

for i in range(ctl.n_cells-1): #교점을 찾는 for문
    p1=ctl.cell_points(i)[0]
    p2=ctl.cell_points(i)[1]
    p3=ctl.cell_points(i)[2]

    if pl.side_point(p1)*pl.side_point(p2)==-1 :
        inter_point=np.vstack((inter_point,pl.intersect_line(Line.from_points(p1,p2))))

    if pl.side_point(p1)*pl.side_point(p3)==-1 :
        inter_point=np.vstack((inter_point,pl.intersect_line(Line.from_points(p1,p3))))

    if pl.side_point(p2)*pl.side_point(p3)==-1 :
        inter_point=np.vstack((inter_point,pl.intersect_line(Line.from_points(p2,p3))))

inter_point=inter_point[1:,] #찾은 교점에서 더미로 입력한 [0,0,0] 제거

print(inter_point) #교점 출력해보기



##시각화하기

pvpoint=pv.PolyData(inter_point) #교점을 PolyData 형식으로 변환

p = pv.Plotter() # 캔버스 정의 
p.add_mesh(ctl, opacity=1, color='red') # STL 시각화
p.add_mesh(pvpoint,point_size=5,style='points') # 교점 시각화
p.show() #그래프 보이기

 

원리를 간단히 설명하겠다. pv.read 로 stl 을 불러와서 ctl에 입력했다. stl 은 삼각형 매쉬로 구성되어 있는데 pyvista 로 불러올 경우 각 매쉬는 cell 이라고 불린다. cell_points 메소드로 각 cell에 접근할 수 있다. 각 cell에 접근해서 세 점을 얻고 p1,p2,p3 에 입력한다. 

 

각 점이 평면의 어느 쪽에 있는지를  판단하기 위해 우리가 정의한 평면의 sidepoint 라는 메소드를 사용한다. 결과는 1 또는 -1이다. 

 

한 매쉬를 이루고 있는 세 점중 두점을 선택하는 방법은 세가지다. if문에서는 (p1,p2) (p1,p3) (p2,p3) 각 쌍이 평면의 같은 쪽에 있는지 아닌지를 판단한다. 서로 다른 쪽에 있는 경우 두 점을 연결한 선분과 평면사이의 교점이 생기고, 이 교점을 저장한다. 

반응형

댓글