Hi @arshad.k ,
First of all, I would like to apologize for not reaching back to you as soon as your comment was up. Two weeks ago, I was busy at work and then Chinese New Year came, so we all had a week of holiday here in Taiwan, I ended up travelling with my peers so I didn't have any chance to reach back to you.
Anyway, I will try to explain how I constrain the stirrups to the concrete cover.
First, I use the CreateFromRebarShape method to create an initial stirrup by using a template rebar shape that is provided by Revit. As you probably have noticed, the initial stirrup follows the size of the template rebar shape and we need to constrain it down to the appropriate size that matches the size of our concrete element.
So the next thing that we need to do is to call the RebarConstraintManager of the particular initial stirrup in order to access and modify the rebar constraints of the initial stirrup.
By using the RebarConstraintManager, I would first collect all of the handles of the stirrup by using the GetAllHandles() Method and stores them inside a list or array. Handles are those interaction points located on the rebar element that one normally uses when trying to modify the shape or size of the rebar through the user interface of Revit.
The logic here is that I would like to move the handles of the stirrup, especially the handles at the legs of the stirrup, so that they can be moved or constrained to the correct concrete cover of our current beam/column element, thus we can obtain the correct stirrup size.
So, the next thing we should do is to iterate through all of the handle in the list of handles that we obtained previously. For each handle, Find all of the constraint candidates that are of the type ToCover using the GetConstraintCandidatesForHandle() Method. Rebar handles can be constrained to a lot of things, but what we want here are the ToCover constraints because we want to constraint a particular handle to the concrete cover. You can imagine each ToCover constraint as a representation of the handles' constraint to a concrete cover. By following this method, a single handle will detect several ToCover constraints. Now, Imagine that you are editing a rebar handle of one stirrup leg, notice that a rectangular column would have eight concrete cover that the leg handle can be constrained to. However, the leg handle shall only be constrained to the correct concrete cover, which in this case is the cover that is closest to the particular leg handle. This is where the GetDistanceToTargetCover plays a role.
But before we get into that, there is something that you need to be careful of, when trying to find all of the ToCover constraint of a particular handle, Revit API will also detect not only the concrete cover of a particular concrete element, but also all of the ToCover constraints of other concrete element in the periphery of the stirrup. Therefore, it is necessary that you first make sure that the ToCover constraint that you are targeting is the same as the concrete element that you will use as the host of your stirrup. In my case, I first checked for the ElementId of the target element of the ToCover constraint and compared it with the ElementId of my host concrete element. If you are not careful, your handle will end up getting constrained to the cover of other adjacent concrete element instead of the intended concrete element.
After you have cleared that, we can safely move on to find the nearest ToCover constraint that we are going to constrain our handle to. I used the GetDistanceToTargetCover() method, this method finds the distance between the current ToCover constraint of the handle to the target cover. Then find the one with absolute minimum distance. When I said absolute, I mean that you first need to find the absolute value of the distance before comparing it to the other distance to find the actual minimum distance. This was actually my issue before, where the handle won't be constrained to the nearest cover. Turns out, my code previously compared non-absolute values. After I debugged the code, I noticed something like: the distance to the nearest cover was 10 but distance to the farthest cover was -400, if we compare non-absolute values, -400 is less than 10 but the absolute value is the true indicator of the distance to the cover. So if we compare the absolute values, it is obvious that 400 is greater than 10.
After we find the nearest cover constraint to the handle, we can go ahead and move the constraint of the handle to the cover itself by using the SetDistanceToTargetCover() method and setting the distance as 0. After the constraint of the handle has been moved to its cover, we can then go ahead and set the constraint as the preferred constraint for the handle by using the SetPreferredConstraintForHandle() method, this will set the constraint that we just moved to the cover as the preferred constraint that the handle will use. At the end, this will move the handle to the cover.
I hope my explanations are clear. If you have further questions, don't hesitate to continue this discussion, I am willing to help.