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.};
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
The template class of WithAttr.
Definition WithAttrBase.hpp:186

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 = 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.
Definition AttributeTool.hpp:33
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();
Label commonLabel = common.GetResultLabel(true);
virtual AMCAX_API void Build()
Perform the modeling build.

Attribute Lookup and Retrieval

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

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.
Definition Attribute.hpp:38
R GetValue()
Get the value of the attribute.
Definition Attribute.hpp:99
The class of ColorAttribute.
Definition ColorAttribute.hpp:19
static AMCAX_API const std::string & GetId()
Get the default id of the attribute.
static const std::string & GetId()
Definition FixedIntAttribute.hpp:115

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 shapeWithAttr(topoShape);
Label boxLabel = shapeWithAttr.GetResultLabel();
WithAttr cylinder{ 5., 10. };
Label cylinderLabel = cylinder.GetResultLabel();
std::vector boxFaceLabels = boxLabel.GetFaceLabels();
std::vector 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(boxFace_1, AMCAX::construct_anonymous_attr, color);
AttributeTool::Set(boxFace_1, AMCAX::construct_anonymous_attr, int8_t(100));
AttributeTool::Set(boxFace_1, AMCAX::construct_anonymous_attr, int16_t(-16));
AttributeTool::Set(boxFace_1, "guid", int16_t(-17));
color = std::make_tuple(1., 1., 1., 1.);
AttributeTool::Set(boxFace_3, AMCAX::construct_anonymous_attr, color);
color = std::make_tuple(0., 1., 0., 1.);
AttributeTool::Set(cylinderFace_1, AMCAX::construct_anonymous_attr, color);
AttributeTool::Set(cylinderFace_1, AMCAX::construct_anonymous_attr, int8_t(32));
AttributeTool::Set(cylinderFace_1, AMCAX::construct_anonymous_attr, int16_t(-32));
WithAttr common{ {boxLabel}, {cylinderLabel} };
common.SetPolicy(AttributeType::INT16_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
common.Build();
// Enable cascading
Label commonLabel = common.GetResultLabel(true);
std::vector 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;
}
}
color = std::make_tuple(0., 1., 1., 1.);
// Trigger cascading update
AttributeTool::Set(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.

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.);
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++));
}

Perform Boolean Operation with KEEP_TOOL Policy

WithAttr<BoolBRepFuse> fuse{{box, box_}, {cylnder}};
// Note: StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL could be used here,
// but SetPolicy takes precedence.
fuse.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuse.Build();
// Enable cascading tracking
auto fuseLabel = fuse.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// Note: 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, creating an attribute conflict.
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// With ATTRIBUTE_POLICY_KEEP_TOOL policy, this outputs "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) {
// Cascading update, this outputs "CYL_2"
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
The class of StringAttribute.
Definition StringAttribute.hpp:16
static AMCAX_API const std::string & GetId()
Get the default id of the attribute.

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.);
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}};
// Note: StringAttribute::policy = AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL could be used here,
// but SetPolicy takes higher precedence.
fuseKeepTool.SetPolicy(AttributeType::STRING_ATTRIBUTE, AttributePolicy::ATTRIBUTE_POLICY_KEEP_TOOL);
fuseKeepTool.Build();
// Enable cascading tracking
auto fuseLabel = fuseKeepTool.GetResultLabel(true);
auto fuseFaces = fuseLabel.GetFaceLabels();
auto boxFace1 = boxFaces[0];
auto cylFace2 = cylinderFaces[1];
// Note: 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, creating an attribute conflict.
auto fuseFace_1 = fuseFaces[0];
if (auto attr = fuseFace_1.FindAttribute(StringAttribute::GetId()); attr) {
// With ATTRIBUTE_POLICY_KEEP_TOOL policy, this outputs "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) {
// Cascading update, this outputs "CYL_2"
std::cout << attr->GetValue<StringAttribute>() << std::endl;
}
return 0;
}

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
AttributeTool::Set<StringAttribute>(labelV1, construct_anonymous_attr, "labelV1");
AttributeTool::Set<StringAttribute>(labelV2, construct_anonymous_attr, "labelV2");
uint64_t cnt = 0;
WithAttr<MakeEdge> edge_01{labelV1, labelV2};
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 boxLabel = WithAttr<MakeBox>(5., 5., 5.).GetResultLabel();
auto boxFace01 = boxLabel.GetFaceLabels()[0];
AttributeTool::Set<StringAttribute>(boxFace01, construct_anonymous_attr, "face01");
auto boxVertex02 = boxFace01.GetVertexLabels()[1];
AttributeTool::Set<StringAttribute>(boxVertex02, construct_anonymous_attr, "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(StringAttribute::GetId());
std::cout << face01Attr->GetValue<StringAttribute>() << std::endl;
auto transBoxVertex02 = transBoxFace01.GetVertexLabels()[1];
auto vertex02Attr = transBoxVertex02.FindAttribute(StringAttribute::GetId());
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
AttributeTool::Set<StringAttribute>(labelV1, construct_anonymous_attr, "labelV1");
AttributeTool::Set<StringAttribute>(labelV2, construct_anonymous_attr, "labelV2");
uint64_t cnt = 0;
WithAttr<MakeEdge> edge_01{ labelV1, labelV2 };
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 boxLabel = WithAttr<MakeBox>(5., 5., 5.).GetResultLabel();
auto boxFace01 = boxLabel.GetFaceLabels()[0];
AttributeTool::Set<StringAttribute>(boxFace01, construct_anonymous_attr, "face01");
auto boxVertex02 = boxFace01.GetVertexLabels()[1];
AttributeTool::Set<StringAttribute>(boxVertex02, construct_anonymous_attr, "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(StringAttribute::GetId());
std::cout << face01Attr->GetValue<StringAttribute>() << std::endl;
auto transBoxVertex02 = transBoxFace01.GetVertexLabels()[1];
auto vertex02Attr = transBoxVertex02.FindAttribute(StringAttribute::GetId());
std::cout << vertex02Attr->GetValue<StringAttribute>() << std::endl;
}