Bắt đầu
Việc lấy về thông tin thuộc tính của đối tượng là việc quan trọng nhất trong các khâu xử lí đối tượng, bởi vì dữ liệu là quan trọng.Vì vậy bài viết hôm nay sẽ tập trung giúp bạn lấy về tất các các thông tin thuộc tính đang có trong Navisworks từ Clash Test mà bạn muốn lấy.Việc lấy dữ liệu đòi hỏi người lấy cần có kinh nghiệm và người cho dữ liệu cần chính xác để kết quả thống kê không bị sai lệch.Thường thì các công việc lấy thuộc tính đối tượng được sử dụng rất nhiều cho các mục đích khác nhau như:
- Thống kê dữ liệu
- Phân tích dữ liệu
- Thêm mới thuộc tính
- Sử dụng dữ liệu chuyển đổi sang một bên thứ ba
- Thay đổi dữ liệu.
- ...
Bạn có thể xem một mẫu danh sách thuộc tính đối tượng cần lấy như sau:
Tìm hiểu dữ liệu
Cào data: Đây cũng là một khái niệm không mấy xa lạ với các Data Science chuyên cào dữ liệu.Đối với một mô hình lớn, vô tình dữ liệu này khiến chúng trở nên to lớn hơn bao giờ hết.Chúng ta hãy thử tính nhẩm một đối tượng bao gồm hàng trăm thông tin thuộc tính và một mô hình chứa hàng triệu đối tượng.
Để hiểu về API và cách làm việc để lấy về các thuộc tính đối tượng, ta cần hiểu và nắm rõ các thông tin cơ bản như :
1.Category: Là loại thuộc tính đối tượng cần lấy.
2.Property: Là tên thuộc tính đối tượng cần lấy.
3.Value: Là giá trị dữ liệu của thuộc tính đối tượng cần lấy.
Đối với Clash Test, ta cũng cần làm rõ các thông tin đối tượng nhận biết trước khi tham chiếu đến API:
1.Clash(Clash Result) giao nhau giữa các đối tượng trong một Clash Test.
2.Clash(Clash Test) Test cho người dùng tạo ra để kiểm tra xung đột, bao gồm hiển thị số lượng Clash Result, Status,Resolved, ...
Dựa vào các thông tin cơ bản đã nắm , bạn có thể dễ dàng triển khai API để lấy về các thuộc tính đối tượng.
Kiểm tra thuộc tính đối tượng
Bạn có thể dùng NavisLookup để kiểm tra nhanh thông tin thuộc tính cần lấy để biết được vị trí API cần lấy.
Đối với công cụ AppInfo, bạn cũng có thể kiểm tra nhanh chóng và dễ dàng.Ở đây sẽ có 5 Categories được tìm thấy và nhiệm vụ của chúng ta là viết mã để lấy dữ liệu thông tin từ chúng.
1.Clash Test.
2.Các kết quả kiểm tra của một Clash Test(Clash Result).
3.Hàm lấy về thông tin thuộc tính đối tượng.
Một mã đơn giản sẽ được viết như sau:
public override void Action() | |
{ | |
GetInfoClash(); | |
} | |
void GetInfoClash() | |
{ | |
Document doc = Application.ActiveDocument; | |
DocumentClash documentClash = doc.GetClash(); | |
foreach (SavedItem savedItem in documentClash.TestsData.Tests) | |
{ | |
ClashTest clashTest = (ClashTest) savedItem; | |
SavedItemCollection savedItemCollection = clashTest.Children; | |
foreach (SavedItem item in savedItemCollection) | |
{ | |
ClashResult clashResult = item as ClashResult; | |
if (clashResult != null) | |
{ | |
PropertyCategoryCollection categories = clashResult.Item1.PropertyCategories; | |
foreach (PropertyCategory category in categories) | |
{ | |
Logger.WriteLine(category.DisplayName); | |
GetPropertiesClashTest(category); | |
} | |
break; | |
} | |
} | |
} | |
Logger.Open(); | |
} | |
void GetPropertiesClashTest(PropertyCategory propertyCategory) | |
{ | |
foreach (DataProperty dataProperty in propertyCategory.Properties) | |
{ | |
Logger.Write($"||Name:{dataProperty.Name}"); | |
Logger.Write($"||DisplayName:{dataProperty.DisplayName}"); | |
Logger.Write($"||Value:{dataProperty.Value}"); | |
Logger.Write($"||CombinedName:{dataProperty.CombinedName}"); | |
Logger.Write("\n"); | |
} | |
} |
Chúng ta sử xem một vài kết quả thu được từ việc lấy thông tin đối tượng.
Lấy về chính xác dữ liệu
Thoạt nhiên, các thuộc tính không bao giờ có kiểu dữ liệu là một mà sẽ có rất nhiều kiểu dữ liệu của các giá trị trả về.Vì vậy để đảm bảo đồng nhất kết quả giá trị lấy về, ta sẽ thống nhất chuyển đổi toàn bộ giá trị sang chuỗi để làm việc.
public static dynamic ToVarDisplayString(this VariantData variantData) | |
{ | |
switch (variantData.DataType) | |
{ | |
case VariantDataType.None: | |
return variantData.ToString(); | |
case VariantDataType.Double: | |
return variantData.ToDouble(); | |
case VariantDataType.Int32: | |
return variantData.ToInt32(); | |
case VariantDataType.Boolean: | |
return variantData.ToBoolean(); | |
case VariantDataType.DisplayString: | |
return variantData.ToDisplayString(); | |
case VariantDataType.DateTime: | |
return variantData.ToDateTime(); | |
case VariantDataType.DoubleLength: | |
return variantData.ToDoubleLength(); | |
case VariantDataType.DoubleAngle: | |
return variantData.ToDoubleAngle(); | |
case VariantDataType.NamedConstant: | |
return variantData.ToNamedConstant(); | |
case VariantDataType.IdentifierString: | |
return variantData.ToIdentifierString(); | |
case VariantDataType.DoubleArea: | |
return variantData.ToDoubleArea(); | |
case VariantDataType.DoubleVolume: | |
return variantData.ToDoubleVolume(); | |
case VariantDataType.Point3D: | |
return variantData.ToPoint3D(); | |
case VariantDataType.Point2D: | |
return variantData.ToPoint2D(); | |
default: | |
return variantData.ToString(); | |
} | |
} |
Nếu nhìn kĩ thông tin bên trên.Do bạn lấy thông tin từ Children Item của Clash Result.Chính vì vậy nếu các loại thuộc tính là loại bên ngoài hoặc thuộc tính tuỳ chỉnh sẽ không thể lấy hết.Do đó bạn cần sửa đổi một chút trong mã của mình.Thuộc tính CompositeItem1 sẽ cho phép bạn lấy về đầy đủ thông tin hơn bao giờ hết.
Cào dữ liệu
Các công việc đã thực hiện xong, bây giờ công việc chính xác của mình là cào dữ liệu về và sử dụng, các thông tin sẽ được ngăn cách nhau bởi một kí tự đặc biệt.
List<string> Categories = new List<string>(); | |
public override void Action() | |
{ | |
GetPropertysFromClashTest(); | |
IEnumerable<string> distinct = Categories.Distinct(); | |
Logger.WriteLine("========================================================="); | |
Logger.WriteLine("Result Report:"); | |
Logger.WriteLine($"Total Categories:{distinct.Count()}"); | |
Logger.WriteLine($"Categorys:{string.Join(",", distinct)}"); | |
Logger.Open(); | |
} | |
/// <summary> | |
/// case user want get all properties full from clash | |
/// </summary> | |
void GetPropertysFromClashTest() | |
{ | |
StringBuilder sb = new StringBuilder(); | |
Document doc = Application.ActiveDocument; | |
DocumentClash documentClash = doc.GetClash(); | |
foreach (SavedItem savedItem in documentClash.TestsData.Tests) | |
{ | |
ClashTest clashTest = (ClashTest) savedItem; | |
SavedItemCollection savedItemCollection = clashTest.Children; | |
foreach (SavedItem item in savedItemCollection) | |
{ | |
ClashResult clashResult = item as ClashResult; | |
if (clashResult != null) | |
{ | |
PropertyCategoryCollection categories = clashResult.CompositeItem1.PropertyCategories; | |
foreach (PropertyCategory category in categories) | |
{ | |
GetPropertiesClashTest(category); | |
} | |
PropertyCategoryCollection categories2 = clashResult.CompositeItem2.PropertyCategories; | |
foreach (PropertyCategory category in categories2) | |
{ | |
GetPropertiesClashTest(category); | |
} | |
//Only test for one clash result | |
break; | |
} | |
} | |
} | |
} | |
void GetPropertiesClashTest(PropertyCategory propertyCategory) | |
{ | |
Logger.WriteLine(propertyCategory.DisplayName); | |
Categories.Add(propertyCategory.DisplayName); | |
foreach (DataProperty dataProperty in propertyCategory.Properties) | |
{ | |
Logger.Write($"Name:{dataProperty.Name}"); | |
Logger.Write($"║ DisplayName:{dataProperty.DisplayName}"); | |
Logger.Write($"║ Value:{dataProperty.Value.ToVarDisplayString()}"); | |
Logger.Write($"║ CombinedName:{dataProperty.CombinedName}"); | |
Logger.WriteLine(""); | |
} | |
} |
Kết quả thật là hoàn hảo phải không nào.Và để làm cho hàng triệu đối tượng, có lẽ mình phải treo máy hàng giờ đồng hồ mất.Để hiểu rõ hơn vê các mã bên trên bạn cũng có thể tham khảo mã hoàn chỉnh tại Source Code Sample
Đánh giá dữ liệu
Nhìn chung các dữ liệu khá lớn vì vậy có lẽ mình sẽ viết tiếp ở phần sau nếu có thời gian!
Mã nguồn mở cuối tuần
- Say Hello to PyScript : Hãy chào đón https://pyscript.net/, cho phép bạn viết python bên trong HTML
- RhodoniteTS : Một mã nguồn mở https://github.com/actnwit/RhodoniteTS sử dụng Web3D trong TypeScript rất đáng xem.