Beispiel #1
0
        /// <summary>
        /// 将一个directShape中的多个Solid进行合并
        /// </summary>
        /// <param name="originalSolids"></param>
        /// <returns>理想情况下,返回的集合中应该只有一个Solid,但是由于Union操作不一定每次都能成功,所以此集合中还会有出现不成功时的那些Solid。</returns>
        private List <Solid> UnionSolid(IList <Solid> originalSolids)
        {
            List <Solid> solids = new List <Solid>();
            double       v1     = 0;

            foreach (Solid s in originalSolids)
            {
                //
                v1 += s.Volume;
            }

            Solid s1 = originalSolids[0];

            solids.Add(s1);

            for (int i = 1; i < originalSolids.Count; i++)
            {
                Solid s2 = originalSolids[i];
                try
                {
                    //  将两个实体进行组合
                    BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(s1, s2, BooleanOperationsType.Union);
                }
                catch (Exception ex)
                {
                    // 说明实体组合不成功,此时应该将未组合进去的Solid记录下来
                    solids.Add(s2);
                }
            }
            return(solids);
        }
Beispiel #2
0
        /// <summary>
        /// 判断当前创建出来的那个实体是否与其他单元相交,如果相交,则在原实体中剪除相交的部分,如果没有相交,则直接返回原实体集合(集合中的元素个数与原 originalSolids 集合中元素个数相同)。
        /// </summary>
        /// <param name="directShape"></param>
        /// <param name="originalSolids"> directShape 所对应的实体,由于 ExecuteBooleanOperationModifyingOriginalSolid 函数中的 OriginalSolid
        /// 不能是直接从Revit的Element中得到的,所以要将前面通过轮廓拉伸出来的实体作为参数传入。</param>
        /// <param name="hasIntersect"></param>剪切后的实体的体积有可能不大于 0 啊
        /// <returns> 返回的集合中的元素个数与原 originalSolids 集合中元素个数相同。剪切后的实体的体积有可能不大于 0 .</returns>
        private IList <Solid> ExcludeIntersect(DirectShape directShape, IList <Solid> originalSolids, out bool hasIntersect)
        {
            // 应用过滤器,在整个文档中搜索与指定Element相交的Element
            FilteredElementCollector       collector     = new FilteredElementCollector(directShape.Document);
            ElementIntersectsElementFilter elementFilter = new ElementIntersectsElementFilter(element: directShape, inverted: false);

            collector.WherePasses(elementFilter);

            // 排除面层本身
            collector.Excluding(new ElementId[] { directShape.Id });

            if (!collector.Any())
            {
                // 说明没有相交的部分
                hasIntersect = false;
                return(originalSolids);
            }

            hasIntersect = true;

            // 将与其相交的实体进行剪切操作
            bool promptWhileError = false;

            foreach (Element interSectElem in collector)
            {
                var interSectSolids = GeoHelper.GetSolidsInModel(interSectElem, GeoHelper.SolidVolumnConstraint.Positive).Keys;  // 与面层对象相交的 Element 中所有的实体
                for (int i = 0; i < originalSolids.Count; i++)
                {
                    Solid originalS = originalSolids[i];

                    foreach (Solid interSectS in interSectSolids)
                    {
                        try
                        {
                            //  在原实体中减去相交的部分
                            BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(originalS, interSectS, BooleanOperationsType.Difference);
                        }
                        catch (Exception ex)
                        {
                            if (promptWhileError)
                            {
                                // 在剪切时如果不能剪切,则不剪切。
                                DialogResult res = MessageBox.Show("实体剪切时出现错误,可能的原因是面层与模型中的其他实体有细微交叉," +
                                                                   "以致剪切后的实体出现细小锯齿。\n\r (忽略此细微交叉对于面层算量并无明显影响)。" +
                                                                   " \n\r 点击“是”以忽略并继续,点击“否”不再提示。", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button2);

                                promptWhileError = (res != DialogResult.No);
                            }
                        }
                    }
                    // 剪切后的实体的体积有可能不大于 0 啊
                    originalSolids[i] = originalS;  // 将剪切完成后的 Solid 再赋值回集合中
                }
            }
            return(originalSolids);
        }
 public static bool TryCutSolid(Solid beingCutted, Solid cuts)
 {
     try
     {
         BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid
             (beingCutted, cuts, BooleanOperationsType.Difference);
         return(true);
     }
     catch (InternalException)
     {
         return(false);
     }
 }
        /***************************************************/

        private static List <ISurface> GetOpeningGeometry(Transaction t, Document doc, List <HostObject> hosts, List <ElementId> inserts, FamilyInstance familyInstance, RevitSettings settings = null)
        {
            List <List <Solid> > solidsWithOpening = new List <List <Solid> >();

            foreach (HostObject h in hosts)
            {
                solidsWithOpening.Add(h.Solids(new Options()).Select(x => SolidUtils.Clone(x)).ToList());
            }

            // Rollback and restart of the transaction is needed because otherwise the object, to which familyInstance is pointing can become invalidated.
            FailureHandlingOptions failureHandlingOptions = t.GetFailureHandlingOptions().SetClearAfterRollback(true);

            t.RollBack(failureHandlingOptions);
            t.Start();

            List <ISurface>  surfaces = new List <ISurface> ();
            List <CurveLoop> loops    = new List <CurveLoop>();

            try
            {
                doc.Delete(inserts);
                doc.Regenerate();

                for (int i = 0; i < hosts.Count; i++)
                {
                    HostObject h = hosts[i];

                    List <Autodesk.Revit.DB.Plane> planes = h.IPanelPlanes();
                    if (planes.Count == 0)
                    {
                        continue;
                    }

                    List <Solid> fullSolids = h.Solids(new Options()).SelectMany(x => SolidUtils.SplitVolumes(x)).ToList();
                    if (h is Wall)
                    {
                        fullSolids = fullSolids.Select(x => BooleanOperationsUtils.CutWithHalfSpace(x, planes[0])).ToList();
                        planes[0]  = Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(-planes[0].Normal, planes[0].Origin);
                    }

                    foreach (Solid s in fullSolids)
                    {
                        foreach (Solid s2 in solidsWithOpening[i])
                        {
                            BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(s, s2, BooleanOperationsType.Difference);
                        }

                        foreach (Autodesk.Revit.DB.Face f in s.Faces)
                        {
                            PlanarFace pf = f as PlanarFace;
                            if (pf == null)
                            {
                                continue;
                            }

                            if (planes.Any(x => Math.Abs(1 - pf.FaceNormal.DotProduct(x.Normal)) <= settings.DistanceTolerance && Math.Abs((pf.Origin - x.Origin).DotProduct(x.Normal)) <= settings.AngleTolerance))
                            {
                                loops.AddRange(pf.GetEdgesAsCurveLoops());
                            }
                        }
                    }
                }
            }
            catch
            {
                loops = null;
            }

            t.RollBack(failureHandlingOptions);

            if (loops != null)
            {
                surfaces.AddRange(loops.Select(x => new PlanarSurface(x.FromRevit(), null)));
            }
            else if (surfaces.Count != 0)
            {
                BH.Engine.Reflection.Compute.RecordWarning(String.Format("Geometrical processing of a Revit element failed due to an internal Revit error. Converted opening might be missing one or more of its surfaces. Revit ElementId: {0}", familyInstance.Id));
            }

            return(surfaces);
        }
 /// <summary>
 /// Boolean difference geometric operation, modify the original solid as the result
 /// </summary>
 /// <param name="solid1">Operation solid 1 and operation result</param>
 /// <param name="solid2">Operation solid 2</param>
 public static void BooleanOperation_Difference(ref Solid solid1, Solid solid2)
 {
     BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(solid1, solid2, BooleanOperationsType.Difference);
 }
 /// <summary>
 /// Boolean union geometric operation, modify the original solid as the result
 /// </summary>
 /// <param name="solid1">Operation solid 1 and operation result</param>
 /// <param name="solid2">Operation solid 2</param>
 public static void BooleanOperation_Union(ref Solid solid1, Solid solid2)
 {
     BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(solid1, solid2, BooleanOperationsType.Union);
 }
 /// <summary>
 /// Boolean intersect geometric operation, modify the original solid as the result
 /// </summary>
 /// <param name="solid1">Operation solid 1 and operation result</param>
 /// <param name="solid2">Operation solid 2</param>
 public static void BooleanOperation_Intersect(ref Solid solid1, Solid solid2)
 {
     BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(solid1, solid2, BooleanOperationsType.Intersect);
 }
Beispiel #8
0
        /// <summary>
        /// Creates a negative block family from the geometry of the target element and boundaries.
        /// </summary>
        /// <remarks>This is the main implementation of the sample command.</remarks>
        /// <param name="targetElement">The target solid element.</param>
        /// <param name="boundaries">The selected curve element boundaries.</param>
        /// <param name="familyLoadOptions">The family load options when loading the new family.</param>
        /// <param name="familyTemplate">The family template.</param>
        public static FailureCondition CreateNegativeBlock(Element targetElement, IList <Reference> boundaries, IFamilyLoadOptions familyLoadOptions, String familyTemplate)
        {
            Document doc = targetElement.Document;

            Autodesk.Revit.ApplicationServices.Application app = doc.Application;

            // Get curve loop for boundary
            IList <Curve> curves = GetContiguousCurvesFromSelectedCurveElements(doc, boundaries);
            CurveLoop     loop   = null;

            try
            {
                loop = CurveLoop.Create(curves);
            }
            catch (Autodesk.Revit.Exceptions.ArgumentException)
            {
                // Curves are not contiguous
                return(FailureCondition.CurvesNotContigous);
            }
            List <CurveLoop> loops = new List <CurveLoop>();

            loops.Add(loop);

            // Get elevation of loop
            double elevation = curves[0].GetEndPoint(0).Z;

            // Get height for extrusion
            BoundingBoxXYZ bbox   = targetElement.get_BoundingBox(null);
            double         height = bbox.Max.Z - elevation;

            if (height <= 1e-5)
            {
                return(FailureCondition.CurveLoopAboveTarget);
            }

            height += 1;

            // Create family
            Document familyDoc = app.NewFamilyDocument(familyTemplate);

            // Create block from boundaries
            Solid block = GeometryCreationUtilities.CreateExtrusionGeometry(loops, XYZ.BasisZ, height);

            // Subtract target element
            IList <Solid> fromElement = GetTargetSolids(targetElement);

            int solidCount = fromElement.Count;

            // Merge all found solids into single one
            Solid toSubtract = null;

            if (solidCount == 1)
            {
                toSubtract = fromElement[0];
            }

            else if (solidCount > 1)
            {
                toSubtract =
                    BooleanOperationsUtils.ExecuteBooleanOperation(fromElement[0], fromElement[1], BooleanOperationsType.Union);
            }

            if (solidCount > 2)
            {
                for (int i = 2; i < solidCount; i++)
                {
                    toSubtract = BooleanOperationsUtils.ExecuteBooleanOperation(toSubtract, fromElement[i],
                                                                                BooleanOperationsType.Union);
                }
            }

            // Subtract merged solid from overall block
            try
            {
                BooleanOperationsUtils.ExecuteBooleanOperationModifyingOriginalSolid(block, toSubtract,
                                                                                     BooleanOperationsType.Difference);
            }
            catch (Autodesk.Revit.Exceptions.InvalidOperationException)
            {
                return(FailureCondition.NoIntersection);
            }

            // Create freeform element
            using (Transaction t = new Transaction(familyDoc, "Add element"))
            {
                t.Start();
                RevitFreeFormElement element = Autodesk.Revit.DB.FreeFormElement.Create(familyDoc, block);
                t.Commit();
            }

            // Load family into document
            Family family = familyDoc.LoadFamily(doc, familyLoadOptions);

            familyDoc.Close(false);

            // Get symbol as first symbol of loaded family
            FilteredElementCollector collector = new FilteredElementCollector(doc);

            collector.WherePasses(new FamilySymbolFilter(family.Id));
            FamilySymbol fs = collector.FirstElement() as FamilySymbol;


            // Place instance at location of original curves
            using (Transaction t2 = new Transaction(doc, "Place instance"))
            {
                t2.Start();
                doc.Create.NewFamilyInstance(XYZ.Zero, fs, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
                t2.Commit();
            }

            return(FailureCondition.Success);
        }