Day 18
(4)
波打つサーフェイスにレンガを等高で配置
#surface#pattern#wave#contour#alignment#parametric

✅ Inputs
- brick_w: float – レンガの幅(X方向)
- brick_h: float – レンガの高さ(Z方向)
- brick_d: float – レンガの奥行き(Y方向)
- gap_x: float – 横方向の隙間(X方向目地)
- gap_z: float – 段ごとの隙間(Z方向目地)
- num_x: int – X方向に並べるレンガ数
- num_z: int – Z方向に積むレンガ段数
- wave_cycles_x: float – X方向に入れる波の繰り返し数
- wave_cycles_z: float – Z方向に入れる波の繰り返し数
- amp_x: float – X方向の波の振幅
- amp_z: float – Z方向の波の振幅
✅ Outputs
- results: list of Box – サーフェイス形状に沿って積まれたレンガの集合体
✅ Code
# === 🔧 入力パラメータ例 ===
# brick_w = 200.0
# brick_h = 60.0
# brick_d = 100.0
# gap_x = 10.0
# gap_z = 10.0
# num_x = 20
# num_z = 50
# wave_cycles_x = 2.0
# wave_cycles_z = 2.0
# amp_x = 150.0
# amp_z = 150.0
import Rhino.Geometry as rg
import math
size_x = num_x * (brick_w + gap_x)
size_z = num_z * (brick_h + gap_z)
freq_x = wave_cycles_x * math.pi * 2 / size_x
freq_z = wave_cycles_z * math.pi * 2 / size_z
count_x = num_x
count_z = num_z
points_grid = []
for i in range(count_z + 1):
row = []
t_z = float(i) / count_z
z = t_z * size_z
for j in range(count_x + 1):
t_x = float(j) / count_x
x = t_x * size_x
y = math.sin(x * freq_x) * amp_x + math.sin(z * freq_z) * amp_z
pt = rg.Point3d(x, y, z)
row.append(pt)
points_grid.append(row)
flat_points = [pt for row in points_grid for pt in row]
surf = rg.NurbsSurface.CreateThroughPoints(
flat_points, count_z + 1, count_x + 1, 3, 3, False, False
)
# === ✂️ 等高カーブ取得 + Box配置 ===
brep = rg.Brep.CreateFromSurface(surf)
results = []
for i in range(num_z):
z = i * (brick_h + gap_z)
plane = rg.Plane(rg.Point3d(0, 0, z), rg.Vector3d(0, 0, 1))
contours = rg.Brep.CreateContourCurves(brep, plane)
if not contours:
continue
for curve in contours:
spacing = brick_w + gap_x
params = curve.DivideByLength(spacing, True)
for p in params:
pt = curve.PointAt(p)
tangent = curve.TangentAt(p)
tangent.Unitize()
xaxis = tangent
zaxis = rg.Vector3d(0, 0, 1)
yaxis = rg.Vector3d.CrossProduct(zaxis, xaxis)
yaxis.Unitize()
plane = rg.Plane(pt, xaxis, yaxis)
# 奇数段だけ X方向に半レンガずらす
if i % 2 == 1:
shift_vec = rg.Vector3d(xaxis) * (brick_w + gap_x) / 2
plane.Origin += shift_vec
# レンガBoxを配置
box = rg.Box(
plane,
rg.Interval(-brick_w / 2, brick_w / 2),
rg.Interval(-brick_d / 2, brick_d / 2),
rg.Interval(0, brick_h)
)
results.append(box)