I want to extract point clouds from NURBS. However, it doesnโt seem to have that function within Rino.
Do I have to convert to mesh and use a program like MeshLab? However, in this case, polyline is omitted. Is there any extension that includes polyline and mesh together?
Itโs possible with Rhino 8 but Iโm pretty sure youโll have to convert the NURBS to a mesh first no matter whatโฆ
Yes, you will have to mesh the object(s) first with the desired density, you can then just run ExtractPt on the selected mesh(es) and polyline(s) with the CreatePointCloud option set to Yes.
I think you can run ExtractPt on the NURBS object directly, but in that case I believe you will only get the control points, which may not be dense enough for your point cloud.
The control points will not be on the surface in general.
Yep, youโre absolutely right, I was thinking of the SolidEdit pointsโฆ I actually donโt know what ExtractPt does on polysurfaces, not where I can test right now.
increase isocurve density (no idea if that is scriptable) then ExtractIsocurve with options both
and all
then Intersect.
Divide command to place points along a curve.
PointCloud command to create a point cloud.
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')
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?
Hello- โimport Rhino as rhโ at the top, rather than rhino3dm .
-Pascal
Import โRhinoโ could not be resolved
Do you know what I need to install?
Hi @์ฅ์ ๊ฒฝ,
Can you explain in detail what you are trying to do and why? Why do you want or need a point cloud from a NURBS surface?
Thanks,
โ Dale