public static SolidIntersection HasIntersection(this Solid solid0, Solid solid1, out Solid result) { result = null; try { result = BooleanOperationsUtils.ExecuteBooleanOperation(solid0, solid1, BooleanOperationsType.Intersect); if (Math.Abs(result.Volume) > 0.000001) { // Intersecting. return(SolidIntersection.Intersecting); } result = BooleanOperationsUtils.ExecuteBooleanOperation (solid0, solid1, BooleanOperationsType.Union); double dArea = Math.Abs(solid0.SurfaceArea + solid1.SurfaceArea - result.SurfaceArea); if (dArea < 0.00001 && solid0.Edges.Size + solid1.Edges.Size == result.Edges.Size) { // Neither intersecting, nor touching. return(SolidIntersection.NonIntersecting); } else { // Touching. return(SolidIntersection.Touching); } } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { return(SolidIntersection.Invalid); } }
public static IEnumerable <ElementId> CastSphere( ModelInfo info, IEnumerable <XYZ> pts, double radius, BuiltInCategory bic = BuiltInCategory.INVALID, View view = null) { if (!pts.Any()) { return(new List <ElementId>()); } var solids = new Queue <Solid>(); foreach (var pt in pts) { solids.Enqueue(CreateSphereAt(pt, radius)); } var union_solid = solids.Dequeue(); while (solids.Any()) { var other = solids.Dequeue(); union_solid = BooleanOperationsUtils.ExecuteBooleanOperation(union_solid, other, BooleanOperationsType.Union); } ElementIntersectsSolidFilter intersectSphere = new ElementIntersectsSolidFilter(union_solid); FilteredElementCollector coll; coll = view != null ? new FilteredElementCollector(info.DOC, view.Id) : new FilteredElementCollector(info.DOC); var intersection = bic == BuiltInCategory.INVALID ? coll.WherePasses(intersectSphere).ToElementIds() : coll.WherePasses(intersectSphere).OfCategory(bic).ToElementIds(); return(intersection); }
public Solid Unionsolid(List <Solid> solids) { List <Solid> MB = new List <Solid> { solids[1], solids[2] }; Solid result = null; foreach (Solid item in solids) { if (result == null) { result = item; } else { try { var t = BooleanOperationsUtils.ExecuteBooleanOperation(result, item, BooleanOperationsType.Intersect); if (t.Volume != 0) { result = BooleanOperationsUtils.ExecuteBooleanOperation(result, item, BooleanOperationsType.Union); } } catch { } } } return(result); }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { Document doc = commandData.Application.ActiveUIDocument.Document; Solid box = Box(); Solid sphere = Sphere(); Solid unionSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Union); Solid intersectSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Intersect); Solid diffSolid = BooleanOperationsUtils.ExecuteBooleanOperation(box, sphere, BooleanOperationsType.Difference); //Use DirectShape to visualise geometries using (Transaction t = new Transaction(doc, "Transaction")) { t.Start(); GeometryObject[] unionGeomObj = new GeometryObject[] { unionSolid }; GeometryObject[] interGeomObj = new GeometryObject[] { intersectSolid }; GeometryObject[] diffGeomObj = new GeometryObject[] { diffSolid }; DirectShape ds1 = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); ds1.SetShape(unionGeomObj); DirectShape ds2 = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); ds2.SetShape(interGeomObj); DirectShape ds3 = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); ds3.SetShape(diffGeomObj); t.Commit(); } return(Result.Succeeded); }
private Solid GetSolid(GeometryElement geoElement) { Solid unionSolid = null; try { Options opt = m_app.Application.Create.NewGeometryOptions(); opt.ComputeReferences = true; opt.DetailLevel = Autodesk.Revit.DB.ViewDetailLevel.Fine; foreach (GeometryObject obj in geoElement) { Solid solid = obj as Solid; if (null != solid) { if (solid.Volume > 0) { if (unionSolid == null) { unionSolid = solid; } else { unionSolid = BooleanOperationsUtils.ExecuteBooleanOperation(unionSolid, solid, BooleanOperationsType.Union); } } } } } catch (Exception ex) { MessageBox.Show("Failed to get solid.\n" + ex.Message, "Get Solid", MessageBoxButtons.OK, MessageBoxIcon.Warning); } return(unionSolid); }
public static double GetIntersectedSolidArea( Document host, Solid hostElement, RevitLinkInstance rins, Solid linkedElement) { // Step 1 "Determine the transformation T from the linked document Q coordinates to P's." Transform transForm = rins.GetTransform(); // Step 2 "Open the linked project Q and retrieve the solid Sb of B." // linkedElement is Solid of linked Link // Step 3 "Transform it to P's coordinate space: T * Sb." Solid tmp = SolidUtils.CreateTransformed(linkedElement, transForm); // Step 4 "Retrieve the solid Sa of A" // hostElement is hostElementSolid Solid result = BooleanOperationsUtils.ExecuteBooleanOperation( hostElement, tmp, BooleanOperationsType.Intersect); return(result.SurfaceArea); }
/// <summary> /// Execute a Boolean operation, and catch the exception. /// </summary> /// <param name="id">The id of the object demanding the Boolean operation.</param> /// <param name="secondId">The id of the object providing the second solid.</param> /// <param name="firstSolid">The first solid parameter to ExecuteBooleanOperation.</param> /// <param name="secondSolid">The second solid parameter to ExecuteBooleanOperation.</param> /// <param name="opType">The Boolean operation type.</param> /// <param name="suggestedShiftDirection">If the Boolean operation fails, a unit vector used to retry with a small shift. Can be null.</param> /// <returns>The result of the Boolean operation, or the first solid if the operation fails.</returns> public static Solid ExecuteSafeBooleanOperation(int id, int secondId, Solid firstSolid, Solid secondSolid, BooleanOperationsType opType, XYZ suggestedShiftDirection) { // Perform default operations if one of the arguments is null. if (firstSolid == null || secondSolid == null) { if (firstSolid == null && secondSolid == null) { return(null); } switch (opType) { case BooleanOperationsType.Union: { if (firstSolid == null) { return(secondSolid); } return(firstSolid); } case BooleanOperationsType.Difference: { if (firstSolid == null) { return(null); } return(firstSolid); } default: // for .Intersect return(null); } } Solid resultSolid = null; try { Solid secondOperand = secondSolid; resultSolid = BooleanOperationsUtils.ExecuteBooleanOperation(firstSolid, secondOperand, opType); } catch (Exception ex) { Importer.TheLog.LogError(id, ex.Message, false); resultSolid = firstSolid; } if (SolidValidator.IsValidGeometry(resultSolid)) { return(resultSolid); } Importer.TheLog.LogError(id, opType.ToString() + " operation failed with void from #" + secondId.ToString(), false); return(firstSolid); }
public static bool CheckSolidsIsIntersect(Solid solid1, Solid solid2) { Solid interSolid = BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect); double volume = Math.Abs(interSolid.Volume); if (volume > 0.000001) { return(true); } return(false); }
/// <summary> /// Execute a Boolean operation, and catch the exception. /// </summary> /// <param name="id">The id of the object demanding the Boolean operation.</param> /// <param name="secondId">The id of the object providing the second solid.</param> /// <param name="firstSolid">The first solid parameter to ExecuteBooleanOperation.</param> /// <param name="secondSolid">The second solid parameter to ExecuteBooleanOperation.</param> /// <param name="opType">The Boolean operation type.</param> /// <returns>The result of the Boolean operation, or the first solid if the operation fails.</returns> public static Solid ExecuteSafeBooleanOperation(int id, int secondId, Solid firstSolid, Solid secondSolid, BooleanOperationsType opType) { if (firstSolid == null || secondSolid == null) { if (firstSolid == null && secondSolid == null) { return(null); } if (opType == BooleanOperationsType.Union) { if (firstSolid == null) { return(secondSolid); } return(firstSolid); } if (opType == BooleanOperationsType.Difference) { if (firstSolid == null) { return(null); } return(firstSolid); } // for .Intersect return(null); } Solid resultSolid = null; try { resultSolid = BooleanOperationsUtils.ExecuteBooleanOperation(firstSolid, secondSolid, opType); } catch (Exception ex) { IFCImportFile.TheLog.LogError(id, ex.Message, false); resultSolid = firstSolid; } if (SolidValidator.IsValidGeometry(resultSolid)) { return(resultSolid); } IFCImportFile.TheLog.LogError(id, opType.ToString() + " operation failed with void from #" + secondId.ToString(), false); return(firstSolid); }
static Solid GetResultingSolid(Solid solid, IList <Solid> solids) { Solid resultingSolid = solid; foreach (Solid currSolid in solids) { resultingSolid = BooleanOperationsUtils .ExecuteBooleanOperation(resultingSolid, currSolid, BooleanOperationsType.Difference); } return(resultingSolid); }
/// <summary> /// Gets the result of between a solid and a solid cross. /// </summary> /// <param name="solid1"></param> /// <param name="solid2"></param> /// <returns></returns> public static bool CrossSolid(this Solid solid1, Solid solid2) { if (solid1 == null) { throw new ArgumentNullException(nameof(solid1)); } if (solid2 == null) { throw new ArgumentNullException(nameof(solid2)); } return(BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect).Volume > 0); }
public Solid MergeSolids(Solid solid1, Solid solid2) { var result = default(Solid); try { result = BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Union); } catch (Exception e) { result = null; } return(result); }
static public Solid Clone(/*this*/ Solid solid) { if (solid == null) { return(null); } // Better than unioning the solid with itself: // use a small cube contained within the original // solid instead, e.g. a 1x1x1 cube at the origin // or something. return(BooleanOperationsUtils .ExecuteBooleanOperation(solid, solid, BooleanOperationsType.Union)); }
/// <summary> /// 获取楼梯合并solid /// </summary> /// <param name="e"></param> /// <returns></returns> public static Solid AllUnionSolid(Element e) { Solid sd = null; try { Options options = new Options(); options.IncludeNonVisibleObjects = false; options.DetailLevel = ViewDetailLevel.Fine; options.ComputeReferences = true; GeometryElement geoElement1 = e.get_Geometry(options);//点进去 IEnumerator enumerator = geoElement1.GetEnumerator(); { while (enumerator.MoveNext()) { GeometryObject gobj = enumerator.Current as GeometryObject; if (gobj is GeometryInstance) { GeometryInstance geoInstance = gobj as GeometryInstance; GeometryElement gElem = geoInstance.SymbolGeometry; IEnumerator enumerator1 = gElem.GetEnumerator(); while (enumerator1.MoveNext()) { GeometryObject gobj1 = enumerator1.Current as GeometryObject; if (gobj1 is Solid) { Solid solid = gobj1 as Solid; if (sd == null) { sd = solid; } else { sd = BooleanOperationsUtils.ExecuteBooleanOperation(sd, solid, BooleanOperationsType.Union); } } } } } } } catch { } return(sd); }
public bool CheckSolid(Solid solid1, Solid solid2) { bool flag = false; try { Solid solid = BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect); if (solid.Volume > 0.000000001) { flag = true; } return(flag); } catch { return(flag); } }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; // Execute the BrepBuilder methods. BRepBuilder brepBuilderSolid = CreateBrepSolid(); BRepBuilder brepBuilderVoid = CreateBrepVoid(); Solid cube = brepBuilderSolid.GetResult(); Solid cylinder = brepBuilderVoid.GetResult(); // Determine their Boolean difference. Solid difference = BooleanOperationsUtils.ExecuteBooleanOperation( cube, cylinder, BooleanOperationsType.Difference); IList <GeometryObject> list = new List <GeometryObject>(); list.Add(difference); using (Transaction tr = new Transaction(doc)) { tr.Start("Create a DirectShape"); // Create a direct shape. DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); ds.SetShape(list); tr.Commit(); } return(Result.Succeeded); }
/// <summary> /// возвращаетд долю от соллда /// </summary> /// <param name="room"></param> /// <param name="el"></param> /// <returns></returns> private double GetPart(Room room, Element el) { List <Solid> roomSolids = (new GetGeometry(room)).Solids; List <Solid> elementSolids = (new GetGeometry(el)).Solids; double old_part = 1000000.0; foreach (var roomSolid in roomSolids) { foreach (var elementSolid in elementSolids) { Solid new_solid = BooleanOperationsUtils.ExecuteBooleanOperation(roomSolid, elementSolid, BooleanOperationsType.Union); double new_part = Math.Round(new_solid.Volume - (roomSolid.Volume + elementSolid.Volume) + new_solid.SurfaceArea - (roomSolid.SurfaceArea + elementSolid.SurfaceArea), 10); if (new_part < old_part) { old_part = new_part; } } } return(old_part); }
static internal XYZ IntersectPointBetweenBeamAndColumn(Element targetBeam, Element targetColumn) { FamilyInstance beamInstance = targetBeam as FamilyInstance; FamilyInstance columnInstance = targetColumn as FamilyInstance; // The beam and the column could have more than one solid modeled on the family // We will querry both and search for the solid that has more volume (main solid) Solid mainBeamSolid = GetMainSolid(beamInstance); Solid mainColumnSolid = GetMainSolid(columnInstance); Solid intersectingSolid = null; XYZ intersectingPoint = null; intersectingSolid = BooleanOperationsUtils.ExecuteBooleanOperation(mainBeamSolid, mainColumnSolid, BooleanOperationsType.Intersect); if (intersectingSolid != null) { intersectingPoint = intersectingSolid.ComputeCentroid(); } return(intersectingPoint); }
/// <summary> /// Основная проверка пересечения солидов /// </summary> /// <param name="room">комната</param> /// <param name="el">елемент</param> /// <returns></returns> private bool IsIntersection(Room room, Element el) { List <Solid> roomSolids = (new GetGeometry(room)).Solids; List <Solid> elementSolids = (new GetGeometry(el)).Solids; foreach (var roomSolid in roomSolids) { foreach (var elementSolid in elementSolids) { Solid new_solid = BooleanOperationsUtils.ExecuteBooleanOperation(roomSolid, elementSolid, BooleanOperationsType.Union); if (Math.Round((new_solid.Volume - roomSolid.Volume - elementSolid.Volume + new_solid.SurfaceArea - roomSolid.SurfaceArea - elementSolid.SurfaceArea), 11) != 0) { return(true); } } } return(false); //else //{ // foreach (var roomSolid in roomSolids) // { // foreach (var elementSolid in elementSolids) // { // Solid new_solid = BooleanOperationsUtils.ExecuteBooleanOperation(roomSolid, elementSolid, BooleanOperationsType.Union); // if (Math.Round((new_solid.SurfaceArea - // (roomSolid.SurfaceArea + elementSolid.SurfaceArea)), 10) != 0) // { // return true; // } // } // } // return false; //} }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; Selection sel = uidoc.Selection; // Retrieve all floors from the model var floors = new FilteredElementCollector(doc) .OfClass(typeof(Floor)) .ToElements() .Cast <Floor>() .ToList(); if (2 != floors.Count) { message = "Please create two intersected floors"; return(Result.Failed); } // Retrieve the floor solids Options opt = new Options(); var geometry1 = floors[0].get_Geometry(opt); var geometry2 = floors[1].get_Geometry(opt); var solid1 = geometry1.FirstOrDefault() as Solid; var solid2 = geometry2.FirstOrDefault() as Solid; // Calculate the intersection solid var intersectedSolid = BooleanOperationsUtils .ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect); // Search for the metric mass family template file string template_path = DirSearch( app.FamilyTemplatePath, "Metric Mass.rft"); // Create a new temporary family var family_doc = app.NewFamilyDocument( template_path); // Create a free form element // from the intersection solid using (var t = new Transaction(family_doc)) { t.Start("Add Free Form Element"); var freeFormElement = FreeFormElement.Create( family_doc, intersectedSolid); t.Commit(); } string dir = Path.GetTempPath(); string filepath = Path.Combine(dir, "floor_intersection_family.rfa"); SaveAsOptions sao = new SaveAsOptions() { OverwriteExistingFile = true }; family_doc.SaveAs(filepath, sao); // Create 3D View var viewFamilyType = new FilteredElementCollector(family_doc) .OfClass(typeof(ViewFamilyType)) .OfType <ViewFamilyType>() .FirstOrDefault(x => x.ViewFamily == ViewFamily.ThreeDimensional); View3D threeDView; using (var t = new Transaction(family_doc)) { t.Start("Create 3D View"); threeDView = View3D.CreateIsometric( family_doc, viewFamilyType.Id); t.Commit(); } // Export to SAT var viewSet = new List <ElementId>() { threeDView.Id }; SATExportOptions exportOptions = new SATExportOptions(); var res = family_doc.Export(dir, "SolidFile.sat", viewSet, exportOptions); return(Result.Succeeded); }
/// <summary> /// Boolean intersect geometric operation, return a new solid as the result /// </summary> /// <param name="solid1">Operation solid 1</param> /// <param name="solid2">Operation solid 2</param> /// <returns>The operation result</returns> public static Solid BooleanOperation_Intersect(Solid solid1, Solid solid2) { return(BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Intersect)); }
/// <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); }
/// <summary> /// 处理碰撞 /// </summary> /// <param name="doc"></param> /// <param name="hostELemID"></param> /// <param name="sd"></param> /// <returns></returns> public static Solid SolidHandle(Document doc, ElementId hostELemID, Solid sd) { //TODO:这里是取得该物体是否剪切别的物体 Element hostElem = doc.GetElement(hostELemID); //碰撞集合 List <Element> elembeCutList = JoinGeometryUtils.GetJoinedElements(doc, hostElem).Where(m => { if (JoinGeometryUtils.AreElementsJoined(doc, doc.GetElement(m), hostElem)) { //if (JoinGeometryUtils.IsCuttingElementInJoin(doc, hostElem, doc.GetElement(m))) //{ return(true); //} } return(false); }).ToList().ConvertAll(m => doc.GetElement(m)); //对于与梁进行碰撞的Solid的处理 if (hostElem.Category.Id == new ElementId(BuiltInCategory.OST_StructuralFraming)) { try { elembeCutList = elembeCutList.Where(m => m.Category .Id == new ElementId(BuiltInCategory.OST_StructuralFraming) || m.Category.Id.IntegerValue == (int)BuiltInCategory.OST_StructuralColumns).ToList(); } catch { SWF.MessageBox.Show(hostELemID + ""); } } else if (hostElem is Floor) { elembeCutList = elembeCutList.Where(m => m.Category.Id == new ElementId(BuiltInCategory.OST_StructuralFraming) || m.Category.Id == new ElementId(BuiltInCategory.OST_StructuralColumns) || m.Category.Id == new ElementId(BuiltInCategory.OST_Walls)) .ToList(); } else if (hostElem.Category.Id.IntegerValue == (int)BuiltInCategory.OST_StructuralColumns) { elembeCutList = elembeCutList.Where(m => m is Wall && m.Name.Contains("DW")).ToList(); } else if (hostElem is Wall) { Curve walCurve = (hostElem.Location as LocationCurve).Curve; XYZ startPoint = walCurve.GetEndPoint(0); XYZ endPoint = walCurve.GetEndPoint(1); startPoint = new XYZ(startPoint.X, startPoint.Y, 0); endPoint = new XYZ(endPoint.X, endPoint.Y, 0); List <Element> walElemList = bc.FilterElementList <Wall>(doc).Where(m => { if (hostElem.Id == m.Id) { return(false); } if (!hostElem.Name.Contains("DW")) { return(false); } if (hostElem.LevelId != m.LevelId) { return(false); } Curve mc = (m.Location as LocationCurve).Curve; XYZ sp = mc.GetEndPoint(0); XYZ ep = mc.GetEndPoint(1); sp = new XYZ(sp.X, sp.Y, 0); ep = new XYZ(ep.X, ep.Y, 0); if (sp.IsAlmostEqualTo(startPoint) || sp.IsAlmostEqualTo(endPoint) || ep.IsAlmostEqualTo(endPoint) || ep.IsAlmostEqualTo(startPoint)) { return(true); } return(false); }).ToList(); elembeCutList = elembeCutList.Where(m => m.Category.Id.IntegerValue == (int)BuiltInCategory.OST_StructuralColumns || (m is Wall && m.Name.Contains("DW"))).ToList(); elembeCutList.AddRange(walElemList); } Solid lastSolid = sd; foreach (Element e in elembeCutList) { Solid sdcut = AllSolid_Of_Element(e)[0]; try { lastSolid = BooleanOperationsUtils.ExecuteBooleanOperation(lastSolid, sdcut, BooleanOperationsType.Difference); }//可能由于几何体太过复杂导致Bool失败 catch { } } return(lastSolid); }
/***************************************************/ /**** Private Methods ****/ /***************************************************/ private static Dictionary <PlanarSurface, List <PlanarSurface> > PanelSurfaces_HostDocument(this HostObject hostObject, IEnumerable <ElementId> insertsToIgnore = null, RevitSettings settings = null) { List <Autodesk.Revit.DB.Plane> planes = hostObject.IPanelPlanes(); if (planes.Count == 0) { return(null); } Document doc = hostObject.Document; Dictionary <PlanarSurface, List <PlanarSurface> > result = new Dictionary <PlanarSurface, List <PlanarSurface> >(); IList <ElementId> inserts = hostObject.FindInserts(true, true, true, true); if (insertsToIgnore != null) { inserts = inserts.Where(x => insertsToIgnore.All(y => x.IntegerValue != y.IntegerValue)).ToList(); } Transaction t = new Transaction(doc); FailureHandlingOptions failureHandlingOptions = t.GetFailureHandlingOptions().SetClearAfterRollback(true); t.Start("Temp Delete Inserts And Unjoin Geometry"); try { foreach (ElementId id in JoinGeometryUtils.GetJoinedElements(doc, hostObject)) { JoinGeometryUtils.UnjoinGeometry(doc, hostObject, doc.GetElement(id)); } if (hostObject is Wall) { WallUtils.DisallowWallJoinAtEnd((Wall)hostObject, 0); WallUtils.DisallowWallJoinAtEnd((Wall)hostObject, 1); } if (insertsToIgnore != null) { doc.Delete(insertsToIgnore.ToList()); } doc.Regenerate(); List <Solid> solidsWithOpenings = hostObject.Solids(new Options()); List <Solid> fullSolids; if (inserts.Count != 0) { solidsWithOpenings = solidsWithOpenings.Select(x => SolidUtils.Clone(x)).ToList(); doc.Delete(inserts); doc.Regenerate(); fullSolids = hostObject.Solids(new Options()); } else { fullSolids = solidsWithOpenings; } fullSolids = fullSolids.SelectMany(x => SolidUtils.SplitVolumes(x)).ToList(); if (hostObject is Wall) { fullSolids.ForEach(x => BooleanOperationsUtils.CutWithHalfSpaceModifyingOriginalSolid(x, planes[0])); Autodesk.Revit.DB.Plane flippedPlane = Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(-planes[0].Normal, planes[0].Origin + planes[0].Normal * 1e-3); fullSolids.ForEach(x => BooleanOperationsUtils.CutWithHalfSpaceModifyingOriginalSolid(x, flippedPlane)); fullSolids = fullSolids.SelectMany(x => SolidUtils.SplitVolumes(x)).ToList(); planes[0] = Autodesk.Revit.DB.Plane.CreateByNormalAndOrigin(-planes[0].Normal, planes[0].Origin); } foreach (Autodesk.Revit.DB.Plane plane in planes) { foreach (Solid s in fullSolids) { List <CurveLoop> loops = new List <CurveLoop>(); foreach (Autodesk.Revit.DB.Face f in s.Faces) { PlanarFace pf = f as PlanarFace; if (pf == null) { continue; } if (Math.Abs(1 - pf.FaceNormal.DotProduct(plane.Normal)) <= settings.DistanceTolerance && Math.Abs((pf.Origin - plane.Origin).DotProduct(plane.Normal)) <= settings.AngleTolerance) { loops.AddRange(pf.GetEdgesAsCurveLoops()); } } CurveLoop outline = loops.FirstOrDefault(x => x.IsCounterclockwise(plane.Normal)); PlanarSurface surface = new PlanarSurface(outline.FromRevit(), null); List <PlanarSurface> openings = new List <PlanarSurface>(); foreach (CurveLoop loop in loops.Where(x => x != outline)) { openings.Add(new PlanarSurface(loop.FromRevit(), null)); } if (inserts.Count != 0) { List <Solid> openingVolumes = new List <Solid>(); foreach (Solid s2 in solidsWithOpenings) { openingVolumes.Add(BooleanOperationsUtils.ExecuteBooleanOperation(s, s2, BooleanOperationsType.Difference)); } foreach (Solid s2 in openingVolumes) { foreach (Autodesk.Revit.DB.Face f in s2.Faces) { PlanarFace pf = f as PlanarFace; if (pf == null) { continue; } if (Math.Abs(1 - pf.FaceNormal.DotProduct(plane.Normal)) <= settings.DistanceTolerance && Math.Abs((pf.Origin - plane.Origin).DotProduct(plane.Normal)) <= settings.AngleTolerance) { foreach (CurveLoop cl in pf.GetEdgesAsCurveLoops()) { openings.Add(new PlanarSurface(cl.FromRevit(), null)); } } } } } result.Add(surface, openings); } } } catch { BH.Engine.Reflection.Compute.RecordError(String.Format("Geometrical processing of a Revit element failed due to an internal Revit error. Converted panel might be missing one or more of its surfaces. Revit ElementId: {0}", hostObject.Id)); } t.RollBack(failureHandlingOptions); return(result); }
/// <summary> /// Execute a Boolean operation, and catch the exception. /// </summary> /// <param name="id">The id of the object demanding the Boolean operation.</param> /// <param name="secondId">The id of the object providing the second solid.</param> /// <param name="firstSolid">The first solid parameter to ExecuteBooleanOperation.</param> /// <param name="secondSolid">The second solid parameter to ExecuteBooleanOperation.</param> /// <param name="opType">The Boolean operation type.</param> /// <param name="suggestedShiftDirection">If the Boolean operation fails, a unit vector used to retry with a small shift. Can be null.</param> /// <returns>The result of the Boolean operation, or the first solid if the operation fails.</returns> public static Solid ExecuteSafeBooleanOperation(int id, int secondId, Solid firstSolid, Solid secondSolid, BooleanOperationsType opType, XYZ suggestedShiftDirection) { const double footToMillimeter = 1.0 / 304.8; // Perform default operations if one of the arguments is null. if (firstSolid == null || secondSolid == null) { if (firstSolid == null && secondSolid == null) { return(null); } switch (opType) { case BooleanOperationsType.Union: { if (firstSolid == null) { return(secondSolid); } return(firstSolid); } case BooleanOperationsType.Difference: { if (firstSolid == null) { return(null); } return(firstSolid); } default: // for .Intersect return(null); } } Solid resultSolid = null; bool failedAllAttempts = true; // We will attempt to do the Boolean operation 3 times: // 1st pass: With the passed-in arguments. // 2nd pass: With a 1mm shift in a direction in suggestedShiftDirection, or +Z if suggestedShiftDirection is null // 3rd pass: With a 1mm shift in a direction in -suggestedShiftDirection, or -Z if suggestedShiftDirection is null for (int ii = 0; ii < 3; ii++) { try { resultSolid = null; Solid secondOperand = secondSolid; if (ii > 0) { // 1 mm shift. XYZ shiftDirection = (suggestedShiftDirection == null) ? new XYZ(0, 0, 1) : suggestedShiftDirection; Transform secondSolidShift = Transform.CreateTranslation(shiftDirection * ((ii == 1) ? footToMillimeter : -footToMillimeter)); secondOperand = SolidUtils.CreateTransformed(secondOperand, secondSolidShift); } resultSolid = BooleanOperationsUtils.ExecuteBooleanOperation(firstSolid, secondOperand, opType); failedAllAttempts = false; } catch (Exception ex) { if (ii < 2) { continue; } Importer.TheLog.LogError(id, ex.Message, false); resultSolid = firstSolid; } if (SolidValidator.IsValidGeometry(resultSolid)) { // If we got here not on out first attempt, generate a warning, unless we got here because we gave up on our 3rd attempt. if (ii > 0 && !failedAllAttempts) { Importer.TheLog.LogWarning(id, "The second argument in the Boolean " + opType.ToString() + " operation was shifted by 1mm to allow the operation to succeed. This may result in a very small difference in appearance.", false); } return(resultSolid); } } Importer.TheLog.LogError(id, opType.ToString() + " operation failed with void from #" + secondId.ToString(), false); return(firstSolid); }
/// <summary> /// Boolean difference geometric operation, return a new solid as the result /// </summary> /// <param name="solid1">Operation solid 1</param> /// <param name="solid2">Operation solid 2</param> /// <returns>The operation result</returns> public static Solid BooleanOperation_Difference(Solid solid1, Solid solid2) { return(BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Difference)); }
/// <summary> /// Retrieve all plan view boundary loops from /// all solids of the given element geometry /// united together. /// </summary> internal static JtLoops GetPlanViewBoundaryLoopsGeo( Autodesk.Revit.Creation.Application creapp, GeometryElement geo, ref int nFailures) { Solid union = null; Plane plane = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero); foreach (GeometryObject obj in geo) { Solid solid = obj as Solid; if (null != solid && 0 < solid.Faces.Size) { // Some solids, e.g. in the standard // content 'Furniture Chair - Office' // cause an extrusion analyser failure, // so skip adding those. try { ExtrusionAnalyzer extrusionAnalyzer = ExtrusionAnalyzer.Create( solid, plane, XYZ.BasisZ); } catch (Autodesk.Revit.Exceptions .InvalidOperationException) { solid = null; ++nFailures; } if (null != solid) { if (null == union) { union = solid; } else { try { union = BooleanOperationsUtils .ExecuteBooleanOperation(union, solid, BooleanOperationsType.Union); } catch (Autodesk.Revit.Exceptions .InvalidOperationException) { ++nFailures; } } } } } JtLoops loops = new JtLoops(1); AddLoops(creapp, loops, union, ref nFailures); return(loops); }
/// <summary> /// Gets the rectangular openings. /// </summary> /// <returns></returns> /// <remarks>This method uses walls, doors, windows and generic models bounding boxes to determine the rectangles. /// These objects can be in the host file or in linked Revit files.</remarks> public static IList <Autodesk.DesignScript.Geometry.Rectangle> GetRectangularOpenings() { Utils.Log(string.Format("OpeningUtils.GetRectangularOpenings started...", "")); Autodesk.Revit.DB.Document doc = DocumentManager.Instance.CurrentDBDocument; //look for Walls, Doors, Windows, Generic Models in the current document and in the linked documents ElementCategoryFilter wallFilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls); ElementCategoryFilter doorFilter = new ElementCategoryFilter(BuiltInCategory.OST_Doors); ElementCategoryFilter windowFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows); ElementCategoryFilter genericFilter = new ElementCategoryFilter(BuiltInCategory.OST_GenericModel); IList <ElementFilter> filterList = new List <ElementFilter>() { wallFilter, doorFilter, windowFilter, genericFilter }; LogicalOrFilter orFilter = new LogicalOrFilter(filterList); IList <Autodesk.DesignScript.Geometry.Solid> solids = new List <Autodesk.DesignScript.Geometry.Solid>(); IList <Autodesk.DesignScript.Geometry.Rectangle> output = new List <Autodesk.DesignScript.Geometry.Rectangle>(); foreach (Autodesk.Revit.DB.Element e in new FilteredElementCollector(doc) .WherePasses(orFilter) .WhereElementIsNotElementType() .Where(x => x.Parameters.Cast <Autodesk.Revit.DB.Parameter>() .First(p => p.Id.IntegerValue == (int)BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).HasValue)) { string comments = e.Parameters.Cast <Autodesk.Revit.DB.Parameter>().First(p => p.Id.IntegerValue == (int)BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString(); if (comments.ToLower() != "opening") { continue; } Transform tr = Transform.Identity; if (e is Instance) { Instance instance = e as Instance; tr = instance.GetTotalTransform(); } IList <Autodesk.Revit.DB.Solid> temp = new List <Autodesk.Revit.DB.Solid>(); foreach (GeometryObject go in e.get_Geometry(new Options())) { if (go is GeometryInstance) { GeometryInstance geoInstance = go as GeometryInstance; foreach (var gi in geoInstance.SymbolGeometry) { if (gi is Autodesk.Revit.DB.Solid) { Autodesk.Revit.DB.Solid s = gi as Autodesk.Revit.DB.Solid; s = SolidUtils.CreateTransformed(s, tr); temp.Add(s); } } } else { if (go is Autodesk.Revit.DB.Solid) { Autodesk.Revit.DB.Solid s = go as Autodesk.Revit.DB.Solid; s = SolidUtils.CreateTransformed(s, tr); temp.Add(s); } } } if (temp.Count > 0) { Autodesk.Revit.DB.Solid s0 = temp[0]; for (int i = 1; i < temp.Count; ++i) { s0 = BooleanOperationsUtils.ExecuteBooleanOperation(s0, temp[i], BooleanOperationsType.Union); } solids.Add(s0.ToProtoType()); } } foreach (RevitLinkInstance rli in new FilteredElementCollector(doc).OfClass(typeof(RevitLinkInstance)).WhereElementIsNotElementType()) { Autodesk.Revit.DB.Document link = rli.GetLinkDocument(); foreach (Autodesk.Revit.DB.Element e in new FilteredElementCollector(link) .WherePasses(orFilter) .WhereElementIsNotElementType() .Where(x => x.Parameters.Cast <Autodesk.Revit.DB.Parameter>() .First(p => p.Id.IntegerValue == (int)BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).HasValue)) { Transform tr = rli.GetTotalTransform(); string comments = e.Parameters.Cast <Autodesk.Revit.DB.Parameter>().First(p => p.Id.IntegerValue == (int)BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString(); if (comments.ToLower() != "opening") { continue; } if (e is Instance) { Instance instance = e as Instance; tr = tr.Multiply(instance.GetTotalTransform()); } IList <Autodesk.Revit.DB.Solid> temp = new List <Autodesk.Revit.DB.Solid>(); foreach (var go in e.get_Geometry(new Options())) { if (go is GeometryInstance) { GeometryInstance geoInstance = go as GeometryInstance; foreach (var gi in geoInstance.SymbolGeometry) { if (gi is Autodesk.Revit.DB.Solid) { Autodesk.Revit.DB.Solid s = gi as Autodesk.Revit.DB.Solid; s = SolidUtils.CreateTransformed(s, tr); temp.Add(s); } } } else { if (go is Autodesk.Revit.DB.Solid) { Autodesk.Revit.DB.Solid s = go as Autodesk.Revit.DB.Solid; s = SolidUtils.CreateTransformed(s, tr); temp.Add(s); } } } if (temp.Count > 0) { Autodesk.Revit.DB.Solid s0 = temp[0]; for (int i = 1; i < temp.Count; ++i) { s0 = BooleanOperationsUtils.ExecuteBooleanOperation(s0, temp[i], BooleanOperationsType.Union); } solids.Add(s0.ToProtoType()); } } } foreach (var s in solids) { IList <Autodesk.DesignScript.Geometry.Point> points = new List <Autodesk.DesignScript.Geometry.Point>(); foreach (var v in s.Vertices) { points.Add(v.PointGeometry); } points = Autodesk.DesignScript.Geometry.Point.PruneDuplicates(points); Autodesk.DesignScript.Geometry.Plane plane = Autodesk.DesignScript.Geometry.Plane.ByBestFitThroughPoints(points); plane = Autodesk.DesignScript.Geometry.Plane.ByOriginNormal(points.Last(), plane.Normal); IList <Autodesk.DesignScript.Geometry.Point> temp = new List <Autodesk.DesignScript.Geometry.Point>(); foreach (var p in points) { foreach (var q in p.Project(plane, plane.Normal)) { temp.Add(q as Autodesk.DesignScript.Geometry.Point); } foreach (var q in p.Project(plane, plane.Normal.Reverse())) { temp.Add(q as Autodesk.DesignScript.Geometry.Point); } } temp = Autodesk.DesignScript.Geometry.Point.PruneDuplicates(temp); CoordinateSystem cs = CoordinateSystem.ByPlane(plane); IList <Autodesk.DesignScript.Geometry.Point> relative = new List <Autodesk.DesignScript.Geometry.Point>(); foreach (var p in temp) { relative.Add(p.Transform(cs.Inverse()) as Autodesk.DesignScript.Geometry.Point); } var min = Autodesk.DesignScript.Geometry.Point.ByCoordinates(relative.Min(p => p.X), relative.Min(p => p.Y), relative.Min(p => p.Z)); var max = Autodesk.DesignScript.Geometry.Point.ByCoordinates(relative.Max(p => p.X), relative.Max(p => p.Y), relative.Max(p => p.Z)); double width = max.X - min.X; double height = max.Y - min.Y; min = min.Transform(cs) as Autodesk.DesignScript.Geometry.Point; max = max.Transform(cs) as Autodesk.DesignScript.Geometry.Point; plane = Autodesk.DesignScript.Geometry.Plane.ByOriginNormal(Autodesk.DesignScript.Geometry.Line.ByStartPointEndPoint(min, max).PointAtParameter(0.5), plane.Normal); Autodesk.DesignScript.Geometry.Rectangle rectangle = Autodesk.DesignScript.Geometry.Rectangle.ByWidthLength(plane, width, height); output.Add(rectangle); plane.Dispose(); cs.Dispose(); min.Dispose(); max.Dispose(); } Utils.Log(string.Format("OpeningUtils.GetRectangularOpenings completed.", "")); return(output); }
/// <summary> /// This method takes the solidsList and clips all of its solids between the given range. /// </summary> /// <param name="elem"> /// The Element from which we obtain our BoundingBoxXYZ. /// </param> /// <param name="geomElem"> /// The top-level GeometryElement from which to gather X and Y coordinates for the intersecting solid. /// </param> /// <param name="range"> /// The IFCRange whose Z values we use to create an intersecting solid to clip the solids in this class's internal solidsList. /// If range boundaries are equal, method returns, performing no clippings. /// </param> public void ClipSolidsList(GeometryElement geomElem, IFCRange range) { if (geomElem == null) { throw new ArgumentNullException("geomElemToUse"); } if (MathUtil.IsAlmostEqual(range.Start, range.End) || solidsList.Count == 0) { return; } double bottomZ; double boundDifference; if (range.Start < range.End) { bottomZ = range.Start; boundDifference = range.End - range.Start; } else { bottomZ = range.End; boundDifference = range.Start - range.End; } // create a new solid using the X and Y of the bounding box on the top level GeometryElement and the Z of the IFCRange BoundingBoxXYZ elemBoundingBox = geomElem.GetBoundingBox(); XYZ pointA = new XYZ(elemBoundingBox.Min.X, elemBoundingBox.Min.Y, bottomZ); XYZ pointB = new XYZ(elemBoundingBox.Max.X, elemBoundingBox.Min.Y, bottomZ); XYZ pointC = new XYZ(elemBoundingBox.Max.X, elemBoundingBox.Max.Y, bottomZ); XYZ pointD = new XYZ(elemBoundingBox.Min.X, elemBoundingBox.Max.Y, bottomZ); List <Curve> perimeter = new List <Curve>(); perimeter.Add(Line.CreateBound(pointA, pointB)); perimeter.Add(Line.CreateBound(pointB, pointC)); perimeter.Add(Line.CreateBound(pointC, pointD)); perimeter.Add(Line.CreateBound(pointD, pointA)); List <CurveLoop> boxPerimeterList = new List <CurveLoop>(); boxPerimeterList.Add(CurveLoop.Create(perimeter)); Solid intersectionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boxPerimeterList, XYZ.BasisZ, boundDifference); // cycle through the elements in solidsList and intersect them against intersectionSolid to create a new list List <Solid> clippedSolidsList = new List <Solid>(); Solid currSolid; foreach (Solid solid in solidsList) { try { // ExecuteBooleanOperation can throw if it fails. In this case, just ignore the clipping. currSolid = BooleanOperationsUtils.ExecuteBooleanOperation(solid, intersectionSolid, BooleanOperationsType.Intersect); if (currSolid != null && currSolid.Volume != 0) { clippedSolidsList.Add(currSolid); } } catch { } } solidsList = clippedSolidsList; }
/// <summary> /// Boolean union geometric operation, return a new solid as the result /// </summary> /// <param name="solid1">Operation solid 1</param> /// <param name="solid2">Operation solid 2</param> /// <returns>The operation result</returns> public static Solid BooleanOperation_Union(Solid solid1, Solid solid2) { return(BooleanOperationsUtils.ExecuteBooleanOperation(solid1, solid2, BooleanOperationsType.Union)); }