First I’m working on a code that converts files and generates a mesh. An error occurs while converting surface to mesh.
Traceback (most recent call last):
File “C:\Users\jjang\Desktop\YG2\nurbs_file\convert_file.py”, line 113, in
convert_to_mesh_and_save_as_ply(objects, f’{filename}.ply’)
File “C:\Users\jjang\Desktop\YG2\nurbs_file\convert_file.py”, line 75, in convert_to_mesh_and_save_as_ply
mesh = rh.Mesh.CreateFromSurface(surface)
AttributeError: type object ‘rhino3dm._rhino3dm.Mesh’ has no attribute ‘CreateFromSurface’
Is there any other good way to generate mesh on surface?
import math
import rhino3dm
import rhino3dm as rh
import ezdxf
from ezdxf.math import BSpline
import numpy as np
from plyfile import PlyData, PlyElement
import os
# 곡선을 DXF 파일로 저장하는 함수
def save_curves_as_dxf(curves, filename):
doc = ezdxf.new('R2010')
msp = doc.modelspace()
for curve in curves:
if isinstance(curve, rh.LineCurve): # 직선 곡선
start = curve.PointAtStart
end = curve.PointAtEnd
msp.add_line((start.X, start.Y, start.Z), (end.X, end.Y, end.Z))
elif isinstance(curve, rh.ArcCurve):
arc = curve.Arc
# 아크의 중심, 반지름, 시작 각도, 끝 각도를 사용
msp.add_arc(
center=(arc.Center.X, arc.Center.Y, arc.Center.Z),
radius=arc.Radius,
start_angle=math.degrees(arc.StartAngle),
end_angle=math.degrees(arc.EndAngle),
is_counter_clockwise=True
)
elif isinstance(curve, rh.NurbsCurve):
# 곡선의 파라미터 범위를 얻음
t0 = curve.Domain.T0 # 시작 파라미터
t1 = curve.Domain.T1 # 끝 파라미터
point_count = max(100, len(curve.Points) * 2) # 충분한 분해능을 위해 점의 개수 조정
points = []
# 곡선을 여러 점들로 이산화
for i in range(point_count + 1):
t = t0 + (t1 - t0) * i / point_count
pt = curve.PointAt(t)
points.append((pt.X, pt.Y, pt.Z))
# 폴리라인으로 변환된 점들을 DXF 파일에 추가
msp.add_lwpolyline(points)
elif isinstance(curve, rh.PolylineCurve):
polyline = curve.ToPolyline() # PolylineCurve를 Polyline 객체로 변환
points = [(pt.X, pt.Y, pt.Z) for pt in polyline] # Polyline의 점들을 가져옴
msp.add_lwpolyline(points)
doc.saveas(filename)
def explode_brep_to_surfaces(brep):
return [brep.Faces[i].UnderlyingSurface() for i in range(len(brep.Faces))]
def convert_to_mesh_and_save_as_ply(objects, filename):
vertices = [] # 메시의 정점들을 저장할 리스트
faces = [] # 메시의 면들을 저장할 리스트
for obj in objects:
surfaces = []
if isinstance(obj, rh.Brep):
# Brep을 개별 서피스로 분해
surfaces.extend(explode_brep_to_surfaces(obj))
elif isinstance(obj, rh.Surface):
# 서피스 객체인 경우 리스트에 추가
surfaces.append(obj)
for surface in surfaces:
mesh = rh.Mesh.CreateFromSurface(surface)
if mesh:
start_index = len(vertices)
vertices.extend([v for v in mesh.Vertices])
faces.extend([[v + start_index for v in f] for f in mesh.Faces])
# 정점과 면 데이터를 PlyElement 형식으로 변환
vertex_element = np.array(vertices, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
face_element = np.array(faces, dtype=[('vertex_indices', 'i4', (3,))])
ply_data = PlyData([PlyElement.describe(vertex_element, 'vertex'),
PlyElement.describe(face_element, 'face')], text=True)
ply_data.write(filename)
pass
# 파일에서 포인트 클라우드 추출하는 함수
def extract_pointcloud_from_file(filename):
# 파일 형식에 따른 포인트 클라우드 추출 로직 필요
return np.random.rand(100, 3) # 예시: 랜덤 포인트 클라우드 생성
# 두 포인트 클라우드를 병합하여 PLY 파일로 저장하는 함수
def merge_and_save_pointclouds_as_ply(pointcloud1, pointcloud2, filename):
merged_pointcloud = np.vstack((pointcloud1, pointcloud2))
# PLY 파일 저장 로직 구현 필요
pass
# Rhino 3dm 파일 불러오기
model = rh.File3dm.Read('C:/Users/jjang/Desktop/YG2/nurbs_file/1113.3dm')
# 객체 분류
curves = [obj.Geometry for obj in model.Objects if obj.Geometry.ObjectType == rh.ObjectType.Curve]
objects = [obj.Geometry for obj in model.Objects if obj.Geometry.ObjectType in [rh.ObjectType.Brep, rh.ObjectType.Surface]]
# 파일 이름 추출 (확장자 제외)
filename = os.path.splitext('C:/Users/jjang/Desktop/YG2/nurbs_file/1113.3dm')[0]
# DXF 및 PLY 파일 저장
save_curves_as_dxf(curves, f'{filename}.dxf')
convert_to_mesh_and_save_as_ply(objects, f'{filename}.ply')
# 포인트 클라우드 추출 및 병합
#pointcloud_dxf = extract_pointcloud_from_file(f'{filename}.ply')
#pointcloud_ply = extract_pointcloud_from_file(f'{filename}.ply')
#merge_and_save_pointclouds_as_ply(pointcloud_dxf, pointcloud_ply, f'{filename}_merged.ply')