Hi All,
I have been working on a script to modify facade mullions to taper depending on the adjacent panel. I have managed to achieve the outcome I need but I had to implement some additional steps that are really redundant.
Here is the situation:
I have measured the angels and they are returned as a list, however the angles needed to be used on facade panels that are part of a 2d array. ie polygon1[0][1]
So to fix this i just combined a fake list and the angle list to create a 2d array and it all worked.
However i am sure there is a nice way to generate a 2d Array of angles from my function.
so far this is the function:
function (Polygon FacadePoly) { double PAngleList = {}; double PAngle = 0.0; double PAngleNext = 0.0; double PAngleLeft = 0.0; for (int i = 0; i < FacadePoly.Count; ++i) { for (int j = 0; j < FacadePoly[i].Count; ++j) { int next = j + 1 >= FacadePoly[j].Count ? j : j + 1; PAngle = FacadePoly[i][j].DPlane3d.Normal.AngleXY.Degrees; PAngleNext = FacadePoly[i][next].DPlane3d.Normal.AngleXY.Degrees; PAngleLeft = (PAngleNext-PAngle)/2; PAngleList.Add(PAngleLeft); } } return PAngleList; }
The results are great, no more overlapping mullions.
Thanks
Wayne
Hi Wayne,
A simple modification will change your angle list into an array:
function (Polygon FacadePoly) { double PAngleArray = {}; double PAngle = 0.0; double PAngleNext = 0.0; double PAngleLeft = 0.0; for (int i = 0; i < FacadePoly.Count; ++i) { double PAngleList = {}; for (int j = 0; j < FacadePoly[i].Count; ++j) { int next = j + 1 >= FacadePoly[j].Count ? j : j + 1; PAngle = FacadePoly[i][j].DPlane3d.Normal.AngleXY.Degrees; PAngleNext = FacadePoly[i][next].DPlane3d.Normal.AngleXY.Degrees; PAngleLeft = (PAngleNext-PAngle)/2; PAngleList.Add(PAngleLeft); } PAngleArray.Add(PAngleList); } return PAngleArray; }
HTH,
Volker
Answer Verified By: Wayne Dickerson
Thanks Volker,
That worked perfectly.
Extending this I decided to look at the next polygon array (adjacent). We generally create facade in segments so it would be good to check to see if the last panel should reference the angle of the first panel of the adjacent polygon array.
To this end I modified your updated script to include a if else statement. not sure if this is an efficient use of the code as it appears to repeat a bit.
The question I have is how do you check to see if NextPoly is not Null? I have inserted a check on count. Is there a better way?
Here is the updated code:
function (Polygon FacadePoly, Polygon NextPoly) { double PAngleArray = {}; double PAngle = 0.0; double PAngleNext = 0.0; double PAngleLeft = 0.0; Polygon IsNextPoly = {}; for (int i = 0; i < FacadePoly.Count; ++i) { double PAngleList = {}; for (int j = 0; j < FacadePoly[i].Count; ++j) { /// Need to find if there is a NextPoly, this will always be 0 if (NextPoly.Count > 0) { IsNextPoly = j + 1 >= FacadePoly[j].Count ? NextPoly : FacadePoly; int next = j + 1 >= FacadePoly[j].Count ? 0 : j + 1; PAngle = FacadePoly[i][j].DPlane3d.Normal.AngleXY.Degrees; PAngleNext = IsNextPoly[i][next].DPlane3d.Normal.AngleXY.Degrees; PAngleLeft = (PAngleNext-PAngle)/2; PAngleList.Add(PAngleLeft); } else { int next = j + 1 >= FacadePoly[j].Count ? j : j + 1; IsNextPoly = FacadePoly; PAngle = FacadePoly[i][j].DPlane3d.Normal.AngleXY.Degrees; PAngleNext = IsNextPoly[i][next].DPlane3d.Normal.AngleXY.Degrees; PAngleLeft = (PAngleNext-PAngle)/2; PAngleList.Add(PAngleLeft); } } PAngleArray.Add(PAngleList); } return PAngleArray; }
Looks like the solution you found is valid. Congratulations! You could try to find increased efficiencies; however, fewer lines of code do not mean faster execution if the additional lines of code are executed in one branch of the logic or another. If there are additional lines of code in the same branch of logic then that usually means longer execution. Consequently, part of the clean-up is aesthetic --and facilitates code maintenance because parallel, similar code passages do not need to be maintained in parallel.
function (Polygon FacadePoly, Polygon NextPoly) { double PAngleArray = {}; double PAngle = 0.0; double PAngleNext = 0.0; double PAngleLeft = 0.0; // perhaps some validity check for NextPoly as done later bool nextPolyValid = false; if (NextPoly.IsList == true && NextPoly.Count > 0) { nextPolyValid = true; } Polygon NeighborPoly = null; for (int i = 0; i < FacadePoly.Count; ++i) { double PAngleList = {}; for (int j = 0; j < FacadePoly[i].Count; ++j) { // find neighboring polygon here, eliminating duplicate code int next = j + 1 >= FacadePoly[j].Count ? 0 : j + 1; if (next > 0) // then we are within FacadePoly { NeighborPoly = FacadePoly[i][next]; } // check that we are within valid bounds of NextPoly else if (nextPolyValid && i < NextPoly.Count && NextPoly[i].Count > 0) { NeighborPoly = NextPoly[i][0]; } else // the second facade has fewer rows { break; // skips out of this level of nesting } // this code only needed once PAngle = FacadePoly[i][j].DPlane3d.Normal.AngleXY.Degrees; PAngleNext = NeighborPoly.DPlane3d.Normal.AngleXY.Degrees; PAngleLeft = (PAngleNext-PAngle)/2; PAngleList.Add(PAngleLeft); } PAngleArray.Add(PAngleList); } return PAngleArray; }
I have not spent excessive amounts of time on this. I made sure, though, that it does work with two neighboring polygon grids. If they are of different height, the last angle is not generated because the break; statement skips out of the inner loop without calculating an angle and, therefore not adding it to the inner list of angles. I hope that makes sense.