AMCAX Kernel
Geometry kernel for CAD/CAE/CAM
九韶内核 1.0.0.0
载入中...
搜索中...
未找到
附加属性示例

概述

九韶内核的拓扑和几何不带附加属性的,为了支持给 TopoShape 挂载属性,应用框架引入 AMCAX::Label。其上关联一个 TopoShape 和一组属性。此外,提供一组 WithAttr 模板类,这组类是对内核建模接口的封装,其上提供了 GetResultLabel,用于获取结果 Label。

命名空间

为了示例代码清晰,使用命名空间。

using namespace AMCAX;
AMCAX 内核提供的所有接口所在的命名空间。
定义 misc.docu:8

附加属性示例一

通过 AMCAX::WithAttr 获取 Label

通过 WithAttr 获取 Label,并为 Label 附加属性。WithAttr 使用上存在两种形式,一种形式是通过 AMCAX 内核构建一个 TopoShape,并通过 WithAttr<TopoShape> 进行构建,另一种形式是使用参数化建模,所支持的带属性参数化建模接口的详细列表参见 API 列表。

TopoShape topoShape = MakeBox(5., 5., 5.);
WithAttr<TopoShape> shapeWithAttr(topoShape);
Label boxLabel = shapeWithAttr.GetResultLabel();
WithAttr<MakeCylinder> cylinder{5., 10.};
Label cylinderLabel = cylinder.GetResultLabel();
The class of Label
定义 Label.hpp:26
创建立方体的类
定义 MakeBox.hpp:18
形状的基类,包含具有位置和方向信息的基础形状
定义 TopoShape.hpp:15
The class of WithAttr
定义 WithAttrBase.hpp:381

为面挂载属性

Label 上提供了获取面上 Label 的接口 GetFaceLabels,用于获取 Label上所有的 Face Labels。AttributeTool 提供了更新/设置Label上属性的工具函数。注意,同一个 Label 上属性 ID 一样的属性只能存在一份,若想给一个 Label 挂载相同类型的不同属性对象,需要指定不同的属性ID。下面给出在 Label 上挂载属性的例子:

std::vector<Label> boxFaceLabels = boxLabel.GetFaceLabels();
std::vector<Label> cylinderFaceLabels = cylinder.GetAllFaceLabel();
Label boxFace_1 = boxFaceLabels.front();
Label boxFace_3 = boxFaceLabels[2];
Label cylinderFace_1 = cylinderFaceLabels.front();
auto color = std::make_tuple(1., 0., 0., 1.);
AttributeTool::Set<ColorAttribute>(boxFace_1, AMCAX::construct_anonymous_attr, color);
AttributeTool::Set<Int8Attribute>(boxFace_1, AMCAX::construct_anonymous_attr, int8_t(100));
AttributeTool::Set<Int16Attribute>(boxFace_1, AMCAX::construct_anonymous_attr, int16_t(-16));
AttributeTool::Set<Int16Attribute>(boxFace_1, "guid", int16_t(-17));
color = std::make_tuple(1., 1., 1., 1.);
AttributeTool::Set<ColorAttribute>(boxFace_3, AMCAX::construct_anonymous_attr, color);
color = std::make_tuple(0., 1., 0., 1.);
AttributeTool::Set<ColorAttribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, color);
AttributeTool::Set<Int8Attribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, int8_t(32));
AttributeTool::Set<Int16Attribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, int16_t(-32));
static AMCAX_API void Set(Label &label, construct_anonymous_attr_t construct_strategy, Args &&... args)
Set an attribute to the label
定义 AttributeTool.hpp:32
AMCAX_API std::vector< Label > GetFaceLabels() const
Get all face labels on the label

布尔操作

WithAttr 对内核的布尔操作进行带属性封装,提供了:

  • WithAttr<BoolBRepFuse>
  • WithAttr<BoolBRepCommon>
  • WithAttr<BoolBRepCut>
  • WithAttr<BoolBRepSplitter>

需要注意的是,带属性布尔接口提供的 GetResultLabel 接口可传递一个布尔参数表示是否需要进行级联追踪,当传递 true 上代表需要,此时更改 arguments 或者 tools上属性或拓扑时,布尔结果会自动更新。布尔结果的属性保留策略,由 AMCAX::AttributePolicy 定义,当前定义了以下三种策略:

enum class AttributePolicy {
// 布尔结果的面不保留属性。
// 布尔结果的面,保留来自 argument 列表上第一个由该拓扑面修改而来其上附着的属性。
// 布尔结果的面,保留来自 tool 列表上第一个由该拓扑面修改而来其上附着的属性。
};
AttributePolicy
The enumeration of attribute policy to resolve attribute conflict
定义 AttributePolicy.hpp:10
@ ATTRIBUTE_POLICY_KEEP_ARGUMENT
When attribute conflicts occur, the attributes from first argument are keeped
定义 AttributePolicy.hpp:14
@ ATTRIBUTE_POLICY_DROP
When attribute conflicts occur, the attributes are dropped
定义 AttributePolicy.hpp:12
@ ATTRIBUTE_POLICY_KEEP_TOOL
When attribute conflicts occur, the attributes from first tool are keeped
定义 AttributePolicy.hpp:16

用户可通过 WithAttr 的 SetPolicy 接口定义指定属性类型的属性策略,也可以使用默认属性策略,当调用了 SetPolicy 接口时,它会覆盖默认属性策略。

WithAttr<BoolBRepCommon> common{{boxLabel}, {cylinderLabel}};
common.SetPolicy(AttributeType::INT16_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
common.Build();
Label commonLabel = common.GetResultLabel(true);
virtual void Build()
Perform the modeling build
定义 WithAttrBase.hpp:31

属性的查找与获取

Label 提供 FindAttribute 接口用于属性的查找,属性上提供 GetValue 接口用于获取属性的值。

std::vector<Label> commonFaceLabels = common.GetAllFaceLabel();
AMCAX::Attribute foundAttr;
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute(ColorAttribute::GetId()); foundAttr) {
auto [r, g, b, a] = foundAttr->GetValue<ColorAttribute>();
std::cout << "r = " << r << ", g = " << g << ", b = " << b << ", a = " << a << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int8Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int16Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("guid"); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
}
The base class of all attributes
定义 Attribute.hpp:36
R GetValue()
Get the value of the attribute
定义 Attribute.hpp:110
The class of ColorAttribute
定义 ColorAttribute.hpp:18
static const std::string & GetId()
Defining a id to identify an attribute.
定义 ColorAttribute.hpp:74
static const std::string & GetId()
Defining a id to identify an attribute.
定义 FixedIntAttribute.hpp:116

点击这里example01可获得附加属性示例一完整源码,大家根据学习需要自行下载。

附录

下面列出了此示例的完整代码:

#include<iostream>
using namespace AMCAX;
int main()
{
TopoShape topoShape = MakeBox(5., 5., 5.);
WithAttr<TopoShape> shapeWithAttr(topoShape);
Label boxLabel = shapeWithAttr.GetResultLabel();
WithAttr<MakeCylinder> cylinder{5., 10.};
Label cylinderLabel = cylinder.GetResultLabel();
std::vector<Label> boxFaceLabels = boxLabel.GetFaceLabels();
std::vector<Label> cylinderFaceLabels = cylinder.GetAllFaceLabel();
Label boxFace_1 = boxFaceLabels.front();
Label boxFace_3 = boxFaceLabels[2];
Label cylinderFace_1 = cylinderFaceLabels.front();
auto color = std::make_tuple(1., 0., 0., 1.);
AttributeTool::Set<ColorAttribute>(boxFace_1, AMCAX::construct_anonymous_attr, color);
AttributeTool::Set<Int8Attribute>(boxFace_1, AMCAX::construct_anonymous_attr, int8_t(100));
AttributeTool::Set<Int16Attribute>(boxFace_1, AMCAX::construct_anonymous_attr, int16_t(-16));
AttributeTool::Set<Int16Attribute>(boxFace_1, "guid", int16_t(-17));
color = std::make_tuple(1., 1., 1., 1.);
AttributeTool::Set<ColorAttribute>(boxFace_3, AMCAX::construct_anonymous_attr, color);
color = std::make_tuple(0., 1., 0., 1.);
AttributeTool::Set<ColorAttribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, color);
AttributeTool::Set<Int8Attribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, int8_t(32));
AttributeTool::Set<Int16Attribute>(cylinderFace_1 , AMCAX::construct_anonymous_attr, int16_t(-32));
WithAttr<BoolBRepCommon> common{{boxLabel}, {cylinderLabel}};
common.SetPolicy(AttributeType::INT16_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
common.Build();
// 开启级联
Label commonLabel = common.GetResultLabel(true);
std::vector<Label> commonFaceLabels = common.GetAllFaceLabel();
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute(ColorAttribute::GetId()); foundAttr) {
auto [r, g, b, a] = foundAttr->GetValue<ColorAttribute>();
std::cout << "r = " << r << ", g = " << g << ", b = " << b << ", a = " << a << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int8Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int16Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("guid"); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
}
color = std::make_tuple(0., 1., 1., 1.);
// 触发级联更新
AttributeTool::Set<ColorAttribute>(boxFace_1, AMCAX::construct_anonymous_attr, color);
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute(ColorAttribute::GetId()); foundAttr) {
auto [r, g, b, a] = foundAttr->GetValue<ColorAttribute>();
std::cout << "r = " << r << ", g = " << g << ", b = " << b << ", a = " << a << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int8Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute(Int16Attribute::GetId()); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("guid"); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
}
return 0;
}
The class of Attribute.
The class of WithAttr<BoolOperation> and its derived classes
The classes of WithAttrModeling.

附加属性示例二

属性冲突是指:操作结果的拓扑从多个面 modified 过来,id 一样的属性,参与操作且发生变化。当属性冲突时才会采用下述策略,否则,属性继承自 modified 过来或者保留的拓扑。

enum class AttributePolicy {
ATTRIBUTE_POLICY_DROP, // 布尔结果不保留属性
ATTRIBUTE_POLICY_KEEP_ARGUMENT, // 布尔结果保留来自argument上的属性
ATTRIBUTE_POLICY_KEEP_TOOL, // 布尔结果保留来自 tool上的属性
};

准备工作

创建两个带属性的 Box 和 一个带属性的 Cylinder,并为它们的面挂上字符串属性。

auto boxWithAttr = WithAttr<MakeBox>(5., 5., 10.);
auto box = boxWithAttr.GetResultLabel();
auto boxFaces = box.GetFaceLabels();
uint64_t cnt = 1;
for (auto boxFace: boxFaces) {
AttributeTool::Set<StringAttribute>(boxFace, construct_anonymous_attr, "box1_" + std::to_string(cnt++));
}
auto boxWithAttr_ = WithAttr<MakeBox>(5., 5., 10.);
auto box_ = boxWithAttr_.GetResultLabel();
auto boxFaces_ = box_.GetFaceLabels();
cnt = 1;
for (auto boxFace: boxFaces_) {
AttributeTool::Set<StringAttribute>(boxFace, construct_anonymous_attr, "box2_" + std::to_string(cnt++));
}
auto cylinderWithAttr = WithAttr<MakeCylinder>(5., 10.);
auto cylnder = cylinderWithAttr.GetResultLabel();
auto cylinderFaces = cylnder.GetFaceLabels();
cnt = 1;
for (auto cylFace: cylinderFaces) {
AttributeTool::Set<StringAttribute>(cylFace, construct_anonymous_attr, "cyl_" + std::to_string(cnt++));
}

执行布尔操作,属性策略为 KEEP_TOOL

WithAttr<BoolBRepFuse> fuse{{box, box_}, {cylnder}};
// 注:此处也可使用 StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL
// 但是,SetPolicy 设定的策略优先级更高。
fuse.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuse.Build();
// 开启级联追踪
auto fuseLabel = fuse.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// 注:可验证布尔结果的第一个面同时从box的第六个面,box_的第六个面和cyl第二个面modified过来,存在属性冲突。
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// 由属性策略是 ATTRIBUTE_POLICY_KEEP_TOOL,此输出为 cyl_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
AttributeTool::Set<StringAttribute>(cylFace2, construct_anonymous_attr, "CYL_2");
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// 级联更新,此输出为 CYL_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
The class of StringAttribute
定义 StringAttribute.hpp:15
static const std::string & GetId()
Defining a id to identify an attribute.
定义 StringAttribute.hpp:77

点击这里example02可获得附加属性示例二完整源码,大家根据学习需要自行下载。

附录

#include <iostream>
using namespace AMCAX;
int main() {
auto boxWithAttr = WithAttr<MakeBox>(5., 5., 10.);
auto box = boxWithAttr.GetResultLabel();
auto boxFaces = box.GetFaceLabels();
uint64_t cnt = 1;
for (auto boxFace: boxFaces) {
AttributeTool::Set<StringAttribute>(boxFace, construct_anonymous_attr, "box1_" + std::to_string(cnt++));
}
auto boxWithAttr_ = WithAttr<MakeBox>(5., 5., 10.);
auto box_ = boxWithAttr_.GetResultLabel();
auto boxFaces_ = box_.GetFaceLabels();
cnt = 1;
for (auto boxFace: boxFaces_) {
AttributeTool::Set<StringAttribute>(boxFace, construct_anonymous_attr, "box2_" + std::to_string(cnt++));
}
auto cylinderWithAttr = WithAttr<MakeCylinder>(5., 10.);
auto cylnder = cylinderWithAttr.GetResultLabel();
auto cylinderFaces = cylnder.GetFaceLabels();
cnt = 1;
for (auto cylFace: cylinderFaces) {
AttributeTool::Set<StringAttribute>(cylFace, construct_anonymous_attr, "cyl_" + std::to_string(cnt++));
}
WithAttr<BoolBRepFuse> fuseKeepTool{{box, box_}, {cylnder}};
// 注:此处也可使用 StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL
// 但是,SetPolicy 设定的策略优先级更高。
fuseKeepTool.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuseKeepTool.Build();
// 开启级联追踪
auto fuseLabel = fuseKeepTool.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// 注:可验证布尔结果的第一个面同时从box的第六个面,box_的第六个面和cyl第二个面modified过来,存在属性冲突。
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// 由属性策略是 ATTRIBUTE_POLICY_KEEP_TOOL,此输出为 cyl_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
AttributeTool::Set<StringAttribute>(cylFace2, construct_anonymous_attr, "CYL_2");
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// 级联更新,此输出为 CYL_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
return 0;
}