Example #1
0
        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);
        }
Example #2
0
        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);
            }
        }