Skip to main content
Cập nhật lần cuối: 25/03/2026

Data Tree trong Grasshopper: Tại sao script của bạn cho kết quả sai và cách fix

Bạn vừa kết nối một loạt component, nhấn preview, và Rhino viewport hiển thị... hoàn toàn không phải thứ bạn muốn. Geometry bị lệch, số lượng element nhân lên gấp đôi không rõ lý do, hoặc tệ hơn - không có gì cả. Bạn kiểm tra từng wire, từng input, nhưng mọi thứ trông có vẻ đúng. Khả năng cao, bạn đang gặp vấn đề với Data Tree - cấu trúc dữ liệu phân cấp của Grasshopper mà hầu hết mọi người học theo kiểu "bị nó hành thì mới hiểu."

Bài viết này sẽ giúp bạn hiểu Data Tree trước khi nó hành bạn.


Data Tree là gì - và tại sao Grasshopper cần nó

Ở mức cơ bản nhất, Grasshopper xử lý dữ liệu qua ba dạng container: Item (một giá trị đơn), List (danh sách phẳng), và Data Tree (cây dữ liệu phân cấp).

Hãy hình dung một tòa nhà nhiều tầng. Mỗi tầng có nhiều căn phòng, mỗi phòng có nhiều đồ vật. Nếu bạn muốn mô tả một chiếc ghế cụ thể, bạn cần địa chỉ đầy đủ: tầng 3, phòng 5, ghế thứ 2. Đó chính xác là cách Data Tree hoạt động - mỗi piece of data nằm trong một branch (nhánh), và mỗi branch được xác định bởi một path (đường dẫn) dạng {0;1;2}.

Tại sao Grasshopper cần cấu trúc phức tạp này? Vì kiến trúc vốn dĩ phân cấp. Một tòa nhà có nhiều tầng, mỗi tầng có nhiều phòng, mỗi phòng có nhiều tường, mỗi tường có nhiều panel. Khi bạn chia một grid thành các row và column, kết quả tự nhiên cần được lưu trữ theo cấu trúc đó - hàng nào thuộc hàng nào, cột nào thuộc cột nào - để các thao tác sau có thể xử lý đúng ngữ cảnh.


Đọc Data Tree trong Grasshopper

Trước khi fix được lỗi, bạn phải đọc được dữ liệu đang có. Có ba cách:

Panel component là công cụ cơ bản nhất. Nối bất kỳ output nào vào một Panel, bạn sẽ thấy toàn bộ cấu trúc: path của từng branch, số lượng item trong mỗi branch, và giá trị cụ thể. Đây là thứ đầu tiên bạn nên làm khi debugging.

Param Viewer (trong tab Params > Util) hiển thị cấu trúc dạng cây trực quan hơn - bạn thấy ngay bao nhiêu branch, bao nhiêu item mỗi branch, mà không bị ngập trong số liệu.

Grasshopper Preview trên Rhino viewport cũng cho bạn thấy kết quả trực quan, nhưng đây là cách cuối cùng bạn nên dùng để debug - nó cho thấy kết quả, không phải nguyên nhân.

Tip thực chiến: Khi một script cho kết quả lạ, việc đầu tiên là thêm Panel vào output của từng component "nghi phạm". Nhìn vào path structure - nếu bạn thấy {0;0}, {0;1}, {1;0}, {1;1}... thì bạn đang có Data Tree 2 cấp. Nếu chỉ thấy {0} - đó là flat list.


Cách Data Tree được tạo ra

Hiểu khi nào Data Tree xuất hiện giúp bạn phòng ngừa thay vì chữa cháy.

Divide Surface là ví dụ điển hình. Khi bạn chia một surface thành UxV grid, output Points sẽ được tổ chức theo nhánh: mỗi nhánh {0;i} chứa tất cả các điểm trong cột i. Đây là cấu trúc tự nhiên và thường hữu ích - nó giữ nguyên thông tin "điểm này thuộc cột nào."

Explode Mesh hay Brep Faces cũng tạo Data Tree khi bạn có nhiều input. Nếu bạn đưa vào 3 Brep, output sẽ có 3 branch tương ứng - branch {0} cho Brep đầu tiên, {1} cho cái thứ hai, v.v.

Graft (nhánh hóa) là thao tác cố tình tạo thêm cấp trong Data Tree. Khi bạn right-click một input hoặc output và chọn Graft, mỗi item sẽ được đẩy vào branch riêng của nó. Nghe có vẻ phức tạp thêm, nhưng đây lại là kỹ thuật bạn sẽ dùng rất thường xuyên.


Ba thao tác cốt lõi để kiểm soát Data Tree

Flatten - Dẹp phẳng mọi thứ

Flatten loại bỏ toàn bộ cấu trúc phân cấp, gộp tất cả item vào một list phẳng duy nhất trong branch {0}. Thao tác này thường dùng khi bạn chỉ cần đếm tổng số lượng, hoặc khi component tiếp theo không cần biết item đến từ branch nào.

Cẩn thận: Flatten là thao tác một chiều - bạn không thể khôi phục cấu trúc phân cấp gốc sau khi đã flatten, trừ khi bạn còn nguồn dữ liệu gốc.

Graft - Tạo thêm cấp phân cấp

Graft làm ngược lại: mỗi item được tách ra thành branch riêng. Nếu bạn có list {0}: [A, B, C], sau Graft bạn có {0;0}: [A], {0;1}: [B], {0;2}: [C].

Khi nào cần Graft? Khi bạn muốn áp dụng một thao tác cho từng item độc lập với nhau. Ví dụ điển hình: bạn có 5 đường cong và muốn chia mỗi đường thành số điểm khác nhau - Graft đường cong trước khi kết nối vào Divide Curve.

Simplify - Dọn dẹp path thừa

Simplify giữ nguyên cấu trúc tương đối của Data Tree nhưng loại bỏ các cấp path không cần thiết. Nếu tất cả data nằm trong {0;0;0}, {0;0;1}, {0;0;2}... - Simplify sẽ rút gọn thành {0}, {1}, {2}. Thao tác này giúp path trở nên dễ đọc hơn mà không mất thông tin.


Data Matching - Khi Grasshopper ghép dữ liệu

Đây là phần mà nhiều người dùng Grasshopper lâu năm vẫn còn nhầm lẫn.

Khi bạn kết nối hai input có số lượng branch hoặc item không khớp nhau, Grasshopper phải quyết định cách ghép chúng. Mặc định là Longest List - Grasshopper lặp lại item cuối cùng của list ngắn hơn cho đến khi khớp với list dài hơn.

Ví dụ: bạn muốn tạo cylinder tại 10 điểm với bán kính khác nhau. Nếu bạn đưa vào 10 điểm nhưng chỉ có 3 giá trị bán kính [1.0, 1.5, 2.0], Grasshopper sẽ dùng 2.0 cho điểm thứ 4 đến thứ 10. Đây không phải lỗi - đây là behavior có chủ ý, nhưng bạn cần biết nó đang xảy ra.

Warning: Sự không khớp giữa Data Tree structure (không phải chỉ số lượng item) là nguồn gốc của hầu hết các lỗi kỳ lạ trong Grasshopper. Khi kết quả trông sai, hãy kiểm tra xem hai input có cùng số branch và cấu trúc path không trước khi làm bất cứ thứ gì khác.


Các component chuyên biệt cho Data Tree

Khi Flatten/Graft/Simplify chưa đủ, Grasshopper có cả một bộ component trong Sets > Tree:

Entwine - gộp nhiều Data Tree thành một, với mỗi tree gốc trở thành một branch cấp cao nhất. Hữu ích khi bạn muốn giữ nguyên cấu trúc của từng tree nhưng đặt chúng vào container chung.

Path Mapper - công cụ mạnh nhất và khó nhất. Cho phép bạn viết lại path theo ý muốn bằng cú pháp {A;B;C} -> {C;A}. Nếu bạn cần hoán đổi thứ tự branch hoặc tạo cấu trúc phân cấp tùy chỉnh, đây là component bạn cần - nhưng hãy chuẩn bị tinh thần đọc documentation kỹ.

Tree StatisticsExplode Tree giúp bạn trích xuất thông tin về cấu trúc (tổng số branch, số item mỗi branch, danh sách path) hoặc tách tree thành các list riêng lẻ để xử lý.


Takeaway

Data Tree không phải bug, không phải tính năng phức tạp được thêm vào để làm khó người dùng. Nó là cách Grasshopper mô hình hóa sự phức tạp phân cấp của kiến trúc theo cách mà máy tính có thể xử lý hiệu quả. Một khi bạn quen với nó, bạn sẽ bắt đầu thiết kế Data Tree của mình thay vì chỉ phản ứng với nó.

Năm điểm cần nhớ:

  1. Luôn dùng Panel để xem cấu trúc dữ liệu khi debugging - không đoán mò.
  2. Flatten khi bạn không cần biết nguồn gốc của từng item. Graft khi bạn muốn xử lý từng item độc lập.
  3. Hai input ghép nhau phải có cùng cấu trúc branch - không chỉ cùng số lượng item.
  4. Simplify thường xuyên để path không bị cồng kềnh không cần thiết.
  5. Khi gặp kết quả lạ, kiểm tra Path structure trước, kiểm tra logic sau.

Bước tiếp theo: mở một definition cũ của bạn và thêm Panel vào mọi output. Nhìn xem cấu trúc Data Tree trông như thế nào ở từng bước. Đây là bài tập tốt nhất để xây dựng intuition - không có shortcut nào thay thế được việc thấy dữ liệu chạy qua từng component.