Stream(ArrayList data, RebarConstraint rbc)
        {
            data.Add(new Snoop.Data.ClassSeparator(typeof(RebarConstraint)));
            data.Add(new Snoop.Data.Bool("IsValid", rbc.IsValid()));
            if (!rbc.IsValid())
            {
                return;
            }
            data.Add(new Snoop.Data.String("ConstraintType", rbc.GetConstraintType().ToString()));
            data.Add(new Snoop.Data.Object("TargetElement", rbc.GetTargetElement()));

            RebarConstraintType type = rbc.GetConstraintType();

            if (type == RebarConstraintType.FixedDistanceToHostFace)
            {
                data.Add(new Snoop.Data.Double("Distance to Target Host Face", rbc.GetDistanceToTargetHostFace()));
            }
            if (type != RebarConstraintType.ToOtherRebar)
            {
                data.Add(new Snoop.Data.String("Target Host Face Type", rbc.GetRebarConstraintTargetHostFaceType().ToString()));
                data.Add(new Snoop.Data.Object("Target Host Face Reference", rbc.GetTargetHostFaceReference()));
            }
            if (type == RebarConstraintType.ToOtherRebar)
            {
                data.Add(new Snoop.Data.String("Rebar Constraint Type", rbc.GetTargetRebarConstraintType().ToString()));
                if (rbc.GetTargetRebarConstraintType() == TargetRebarConstraintType.BarBend)
                {
                    data.Add(new Snoop.Data.Int("Target RebarBendNumber", rbc.GetTargetRebarBendNumber()));
                }
            }
        }
        CollectEvent(object sender, CollectorEventArgs e)
        {
            // cast the sender object to the SnoopCollector we are expecting
            Collector snoopCollector = sender as Collector;

            if (snoopCollector == null)
            {
                Debug.Assert(false); // why did someone else send us the message?
                return;
            }

            // see if it is a type we are responsible for
            Color color = e.ObjToSnoop as Color;

            if (color != null)
            {
                Stream(snoopCollector.Data(), color);
                return;
            }

            LayoutRule layoutRule = e.ObjToSnoop as LayoutRule;

            if (layoutRule != null)
            {
                Stream(snoopCollector.Data(), layoutRule);
                return;
            }

            FormatOptions formatOptions = e.ObjToSnoop as FormatOptions;

            if (formatOptions != null)
            {
                Stream(snoopCollector.Data(), formatOptions);
                return;
            }

            CurtainGrid curtainGrid = e.ObjToSnoop as CurtainGrid;

            if (curtainGrid != null)
            {
                Stream(snoopCollector.Data(), curtainGrid);
                return;
            }

            CurtainCell curtainCell = e.ObjToSnoop as CurtainCell;

            if (curtainCell != null)
            {
                Stream(snoopCollector.Data(), curtainCell);
                return;
            }

            RebarHostData rebarHostData = e.ObjToSnoop as RebarHostData;

            if (rebarHostData != null)
            {
                Stream(snoopCollector.Data(), rebarHostData);
                return;
            }

            Leader leader = e.ObjToSnoop as Leader;

            if (leader != null)
            {
                Stream(snoopCollector.Data(), leader);
                return;
            }

            AreaVolumeSettings areaSettings = e.ObjToSnoop as AreaVolumeSettings;

            if (areaSettings != null)
            {
                Stream(snoopCollector.Data(), areaSettings);
                return;
            }

            ViewSheetSetting viewSheetSetting = e.ObjToSnoop as ViewSheetSetting;

            if (viewSheetSetting != null)
            {
                Stream(snoopCollector.Data(), viewSheetSetting);
                return;
            }

            Autodesk.Revit.UI.Events.DialogBoxData dlgBoxData = e.ObjToSnoop as Autodesk.Revit.UI.Events.DialogBoxData;
            if (dlgBoxData != null)
            {
                Stream(snoopCollector.Data(), dlgBoxData);
                return;
            }

            Construction construct = e.ObjToSnoop as Construction;

            if (construct != null)
            {
                Stream(snoopCollector.Data(), construct);
                return;
            }

            FamilyElementVisibility famElemVisib = e.ObjToSnoop as FamilyElementVisibility;

            if (famElemVisib != null)
            {
                Stream(snoopCollector.Data(), famElemVisib);
                return;
            }

            FamilyManager famManager = e.ObjToSnoop as FamilyManager;

            if (famManager != null)
            {
                Stream(snoopCollector.Data(), famManager);
                return;
            }

            FamilyParameter famParam = e.ObjToSnoop as FamilyParameter;

            if (famParam != null)
            {
                Stream(snoopCollector.Data(), famParam);
                return;
            }

            FamilyType famType = e.ObjToSnoop as FamilyType;

            if (famType != null)
            {
                Stream(snoopCollector.Data(), famType);
                return;
            }

            MEPSpaceConstruction mepSpaceConstuct = e.ObjToSnoop as MEPSpaceConstruction;

            if (mepSpaceConstuct != null)
            {
                Stream(snoopCollector.Data(), mepSpaceConstuct);
                return;
            }

            BuildingSiteExportOptions bldSiteExpOptions = e.ObjToSnoop as BuildingSiteExportOptions;

            if (bldSiteExpOptions != null)
            {
                Stream(snoopCollector.Data(), bldSiteExpOptions);
                return;
            }

            DGNExportOptions dgnExpOptions = e.ObjToSnoop as DGNExportOptions;

            if (dgnExpOptions != null)
            {
                Stream(snoopCollector.Data(), dgnExpOptions);
                return;
            }

            DWFExportOptions dwfExpOptions = e.ObjToSnoop as DWFExportOptions;

            if (dwfExpOptions != null)
            {
                Stream(snoopCollector.Data(), dwfExpOptions);
                return;
            }

            DWGExportOptions dwgExpOptions = e.ObjToSnoop as DWGExportOptions;

            if (dwgExpOptions != null)
            {
                Stream(snoopCollector.Data(), dwgExpOptions);
                return;
            }

            DWGImportOptions dwgImpOptions = e.ObjToSnoop as DWGImportOptions;

            if (dwgImpOptions != null)
            {
                Stream(snoopCollector.Data(), dwgImpOptions);
                return;
            }

            FBXExportOptions fbxExpOptions = e.ObjToSnoop as FBXExportOptions;

            if (fbxExpOptions != null)
            {
                Stream(snoopCollector.Data(), fbxExpOptions);
                return;
            }

            TrussMemberInfo trussInfo = e.ObjToSnoop as TrussMemberInfo;

            if (trussInfo != null)
            {
                Stream(snoopCollector.Data(), trussInfo);
                return;
            }

            VertexIndexPair vertIndPair = e.ObjToSnoop as VertexIndexPair;

            if (vertIndPair != null)
            {
                Stream(snoopCollector.Data(), vertIndPair);
                return;
            }

            PointElementReference ptElemRef = e.ObjToSnoop as PointElementReference;

            if (ptElemRef != null)
            {
                Stream(snoopCollector.Data(), ptElemRef);
                return;
            }

            Autodesk.Revit.DB.Architecture.BoundarySegment boundSeg = e.ObjToSnoop as Autodesk.Revit.DB.Architecture.BoundarySegment;
            if (boundSeg != null)
            {
                Stream(snoopCollector.Data(), boundSeg);
                return;
            }

            PointLocationOnCurve ptLocOnCurve = e.ObjToSnoop as PointLocationOnCurve;

            if (ptLocOnCurve != null)
            {
                Stream(snoopCollector.Data(), ptLocOnCurve);
                return;
            }

            Entity entity = e.ObjToSnoop as Entity;

            if (entity != null)
            {
                Stream(snoopCollector.Data(), entity);
                return;
            }

            Field field = e.ObjToSnoop as Field;

            if (field != null)
            {
                Stream(snoopCollector.Data(), field);
                return;
            }

            ExtensibleStorageField storeagefield = e.ObjToSnoop as ExtensibleStorageField;

            if (storeagefield != null)
            {
                Stream(snoopCollector.Data(), storeagefield);
                return;
            }

            IList <Autodesk.Revit.DB.BoundarySegment> boundSegs = e.ObjToSnoop as
                                                                  IList <Autodesk.Revit.DB.BoundarySegment>;

            if (boundSegs != null)
            {
                Stream(snoopCollector.Data(), boundSegs);
                return;
            }

            if (e.ObjToSnoop is KeyValuePair <String, String> )
            {
                KeyValuePair <String, String> stringspair = (KeyValuePair <String, String>)e.ObjToSnoop;
                Stream(snoopCollector.Data(), stringspair);
                return;
            }

            Schema schema = e.ObjToSnoop as Schema;

            if (schema != null)
            {
                Stream(snoopCollector.Data(), schema);
                return;
            }

            ElementId elemId = e.ObjToSnoop as ElementId;

            if (elemId != null)
            {
                Stream(snoopCollector.Data(), elemId);
                return;
            }

            PlanViewRange plvr = e.ObjToSnoop as PlanViewRange;

            if (plvr != null)
            {
                Stream(snoopCollector.Data(), plvr);
                return;
            }
            //TF
            RebarConstraintsManager rbcm = e.ObjToSnoop as RebarConstraintsManager;

            if (rbcm != null)
            {
                Stream(snoopCollector.Data(), rbcm);
                return;
            }

            RebarConstrainedHandle rbch = e.ObjToSnoop as RebarConstrainedHandle;

            if (rbch != null)
            {
                Stream(snoopCollector.Data(), rbch);
                return;
            }

            RebarConstraint rbc = e.ObjToSnoop as RebarConstraint;

            if (rbc != null)
            {
                Stream(snoopCollector.Data(), rbc);
                return;
            }

            //TFEND

            if (Utils.IsSupportedType(e.ObjToSnoop) && e.ObjToSnoop != null)
            {
                Utils.StreamWithReflection(snoopCollector.Data(), e.ObjToSnoop.GetType(), e.ObjToSnoop);
            }
        }
      Stream(ArrayList data, RebarConstraint rbc)
      {
          data.Add(new Snoop.Data.ClassSeparator(typeof(RebarConstraint)));

          data.Add(new Snoop.Data.Bool("IsValid", rbc.IsValid()));
          data.Add(new Snoop.Data.String("ConstraintType", rbc.GetConstraintType().ToString()));
          if (rbc.GetConstraintType() == RebarConstraintType.FixedDistanceToHostFace)
          {
              data.Add(new Snoop.Data.Double("Distance to Target Host Face", rbc.GetDistanceToTargetHostFace()));
          }
          if (rbc.GetConstraintType() != RebarConstraintType.ToOtherRebar)
          {
              data.Add(new Snoop.Data.String("Target Host Face Type", rbc.GetRebarConstraintTargetHostFaceType().ToString()));
          }
          if (rbc.GetConstraintType() == RebarConstraintType.ToOtherRebar)
          {
              data.Add(new Snoop.Data.String("Rebar Constraint Type", rbc.GetTargetRebarConstraintType().ToString()));
              if (rbc.GetTargetRebarConstraintType() == TargetRebarConstraintType.BarBend)
              {
                  data.Add(new Snoop.Data.Int("Target RebarBendNumber", rbc.GetTargetRebarBendNumber()));
              }
          }
      }
        /// <summary>
        /// Implement this method as an external command for Revit.
        /// </summary>
        /// <param name="commandData">An object that is passed to the external application
        /// which contains data related to the command,
        /// such as the application object and active view.</param>
        /// <param name="message">A message that can be set by the external application
        /// which will be displayed if a failure or cancellation is returned by
        /// the external command.</param>
        /// <param name="elements">A set of elements to which the external application
        /// can add elements that are to be highlighted in case of failure or cancellation.</param>
        /// <returns>Return the status of the external command.
        /// A result of Succeeded means that the API external method functioned as expected.
        /// Cancelled can be used to signify that the user cancelled the external operation
        /// at some point. Failure should be returned if the application is unable to proceed with
        /// the operation.</returns>
        public virtual Result Execute(ExternalCommandData commandData
                                      , ref string message, ElementSet elements)
        {
            try
            {
                Document doc = commandData.Application.ActiveUIDocument.Document;
                if (doc == null)
                {
                    return(Result.Failed);
                }

                //Fetch a RebarBarType element to be used in Rebar creation.
                FilteredElementCollector fec = new FilteredElementCollector(doc).OfClass(typeof(RebarBarType));
                if (fec.GetElementCount() <= 0)
                {
                    return(Result.Failed);
                }
                RebarBarType barType   = fec.FirstElement() as RebarBarType;
                Rebar        rebar     = null;
                CurveElement curveElem = null;
                using (Transaction tran = new Transaction(doc, "Create Rebar"))
                {
                    Element   host = null;
                    Selection sel  = commandData.Application.ActiveUIDocument.Selection;
                    try
                    {
                        //Select structural Host.
                        Reference hostRef = sel.PickObject(ObjectType.Element, "Select Host");
                        host = doc.GetElement(hostRef.ElementId);
                        if (host == null)
                        {
                            return(Result.Failed);
                        }
                    }
                    catch (Exception e)
                    {
                        message = e.Message;
                        return(Result.Failed);
                    }

                    try
                    {
                        //Select curve element
                        Reference lineRef = sel.PickObject(ObjectType.Element, "Select Model curve");
                        curveElem = doc.GetElement(lineRef.ElementId) as CurveElement;
                    }
                    catch (Exception)
                    {
                        curveElem = null;
                    }

                    tran.Start();

                    // Create Rebar Free Form by specifying the GUID defining the custom external server.
                    // The Rebar element returned needs to receive constraints, so that regeneration can
                    // call the custom geometry calculations and create the bars
                    rebar = Rebar.CreateFreeForm(doc, RebarUpdateServer.SampleGuid, barType, host);
                    // Get all bar handles to set constraints to them, so that the bar can generate its geometry
                    RebarConstraintsManager        rManager = rebar.GetRebarConstraintsManager();
                    IList <RebarConstrainedHandle> handles  = rManager.GetAllHandles();

                    // if bar has no handles then the server can't generate rebar geometry
                    if (handles.Count <= 0)
                    {
                        tran.RollBack();
                        return(Result.Failed);
                    }

                    // iterate through the rebar handles and prompt for face selection for each of them, to get user input
                    foreach (RebarConstrainedHandle handle in handles)
                    {
                        if (handle.GetHandleType() == RebarHandleType.StartOfBar ||
                            handle.GetHandleType() == RebarHandleType.EndOfBar)
                        {
                            continue;// Start handle and end handle will receive constraints from the custom external server execution
                        }
                        try
                        {
                            Reference reference = sel.PickObject(ObjectType.Face, "Select face for " + handle.GetHandleName());
                            if (reference == null)
                            {
                                continue;
                            }
                            // create constraint using the picked faces and set it to the associated handle
                            List <Reference> refs = new List <Reference>();
                            refs.Add(reference);
                            RebarConstraint constraint = RebarConstraint.Create(handle, refs, true, 0.0);
                            rManager.SetPreferredConstraintForHandle(handle, constraint);
                        }
                        catch (Exception e)
                        {
                            message = e.Message;
                            tran.RollBack();
                            return(Result.Cancelled);
                        }
                    }

                    try
                    {
                        //here we add a value to the shared parameter and add it to the regeneration dependencies
                        Parameter newSharedParam  = rebar.LookupParameter(AddSharedParams.m_paramName);
                        Parameter newSharedParam2 = rebar.LookupParameter(AddSharedParams.m_CurveIdName);
                        if (newSharedParam != null && newSharedParam2 != null)
                        {
                            newSharedParam.Set(0);
                            newSharedParam2.Set(curveElem == null ? -1 : curveElem.Id.IntegerValue);

                            RebarFreeFormAccessor accesRebar = rebar.GetFreeFormAccessor();
                            accesRebar.AddUpdatingSharedParameter(newSharedParam.Id);
                            accesRebar.AddUpdatingSharedParameter(newSharedParam2.Id);
                        }
                        else
                        {
                            // The AddSharedParams command should be executed to create and bind these parameters to rebar.
                        }
                    }
                    catch (Exception ex)
                    {
                        message = ex.Message;
                        tran.RollBack();
                        return(Result.Cancelled);
                    }
                    tran.Commit();
                    return(Result.Succeeded);
                }
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return(Result.Failed);
            }
        }
Exemple #5
0
        /// <summary>
        /// function used to extract offset value from constraint
        /// </summary>
        /// <param name="updateData"> data used to pass or get information regarding constraints cover</param>
        /// <param name="constraint">constraint from which we extract the offset information</param>
        /// <param name="targetIdx">index of target in constraint</param>
        /// <param name="offset"> output value </param>
        /// <returns></returns>
        public static bool getOffsetFromConstraintAtTarget(RebarUpdateCurvesData updateData, RebarConstraint constraint, int targetIdx, out double offset)
        {
            offset = 0.0;
            if (updateData == null || constraint == null)
            {
                return(false);
            }

            double barDiam    = updateData.GetBarModelDiameter();
            var    rebarStyle = updateData.GetRebarStyle();
            var    attachment = updateData.GetAttachmentType();
            bool   bIsInside  = rebarStyle == RebarStyle.Standard || (rebarStyle != RebarStyle.Standard && attachment == StirrupTieAttachmentType.InteriorFace);

            if (constraint.IsToCover())
            {
                if (targetIdx < 0 || targetIdx >= constraint.NumberOfTargets)
                {
                    return(false); // incorrect index
                }
                RebarCoverType coverType      = constraint.GetTargetCoverType(targetIdx);
                double         coverDist      = (coverType == null) ? 0.0 : coverType.CoverDistance;
                double         diameterOffset = (barDiam / 2);
                if (bIsInside)
                {
                    diameterOffset *= -1;
                }
                offset = constraint.GetDistanceToTargetCover() - coverDist + diameterOffset;
                return(true);
            }

            offset = constraint.GetDistanceToTargetHostFace();
            return(true);
        }
Exemple #6
0
        /// <summary>
        /// Function used to adjust the computed geometry information of the rebar element and has two logical parts:
        ///  - Selection of structural faces for creation of Start of Bar and End of Bar Constraints when needed
        ///  (Constraints created here are visible and modifiable in the Graphical Constraints Manager in native Revit)
        ///      The constraint search is done by listing all the faces from the structural pointed to by the FirstHandle constraint
        ///      and then picking the face that has the closest intersection point with either the curves in the rebar, or their extensions
        ///  - Adjustments are done to the start/end of the bars according to the corresponding constraints
        ///      Each bar will be lengthened to the intersection point of the tangent in the curve's specified end with the corresponding constraint face,
        ///      or it will be shortened to the intersection point of the curve itself with the corresponding constraint face.
        ///  - Hook normals for each bar are calculated for the newly modified curves.
        ///  This function is called after the successful execution of GenerateCurves
        /// </summary>
        /// <param name="data">Class used to pass information from the external application to the internal Rebar Element.
        /// Interfaces with the Rebar Element and exposes information needed for Constraint creation, face searching, and
        /// receives the result of the Start/End constraint calculation.
        /// updates are done on the element after the entire function finished successfully.
        /// </param>
        /// <returns> true if execution was completed successfully, false otherwise</returns>
        public bool TrimExtendCurves(RebarTrimExtendData data)
        {
            if (getSelectedCurveElement(getCurrentRebar(data.GetRebarUpdateCurvesData()), data.GetRebarUpdateCurvesData()) != null)
            {
                return(true);
            }

            // extract the curves from the element.
            IList <Curve> allbars = new List <Curve>();

            for (int ii = 0; ii < data.GetRebarUpdateCurvesData().GetBarsNumber(); ii++)
            {
                allbars.Add(data.GetRebarUpdateCurvesData().GetBarGeometry(ii)[0]);
            }
            // Place for caching the faces of the host used in constraint search.
            List <TargetFace> hostFaces = new List <TargetFace>();

            // repeat process for each end of the Rebar.
            for (int iBarEnd = 0; iBarEnd < 2; iBarEnd++)
            {
                List <TargetFace> faces = new List <TargetFace>();
                // get current Start/End constraint
                RebarConstraint constraint = (iBarEnd == 0) ? data.GetRebarUpdateCurvesData().GetStartConstraint() :
                                             data.GetRebarUpdateCurvesData().GetEndConstraint();

                //if no constraint present, then search for a new one
                if (constraint == null)
                {
                    if (hostFaces.Count <= 0)// fetch the faces of the structural used for searching constraints.
                    {
                        // used compute references to true to make sure we can create constraints with the faces we find
                        Options geomOptions = new Options();
                        geomOptions.ComputeReferences = true;
                        // the host structural is considered the first structural in the first constraint
                        GeometryElement elemGeometry = data.GetRebarUpdateCurvesData().GetCustomConstraints()[0].GetTargetElement(0).get_Geometry(geomOptions);
                        if (elemGeometry == null)
                        {
                            return(false);
                        }
                        hostFaces = getFacesFromElement(elemGeometry);
                    }

                    // for each bar try to find the closest face that intersects with it, or its extension, at the specified end
                    for (int idx = 0; idx < allbars.Count; idx++)
                    {
                        faces.Add(searchForFace(allbars[idx], hostFaces, iBarEnd));
                    }

                    // gather valid references for constraint creation
                    List <Reference> refs = new List <Reference>();
                    foreach (TargetFace face in faces)
                    {
                        if (face.Face.Reference != null && !refs.Contains(face.Face.Reference))
                        {
                            refs.Add(face.Face.Reference);
                        }
                    }

                    // if we have any valid references, we create the constraint for the specified bar end.
                    if (refs.Count > 0)
                    {
                        if (iBarEnd == 0)
                        {
                            data.CreateStartConstraint(refs, false, 0.0);
                        }
                        else
                        {
                            data.CreateEndConstraint(refs, false, 0.0);
                        }
                    }
                }
                else// if constraint is present, extract needed information to calculate trim/extend
                {
                    for (int nTarget = 0; nTarget < constraint.NumberOfTargets; nTarget++)
                    {
                        var  trf             = Transform.Identity;
                        Face constrainedFace = constraint.GetTargetHostFaceAndTransform(nTarget, trf);
                        if (constrainedFace == null)
                        {
                            continue;
                        }
                        double dfOffset;
                        if (getOffsetFromConstraintAtTarget(data.GetRebarUpdateCurvesData(), constraint, 0, out dfOffset))
                        {
                            faces.Add(new TargetFace()
                            {
                                Face = constrainedFace, Transform = trf, Offset = dfOffset
                            });
                        }
                    }
                }

                // for each bar, find out where it intersects with the selected faces and replace the original curve with a new one that is shorter or longer.
                // first search for extension intersection (use tangent curve in the end point of the curve), then search for actual curve intersection
                for (int idx = 0; idx < allbars.Count; idx++)
                {
                    XYZ   intersection;
                    Curve barCurve = allbars[idx];
                    if (!(barCurve is Line))// this code only deals with input curves that are straight lines
                    {
                        return(false);
                    }
                    Line   tangent  = Line.CreateUnbound(barCurve.GetEndPoint(iBarEnd), barCurve.ComputeDerivatives(iBarEnd, true).BasisX.Normalize() * (iBarEnd == 0 ? -1 : 1));
                    double dfOffset = 0.0;
                    if (getIntersection(tangent, faces, out intersection, out dfOffset) || getIntersection(barCurve, faces, out intersection, out dfOffset))
                    {
                        Curve newCurve = null;
                        try
                        {
                            XYZ barDir = (barCurve.GetEndPoint(1) - barCurve.GetEndPoint(0)).Normalize();
                            if ((iBarEnd == 0))
                            {
                                newCurve = Line.CreateBound(intersection - barDir * dfOffset, barCurve.GetEndPoint(1));
                            }
                            else
                            {
                                newCurve = Line.CreateBound(barCurve.GetEndPoint(0), intersection + barDir * dfOffset);
                            }
                        }
                        catch { }
                        // if new curve available, replace the old one.
                        if (newCurve != null)
                        {
                            allbars[idx] = newCurve;
                        }
                    }
                }
            }


            // get the FirstHandle constraint and extract the target face to use in determining the hook orientation for each bar
            TargetFace firstFace = new TargetFace();
            IList <RebarConstraint> constraints = data.GetRebarUpdateCurvesData().GetCustomConstraints();

            foreach (RebarConstraint constraint in constraints)
            {
                if ((BarHandle)constraint.GetCustomHandleTag() == BarHandle.FirstHandle)
                {
                    Transform tempTrf = Transform.Identity;
                    double    dfOffset;
                    if (!getOffsetFromConstraintAtTarget(data.GetRebarUpdateCurvesData(), constraint, 0, out dfOffset))
                    {
                        return(false);
                    }
                    firstFace = new TargetFace()
                    {
                        Face = constraint.GetTargetHostFaceAndTransform(0, tempTrf), Transform = tempTrf, Offset = dfOffset
                    };
                    break;
                }
            }

            // add each curve as separate bar in the set.
            for (int ii = 0; ii < allbars.Count; ii++)
            {
                List <Curve> barCurve = new List <Curve>();
                barCurve.Add(allbars[ii]);
                data.AddBarGeometry(barCurve);
                // hook normals are reset when adding new bar geometry, so  we need to
                // set the hook normals for each bar that was modified
                for (int i = 0; i < 2; i++)
                {
                    XYZ normal = computeNormal(allbars[ii], firstFace, i);
                    if (normal != null && !normal.IsZeroLength())
                    {
                        data.GetRebarUpdateCurvesData().SetHookPlaneNormalForBarIdx(i, ii, normal);
                    }
                }
            }
            return(true);
        }