@@ -879,11 +879,27 @@ class HeatEquationDemo extends P5DemoBase {
879879 const plotMid = ( plotTop + plotBottom ) / 2 ;
880880 const plotHalfHeight = ( plotBottom - plotTop ) / 2 ;
881881
882+ // Baseline at u=0.
882883 p . stroke ( this . colors . axis ) ;
883884 p . strokeWeight ( 1 ) ;
884885 p . line ( 0 , plotMid , w , plotMid ) ;
885886 p . noStroke ( ) ;
886887
888+ // Mean temperature — dashed line and numeric readout. Clamp visually to the plot
889+ // window but show the true numeric value in the label.
890+ const mean = this . computeMean ( ) ;
891+ const meanClamped = Math . max ( - 1 , Math . min ( 1 , mean ) ) ;
892+ const meanY = plotMid - meanClamped * plotHalfHeight ;
893+ p . push ( ) ;
894+ const ctx = p . drawingContext as CanvasRenderingContext2D ;
895+ ctx . setLineDash ( [ 4 , 4 ] ) ;
896+ p . stroke ( this . colors . warning ) ;
897+ p . strokeWeight ( 1 ) ;
898+ p . line ( 0 , meanY , w , meanY ) ;
899+ ctx . setLineDash ( [ ] ) ;
900+ p . pop ( ) ;
901+
902+ // Solution curve.
887903 p . stroke ( this . colors . accent ) ;
888904 p . strokeWeight ( 2 ) ;
889905 p . noFill ( ) ;
@@ -896,6 +912,20 @@ class HeatEquationDemo extends P5DemoBase {
896912 }
897913 p . endShape ( ) ;
898914 p . noStroke ( ) ;
915+
916+ // Mean label at the right edge of the dashed line.
917+ p . fill ( this . colors . warning ) ;
918+ p . textAlign ( p . RIGHT , p . BOTTOM ) ;
919+ p . textSize ( 12 ) ;
920+ p . text ( `⟨u⟩ = ${ mean . toFixed ( 3 ) } ` , w - 6 , meanY - 2 ) ;
921+ }
922+
923+ /** Spatial mean of the current u(x) buffer via trapezoidal rule on the render grid. */
924+ private computeMean ( ) : number {
925+ const n = this . uBuffer . length ;
926+ let s = 0.5 * ( this . uBuffer [ 0 ] + this . uBuffer [ n - 1 ] ) ;
927+ for ( let i = 1 ; i < n - 1 ; i ++ ) s += this . uBuffer [ i ] ;
928+ return s / ( n - 1 ) ;
899929 }
900930
901931 private sampleU ( x : number ) : number {
0 commit comments