use crate::feature_pipeline::features::{common, transform_bake};
use crate::feature_pipeline::{FeatureContext, FeatureResult};
use crate::{make_cylinder_brep, Vec3};
const FACE_SUFFIX: [&str; 3] = ["_S", "_B", "_T"];
pub fn execute(ctx: &FeatureContext) -> FeatureResult {
match build(ctx) {
Ok(result) => result,
Err(error) => ctx.fail(error),
}
}
pub(crate) fn validate_radius(radius: f64) -> Result<(), String> {
if !radius.is_finite() || radius <= 0.0 {
return Err("invalid_arguments: cylinder radius must be finite and greater than zero; use height or a transform to change direction".into());
}
Ok(())
}
fn build(ctx: &FeatureContext) -> Result<FeatureResult, String> {
let radius = ctx.number("radius")?;
validate_radius(radius)?;
let height = ctx.number("height")?;
let mut solid = make_cylinder_brep(
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 1.0, 0.0),
radius,
height.abs(),
)?;
let faces = &mut solid
.shells
.get_mut(0)
.ok_or("cylinder builder produced no shell")?
.faces;
if faces.len() != FACE_SUFFIX.len() {
return Err(format!(
"cylinder builder produced {} faces, expected 3",
faces.len()
));
}
for (face, suffix) in faces.iter_mut().zip(FACE_SUFFIX) {
face.name = Some(format!("{}{}", ctx.id, suffix));
}
let solid = if height < 0.0 {
common::rotate_half_turn_about_x(solid)?
} else {
solid
};
let solid = transform_bake::apply(ctx, solid)?;
Ok(common::finalize_solid(ctx, solid, &ctx.id))
}
pub fn context_applicable(_probe: &crate::feature_pipeline::SelectionProbe) -> bool {
false
}
pub fn schema() -> serde_json::Value {
serde_json::json!({
"type": "P.CY",
"shortName": "P.CY",
"longName": "Primitive Cylinder",
"ribbonPath": "Home/Primitives/Cylinder",
"commandSize": "Compact",
"displayBuilder": false,
"inputParamsSchema": {
"id": {
"type": "string",
"default_value": null,
"hint": "Unique identifier for the feature"
},
"radius": {
"type": "number",
"default_value": 5,
"exclusiveMinimum": 0,
"hint": "Radius of the cylinder; must be greater than zero"
},
"height": {
"type": "number",
"default_value": 10,
"hint": "Height of the cylinder along Y-axis"
},
"transform": common::primitive_transform_schema(),
"boolean": common::optional_boolean_schema()
}
})
}