AMCAX Kernel 1.0.0.0
Loading...
Searching...
No Matches
Additional Attributes Example

Overview

The topology and geometry of the Jiushao kernel do not carry additional attributes by default. To support attaching attributes to TopoShape, the application framework introduces AMCAX::Label, which associates with a TopoShape and a set of attributes. Additionally, a group of WithAttr template classes are provided. These classes encapsulate the kernel modeling interfaces and offer GetResultLabel for retrieving the resulting Label.

Namespace

For clarity in example code, namespaces are used.

using namespace AMCAX;
Namespace of all interface in the AMCAX kernel.
Definition misc.docu:8

Additional Attributes Example 1

Obtaining Label via AMCAX::WithAttr

Labels are obtained through WithAttr, and attributes are attached to the Label. WithAttr can be used in two forms: one involves manually creating a TopoShape through the ​​AMCAX kernel​​ , and constructing it via WithAttr, while the other uses parametric modeling. For a detailed list of supported parametric modeling interfaces with attributes, refer to the API list.

TopoShape topoShape = MakeBox(5., 5., 5.);
WithAttr<TopoShape> shapeWithAttr(topoShape);
Label boxLabel = shapeWithAttr.GetResultLabel();
WithAttr<MakeCylinder> cylinder{5., 10.};
cylinder.Build();
Label cylinderLabel = cylinder.GetResultLabel();
The class of Label.
Definition Label.hpp:27
Class of making a box.
Definition MakeBox.hpp:20
Base class of shape, containing an underlying shape with a location and an orientation.
Definition TopoShape.hpp:15
virtual AMCAX_API void Build()
Perform the modeling build.
The template class of WithAttr.
Definition WithAttrBase.hpp:217

Attaching Attributes to Faces

The Label interface provides GetFaceLabels to retrieve all Face Labels on a Label. AttributeTool offers utility functions for updating/setting attributes on a Label. Note that only one attribute with the same ID can exist on a single Label. To attach different attribute objects of the same type to a Label, different attribute IDs must be specified. Below is an example of attaching attributes to a Label:

std::vector<Label> boxFaceLabels = boxLabel.GetFaceLabels();
std::vector<Label> cylinderFaceLabels = cylinderLabel.GetFaceLabels();
Label boxFace_1 = boxFaceLabels.front();
Label boxFace_3 = boxFaceLabels[2];
Label cylinderFace_1 = cylinderFaceLabels.front();
auto color = std::make_tuple(1., 0., 0., 1.);
color = std::make_tuple(1., 1., 1., 1.);
color = std::make_tuple(0., 1., 0., 1.);
cylinderFace_1.AddAttribute(AttributeTool::MakeAttribute<Int8Attribute>("int8", int8_t(32)));
cylinderFace_1.AddAttribute(AttributeTool::MakeAttribute<Int16Attribute>("int16", int16_t(-32)));
static AMCAX_API std::shared_ptr< Attribute > MakeAttribute(const std::string &id, Args &&... args)
Make an attribute with the given id and arguments.
Definition AttributeTool.hpp:37
AMCAX_API bool AddAttribute(const std::shared_ptr< Attribute > attribute)
Add attribute on the label.
AMCAX_API std::vector< Label > GetFaceLabels() const
Get all face labels on the label.

Boolean Operations

WithAttr encapsulates the kernel's Boolean operations with attributes, providing:

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

Note that the GetResultLabel interface of the attribute-enabled Boolean operations can accept a Boolean parameter indicating whether cascading tracking is needed. When set to true, changes to the attributes or topology of arguments or tools will automatically update the Boolean result. The attribute retention policy for Boolean results is defined by AMCAX::AttributePolicy, which currently includes the following three strategies:

enum class AttributePolicy {
// Boolean result faces do not retain attributes.
// Boolean result faces retain attributes from the first topological face in the argument list that modifies them.
// Boolean result faces retain attributes from the first topological face in the tool list that modifies them.
};
AttributePolicy
The enumeration of attribute policy to resolve attribute conflict.
Definition AttributePolicy.hpp:11
@ ATTRIBUTE_POLICY_KEEP_ARGUMENT
When attribute conflicts occur, the attributes from first argument are keeped.
Definition AttributePolicy.hpp:15
@ ATTRIBUTE_POLICY_DROP
When attribute conflicts occur, the attributes are dropped.
Definition AttributePolicy.hpp:13
@ ATTRIBUTE_POLICY_KEEP_TOOL
When attribute conflicts occur, the attributes from first tool are keeped.
Definition AttributePolicy.hpp:17

Users can define attribute policies for specific attribute types via WithAttr's SetPolicy interface or use the default policy. When SetPolicy is called, it overrides the default policy.

WithAttr<BoolBRepCommon> common{{boxLabel}, {cylinderLabel}};
common.SetPolicy(AttributeType::INT16_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
common.Build();
// Enable cascading
Label commonLabel = common.GetResultLabel(true);

Attribute Lookup and Retrieval

The Label interface provides FindAttribute for attribute lookup, and attributes offer GetValue for retrieving attribute values.

std::vector<Label> commonFaceLabels = commonLabel.GetFaceLabels();
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute("color"); 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("int8"); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("int16"); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("guid"); foundAttr) {
std::cout << foundAttr->GetValue<Int16Attribute>() << std::endl;
}
}
The class of ColorAttribute.
Definition ColorAttribute.hpp:20

Click here example01 to get the full source code of the additional attributes example 1, you can download it according to your learning needs.

Appendix

Below is the complete code for this example:

#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.};
cylinder.Build();
Label cylinderLabel = cylinder.GetResultLabel();
std::vector<Label> boxFaceLabels = boxLabel.GetFaceLabels();
std::vector<Label> cylinderFaceLabels = cylinderLabel.GetFaceLabels();
Label boxFace_1 = boxFaceLabels.front();
Label boxFace_3 = boxFaceLabels[2];
Label cylinderFace_1 = cylinderFaceLabels.front();
auto color = std::make_tuple(1., 0., 0., 1.);
color = std::make_tuple(1., 1., 1., 1.);
color = std::make_tuple(0., 1., 0., 1.);
cylinderFace_1.AddAttribute(AttributeTool::MakeAttribute<Int8Attribute>("int8", int8_t(32)));
cylinderFace_1.AddAttribute(AttributeTool::MakeAttribute<Int16Attribute>("int16", int16_t(-32)));
WithAttr<BoolBRepCommon> common{{boxLabel}, {cylinderLabel}};
common.SetPolicy(AttributeType::INT16_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
common.Build();
// Enable cascading
Label commonLabel = common.GetResultLabel(true);
std::vector<Label> commonFaceLabels = commonLabel.GetFaceLabels();
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute("color"); 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("int8"); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("int16"); 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.);
// Trigger cascading update
for (auto commonFacelabel : commonFaceLabels) {
if (auto foundAttr = commonFacelabel.FindAttribute("color"); 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("int8"); foundAttr) {
std::cout << foundAttr->GetValue<Int8Attribute>() << std::endl;
}
if (auto foundAttr = commonFacelabel.FindAttribute("int16"); 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 WithAttr<BoolOperation> and its derived classes.
The classes of WithAttrModeling.
AMCAX_API bool UpdateAttribute(const std::shared_ptr< Attribute > attr)
Update the attribute of the label, if the attribute of given id is not existing, return false.

Additional Attributes Example 2

Attribute conflict​ occurs when: The resulting topology is modified from multiple faces with identical attribute IDs that participated in the operation and underwent changes. The following strategies are only applied when attribute conflicts exist; otherwise, attributes are inherited from the modified or preserved topology.

enum class AttributePolicy {
ATTRIBUTE_POLICY_DROP, // Boolean result discards all attributes
ATTRIBUTE_POLICY_KEEP_ARGUMENT,// Boolean result keeps attributes from the argument
ATTRIBUTE_POLICY_KEEP_TOOL // Boolean result keeps attributes from the tool
};

Preparation

Create two boxes and one cylinder with attributes, then assign string attributes to their faces.

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

Perform Boolean Operation with KEEP_TOOL Policy

WithAttr<BoolBRepFuse> fuseKeepTool{ {box, box_}, {cylinder} };
// Note: You can also use StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL here
// However, the policy set by SetPolicy has higher priority.
fuseKeepTool.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuseKeepTool.Build();
// Enable cascade tracking
auto fuseLabel = fuseKeepTool.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// Note: It can be verified that the first face of the boolean result is modified from the 6th face of box, the 6th face of box_, and the 2nd face of cyl simultaneously, resulting in attribute conflicts.
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute("string"); attr) {
// Due to the attribute policy being ATTRIBUTE_POLICY_KEEP_TOOL, the output here is cyl_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
cylFace2.UpdateAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "CYL_2"));
if (auto attr = fuseFace_1.FindAttribute("string"); attr) {
// Cascade update, the output here is CYL_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
The class of StringAttribute.
Definition StringAttribute.hpp:16

Click here example02 to get the full source code of the additional attributes example 2, you can download it according to your learning needs.

Appendix

#include <iostream>
using namespace AMCAX;
int main()
{
auto boxWithAttr = WithAttr<MakeBox>(5., 5., 10.);
boxWithAttr.Build();
auto box = boxWithAttr.GetResultLabel();
auto boxFaces = box.GetFaceLabels();
uint64_t cnt = 1;
for (auto boxFace: boxFaces) {
boxFace.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "box1_" + std::to_string(cnt++)));
}
auto boxWithAttr_ = WithAttr<MakeBox>(5., 5., 10.);
boxWithAttr_.Build();
auto box_ = boxWithAttr_.GetResultLabel();
auto boxFaces_ = box_.GetFaceLabels();
cnt = 1;
for (auto boxFace: boxFaces_) {
boxFace.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "box2_" + std::to_string(cnt++)));
}
auto cylinderWithAttr = WithAttr<MakeCylinder>(5., 10.);
cylinderWithAttr.Build();
auto cylnder = cylinderWithAttr.GetResultLabel();
auto cylinderFaces = cylnder.GetFaceLabels();
cnt = 1;
for (auto cylFace: cylinderFaces) {
cylFace.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "cyl_" + std::to_string(cnt++)));
}
WithAttr<BoolBRepFuse> fuseKeepTool{{box, box_}, {cylnder}};
// Note: You can also use StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL here
// However, the policy set by SetPolicy has higher priority.
fuseKeepTool.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuseKeepTool.Build();
// Enable cascade tracking
auto fuseLabel = fuseKeepTool.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// Note: It can be verified that the first face of the boolean result is modified from the 6th face of box, the 6th face of box_, and the 2nd face of cyl simultaneously, resulting in attribute conflicts.
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute("string"); attr) {
// Due to the attribute policy being ATTRIBUTE_POLICY_KEEP_TOOL, the output here is cyl_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
cylFace2.UpdateAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "CYL_2"));
if (auto attr = fuseFace_1.FindAttribute("string"); attr) {
// Cascade update, the output here is CYL_2
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
}
The class of Attribute.

Additional Attributes Example 3

The application framework provides attribute-wrapped interfaces for kernel modeling. Two examples are given below.

WithAttr<MakeEdge> Example

Point3 p1{0.,0.,0.}, p2{1.,0.,0.}, p{0.,0.,0.};
auto labelV1 = v1.GetResultLabel();
auto labelV2 = v2.GetResultLabel();
// Attach attributes to vertices
labelV2.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "labelV2"));
WithAttr<MakeEdge> edge_01{labelV1, labelV2};
edge_01.Build();
auto edgeLabel_01 = edge_01.GetResultLabel();
// Verify attribute inheritance
for (ChildIterator iter{edgeLabel_01}; iter.More(); iter.Next()) {
auto attrs = iter.Value().FindAllAttributes();
std::cout << attrs[0]->GetValue<StringAttribute>() << std::endl;
}
The class of ChildIterator.
Definition LabelIterator.hpp:19
AMCAX_API bool More()
Check if has more child label.
Class of making a vertex.
Definition MakeVertex.hpp:18
virtual AMCAX_API Label & GetResultLabel(bool keepTrack=false)
Get label build by WithAttr.
PointT< double, 3 > Point3
3D point
Definition PointT.hpp:459

WithAttr<TransformShape> Example

auto boxWithAttr = WithAttr<MakeBox>(5., 5., 5.);
boxWithAttr.Build();
auto boxLabel = boxWithAttr.GetResultLabel();
auto boxFace01 = boxLabel.GetFaceLabels()[0];
boxFace01.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "face01"));
auto boxVertex02 = boxFace01.GetVertexLabels()[1];
boxVertex02.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "vertex02"));
trans.SetTranslation(Vector3{1., 1., 1.});
WithAttr<TransformShape> transShape{trans};
transShape.Perform(boxLabel);
auto transBoxLabel = transShape.GetResultLabel();
auto transBoxFace01 = transBoxLabel.GetFaceLabels()[0];
// Verify attribute persistence
auto face01Attr = transBoxFace01.FindAttribute("string");
std::cout << face01Attr->GetValue<StringAttribute>() << std::endl;
auto transBoxVertex02 = transBoxFace01.GetVertexLabels()[1];
auto vertex02Attr = transBoxVertex02.FindAttribute("string");
std::cout << vertex02Attr->GetValue<StringAttribute>() << std::endl
AMCAX_API std::string & GetValue() noexcept
Get the value of the StringAttribute.
constexpr void SetTranslation(const VectorT< OtherScalar, DIM > &vec) noexcept
Set the transformation as the translation.
Definition TransformationT.hpp:311
TransformationT< double, 3 > Transformation3
3D transformation
Definition TransformationT.hpp:1115
VectorT< double, 3 > Vector3
3D vector
Definition VectorT.hpp:707

Click here example03 to get the full source code of the additional attributes example 3, you can download it according to your learning needs.

Appendix

#include<iostream>
using namespace AMCAX;
int main()
{
Point3 p1{0.,0.,0.}, p2{1.,0.,0.}, p{0.,0.,0.};
auto labelV1 = v1.GetResultLabel();
auto labelV2 = v2.GetResultLabel();
// Attach attributes to vertices
labelV2.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "labelV2"));
uint64_t cnt = 0;
WithAttr<MakeEdge> edge_01{labelV1, labelV2};
edge_01.Build();
auto edgeLabel_01 = edge_01.GetResultLabel();
// Verify attribute inheritance
for (ChildIterator iter{edgeLabel_01}; iter.More(); iter.Next()) {
auto attrs = iter.Value().FindAllAttributes();
std::cout << attrs[0]->GetValue<StringAttribute>() << std::endl;
}
auto boxWithAttr = WithAttr<MakeBox>(5., 5., 5.);
boxWithAttr.Build();
auto boxLabel = boxWithAttr.GetResultLabel();
auto boxFace01 = boxLabel.GetFaceLabels()[0];
boxFace01.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "face01"));
auto boxVertex02 = boxFace01.GetVertexLabels()[1];
boxVertex02.AddAttribute(AttributeTool::MakeAttribute<StringAttribute>("string", "vertex02"));
trans.SetTranslation(Vector3{1., 1., 1.});
WithAttr<TransformShape> transShape{trans};
transShape.Perform(boxLabel);
auto transBoxLabel = transShape.GetResultLabel();
auto transBoxFace01 = transBoxLabel.GetFaceLabels()[0];
// Verify attribute persistence
auto face01Attr = transBoxFace01.FindAttribute("string");
std::cout << face01Attr->GetValue<StringAttribute>() << std::endl;
auto transBoxVertex02 = transBoxFace01.GetVertexLabels()[1];
auto vertex02Attr = transBoxVertex02.FindAttribute("string");
std::cout << vertex02Attr->GetValue<StringAttribute>() << std::endl;
}