@@ -31,6 +31,12 @@ protected override void RegisterInputParams(GH_Component.GH_InputParamManager pM
3131 Plane . WorldXY ) ;
3232 pManager . AddNumberParameter ( "Height" , "H" , "Height of the tree." , GH_ParamAccess . list ) ;
3333 pManager . AddIntegerParameter ( "Phase" , "phase" , "Phase of the tree." , GH_ParamAccess . list ) ;
34+ pManager . AddNumberParameter ( "SideBranchAngle" ,
35+ "sbAng" ,
36+ "Opening angle of side branches in degrees (30-120)." ,
37+ GH_ParamAccess . list ,
38+ 95.0 ) ;
39+ pManager [ 3 ] . Optional = true ;
3440 }
3541
3642 protected override void RegisterOutputParams ( GH_Component . GH_OutputParamManager pManager ) {
@@ -62,6 +68,9 @@ protected override void SolveInstance(IGH_DataAccess DA) {
6268 return ;
6369 }
6470
71+ var angLst = new List < double > ( ) ;
72+ DA . GetDataList ( "SideBranchAngle" , angLst ) ;
73+
6574 var trunk = new List < Curve > ( ) ;
6675 var canopyC = new List < Curve > ( ) ;
6776 var sideB = new List < Curve > ( ) ;
@@ -91,6 +100,26 @@ protected override void SolveInstance(IGH_DataAccess DA) {
91100 return ;
92101 }
93102
103+ // Handle angle list - replicate single value or validate count
104+ if ( angLst . Count == 0 )
105+ angLst = Enumerable . Repeat ( 95.0 , plnLst . Count ) . ToList ( ) ;
106+ else if ( angLst . Count == 1 )
107+ angLst = Enumerable . Repeat ( angLst [ 0 ] , plnLst . Count ) . ToList ( ) ;
108+ else if ( angLst . Count != plnLst . Count ) {
109+ AddRuntimeMessage ( GH_RuntimeMessageLevel . Error ,
110+ "SideBranchAngle # does not match Plane #, please check." ) ;
111+ return ;
112+ }
113+
114+ // Validate angle range
115+ foreach ( var ang in angLst ) {
116+ if ( ang < 30 || ang > 120 ) {
117+ AddRuntimeMessage ( GH_RuntimeMessageLevel . Warning ,
118+ "SideBranchAngle should be within [30, 120]. Values will be clamped." ) ;
119+ break ;
120+ }
121+ }
122+
94123 // Create a copy of plane list for sorting (while keeping original order intact)
95124 var sortedPlaneIndices = Enumerable . Range ( 0 , plnLst . Count ) . ToList ( ) ;
96125 sortedPlaneIndices . Sort ( ( i1 , i2 ) => {
@@ -115,7 +144,9 @@ protected override void SolveInstance(IGH_DataAccess DA) {
115144 //! 2. Draw trees in original order, collect tree widths
116145 var widCol = new List < double > ( ) ;
117146 for ( int i = 0 ; i < plnLst . Count ; i ++ ) {
118- var t = new Tree2D ( plnLst [ i ] , hLst [ i ] , false ) ;
147+ // Clamp angle to valid range
148+ double clampedAngle = Math . Max ( 30 , Math . Min ( 120 , angLst [ i ] ) ) ;
149+ var t = new Tree2D ( plnLst [ i ] , hLst [ i ] , false , clampedAngle ) ;
119150 var res = t . GrowToPhase ( phLst [ i ] ) ;
120151
121152 if ( ! res . Item1 ) {
@@ -158,8 +189,12 @@ protected override void SolveInstance(IGH_DataAccess DA) {
158189 }
159190 } else if ( plnLst . Count == 1 ) // special case: only one tree
160191 {
192+ // Handle angle for single tree
193+ double singleAngle = angLst . Count > 0 ? angLst [ 0 ] : 95.0 ;
194+ singleAngle = Math . Max ( 30 , Math . Min ( 120 , singleAngle ) ) ;
195+
161196 tscal . Add ( Tuple . Create ( 1.0 , 1.0 ) ) ;
162- treeCol . Add ( new Tree2D ( plnLst [ 0 ] , hLst [ 0 ] , false ) ) ;
197+ treeCol . Add ( new Tree2D ( plnLst [ 0 ] , hLst [ 0 ] , false , singleAngle ) ) ;
163198 var res = treeCol . Last ( ) . GrowToPhase ( phLst [ 0 ] ) ;
164199
165200 if ( ! res . Item1 ) {
0 commit comments