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)