"""Cosmetic Bend API sample — demonstrates creating sheet metal cosmetic bend features in a flat pattern: a press brake bend with an explicit radius override and custom angle, and a crease bend with manufacturing notes. Builds its own flat, sheet-metal plate and flat pattern in a new document, so it can be run as-is without any external data file. """ import math import traceback import adsk.core import adsk.fusion app = adsk.core.Application.get() PLATE_SIZE_CM = 10.0 PRESS_BRAKE_ANGLE_RADIANS = math.pi / 3 # 60 degrees PRESS_BRAKE_RADIUS_CM = 0.2 # explicit radius override PRESS_BRAKE_NOTES = 'Press brake bend: explicit 0.2 cm radius override' CREASE_NOTES = 'Crease: sharp fold, no radius' def createFlatPatternComponent(design): """Extrudes a flat plate, converts it to sheet metal, and creates its flat pattern. Returns (FlatPatternComponent, topFace), or (None, None) on failure. The flat pattern's own Sketches/Features live on a FlatPatternComponent, reached through the FlatPatternProduct in the document that matches the new flat pattern's entity token.""" rootComp = design.rootComponent # Use the first library sheet metal rule's own thickness for the plate, so the extruded body # is guaranteed to match the rule convertToSheetMetal() is given below -- no need to probe the # body's thickness back out after the fact. libraryRules = design.librarySheetMetalRules if libraryRules.count == 0: return None, None rule = libraryRules.item(0) thickness = rule.thickness.value sketch = rootComp.sketches.add(rootComp.xYConstructionPlane) sketch.sketchCurves.sketchLines.addTwoPointRectangle( adsk.core.Point3D.create(0, 0, 0), adsk.core.Point3D.create(PLATE_SIZE_CM, PLATE_SIZE_CM, 0)) prof = sketch.profiles.item(0) extrudes = rootComp.features.extrudeFeatures extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) extInput.setDistanceExtent(False, adsk.core.ValueInput.createByReal(thickness)) extInput.isSolid = True ext = extrudes.add(extInput) body = ext.bodies.item(0) # Find the largest planar face -- this becomes the sheet metal body's stationary face. largestFace = None maxArea = 0.0 for face in body.faces: if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType and face.area > maxArea: maxArea = face.area largestFace = face if largestFace is None: return None, None if not body.convertToSheetMetal(largestFace, rule): return None, None flatPattern = rootComp.createFlatPattern(largestFace) if flatPattern is None: return None, None products = design.parentDocument.products for i in range(products.count): candidate = adsk.fusion.FlatPatternProduct.cast(products.item(i)) if candidate and candidate.flatPattern and candidate.flatPattern.entityToken == flatPattern.entityToken: return adsk.fusion.FlatPatternComponent.cast(candidate.rootComponent), flatPattern.topFace return None, None def run(_context: str): """Documentation sample: Create sheet metal cosmetic bend features in a flat pattern.""" try: app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) design = adsk.fusion.Design.cast(app.activeProduct) fpComponent, topFace = createFlatPatternComponent(design) if fpComponent is None: app.log('Failed: could not create the flat pattern component') return Measure the face's true border in ITS OWN plane, not world X/Y -- createFlatPattern() can lay the flat pattern body out at an arbitrary orientation, so a world-axis-aligned bounding box can cut corners off the actual (rotated) rectangle. Project every vertex onto the face's own uDirection/vDirection basis instead; that basis is exactly aligned with the face's real edges, so a bounding box in that space is a tight fit regardless of the face's orientation. plane = adsk.core.Plane.cast(topFace.geometry) if plane is None: app.log('Failed: top face geometry is not a Plane') return origin = plane.origin uDir = plane.uDirection vDir = plane.vDirection minU = maxU = minV = maxV = 0.0 haveBounds = False for vertex in topFace.vertices: pt = vertex.geometry relX, relY, relZ = pt.x - origin.x, pt.y - origin.y, pt.z - origin.z u = relX * uDir.x + relY * uDir.y + relZ * uDir.z v = relX * vDir.x + relY * vDir.y + relZ * vDir.z if not haveBounds: minU = maxU = u minV = maxV = v haveBounds = True else: minU, maxU = min(minU, u), max(maxU, u) minV, maxV = min(minV, v), max(maxV, v) if not haveBounds: app.log('Failed: top face has no vertices') return fpSketch = fpComponent.sketches.add(topFace) addByTwoPoints expects points in the SKETCH's own local coordinate space, not model space -- build each point in model space from the (u, v) face-plane basis, then explicitly convert via modelToSketchSpace() before handing it to the sketch curve creator. def pointAtUV(u, v): modelPoint = adsk.core.Point3D.create( origin.x + u * uDir.x + v * vDir.x, origin.y + u * uDir.y + v * vDir.y, origin.z + u * uDir.z + v * vDir.z) return fpSketch.modelToSketchSpace(modelPoint) lines = fpSketch.sketchCurves.sketchLines Two bend lines placed at 30% and 70% across the face, each spanning border to border. line1U = minU + (maxU - minU) * 0.3 line2U = minU + (maxU - minU) * 0.7 line1 = lines.addByTwoPoints(pointAtUV(line1U, minV), pointAtUV(line1U, maxV)) line2 = lines.addByTwoPoints(pointAtUV(line2U, minV), pointAtUV(line2U, maxV)) features = fpComponent.features Example 1: Create a press brake cosmetic bend with an explicit radius override cbFeatures = features.cosmeticBendFeatures angleInput = adsk.core.ValueInput.createByReal(PRESS_BRAKE_ANGLE_RADIANS) inp1 = cbFeatures.createInput(line1, adsk.fusion.CosmeticBendTypes.PressBrakeCosmeticBendType, angleInput) if inp1 is None: app.log('Failed: createInput() for the first line returned None') return radiusInput = adsk.core.ValueInput.createByReal(PRESS_BRAKE_RADIUS_CM) if not inp1.setToPressBrake(angleInput): app.log('Failed: setToPressBrake() returned False') return inp1RadiusOverride = inp1.bendRadiusOverride if inp1RadiusOverride is None: app.log('Failed: bendRadiusOverride() returned None') return if not inp1RadiusOverride.setOverride(radiusInput): app.log('Failed: setOverride() returned False') return inp1.notes = PRESS_BRAKE_NOTES pressBrakeFeature = cbFeatures.add(inp1) if pressBrakeFeature is None: app.log('Failed: add() for the press brake bend returned None') return pressBrakeRadiusOverride = pressBrakeFeature.bendRadiusOverride if pressBrakeRadiusOverride is None: app.log('Failed: bendRadiusOverride() on feature returned None') return app.log('Created press brake cosmetic bend: {}, angle={} rad, radius={} cm'.format( pressBrakeFeature.name, pressBrakeFeature.angle.value, pressBrakeRadiusOverride.bendRadius.value)) Example 2: Create a crease cosmetic bend (sharp fold, no radius/angle) cbFeatures = features.cosmeticBendFeatures inp2 = cbFeatures.createInput(line2, adsk.fusion.CosmeticBendTypes.CreaseCosmeticBendType) if inp2 is None: app.log('Failed: createInput() for the second line returned None') return inp2.notes = CREASE_NOTES creaseFeature = cbFeatures.add(inp2) if creaseFeature is None: app.log('Failed: add() for the crease bend returned None') return app.log('Created crease cosmetic bend: {}'.format(creaseFeature.name)) app.log('CosmeticBendSample completed successfully.') except Exception: app.log(f'Failed:\n{traceback.format_exc()}')
// Cosmetic Bend API sample — demonstrates creating sheet metal cosmetic bend features in a flat // pattern: a press brake bend with an explicit radius override and custom angle, and a crease bend // with manufacturing notes. // // Builds its own flat, sheet-metal plate and flat pattern in a new document, so it can be run as-is // without any external data file. #include <Core/CoreAll.h> #include <Fusion/FusionAll.h> #include <string> using namespace adsk::core; using namespace adsk::fusion; static const double PI = 3.14159265358979323846; static const double PLATE_SIZE_CM = 10.0; static const double PRESS_BRAKE_ANGLE_RADIANS = PI / 3.0; // 60 degrees static const double PRESS_BRAKE_RADIUS_CM = 0.2; // explicit radius override static const char* PRESS_BRAKE_NOTES = "Press brake bend: explicit 0.2 cm radius override"; static const char* CREASE_NOTES = "Crease: sharp fold, no radius"; Ptr<Application> app; #define CHECK(expr) \ if (!(expr)) \ { \ app->log("FAIL: " #expr); \ return false; \ } #define CHECK_PTR(ptr) CHECK((ptr) != nullptr) // Extrudes a flat plate, converts it to sheet metal, and creates its flat pattern. The flat // pattern's own Sketches/Features live on a FlatPatternComponent, reached through the // FlatPatternProduct in the document that matches the new flat pattern's entity token. static Ptr<FlatPatternComponent> createFlatPatternComponent(const Ptr<Design>& design, Ptr<BRepFace>& outTopFace) { auto rootComp = design->rootComponent(); if (!rootComp) return nullptr; // Use the first library sheet metal rule's own thickness for the plate, so the extruded body // is guaranteed to match the rule convertToSheetMetal() is given below -- no need to probe the // body's thickness back out after the fact. auto libraryRules = design->librarySheetMetalRules(); if (!libraryRules || libraryRules->count() == 0) return nullptr; auto rule = libraryRules->item(0); if (!rule || !rule->thickness()) return nullptr; double thickness = rule->thickness()->value(); auto sketch = rootComp->sketches()->add(rootComp->xYConstructionPlane()); if (!sketch) return nullptr; sketch->sketchCurves()->sketchLines()->addTwoPointRectangle( Point3D::create(0, 0, 0), Point3D::create(PLATE_SIZE_CM, PLATE_SIZE_CM, 0)); auto prof = sketch->profiles()->item(0); if (!prof) return nullptr; auto extrudes = rootComp->features()->extrudeFeatures(); if (!extrudes) return nullptr; auto extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation); if (!extInput) return nullptr; extInput->setDistanceExtent(false, ValueInput::createByReal(thickness)); extInput->isSolid(true); auto ext = extrudes->add(extInput); if (!ext) return nullptr; auto body = ext->bodies()->item(0); if (!body) return nullptr; // Find the largest planar face -- this becomes the sheet metal body's stationary face. Ptr<BRepFace> largestFace; double maxArea = 0.0; auto faces = body->faces(); if (!faces) return nullptr; for (size_t i = 0; i < faces->count(); ++i) { auto face = faces->item(i); if (face && face->geometry()->surfaceType() == SurfaceTypes::PlaneSurfaceType && face->area() > maxArea) { maxArea = face->area(); largestFace = face; } } if (!largestFace) return nullptr; if (!body->convertToSheetMetal(largestFace, rule)) return nullptr; auto flatPattern = rootComp->createFlatPattern(largestFace); if (!flatPattern) return nullptr; outTopFace = flatPattern->topFace(); auto document = design->parentDocument(); if (!document) return nullptr; auto products = document->products(); if (!products) return nullptr; for (size_t i = 0; i < products->count(); ++i) { auto candidate = products->item(i)->cast<FlatPatternProduct>(); if (candidate && candidate->flatPattern() && candidate->flatPattern()->entityToken() == flatPattern->entityToken()) return candidate->rootComponent()->cast<FlatPatternComponent>(); } return nullptr; } extern "C" XI_EXPORT bool run(const char* context) { app = Application::get(); if (!app) return false; auto doc = app->documents()->add(DocumentTypes::FusionDesignDocumentType); CHECK_PTR(doc); auto design = app->activeProduct()->cast<Design>(); CHECK_PTR(design); Ptr<BRepFace> topFace; auto fpComponent = createFlatPatternComponent(design, topFace); CHECK_PTR(fpComponent); CHECK_PTR(topFace); Measure the face's true border in ITS OWN plane, not world X/Y -- createFlatPattern() can lay the flat pattern body out at an arbitrary orientation, so a world-axis-aligned bounding box can cut corners off the actual (rotated) rectangle. Project every vertex onto the face's own uDirection/vDirection basis instead; that basis is exactly aligned with the face's real edges, so a bounding box in that space is a tight fit regardless of the face's orientation. auto plane = topFace->geometry()->cast<Plane>(); CHECK_PTR(plane); auto origin = plane->origin(); auto uDir = plane->uDirection(); auto vDir = plane->vDirection(); CHECK_PTR(origin); CHECK_PTR(uDir); CHECK_PTR(vDir); auto vertices = topFace->vertices(); CHECK_PTR(vertices); CHECK(vertices->count() > 0); double minU = 0.0, maxU = 0.0, minV = 0.0, maxV = 0.0; bool haveBounds = false; for (size_t i = 0; i < vertices->count(); ++i) { auto vertex = vertices->item(i); if (!vertex) continue; auto pt = vertex->geometry(); if (!pt) continue; double relX = pt->x() - origin->x(); double relY = pt->y() - origin->y(); double relZ = pt->z() - origin->z(); double u = relX * uDir->x() + relY * uDir->y() + relZ * uDir->z(); double v = relX * vDir->x() + relY * vDir->y() + relZ * vDir->z(); if (!haveBounds) { minU = maxU = u; minV = maxV = v; haveBounds = true; continue; } if (u < minU) minU = u; if (u > maxU) maxU = u; if (v < minV) minV = v; if (v > maxV) maxV = v; } CHECK(haveBounds); auto fpSketch = fpComponent->sketches()->add(topFace); CHECK_PTR(fpSketch); addByTwoPoints expects points in the SKETCH's own local coordinate space, not model space -- build each point in model space from the (u, v) face-plane basis, then explicitly convert via modelToSketchSpace() before handing it to the sketch curve creator. auto pointAtUV = [&](double u, double v) { Ptr<Point3D> modelPoint = Point3D::create( origin->x() + u * uDir->x() + v * vDir->x(), origin->y() + u * uDir->y() + v * vDir->y(), origin->z() + u * uDir->z() + v * vDir->z()); return fpSketch->modelToSketchSpace(modelPoint); }; auto lines = fpSketch->sketchCurves()->sketchLines(); CHECK_PTR(lines); Two bend lines placed at 30% and 70% across the face, each spanning border to border. double line1U = minU + (maxU - minU) * 0.3; double line2U = minU + (maxU - minU) * 0.7; auto line1 = lines->addByTwoPoints(pointAtUV(line1U, minV), pointAtUV(line1U, maxV)); CHECK_PTR(line1); auto line2 = lines->addByTwoPoints(pointAtUV(line2U, minV), pointAtUV(line2U, maxV)); CHECK_PTR(line2); auto features = fpComponent->features(); CHECK_PTR(features); Example 1: Create a press brake cosmetic bend with an explicit radius override auto cbFeatures = features->cosmeticBendFeatures(); CHECK_PTR(cbFeatures); auto angleInput = ValueInput::createByReal(PRESS_BRAKE_ANGLE_RADIANS); auto inp1 = cbFeatures->createInput(line1, CosmeticBendTypes::PressBrakeCosmeticBendType, angleInput); CHECK_PTR(inp1); auto radiusInput = ValueInput::createByReal(PRESS_BRAKE_RADIUS_CM); CHECK(inp1->setToPressBrake(angleInput)); auto inp1RadiusOverride = inp1->bendRadiusOverride(); CHECK_PTR(inp1RadiusOverride); CHECK(inp1RadiusOverride->setOverride(radiusInput)); CHECK(inp1->notes(PRESS_BRAKE_NOTES)); auto pressBrakeFeature = cbFeatures->add(inp1); CHECK_PTR(pressBrakeFeature); auto pressBrakeRadiusOverride = pressBrakeFeature->bendRadiusOverride(); CHECK_PTR(pressBrakeRadiusOverride); app->log( "Created press brake cosmetic bend: " + pressBrakeFeature->name() + ", angle=" + std::to_string(pressBrakeFeature->angle()->value()) + " rad, radius=" + std::to_string(pressBrakeRadiusOverride->bendRadius()->value()) + " cm"); Example 2: Create a crease cosmetic bend (sharp fold, no radius/angle) cbFeatures = features->cosmeticBendFeatures(); CHECK_PTR(cbFeatures); auto inp2 = cbFeatures->createInput(line2, CosmeticBendTypes::CreaseCosmeticBendType); CHECK_PTR(inp2); CHECK(inp2->notes(CREASE_NOTES)); auto creaseFeature = cbFeatures->add(inp2); CHECK_PTR(creaseFeature); app->log("Created crease cosmetic bend: " + creaseFeature->name()); app->log("CosmeticBendSample completed successfully."); return true; } #undef CHECK_PTR #undef CHECK
/** * Cosmetic Bend API sample — demonstrates creating sheet metal cosmetic bend features in a flat * pattern: a press brake bend with an explicit radius override and custom angle, and a crease * bend with manufacturing notes. * * Builds its own flat, sheet-metal plate and flat pattern in a new document, so it can be run * as-is without any external data file. */ import { adsk } from '@adsk/fusion'; const PLATE_SIZE_CM = 10.0; const PRESS_BRAKE_ANGLE_RADIANS = Math.PI / 3; // 60 degrees const PRESS_BRAKE_RADIUS_CM = 0.2; // explicit radius override const PRESS_BRAKE_NOTES = 'Press brake bend: explicit 0.2 cm radius override'; const CREASE_NOTES = 'Crease: sharp fold, no radius'; // Extrudes a flat plate, converts it to sheet metal, and creates its flat pattern. The flat // pattern's own Sketches/Features live on a FlatPatternComponent, reached through the // FlatPatternProduct in the document that matches the new flat pattern's entity token. function createFlatPatternComponent( design: adsk.fusion.Design): { fpComponent: adsk.fusion.FlatPatternComponent; topFace: adsk.fusion.BRepFace } { const rootComp = design.rootComponent; // Use the first library sheet metal rule's own thickness for the plate, so the extruded body // is guaranteed to match the rule convertToSheetMetal() is given below -- no need to probe the // body's thickness back out after the fact. const libraryRules = design.librarySheetMetalRules; if (libraryRules.count === 0) throw Error('No sheet metal rules available in the design.'); const rule = libraryRules.item(0); const thickness = rule.thickness.value; const sketch = rootComp.sketches.add(rootComp.xYConstructionPlane); sketch.sketchCurves.sketchLines.addTwoPointRectangle( adsk.core.Point3D.create(0, 0, 0), adsk.core.Point3D.create(PLATE_SIZE_CM, PLATE_SIZE_CM, 0)); const prof = sketch.profiles.item(0); const extrudes = rootComp.features.extrudeFeatures; const extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation); extInput.setDistanceExtent(false, adsk.core.ValueInput.createByReal(thickness)); extInput.isSolid = true; const ext = extrudes.add(extInput); const body = ext.bodies.item(0); // Find the largest planar face -- this becomes the sheet metal body's stationary face. let largestFace: adsk.fusion.BRepFace | null = null; let maxArea = 0.0; for (let i = 0; i < body.faces.count; i++) { const face = body.faces.item(i); if (face && face.geometry.surfaceType === adsk.core.SurfaceTypes.PlaneSurfaceType && face.area > maxArea) { maxArea = face.area; largestFace = face; } } if (!largestFace) throw Error('No planar face found on the extruded body.'); if (!body.convertToSheetMetal(largestFace, rule)) throw Error('convertToSheetMetal() failed.'); const flatPattern = rootComp.createFlatPattern(largestFace); if (!flatPattern) throw Error('createFlatPattern() returned null.'); const products = design.parentDocument.products; for (let i = 0; i < products.count; i++) { const candidate = products.item(i) as adsk.fusion.FlatPatternProduct; if (candidate && candidate.flatPattern && candidate.flatPattern.entityToken === flatPattern.entityToken) { const fpComponent = candidate.rootComponent as adsk.fusion.FlatPatternComponent; if (!fpComponent) throw Error('FlatPatternProduct.rootComponent is not a FlatPatternComponent.'); return { fpComponent, topFace: flatPattern.topFace }; } } throw Error('Could not find the FlatPatternComponent for the new flat pattern in document.products.'); } function run() { // Get the Fusion API's application object const app = adsk.core.Application.get(); if (!app) throw Error('No adsk.core.Application.'); app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType); const design = app.activeProduct as adsk.fusion.Design; if (!design) throw Error('No active Design.'); const { fpComponent, topFace } = createFlatPatternComponent(design); // Measure the face's true border in ITS OWN plane, not world X/Y -- createFlatPattern() can lay // the flat pattern body out at an arbitrary orientation, so a world-axis-aligned bounding box // can cut corners off the actual (rotated) rectangle. Project every vertex onto the face's own // uDirection/vDirection basis instead; that basis is exactly aligned with the face's real edges, // so a bounding box in that space is a tight fit regardless of the face's orientation. const plane = topFace.geometry as adsk.core.Plane; if (!plane) throw Error('Top face geometry is not a Plane.'); const origin = plane.origin; const uDir = plane.uDirection; const vDir = plane.vDirection; let minU = 0, maxU = 0, minV = 0, maxV = 0; let haveBounds = false; for (let i = 0; i < topFace.vertices.count; i++) { const pt = topFace.vertices.item(i).geometry; const relX = pt.x - origin.x, relY = pt.y - origin.y, relZ = pt.z - origin.z; const u = relX * uDir.x + relY * uDir.y + relZ * uDir.z; const v = relX * vDir.x + relY * vDir.y + relZ * vDir.z; if (!haveBounds) { minU = maxU = u; minV = maxV = v; haveBounds = true; } else { minU = Math.min(minU, u); maxU = Math.max(maxU, u); minV = Math.min(minV, v); maxV = Math.max(maxV, v); } } if (!haveBounds) throw Error('Top face has no vertices.'); const fpSketch = fpComponent.sketches.add(topFace); // addByTwoPoints expects points in the SKETCH's own local coordinate space, not model space -- // build each point in model space from the (u, v) face-plane basis, then explicitly convert via // modelToSketchSpace() before handing it to the sketch curve creator. const pointAtUV = (u: number, v: number): adsk.core.Point3D => { const modelPoint = adsk.core.Point3D.create( origin.x + u * uDir.x + v * vDir.x, origin.y + u * uDir.y + v * vDir.y, origin.z + u * uDir.z + v * vDir.z); return fpSketch.modelToSketchSpace(modelPoint); }; const lines = fpSketch.sketchCurves.sketchLines; // Two bend lines placed at 30% and 70% across the face, each spanning border to border. const line1U = minU + (maxU - minU) * 0.3; const line2U = minU + (maxU - minU) * 0.7; const line1 = lines.addByTwoPoints(pointAtUV(line1U, minV), pointAtUV(line1U, maxV)); const line2 = lines.addByTwoPoints(pointAtUV(line2U, minV), pointAtUV(line2U, maxV)); const features = fpComponent.features; // Example 1: Create a press brake cosmetic bend with an explicit radius override let cbFeatures = features.cosmeticBendFeatures; const angleInput = adsk.core.ValueInput.createByReal(PRESS_BRAKE_ANGLE_RADIANS); const inp1 = cbFeatures.createInput(line1, adsk.fusion.CosmeticBendTypes.PressBrakeCosmeticBendType, angleInput); if (!inp1) throw Error('createInput() for the first line returned null.'); const radiusInput = adsk.core.ValueInput.createByReal(PRESS_BRAKE_RADIUS_CM); if (!inp1.setToPressBrake(angleInput)) throw Error('setToPressBrake() failed.'); const inp1RadiusOverride = inp1.bendRadiusOverride; if (!inp1RadiusOverride) throw Error('bendRadiusOverride() returned null.'); if (!inp1RadiusOverride.setOverride(radiusInput)) throw Error('setOverride() failed.'); inp1.notes = PRESS_BRAKE_NOTES; const pressBrakeFeature = cbFeatures.add(inp1); if (!pressBrakeFeature) throw Error('add() for the press brake bend returned null.'); const pressBrakeRadiusOverride = pressBrakeFeature.bendRadiusOverride; if (!pressBrakeRadiusOverride) throw Error('bendRadiusOverride() on feature returned null.'); adsk.log(`Created press brake cosmetic bend: ${pressBrakeFeature.name}` + `, angle=${pressBrakeFeature.angle.value} rad, radius=${pressBrakeRadiusOverride.bendRadius.value} cm`); // Example 2: Create a crease cosmetic bend (sharp fold, no radius/angle) cbFeatures = features.cosmeticBendFeatures; const inp2 = cbFeatures.createInput(line2, adsk.fusion.CosmeticBendTypes.CreaseCosmeticBendType); if (!inp2) throw Error('createInput() for the second line returned null.'); inp2.notes = CREASE_NOTES; const creaseFeature = cbFeatures.add(inp2); if (!creaseFeature) throw Error('add() for the crease bend returned null.'); adsk.log(`Created crease cosmetic bend: ${creaseFeature.name}`); adsk.log('CosmeticBendSample completed successfully.'); } run();