@@ -25,7 +25,7 @@ use processing_render::{
2525use processing_render:: { GEN_GAUSSIAN , GEN_SIGNED , GEN_UNIFORM } ;
2626use processing_render:: {
2727 MAP_ABS , MAP_AFFINE , MAP_CLAMP , MAP_EQ , MAP_FLOOR , MAP_GEQ , MAP_GREATER , MAP_LEQ , MAP_LESS ,
28- MAP_NEGATE , MAP_NEQ , MAP_SQRT , MAP_SQUARE ,
28+ MAP_LIMIT , MAP_NEGATE , MAP_NEQ , MAP_NORMALIZE , MAP_SQRT , MAP_SQUARE ,
2929} ;
3030use processing_render:: {
3131 REDUCE_LENGTH , REDUCE_MAX , REDUCE_MEAN , REDUCE_MIN , REDUCE_SUM , REDUCE_SUMSQ ,
@@ -46,6 +46,8 @@ fn parse_map_op(s: &str) -> PyResult<u32> {
4646 _ if s. eq_ignore_ascii_case ( c:: LEQ ) => Ok ( MAP_LEQ ) ,
4747 _ if s. eq_ignore_ascii_case ( c:: EQ ) => Ok ( MAP_EQ ) ,
4848 _ if s. eq_ignore_ascii_case ( c:: NEQ ) => Ok ( MAP_NEQ ) ,
49+ _ if s. eq_ignore_ascii_case ( c:: NORMALIZE ) => Ok ( MAP_NORMALIZE ) ,
50+ _ if s. eq_ignore_ascii_case ( c:: LIMIT ) => Ok ( MAP_LIMIT ) ,
4951 _ => Err ( PyValueError :: new_err ( format ! ( "map: unknown op {s:?}" ) ) ) ,
5052 }
5153}
@@ -239,6 +241,11 @@ fn map_params(kwargs: Option<&Bound<'_, PyDict>>, op: u32) -> PyResult<(f32, f32
239241 kw_f32 ( kwargs, "offset" , 0.0 ) ?,
240242 ) ,
241243 MAP_CLAMP => ( kw_f32 ( kwargs, "lo" , 0.0 ) ?, kw_f32 ( kwargs, "hi" , 1.0 ) ?) ,
244+ MAP_NORMALIZE => ( kw_f32 ( kwargs, "length" , 1.0 ) ?, 0.0 ) ,
245+ MAP_LIMIT => (
246+ kw_f32 ( kwargs, "min_length" , 0.0 ) ?,
247+ kw_f32 ( kwargs, "max_length" , f32:: MAX ) ?,
248+ ) ,
242249 MAP_GREATER | MAP_LESS | MAP_GEQ | MAP_LEQ | MAP_EQ | MAP_NEQ => (
243250 kw_f32 ( kwargs, "threshold" , 0.0 ) ?,
244251 kw_f32 ( kwargs, "epsilon" , 1.0e-6 ) ?,
@@ -251,6 +258,8 @@ fn map_param_keys(op: u32) -> &'static [&'static str] {
251258 match op {
252259 MAP_AFFINE => & [ "scale" , "offset" ] ,
253260 MAP_CLAMP => & [ "lo" , "hi" ] ,
261+ MAP_NORMALIZE => & [ "length" ] ,
262+ MAP_LIMIT => & [ "min_length" , "max_length" ] ,
254263 MAP_GREATER | MAP_LESS | MAP_GEQ | MAP_LEQ | MAP_EQ | MAP_NEQ => & [ "threshold" , "epsilon" ] ,
255264 _ => & [ ] ,
256265 }
@@ -567,9 +576,9 @@ impl Particles {
567576 reject_unknown_kwargs ( kwargs, & [ "a" , "b" , "out" , "op" , "b_scale" , "b_offset" ] ) ?;
568577 let ( a, comp) = self . operand ( kwargs, "a" ) ?;
569578 let ( b, b_comp) = self . operand ( kwargs, "b" ) ?;
570- if b_comp != comp {
579+ if b_comp != comp && b_comp != 1 {
571580 return Err ( PyValueError :: new_err ( format ! (
572- "apply(combine): `a` has {comp} components but `b` has {b_comp} (must match) "
581+ "apply(combine): the first operand has {comp} components, so the second needs {comp} or 1, not {b_comp} "
573582 ) ) ) ;
574583 }
575584 let out = self . dest ( kwargs, a) ?;
0 commit comments