@@ -186,24 +186,29 @@ struct AxisInfo {
186186 domain : Option < ( f64 , f64 ) > ,
187187 breaks : Vec < f64 > ,
188188 labels : Vec < ( f64 , String ) > ,
189- is_free : bool ,
189+ suppress : bool ,
190190}
191191
192192impl AxisInfo {
193193 fn new ( aesthetic : & str , scales : & [ Scale ] , facet : Option < & crate :: plot:: Facet > ) -> Self {
194- let ( domain, labels) = match scales. iter ( ) . find ( |s| s. aesthetic == aesthetic) {
194+ let scale = scales. iter ( ) . find ( |s| s. aesthetic == aesthetic) ;
195+ let ( domain, labels) = match scale {
195196 Some ( s) => ( s. numeric_domain ( ) , s. break_labels ( ) ) ,
196197 None => ( None , Vec :: new ( ) ) ,
197198 } ;
198199 // Set domain to None if zero-range
199200 let domain = domain. filter ( |( min, max) | ( max - min) . abs ( ) > f64:: EPSILON ) ;
200201 let breaks = labels. iter ( ) . map ( |( v, _) | * v) . collect ( ) ;
201- let is_free = facet. is_some_and ( |f| f. is_free ( aesthetic) ) ;
202+ // Free facet scales have per-panel domains that don't match the global
203+ // positions used for decoration; dummy scales are stat-injected placeholders
204+ // with no meaningful domain to label.
205+ let suppress =
206+ facet. is_some_and ( |f| f. is_free ( aesthetic) ) || scale. is_some_and ( |s| s. is_dummy ( ) ) ;
202207 Self {
203208 domain,
204209 breaks,
205210 labels,
206- is_free ,
211+ suppress ,
207212 }
208213 }
209214}
@@ -403,7 +408,7 @@ impl ProjectionRenderer for PolarProjection {
403408impl PolarProjection {
404409 fn grid_rings ( & self , theme : & Value ) -> Vec < Value > {
405410 let p = & self . panel ;
406- if p. radial . is_free {
411+ if p. radial . suppress {
407412 return Vec :: new ( ) ;
408413 }
409414 let Some ( ( domain_min, domain_max) ) = p. radial . domain else {
@@ -464,7 +469,7 @@ impl PolarProjection {
464469
465470 fn grid_spokes ( & self , theme : & Value ) -> Vec < Value > {
466471 let p = & self . panel ;
467- if p. angle . is_free || p. angle . domain . is_none ( ) {
472+ if p. angle . suppress || p. angle . domain . is_none ( ) {
468473 return Vec :: new ( ) ;
469474 }
470475 if p. angle . breaks . is_empty ( ) {
@@ -509,7 +514,7 @@ impl PolarProjection {
509514
510515 fn radial_axis ( & self , theme : & Value ) -> Vec < Value > {
511516 let p = & self . panel ;
512- if p. radial . is_free {
517+ if p. radial . suppress {
513518 return Vec :: new ( ) ;
514519 }
515520 if p. radial . domain . is_none ( ) {
@@ -661,7 +666,7 @@ impl PolarProjection {
661666
662667 fn angular_axis ( & self , theme : & Value ) -> Vec < Value > {
663668 let p = & self . panel ;
664- if p. angle . is_free {
669+ if p. angle . suppress {
665670 return Vec :: new ( ) ;
666671 }
667672 let Some ( ( domain_min, domain_max) ) = p. angle . domain else {
@@ -722,7 +727,7 @@ impl PolarProjection {
722727 . collect ( ) ;
723728 let theta = p. expr_normalize_theta ( "datum.v" ) ;
724729
725- let tick_just: f64 = if p . is_full_circle { 0.5 } else { 0.0 } ;
730+ let tick_just: f64 = 0.0 ;
726731
727732 let outer_cx = p. expr_x ( & outer_s, & theta) ;
728733 let outer_cy = p. expr_y ( & outer_s, & theta) ;
@@ -2131,6 +2136,29 @@ mod tests {
21312136 assert ! ( !proj. angular_axis( & theme) . is_empty( ) ) ;
21322137 }
21332138
2139+ #[ test]
2140+ fn dummy_scale_suppresses_decoration ( ) {
2141+ use crate :: naming:: stat_column;
2142+ use crate :: plot:: types:: ArrayElement ;
2143+
2144+ let dummy_sentinel = stat_column ( "dummy" ) ;
2145+ let mut dummy = Scale :: new ( "pos1" ) ;
2146+ dummy. input_range = Some ( vec ! [ ArrayElement :: String ( dummy_sentinel) ] ) ;
2147+
2148+ let angle = scale_with_breaks ( "pos2" , ( 0.0 , 360.0 ) , vec ! [ 90.0 , 180.0 , 270.0 ] ) ;
2149+ let scales = vec ! [ dummy, angle] ;
2150+
2151+ let proj = PolarProjection {
2152+ panel : PolarContext :: new ( None , None , & scales) ,
2153+ } ;
2154+ let theme = Value :: Null ;
2155+
2156+ assert ! ( proj. grid_rings( & theme) . is_empty( ) ) ;
2157+ assert ! ( proj. radial_axis( & theme) . is_empty( ) ) ;
2158+ assert ! ( !proj. grid_spokes( & theme) . is_empty( ) ) ;
2159+ assert ! ( !proj. angular_axis( & theme) . is_empty( ) ) ;
2160+ }
2161+
21342162 // =========================================================================
21352163 // Discrete channel: indexof expression
21362164 // =========================================================================
0 commit comments