Introduction
Parametric Feature is powerful way of creating complex geometry associatively. Various parametric features can be combined to form a chain; often called as a feature tree.
What does the example demonstrate?
'Parametric Feature Tree Tool' app demonstrates how to create a complex chain of Parametric Features programmatically.
To run the Example
Code Walkthrough
Please refer MstnExamples/Elements/exampleSolids/exampleParametricFeatureTree.cpp file for comprehensive steps.
Following is important excerpts:
Step 1: Create Ellipse (a primary profile for a extrude feature node)
DgnModelRefP modelRef = NULL; if (modelName) modelRef = getModel(modelName); else modelRef = ISessionMgr::GetActiveDgnModelP(); if (modelRef) { if (SUCCESS == EllipseHandler::CreateEllipseElement(eeh, NULL, center, major, minor, 0, modelRef->Is3d(), *modelRef)) eeh.AdToModel(); else BeAssert(false); }
Step 2: Create Extrude
// Step 2.a: First always cook the setting of a parametric feature. In this case - ExtrudeSettings CurveVectorPtr curveVector; if (SUCCESS != SmartFeatureUtil::GetCurveVector(curveVector, ellipseEh, true)) return ERROR; DPlane3d plane; SmartFeatureUtil::GetCurveVectorPlane(plane, *curveVector); ExtrudeSettings settings(hitPt, false, false, NULL, 1.0, 1.0, 0.0, false, 0, 0.0, ev, *curveVector); // Step 2.b: Create a extrude feature node by using the feature settings. SmartFeatureNodePtr extrudeFeatureNode = FeatureCreate::CreateExtrudeFeature(settings); if(!extrudeFeatureNode.IsValid()) return ERROR; // Step 2.c: Write extrude feature node over an element and the element into the dgn file. T_ChildElementToControlFlagsMap childElementToControlFlagsMap; T_ControlFlagsVector controlFlags(3, false); // {visible, temporary, profile} - Irrevalent for Smart Feature with single child. childElementToControlFlagsMap[ellipseEh.GetElementRef()] = controlFlags; EditElementHandle extrudeEeh; if (SUCCESS != SmartFeatureElement::CreateAndWriteSmartFeatureElement(extrudeEeh, ellipseEh, ellipseEh.GetDgnModelP(), *extrudeFeatureNode, childElementToControlFlagsMap, false /*mergeParametrics*/)) return ERROR;
Step 3: Create Blend
// Step 3.a: Retrieve solid body of extrude feature node. if (!extrudeEeh.IsValid()) return ERROR; ISolidKernelEntityPtr body; if (SUCCESS != extrudeFeatureNode->GetBody(body, extrudeEeh, true, true, true, false)) return ERROR; // Step 3.b: Get edges of extruded solid body. bvector<ISubEntityPtr> edges; SolidUtil::GetBodyEdges(&edges, *body); // Step 3.c: Since the Blend creation API don't require any specific settings to be cooked, create a Blend feature node directly. double blendRadius = 5000.00; SmartFeatureNodePtr blendFeatureNode; if (SUCCESS != FeatureCreate::CreateBlendFeature(blendFeatureNode, edges, blendRadius, true /*propogateSmooth*/)) return ERROR; if (!blendFeatureNode.IsValid()) return ERROR; childElementToControlFlagsMap.clear(); childElementToControlFlagsMap[extrudeEeh.GetElementRef()] = controlFlags; // Step 3.d: Write a blend feature node over an element and eventually into the dgn file. EditElementHandle blendEeh; if (SUCCESS != SmartFeatureElement::CreateAndWriteSmartFeatureElement(blendEeh, extrudeEeh, extrudeEeh.GetDgnModelP(), *blendFeatureNode, childElementToControlFlagsMap, false /*mergeParametrics*/)) return ERROR;
Step 4: Create Ellipse (a tool element for a Cut)
Step 5: Create Cut
// Step a: Create a cut feature node SmartFeatureNodePtr cutFeatureNode; SolidUtil::Modify::CutDepthMode depthMode = SolidUtil::Modify::CutDepthMode::All; SolidUtil::Modify::CutDirectionMode directionMode = SolidUtil::Modify::CutDirectionMode::Forward; bool outsideProfile = true; // Cut outside the profile double depth = 0.0; // Irrelevant - due to depthMode = All DVec3d defaultNormal = DVec3d::From(0.0, 0.0, 1.0); // Along Z-axis if (SUCCESS != FeatureCreate::CreateCutFeature(cutFeatureNode, depthMode, directionMode, outsideProfile, depth, &defaultNormal)) return ERROR; if (!cutFeatureNode.IsValid()) return ERROR; // Step b: Write a cut feature node on element handle and write element handle in dgn file. childElementToControlFlagsMap.clear(); childElementToControlFlagsMap[blendEeh.GetElementRef()] = controlFlags; // {visible = false, temporary = false, profile = false} controlFlags.clear(); controlFlags.push_back(false); controlFlags.push_back(false); controlFlags.push_back(true); childElementToControlFlagsMap[ellipseCutProfileEh.GetElementRef()] = controlFlags; // {visible = false, temporary = false, profile = true} EditElementHandle cutEeh; if (SUCCESS != SmartFeatureElement::CreateAndWriteSmartFeatureElement(cutEeh, blendEeh, blendEeh.GetDgnModelP(), *blendFeatureNode, childElementToControlFlagsMap, true /*mergeParametrics*/)) return ERROR;
Path MstnExamples/Elements/ is, I believe, an internal path for Bentley Systems developers. The SDK examples for the rest of us are found, by default, in MicroStationCONNECTSDK\examples\.