use super::super::mapping::{require_axis, ConstraintFailure, MappedConstraint, ResolvedElement, mate};
use super::mechanical::{held_here, perpendicular, positive, radius_of};
use super::{elements_field, id_field, pair_applicable, schema_entry, ConstraintTypeDef};
use crate::feature_pipeline::assembly::ConstraintEntry;
use crate::feature_pipeline::{Env, SelectionProbe};
use crate::MateKind;
pub(super) const DEF: ConstraintTypeDef = ConstraintTypeDef {
type_id: "gear",
label: "Gear",
short_name: "GEAR",
icon: "\u{2699}",
long_name: "\u{2699} Gear",
min_elements: 2,
max_elements: 2,
duplicate_family: false,
applicable,
};
fn applicable(probe: &SelectionProbe) -> bool {
pair_applicable(probe, probe.faces + probe.edges)
}
pub(super) fn schema() -> serde_json::Value {
schema_entry(&DEF, serde_json::json!({
"id": id_field(),
"elements": elements_field(&["FACE", "EDGE"], 2, 2,
"Select the two gears' axis faces or edges (cylindrical faces, circular or straight edges)"),
"ratio": {
"type": "number",
"step": 0.1,
"default_value": 0,
"hint": "Turns of the second gear per turn of the first (teeth of the first / teeth of the second); 0 takes it from the two radii"
},
"reverse": {
"type": "boolean",
"default_value": false,
"hint": "Turn both gears the same way (an internal mesh or a belt) instead of opposite ways"
},
}))
}
pub(in crate::feature_pipeline::assembly) fn map(
entry: &ConstraintEntry,
a: &ResolvedElement,
b: &ResolvedElement,
env: &Env,
) -> Result<MappedConstraint, ConstraintFailure> {
let (axis_a, axis_b) = (require_axis(a)?, require_axis(b)?);
let ratio = match positive(entry, "ratio", env)? {
Some(ratio) => ratio,
None => match (radius_of(a), radius_of(b)) {
(Some(ra), Some(rb)) => ra / rb,
_ => 1.0,
},
};
let kind = MateKind::Gear {
axis_a,
ref_a: perpendicular(axis_a.direction),
world_ref_a: [0.0; 3],
axis_b,
ref_b: perpendicular(axis_b.direction),
world_ref_b: [0.0; 3],
ratio,
reverse: entry.flag("reverse"),
};
Ok(MappedConstraint {
mates: vec![mate(a, b, held_here(kind, a, b, entry))],
note: Some(format!("Ratio {ratio:.4}")),
..Default::default()
})
}