public FamilyCreator GetSimilarCreator()
        {
            var info = new LineBasedFamilyInfo(this.FI);

            if (info.HostCondition == HostCondition.Level)
            {
                var level = this.FI.Host as Level;
                this.SimilarCreator = new LineBasedFamilyCreator_onLevel
                                          (this.FI.Symbol, this.OffsetLocLine, this.facing, level, this.FI.StructuralType, this.paramValues, this.Context);
            }
            else
            {
                if (this.FI.HostFace != null &&
                    this.FI.HostFace.ElementReferenceType != ElementReferenceType.REFERENCE_TYPE_NONE)
                {
                    this.SimilarCreator = new LineBasedFamilyCreator_onPlanarFace
                                              (this.FI.Symbol, this.OffsetLocLine, this.facing, this.FI.HostFace, this.paramValues, this.Context);
                }
                else
                {
                    //search for host face on the run
                    var locLine  = this.FI.LocationLine();
                    var hostCat  = HostUtils.GetHostCategory(this.FI);
                    var bbFilter = Methods.GetBBIntersectFilter
                                       (this.FI.GetBoundingBoxInModelCS(null),
                                       HostSearchSession.HostSearchRange);
                    var hostDir  = HostUtils.GetHostDir(this.FI);
                    var faceNorm = this.FI.GetPlane().Normal;
                    var dop      = this.FI.DesignOption;
                    var search   = new HostSearchSession
                                       (this.FI.Document, hostCat, bbFilter, hostDir, faceNorm, dop);
                    Element host;
                    var     hostFace = search.FindHostFace(locLine, out host);
                    if (hostFace == null)
                    {
                        throw new goa.Common.Exceptions.HostNotFoundException(this.FI.Id.ToString());
                    }

                    this.SimilarCreator = new LineBasedFamilyCreator_onPlanarFace
                                              (this.FI.Symbol, this.OffsetLocLine, this.facing, host, hostFace, this.paramValues, this.Context);
                }
                Methods.GetCutsAndJoins
                    (this.FI,
                    out this.SimilarCreator.Cuts,
                    out this.SimilarCreator.CutBy,
                    out this.SimilarCreator.Joins);
            }
            return(this.SimilarCreator);
        }
        /// <summary>
        /// Copy line-based family instances to multiple levels.
        /// </summary>
        /// <param name="_refs">line-based family instances to be copied.</param>
        /// <param name="_tarLevels">target levels</param>
        /// <param name="_baseLevel">base level for calculating height change.</param>
        /// <param name="_snapShot">snap shot of potential host faces. Need to scan before calling this method.</param>
        /// <returns>Line-based family creators of correct type.</returns>
        public static List <FamilyCreator> CopyToLevels
            (FamilyInstance _refFI,
            IEnumerable <Level> _tarLevels,
            Level _baseLevel,
            double _searchRange)
        {
            var doc        = _refFI.Document;
            var dop        = doc.GetElement(DesignOption.GetActiveDesignOptionId(doc)) as DesignOption;
            var ops        = new List <FamilyCreator>();
            var refLocLine = _refFI.LocationLine();
            //get params
            var param = _refFI.GetAllEditableParams();
            //get orientation
            var facing     = _refFI.FacingOrientation;
            var faceNormal = _refFI.GetPlane().Normal;
            //scan for host face
            var hostCat = HostUtils.GetHostCategory(_refFI);
            var hostDir = HostUtils.GetHostDir(_refFI);
            var bbRef   = _refFI.GetBoundingBoxForSolidGeometries();

            if (bbRef == null)
            {
                bbRef = _refFI.GetBoundingBoxInModelCS(null);
            }
            bool cutsHost = HostUtils.CutsHost(_refFI);

            foreach (var tarLevel in _tarLevels)
            {
                //skip base level
                if (tarLevel.Id == _baseLevel.Id)
                {
                    continue;
                }
                var deltaZ     = tarLevel.ProjectElevation - _baseLevel.ProjectElevation;
                var tf         = Transform.CreateTranslation(new XYZ(0, 0, deltaZ));
                var tarLocLine = refLocLine.CreateTransformed(tf) as Line;
                //check host dir
                FamilyCreator ctr  = null;
                var           info = new LineBasedFamilyInfo(_refFI);
                //host on level
                if (hostCat == HostCategory.Level)
                {
                    ctr = new LineBasedFamilyCreator_onLevel
                              (_refFI.Symbol,
                              tarLocLine,
                              _refFI.FacingOrientation,
                              tarLevel,
                              _refFI.StructuralType,
                              param,
                              null);
                }
                //host on face
                else
                {
                    //search host face
                    var     bbTar  = bbRef.GetTransformed(tf);
                    var     filter = Methods.GetBBIntersectFilter(bbTar, _searchRange);
                    var     search = new HostSearchSession(doc, hostCat, filter, hostDir, faceNormal, dop);
                    Element host;
                    var     hostFace = search.FindHostFace(tarLocLine, out host);
                    if (hostFace == null)
                    {
                        throw new HostNotFoundException(_refFI.Id.ToString());
                    }
                    var refOffsetLocLine = LineBasedFamilyUtils.GetOffsetLocLine(_refFI);
                    var tarOffsetLocLine = refOffsetLocLine.CreateTransformed(tf) as Line;
                    var lineBasedCtr     = new LineBasedFamilyCreator_onPlanarFace
                                               (_refFI.Symbol,
                                               tarOffsetLocLine,
                                               facing,
                                               host,
                                               hostFace,
                                               param,
                                               null);
                    lineBasedCtr.CutsHost = cutsHost;
                    ctr = lineBasedCtr;
                }
                ops.Add(ctr);
            }
            return(ops);
        }