# Surface to mesh python

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')
``````

The syntax error in your Python script seems to be related to the use of an f-string, which is a feature introduced in Python 3.6. If you’re encountering a syntax error with the f-string, it could be due to running the script in an environment with a Python version earlier than 3.6.

To fix this, you can modify the string formatting to be compatible with older versions of Python

``````save_curves_as_dxf(curves, '{}.dxf'.format(filename))
convert_to_mesh_and_save_as_ply(objects, '{}.ply'.format(filename))
``````

or

``````save_curves_as_dxf(curves, filename + '.dxf')
convert_to_mesh_and_save_as_ply(objects, filename + '.ply')
``````
1 Like

Hi @장유경,

The openNURBS toolkit, on which Rhino3dm is based on, does not tesselate (mesh) surfaces or Breps.

More limitations of openNURBS:

Hope this helps.

– Dale

1 Like

So can’t I convert the surface to mesh in this code??

Hi @장유경,

Not using Rhino3dm. You’ll need full Rhino in order to do this, which can include Rhino.Inside and Rhino.Compute.

– Dale

1 Like