public static bool IsOutlineRectangular <TEdge, TOpening>(this IPanel <TEdge, TOpening> panel)
            where TEdge : IEdge
            where TOpening : IOpening <TEdge>
        {
            PolyCurve polycurve = ExternalPolyCurve(panel);

            if (polycurve == null)
            {
                return(false);
            }

            if (polycurve.SubParts().Any(x => !x.IIsLinear()))
            {
                return(false);
            }

            List <Point> points = polycurve.DiscontinuityPoints();

            if (points.Count != 4)
            {
                return(false);
            }
            if (!points.IsCoplanar())
            {
                return(false);
            }

            List <Vector> vectors = VectorsBetweenPoints(points);

            List <double> angles = AnglesBetweenVectors(vectors);

            //Check the three angles are pi/2 degrees within tolerance
            return((angles.Any(x => Math.Abs(Math.PI / 2 - x) > Tolerance.Angle)) ? false : true);
        }
Exemple #2
0
        public static bool IsOutlineQuad <TEdge, TOpening>(this IPanel <TEdge, TOpening> panel)
            where TEdge : IEdge
            where TOpening : IOpening <TEdge>
        {
            PolyCurve polycurve = ExternalPolyCurve(panel);

            if (polycurve == null)
            {
                return(false);
            }

            if (polycurve.SubParts().Any(x => !x.IIsLinear()))
            {
                return(false);
            }

            List <Point> points = polycurve.DiscontinuityPoints();

            if (points.Count != 4)
            {
                return(false);
            }

            return(points.IsCoplanar());
        }
Exemple #3
0
        /***************************************************/

        public static IStory GetStory(this Panel panel, IStories ramStories)
        {
            double elev;

            List <double> panelHeights = new List <double>();
            List <Point>  panelPoints  = new List <Point>();

            // Get heights of wall and floor corners to create levels
            PolyCurve panelOutline = Engine.Spatial.Query.OutlineCurve(panel);

            panelPoints = panelOutline.DiscontinuityPoints();

            foreach (Point pt in panelPoints)
            {
                panelHeights.Add(Math.Round(pt.Z, 0));
            }

            // Get elevation of panel per max elevation
            elev = panelHeights.Max().ToInch();

            //There must be a better way to iterate over IStories
            List <IStory> storeys    = new List <IStory>();
            int           numStories = ramStories.GetCount();

            for (int i = 0; i < numStories; i++)
            {
                storeys.Add(ramStories.GetAt(i));
            }
            return(storeys.OrderBy(x => Math.Abs(x.dElevation - elev)).First());
        }
Exemple #4
0
        public static bool IsOutlineSquare <TEdge, TOpening>(this IPanel <TEdge, TOpening> panel)
            where TEdge : IEdge
            where TOpening : IOpening <TEdge>
        {
            PolyCurve polycurve = ExternalPolyCurve(panel);

            if (polycurve == null)
            {
                return(false);
            }

            if (polycurve.SubParts().Any(x => !x.IIsLinear()))
            {
                return(false);
            }

            List <Point> points = polycurve.DiscontinuityPoints();

            if (points.Count != 4)
            {
                return(false);
            }
            if (!points.IsCoplanar())
            {
                return(false);
            }

            List <Vector> vectors = VectorsBetweenPoints(points);

            List <double> angles = AnglesBetweenVectors(vectors);

            //Check the three angles are pi/2 degrees within tolerance
            if (angles.Any(x => Math.Abs(Math.PI / 2 - x) > Tolerance.Angle))
            {
                return(false);
            }

            //Check all lengths are the same within tolerance
            double length = vectors.First().Length();

            return(vectors.Skip(0).All(x => (Math.Abs(x.Length() - length) < Tolerance.Distance)) ? true : false);
        }
Exemple #5
0
        public static PolyCurve Offset(this PolyCurve curve, double offset, Vector normal = null, bool tangentExtensions = false, double tolerance = Tolerance.Distance)
        {
            if (curve == null || curve.Length() < tolerance)
            {
                return(null);
            }

            //if there are only Line segmensts switching to polyline method which is more reliable
            if (curve.Curves.All(x => x is Line))
            {
                Polyline polyline = ((Polyline)curve).Offset(offset, normal, tangentExtensions, tolerance);
                if (polyline == null)
                {
                    return(null);
                }

                return(new PolyCurve {
                    Curves = polyline.SubParts().Cast <ICurve>().ToList()
                });
            }

            List <ICurve> subParts = curve.SubParts();

            //Check if contains any circles, if so, handle them explicitly, and offset any potential leftovers by backcalling this method
            if (subParts.Any(x => x is Circle))
            {
                IEnumerable <Circle> circles            = subParts.Where(x => x is Circle).Cast <Circle>().Select(x => x.Offset(offset, normal, tangentExtensions, tolerance));
                PolyCurve            nonCirclePolyCurve = new PolyCurve {
                    Curves = curve.Curves.Where(x => !(x is Circle)).ToList()
                };
                if (nonCirclePolyCurve.Curves.Count != 0)
                {
                    nonCirclePolyCurve = nonCirclePolyCurve.Offset(offset, normal, tangentExtensions, tolerance);
                }

                nonCirclePolyCurve.Curves.AddRange(circles);
                return(nonCirclePolyCurve);
            }

            if (!curve.IsPlanar(tolerance))
            {
                BH.Engine.Reflection.Compute.RecordError("Offset works only on planar curves");
                return(null);
            }

            if (curve.IsSelfIntersecting(tolerance))
            {
                BH.Engine.Reflection.Compute.RecordError("Offset works only on non-self intersecting curves");
                return(null);
            }

            if (offset == 0)
            {
                return(curve);
            }

            bool isClosed = curve.IsClosed(tolerance);

            if (normal == null)
            {
                if (!isClosed)
                {
                    BH.Engine.Reflection.Compute.RecordError("Normal is missing. Normal vector is not needed only for closed curves");
                    return(null);
                }
                else
                {
                    normal = curve.Normal();
                }
            }

            if (offset > 0.05 * curve.Length())
            {
                return((curve.Offset(offset / 2, normal, tangentExtensions, tolerance))?.Offset(offset / 2, normal, tangentExtensions, tolerance));
            }

            PolyCurve result = new PolyCurve();

            Vector normalNormalised = normal.Normalise();

            //First - offseting each individual element
            List <ICurve> offsetCurves = new List <ICurve>();

            foreach (ICurve crv in subParts)
            {
                if (crv.IOffset(offset, normal, false, tolerance) != null)
                {
                    offsetCurves.Add(crv.IOffset(offset, normal, false, tolerance));
                }
            }

            int counter = 0;

            //removing curves that are on a wrong side of the main curve
            for (int i = 0; i < offsetCurves.Count; i++)
            {
                Point  sp        = offsetCurves[i].IStartPoint();
                Point  ep        = offsetCurves[i].IEndPoint();
                Point  mp        = offsetCurves[i].IPointAtParameter(0.5);
                Point  spOnCurve = curve.ClosestPoint(sp);
                Point  epOnCurve = curve.ClosestPoint(ep);
                Point  mpOnCurve = curve.ClosestPoint(mp);
                Vector sTan      = curve.TangentAtPoint(spOnCurve, tolerance);
                Vector eTan      = curve.TangentAtPoint(epOnCurve, tolerance);
                Vector mTan      = curve.TangentAtPoint(mpOnCurve, tolerance);
                Vector sCheck    = sp - spOnCurve;
                Vector eCheck    = ep - epOnCurve;
                Vector mCheck    = mp - mpOnCurve;
                Vector sCP       = sTan.CrossProduct(sCheck).Normalise();
                Vector eCP       = eTan.CrossProduct(eCheck).Normalise();
                Vector mCP       = mTan.CrossProduct(mCheck).Normalise();
                if (offset > 0)
                {
                    if (sCP.IsEqual(normalNormalised, tolerance) && eCP.IsEqual(normalNormalised, tolerance) && mCP.IsEqual(normalNormalised, tolerance))
                    {
                        offsetCurves.RemoveAt(i);
                        i--;
                        counter++;
                    }
                }
                else
                {
                    if (!sCP.IsEqual(normalNormalised, tolerance) && !eCP.IsEqual(normalNormalised, tolerance) && !mCP.IsEqual(normalNormalised, tolerance))
                    {
                        offsetCurves.RemoveAt(i);
                        i--;
                        counter++;
                    }
                }
            }

            //Again if there are only Line segments switching to polyline method as it is more reliable
            if (offsetCurves.All(x => x is Line))
            {
                Polyline polyline = new Polyline {
                    ControlPoints = curve.DiscontinuityPoints()
                };
                result.Curves.AddRange(polyline.Offset(offset, normal, tangentExtensions, tolerance).SubParts());
                return(result);
            }

            bool connectingError = false;

            //Filleting offset curves to create continuous curve
            for (int i = 0; i < offsetCurves.Count; i++)
            {
                int j;
                if (i == offsetCurves.Count - 1)
                {
                    if (isClosed)
                    {
                        j = 0;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    j = i + 1;
                }

                PolyCurve temp = offsetCurves[i].Fillet(offsetCurves[j], tangentExtensions, true, false, tolerance);
                if (temp == null) //trying to fillet with next curve
                {
                    offsetCurves.RemoveAt(j);

                    if (j == 0)
                    {
                        i--;
                    }

                    if (j == offsetCurves.Count)
                    {
                        j = 0;
                    }
                    temp = offsetCurves[i].Fillet(offsetCurves[j], tangentExtensions, true, false, tolerance);
                }

                if (!(temp == null)) //inserting filetted curves
                {
                    if (j != 0)
                    {
                        offsetCurves.RemoveRange(i, 2);
                        offsetCurves.InsertRange(i, temp.Curves);
                    }
                    else
                    {
                        offsetCurves.RemoveAt(i);
                        offsetCurves.RemoveAt(0);
                        offsetCurves.InsertRange(i - 1, temp.Curves);
                    }
                    i = i + temp.Curves.Count - 2;
                }
                else
                {
                    connectingError = true;
                }
            }

            //removing curves that are to close to the main curve
            for (int i = 0; i < offsetCurves.Count; i++)
            {
                if ((offsetCurves[i].IPointAtParameter(0.5).Distance(curve) + tolerance < Math.Abs(offset) &&
                     (offsetCurves[i].IStartPoint().Distance(curve) + tolerance < Math.Abs(offset) ||
                      offsetCurves[i].IEndPoint().Distance(curve) + tolerance < Math.Abs(offset))))
                {
                    PolyCurve temp = offsetCurves[((i - 1) + offsetCurves.Count) % offsetCurves.Count].Fillet(offsetCurves[(i + 1) % offsetCurves.Count], tangentExtensions, true, false, tolerance);
                    if (temp != null)
                    {
                        if (i == 0)
                        {
                            offsetCurves.RemoveRange(0, 2);
                            offsetCurves.RemoveAt(offsetCurves.Count - 1);
                            offsetCurves.InsertRange(0, temp.Curves);
                            i = temp.Curves.Count - 1;
                        }
                        else if (i == offsetCurves.Count - 1)
                        {
                            offsetCurves.RemoveRange(i - 1, 2);
                            offsetCurves.RemoveAt(0);
                            offsetCurves.InsertRange(offsetCurves.Count - 1, temp.Curves);
                            i = offsetCurves.Count - 1;
                        }
                        else
                        {
                            offsetCurves.RemoveRange(i - 1, 3);
                            offsetCurves.InsertRange(i - 1, temp.Curves);
                            i = i - 3 + temp.Curves.Count;
                        }
                    }

                    if (offsetCurves.Count < 1)
                    {
                        Reflection.Compute.ClearCurrentEvents();
                        Reflection.Compute.RecordError("Method failed to produce correct offset. Returning null.");
                        return(null);
                    }
                    counter++;
                }
            }

            Reflection.Compute.ClearCurrentEvents();

            if (connectingError)
            {
                Reflection.Compute.RecordWarning("Couldn't connect offset subCurves properly.");
            }

            if (offsetCurves.Count == 0)
            {
                Reflection.Compute.RecordError("Method failed to produce correct offset. Returning null.");
                return(null);
            }

            List <PolyCurve> resultList = Compute.IJoin(offsetCurves, tolerance);

            if (resultList.Count == 1)
            {
                result = resultList[0];
            }
            else
            {
                result.Curves = offsetCurves;
                Reflection.Compute.RecordWarning("Offset may be wrong. Please inspect the results.");
            }

            if (counter > 0)
            {
                Reflection.Compute.RecordWarning("Reduced " + counter + " line(s). Please inspect the results.");
            }

            if (result.IsSelfIntersecting(tolerance) || result.CurveIntersections(curve, tolerance).Count != 0)
            {
                Reflection.Compute.RecordWarning("Intersections occured. Please inspect the results.");
            }

            if (isClosed && !result.IsClosed(tolerance))
            {
                Reflection.Compute.RecordError("Final curve is not closed. Please inspect the results.");
            }

            return(result);
        }
Exemple #6
0
        /***************************************************/
        /**** Private methods                           ****/
        /***************************************************/

        private bool CreateCollection(IEnumerable <Panel> bhomPanels)
        {
            //Code for creating a collection of floors and walls in the software

            List <Panel> panels = bhomPanels.ToList();

            // Register Floor types
            IFloorType ramFloorType;
            IStories   ramStories;
            IStory     ramStory;

            //Create wall and floor lists with individual heights
            List <Panel>  wallPanels   = new List <Panel>();
            List <Panel>  floors       = new List <Panel>();
            List <double> panelHeights = new List <double>();
            List <Point>  panelPoints  = new List <Point>();

            // Split walls and floors and get all elevations
            foreach (Panel panel in panels)
            {
                double panelNormZ = panel.Normal().Z;

                //Split walls and floors
                if (Math.Abs(panelNormZ) < 0.707) // check normal against 45 degree slope
                {
                    wallPanels.Add(panel);
                }
                else
                {
                    floors.Add(panel);
                }
            }

            ramStories = m_Model.GetStories();

            #region Create Floors

            // Cycle through floors and create on story
            foreach (Panel panel in floors)
            {
                RAMId     RAMId           = new RAMId();
                string    name            = panel.Name;
                PolyCurve outlineExternal = panel.OutlineCurve();
                ramStory     = panel.GetStory(ramStories);
                ramFloorType = ramStory.GetFloorType();

                try
                {
                    // Set slab edges on FloorType in RAM for external edges
                    ISlabEdges ramSlabEdges    = ramFloorType.GetAllSlabEdges();
                    ISlabEdges ramOpeningEdges = ramFloorType.GetAllSlabOpenings();

                    // Get external and internal edges of floor panel
                    List <PolyCurve> panelOutlines   = new List <PolyCurve>();
                    List <PolyCurve> openingOutlines = new List <PolyCurve>();

                    Vector zDown = BH.Engine.Geometry.Create.Vector(0, 0, -1);

                    // RAM requires edges clockwise, flip if counterclockwise
                    PolyCurve cwOutline = (outlineExternal.IsClockwise(zDown) == false) ? outlineExternal.Flip() : outlineExternal;

                    List <ICurve> edgeCrvs = cwOutline.Curves;

                    foreach (ICurve crv in edgeCrvs)
                    {
                        Point startPt = crv.IStartPoint();
                        Point endPt   = crv.IEndPoint();
                        ramSlabEdges.Add(startPt.X.ToInch(), startPt.Y.ToInch(), endPt.X.ToInch(), endPt.Y.ToInch(), 0);
                    }

                    List <Opening> panelOpenings = panel.Openings;

                    foreach (Opening opening in panelOpenings)
                    {
                        PolyCurve outlineOpening = opening.OutlineCurve();
                        openingOutlines.Add(outlineOpening);
                    }

                    foreach (PolyCurve outline in openingOutlines)
                    {
                        // RAM requires edges clockwise, flip if counterclockwise
                        PolyCurve cwOpenOutline = (outline.IsClockwise(zDown) == false) ? outline.Flip() : outline;

                        if (!(outlineExternal.IsContaining(cwOpenOutline, false)))
                        {
                            cwOpenOutline = outlineExternal.BooleanIntersection(cwOpenOutline)[0];
                            Engine.Base.Compute.RecordWarning("Panel " + name + " opening intersects floor boundary. Boolean intersection was used to get opening extents on panel, confirm opening extents in RAM.");
                        }

                        List <ICurve> openEdgeCrvs = cwOpenOutline.Curves;

                        foreach (ICurve crv in openEdgeCrvs)
                        {
                            Point startPt = crv.IStartPoint();
                            Point endPt   = crv.IEndPoint();
                            ramOpeningEdges.Add(startPt.X.ToInch(), startPt.Y.ToInch(), endPt.X.ToInch(), endPt.Y.ToInch(), 0);
                        }
                    }

                    // Create Deck
                    List <Point> ctrlPoints = cwOutline.ControlPoints();

                    if (ctrlPoints.First() != ctrlPoints.Last())
                    {
                        ctrlPoints.Add(ctrlPoints.Last().DeepClone());
                    }

                    ISurfaceProperty srfProp = panel.Property;
                    int deckProplUID         = GetAdapterId <int>(srfProp);

                    //Add decks, then set deck points per outline
                    IDecks ramDecks = ramFloorType.GetDecks();
                    IDeck  ramDeck  = ramDecks.Add(deckProplUID, ctrlPoints.Count);

                    IPoints ramPoints = ramDeck.GetPoints();

                    // Create list of SCoordinates for floor outlines
                    List <SCoordinate> cornersExt = new List <SCoordinate>();

                    foreach (Point point in ctrlPoints)
                    {
                        SCoordinate cornerExt = point.ToRAM();
                        cornersExt.Add(cornerExt);
                    }

                    for (int k = 0; k < cornersExt.Count; k++)
                    {
                        ramPoints.Delete(k);
                        ramPoints.InsertAt(k, cornersExt[k]);
                    }

                    ramDeck.SetPoints(ramPoints);

                    // Add warning to report floors flattened to level as required for RAM
                    if (Math.Abs(panel.Normal().Z) < 1)
                    {
                        Engine.Base.Compute.RecordWarning("Panel " + name + " snapped to level " + ramStory.strLabel + ".");
                    }
                }
                catch
                {
                    CreateElementError("panel", name);
                }
            }
            #endregion

            #region Create Walls
            //Cycle through walls; if wall crosses level place at level
            foreach (Panel wallPanel in wallPanels)
            {
                string name = wallPanel.Name;

                try
                {
                    double thickness = 0.2; // default thickness
                    if (wallPanel.Property is ConstantThickness)
                    {
                        ConstantThickness prop = (ConstantThickness)wallPanel.Property;
                        thickness = prop.Thickness;
                    }

                    // Find outline of planar panel
                    PolyCurve    outline       = BH.Engine.Spatial.Query.OutlineCurve(wallPanel);
                    List <Point> wallPts       = outline.DiscontinuityPoints();
                    List <Point> sortedWallPts = wallPts.OrderBy(p => p.X).ToList();
                    Point        leftPt        = sortedWallPts.First();
                    Point        rtPt          = sortedWallPts.Last();
                    bool         downToRight   = leftPt.Y > rtPt.Y;

                    BoundingBox wallBounds = BH.Engine.Geometry.Query.Bounds(outline);
                    Point       wallMin    = wallBounds.Min;
                    Point       wallMax    = wallBounds.Max;
                    double      tempY      = wallMin.Y;

                    wallMin.Y = downToRight ? wallMax.Y : wallMin.Y;
                    wallMax.Y = downToRight ? tempY : wallMax.Y;

                    for (int i = 0; i < ramStories.GetCount(); i++)
                    {
                        ramStory = ramStories.GetAt(i);
                        // If wall crosses level, add wall to ILayoutWalls for that level
                        if (Math.Round(wallMax.Z.ToInch(), 0) >= ramStory.dElevation && Math.Round(wallMin.Z.ToInch(), 0) < ramStory.dElevation)
                        {
                            ramFloorType = ramStory.GetFloorType();

                            //Get ILayoutWalls of FloorType and add wall
                            ILayoutWalls ramLayoutWalls = ramFloorType.GetLayoutWalls();
                            ILayoutWall  ramLayoutWall  = ramLayoutWalls.Add(EMATERIALTYPES.EWallPropConcreteMat, wallMin.X.ToInch(), wallMin.Y.ToInch(), 0, 0, wallMax.X.ToInch(), wallMax.Y.ToInch(), 0, 0, thickness.ToInch());

                            //Set lateral
                            ramLayoutWall.eFramingType = EFRAMETYPE.MemberIsLateral;

                            IWalls ramWalls = ramLayoutWall.GetAssociatedStoryWalls();
                            IWall  ramWall  = ramWalls.GetAt(0);

                            // Find opening location, width, and height from outline and apply
                            foreach (Opening open in wallPanel.Openings)
                            {
                                PolyCurve   openOutline = open.OutlineCurve();
                                BoundingBox openBounds  = BH.Engine.Geometry.Query.Bounds(openOutline);
                                Point       openMin     = openBounds.Min;
                                Point       openMax     = openBounds.Max;

                                if ((openMin.Z.ToInch() >= ramStory.dElevation - ramStory.dFlrHeight) && (openMin.Z.ToInch() < ramStory.dElevation))
                                {
                                    IFinalWallOpenings ramWallOpenings = ramWall.GetFinalOpenings();

                                    int openOverlapCount = 0;

                                    for (int j = 0; i < ramWallOpenings.GetCount(); j++)
                                    {
                                        IFinalWallOpening testOpen   = ramWallOpenings.GetAt(j);
                                        IPoints           openingPts = testOpen.GetOpeningVertices();

                                        //Re-add first point to close Polygon
                                        IPoint      firstOPt    = openingPts.GetAt(0);
                                        SCoordinate firstOCoord = new SCoordinate();
                                        firstOPt.GetCoordinate(ref firstOCoord);
                                        openingPts.Add(firstOCoord);

                                        Polyline     wallOpeningOutline = openingPts.ToPolyline();
                                        List <Point> intPts             = wallOpeningOutline.ICurveIntersections(openOutline);
                                        if (wallOpeningOutline.IsContaining(openOutline) || openOutline.IsContaining(wallOpeningOutline) || intPts.Count > 0)
                                        {
                                            openOverlapCount += 1;
                                        }
                                    }

                                    if (openOverlapCount == 0)
                                    {
                                        //Get opening on wall extents
                                        if (!(outline.IsContaining(openOutline, false)))
                                        {
                                            openOutline = outline.BooleanIntersection(openOutline)[0];
                                            Engine.Base.Compute.RecordWarning("Panel " + name + " opening intersects wall boundary. Boolean intersection was used to get opening extents on panel.");
                                        }

                                        Point  closestOpenPt = BH.Engine.Geometry.Query.ClosestPoint(wallMin, openOutline.ControlPoints());
                                        double distX         = Math.Sqrt(Math.Pow(closestOpenPt.X - wallMin.X, 2) + Math.Pow(closestOpenPt.Y - wallMin.Y, 2));
                                        double distZinch     = openBounds.Min.Z.ToInch() - (ramStory.dElevation - ramStory.dFlrHeight);
                                        double openWidth     = Math.Sqrt(Math.Pow(openBounds.Max.X - openBounds.Min.X, 2) + Math.Pow(openBounds.Max.Y - openBounds.Min.Y, 2));
                                        double openHt        = openBounds.Max.Z - openBounds.Min.Z;

                                        //Add opening to RAM
                                        IRawWallOpenings ramRawWallOpenings = ramWall.GetRawOpenings();
                                        ramRawWallOpenings.Add(EDA_MEMBER_LOC.eBottomStart, distX.ToInch(), distZinch, openWidth.ToInch(), openHt.ToInch());
                                    }
                                }
                            }
                        }
                    }
                }
                catch
                {
                    CreateElementError("panel", name);
                }
            }
            #endregion

            //Save file
            m_IDBIO.SaveDatabase();

            return(true);
        }