public static List <Autodesk.Revit.DB.Wall> TrimOrExtendWall(this IEnumerable <Autodesk.Revit.DB.Wall> walls, double maxDistance, double tolerance = Core.Tolerance.Distance) { Dictionary <double, Dictionary <Autodesk.Revit.DB.Wall, Segment2D> > dictionary = new Dictionary <double, Dictionary <Autodesk.Revit.DB.Wall, Segment2D> >(); foreach (Autodesk.Revit.DB.Wall wall in walls) { Curve curve = (wall.Location as LocationCurve).Curve; Segment3D segment3D = Geometry.Revit.Convert.ToSAM_Segment3D(curve); double elevation = Math.Min(segment3D[0].Z, segment3D[1].Z); Dictionary <Autodesk.Revit.DB.Wall, Segment2D> dictionary_Wall = null; if (!dictionary.TryGetValue(elevation, out dictionary_Wall)) { dictionary_Wall = new Dictionary <Autodesk.Revit.DB.Wall, Segment2D>(); dictionary[elevation] = dictionary_Wall; } dictionary_Wall[wall] = Geometry.Spatial.Plane.WorldXY.Convert(segment3D); } List <Autodesk.Revit.DB.Wall> result = new List <Autodesk.Revit.DB.Wall>(); foreach (KeyValuePair <double, Dictionary <Autodesk.Revit.DB.Wall, Segment2D> > keyValuePair in dictionary) { List <Segment2D> segment2Ds = keyValuePair.Value.Values.ToList(); //Filtering Walls by Level List <Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> > tupleList = new List <Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> >(); foreach (KeyValuePair <Autodesk.Revit.DB.Wall, Segment2D> keyValuePair_Wall in keyValuePair.Value) { LocationCurve locationCurve = keyValuePair_Wall.Key.Location as LocationCurve; List <int> indexes = new List <int>(); ElementArray elementArray = null; elementArray = locationCurve.get_ElementsAtJoin(0); if (elementArray == null || elementArray.Size == 0) { indexes.Add(0); } elementArray = locationCurve.get_ElementsAtJoin(1); if (elementArray == null || elementArray.Size == 0) { indexes.Add(1); } //if (indexes.Count > 0) tupleList.Add(new Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool>(keyValuePair_Wall.Key, keyValuePair_Wall.Value, indexes, false)); } //Seeking for walls to be extended/trimmed bool updated = true; while (updated) { updated = false; List <Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> > tupleList_Unconnected = tupleList.FindAll(x => x.Item3 != null && x.Item3.Count > 0); for (int i = 0; i < tupleList_Unconnected.Count; i++) { Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> tuple = tupleList_Unconnected[i]; List <Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> > tupleList_Temp = new List <Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> >(tupleList); tupleList_Temp.Remove(tuple); Segment2D segment2D = tuple.Item2; List <Tuple <Point2D, Segment2D> > tupleList_Intersection = new List <Tuple <Point2D, Segment2D> >(); foreach (Segment2D segment2D_Temp in tupleList_Temp.ConvertAll(x => x.Item2)) { Point2D point2D_Intersection = segment2D_Temp.Intersection(segment2D, false, tolerance); if (point2D_Intersection == null) { //Checking Colinear Segment2Ds if can be extended Vector2D direction_Temp = segment2D_Temp.Direction; Vector2D direction = segment2D.Direction; if (!direction_Temp.AlmostEqual(direction, tolerance) && !direction_Temp.AlmostEqual(direction.GetNegated(), tolerance)) { continue; } Point2D point2D_Temp = null; Point2D point2D = null; if (!Geometry.Planar.Query.Closest(segment2D_Temp, segment2D, out point2D_Temp, out point2D, tolerance)) { continue; } if (point2D_Temp.AlmostEquals(point2D, tolerance)) { continue; } Vector2D direction_New = new Vector2D(point2D, point2D_Temp).Unit; if (!direction_Temp.AlmostEqual(direction_New, tolerance) && !direction_Temp.AlmostEqual(direction_New.GetNegated(), tolerance)) { continue; } point2D_Intersection = point2D; } double distance; distance = segment2D.Distance(point2D_Intersection); if (distance > maxDistance) { continue; } distance = segment2D_Temp.Distance(point2D_Intersection); if (distance > maxDistance) { continue; } tupleList_Intersection.Add(new Tuple <Point2D, Segment2D>(point2D_Intersection, segment2D_Temp)); } if (tupleList_Intersection.Count == 0) { continue; } foreach (int index in tuple.Item3) { Point2D point2D = segment2D[index]; tupleList_Intersection.Sort((x, y) => x.Item1.Distance(point2D).CompareTo(y.Item1.Distance(point2D))); Tuple <Point2D, Segment2D> tuple_Intersection = tupleList_Intersection.Find(x => x.Item1.Distance(point2D) < maxDistance); if (tuple_Intersection == null) { continue; } Segment2D segment2D_Intersection = tuple_Intersection.Item2; int j = tupleList.FindIndex(x => x.Item2 == segment2D_Intersection); if (j == -1) { continue; } int k = tupleList.FindIndex(x => x.Item2 == segment2D); if (k == -1) { continue; } //TODO: Double Check if works (added 2020.05.14) if ((index == 0 && segment2D[1].AlmostEquals(tuple_Intersection.Item1)) || (index == 1 && segment2D[0].AlmostEquals(tuple_Intersection.Item1))) { tupleList[k] = new Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool>(tuple.Item1, new Segment2D(tuple_Intersection.Item1, tuple_Intersection.Item1), tuple.Item3.FindAll(x => x != index), true); updated = true; break; } Segment2D segment2D_Temp; if (segment2D_Intersection[0].Distance(tuple_Intersection.Item1) < maxDistance || segment2D_Intersection[1].Distance(tuple_Intersection.Item1) < maxDistance) { segment2D_Temp = new Segment2D(segment2D_Intersection); segment2D_Temp.Adjust(tuple_Intersection.Item1); if (!segment2D_Temp.AlmostSimilar(segment2D_Intersection) && segment2D_Temp.GetLength() > segment2D_Intersection.GetLength()) { tupleList[j] = new Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool>(tupleList[j].Item1, segment2D_Temp, tupleList[j].Item3.FindAll(x => x != segment2D_Temp.GetEndIndex(tuple_Intersection.Item1)), true); } } segment2D_Temp = new Segment2D(segment2D); segment2D_Temp.Adjust(tuple_Intersection.Item1); if (segment2D_Temp.AlmostSimilar(segment2D)) { continue; } tupleList[k] = new Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool>(tuple.Item1, segment2D_Temp, tuple.Item3.FindAll(x => x != index), true); updated = true; break; } if (updated) { break; } } } tupleList.RemoveAll(x => !x.Item4); //Updating Revit Walls foreach (Tuple <Autodesk.Revit.DB.Wall, Segment2D, List <int>, bool> tuple in tupleList) { Autodesk.Revit.DB.Wall wall = tuple.Item1; if (!wall.IsValidObject) { continue; } Segment2D segment2D = tuple.Item2; if (segment2D.GetLength() < tolerance) { wall.Document.Delete(wall.Id); continue; } LocationCurve locationCurve = wall.Location as LocationCurve; JoinType[] joinTypes = new JoinType[] { locationCurve.get_JoinType(0), locationCurve.get_JoinType(1) }; WallUtils.DisallowWallJoinAtEnd(wall, 0); WallUtils.DisallowWallJoinAtEnd(wall, 1); Segment3D segment3D = new Segment3D(new Point3D(segment2D[0].X, segment2D[0].Y, keyValuePair.Key), new Point3D(segment2D[1].X, segment2D[1].Y, keyValuePair.Key)); Line line = Geometry.Revit.Convert.ToRevit(segment3D); locationCurve.Curve = line; WallUtils.AllowWallJoinAtEnd(wall, 0); locationCurve.set_JoinType(0, joinTypes[0]); WallUtils.AllowWallJoinAtEnd(wall, 1); locationCurve.set_JoinType(1, joinTypes[1]); result.Add(tuple.Item1); } } return(result); }
protected override void TrySolveInstance(IGH_DataAccess dataAccess) { int index = -1; bool run = false; index = Params.IndexOfInputParam("_run"); if (index == -1 || !dataAccess.GetData(index, ref run) || !run) { return; } double maxDistance = 0.2; index = Params.IndexOfInputParam("_maxDistance"); if (index == -1 || !dataAccess.GetData(index, ref maxDistance)) { return; } RhinoInside.Revit.GH.Types.Level level_GH = null; index = Params.IndexOfInputParam("_level"); if (index == -1 || !dataAccess.GetData(index, ref level_GH)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data"); return; } RhinoInside.Revit.GH.Types.Level referenceLevel_GH = null; index = Params.IndexOfInputParam("_referenceLevel"); if (index == -1 || !dataAccess.GetData(index, ref referenceLevel_GH)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data"); return; } Level level = level_GH.Value; if (level == null) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data"); return; } Level referenceLevel = referenceLevel_GH.Value; if (level == null) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid data"); return; } #if Revit2017 || Revit2018 || Revit2019 || Revit2020 double elevation = UnitUtils.ConvertFromInternalUnits(level.Elevation, DisplayUnitType.DUT_METERS); double referenceElevation = UnitUtils.ConvertFromInternalUnits(referenceLevel.Elevation, DisplayUnitType.DUT_METERS); #else double elevation = UnitUtils.ConvertFromInternalUnits(level.Elevation, UnitTypeId.Meters); double referenceElevation = UnitUtils.ConvertFromInternalUnits(referenceLevel.Elevation, UnitTypeId.Meters); #endif Document document = level.Document; IEnumerable <Autodesk.Revit.DB.Wall> walls_All = new FilteredElementCollector(document).OfClass(typeof(Autodesk.Revit.DB.Wall)).Cast <Autodesk.Revit.DB.Wall>(); if (walls_All == null || walls_All.Count() == 0) { return; } StartTransaction(document); ConvertSettings convertSettings = new ConvertSettings(true, true, true); List <Panel> panels = new List <Panel>(); List <Panel> panels_Reference = new List <Panel>(); foreach (Autodesk.Revit.DB.Wall wall in walls_All) { List <Panel> panels_Temp = Analytical.Revit.Convert.ToSAM(wall, convertSettings); foreach (Panel panel in panels_Temp) { double max = panel.MaxElevation(); double min = panel.MinElevation(); if (Math.Abs(min - elevation) < Core.Tolerance.Distance || (min - Core.Tolerance.Distance < elevation && max - Core.Tolerance.Distance > elevation)) { panels.Add(panel); } if (Math.Abs(min - referenceElevation) < Core.Tolerance.Distance || (min - Core.Tolerance.Distance < referenceElevation && max - Core.Tolerance.Distance > referenceElevation)) { panels_Reference.Add(panel); } } } IEnumerable <ElementId> elementIds = panels.ConvertAll(x => x.ElementId()).Distinct(); IEnumerable <ElementId> elementIds_Reference = panels_Reference.ConvertAll(x => x.ElementId()).Distinct(); Geometry.Spatial.Plane plane = new Geometry.Spatial.Plane(new Point3D(0, 0, elevation), Vector3D.WorldZ); Dictionary <Segment2D, HostObjAttributes> dictionary_Reference = new Dictionary <Segment2D, HostObjAttributes>(); foreach (ElementId elementId in elementIds_Reference) { Element element = document.GetElement(elementId); if (element == null) { continue; } HostObjAttributes hostObjAttributes = document.GetElement(element.GetTypeId()) as HostObjAttributes; if (hostObjAttributes == null) { continue; } LocationCurve locationCurve = element.Location as LocationCurve; ISegmentable3D segmentable3D = locationCurve.ToSAM() as ISegmentable3D; if (segmentable3D == null) { continue; } List <Segment3D> segment3Ds = segmentable3D.GetSegments(); if (segment3Ds == null || segment3Ds.Count == 0) { continue; } segment3Ds.ForEach(x => dictionary_Reference[plane.Convert(x)] = hostObjAttributes); } Dictionary <Segment2D, ElementId> dictionary = new Dictionary <Segment2D, ElementId>(); foreach (ElementId elementId in elementIds) { LocationCurve locationCurve = document.GetElement(elementId).Location as LocationCurve; Segment3D segment3D = locationCurve.ToSAM() as Segment3D; if (segment3D == null) { continue; } dictionary[plane.Convert(plane.Project(segment3D))] = elementId; } Dictionary <Segment2D, ElementId> dictionary_Result = new Dictionary <Segment2D, ElementId>(); foreach (KeyValuePair <Segment2D, ElementId> keyValuePair in dictionary) { Segment2D segment2D = keyValuePair.Key; List <Segment2D> segment2Ds_Temp = dictionary_Reference.Keys.ToList().FindAll(x => x.Collinear(segment2D) && x.Distance(segment2D) <= maxDistance + Core.Tolerance.MacroDistance && x.Distance(segment2D) > Core.Tolerance.MacroDistance); if (segment2Ds_Temp == null || segment2Ds_Temp.Count == 0) { continue; } Element element = document.GetElement(keyValuePair.Value); if (element == null) { continue; } HostObjAttributes hostObjAttributes = document.GetElement(element.GetTypeId()) as HostObjAttributes; if (hostObjAttributes == null) { continue; } segment2Ds_Temp.Sort((x, y) => segment2D.Distance(x).CompareTo(segment2D.Distance(y))); Segment2D segment2D_Reference = null; foreach (Segment2D segment2D_Temp in segment2Ds_Temp) { HostObjAttributes hostObjAttributes_Temp = dictionary_Reference[segment2D_Temp]; if (hostObjAttributes.Name.Equals(hostObjAttributes_Temp.Name)) { segment2D_Reference = segment2D_Temp; break; } } if (segment2D_Reference == null) { HashSet <PanelType> panelTypes = new HashSet <PanelType>(); panelTypes.Add(Analytical.Revit.Query.PanelType(hostObjAttributes)); switch (panelTypes.First()) { case PanelType.CurtainWall: panelTypes.Add(PanelType.WallExternal); break; case PanelType.UndergroundWall: panelTypes.Add(PanelType.WallExternal); break; case PanelType.Undefined: panelTypes.Add(PanelType.WallInternal); break; } foreach (Segment2D segment2D_Temp in segment2Ds_Temp) { HostObjAttributes hostObjAttributes_Temp = dictionary_Reference[segment2D_Temp]; PanelType panelType_Temp = Analytical.Revit.Query.PanelType(hostObjAttributes_Temp); if (panelTypes.Contains(panelType_Temp)) { segment2D_Reference = segment2D_Temp; break; } } } if (segment2D_Reference == null) { segment2D_Reference = segment2Ds_Temp.First(); } Segment2D segment2D_Project = segment2D_Reference.Project(segment2D); if (segment2D_Project == null) { continue; } dictionary_Result[segment2D_Project] = dictionary[segment2D]; } List <HostObject> result = new List <HostObject>(); foreach (KeyValuePair <Segment2D, ElementId> keyValuePair in dictionary_Result) { Autodesk.Revit.DB.Wall wall = document.GetElement(keyValuePair.Value) as Autodesk.Revit.DB.Wall; if (wall == null || !wall.IsValidObject) { continue; } Segment2D segment2D = keyValuePair.Key; bool pinned = wall.Pinned; if (wall.Pinned) { using (SubTransaction subTransaction = new SubTransaction(document)) { subTransaction.Start(); wall.Pinned = false; subTransaction.Commit(); } } Segment3D segment3D = plane.Convert(segment2D); LocationCurve locationCurve = wall.Location as LocationCurve; using (SubTransaction subTransaction = new SubTransaction(document)) { subTransaction.Start(); document.Regenerate(); locationCurve.Curve = Geometry.Revit.Convert.ToRevit(segment3D); subTransaction.Commit(); } if (wall.Pinned != pinned) { using (SubTransaction subTransaction = new SubTransaction(document)) { subTransaction.Start(); wall.Pinned = pinned; subTransaction.Commit(); } } result.Add(wall); } index = Params.IndexOfOutputParam("walls"); if (index != -1) { dataAccess.SetDataList(index, result); } }