예제 #1
0
        public Result CalculateLoads(Document doc, ref int totalLoops, ref StringBuilder debug)
        {
            try
            {
                //Log
                int nrTotal = 0;

                //Get the transform
                Transform trfO = Origo.GetTransform();
                Transform trf  = trfO.Inverse;

                //Get the list of boundaries and walls (to simplify the synthax)
                HashSet <CurveElement>   Bd         = BoundaryData.BoundaryLines;
                HashSet <FamilyInstance> Walls      = WallsAlong.WallSymbols.ToHashSet();
                HashSet <FamilyInstance> Beams      = BearingBeams.WallSymbols.ToHashSet();
                HashSet <Element>        BdAndWalls = new HashSet <Element>();
                BdAndWalls.UnionWith(Bd);
                BdAndWalls.UnionWith(Walls);
                BdAndWalls.UnionWith(Beams);

                //I know it's messy, but beams need to be in walls too, apparently
                Walls.UnionWith(Beams);

                HashSet <LoadArea> LoadAreas = LoadData.LoadAreas;

                //Roof load intensity
                double roofLoadIntensity = double.Parse(mySettings.Default.roofLoadIntensity, CultureInfo.InvariantCulture);

                //Create a list of ALL X Points of Interest ie. Start and End points
                IList <XYZ> allPoiX = new List <XYZ>();
                foreach (Element el in BdAndWalls)
                {
                    allPoiX.Add(StartPoint(el, trf));
                    allPoiX.Add(EndPoint(el, trf));
                }
                //Clean list of duplicates and sort by value of X
                allPoiX = allPoiX.DistinctBy(pt => pt.X.FtToMillimeters()).OrderBy(pt => pt.X.FtToMillimeters()).ToList();

                foreach (FamilyInstance fi in Walls)
                {
                    //Debug
                    debug.Append("\n" + fi.Id + "\n");

                    //Initialize variables
                    double load      = 0;
                    double totalArea = 0;

                    //Determine the start X
                    double Xmin = StartPoint(fi, trf).X;

                    //Determine the end X
                    double Xmax = EndPoint(fi, trf).X;

                    //The y of the wall
                    double Ycur = StartPoint(fi, trf).Y;

                    //Længde af væggen
                    double length = (Xmax - Xmin).FtToMeters();

                    //TODO: New implementation -- start here

                    //Determine the POIX in scope of the wall (POIX = Point Of Interest on X axis)
                    var poixInScope = (from XYZ pt in allPoiX
                                       where pt.X.FtToMillimeters() >= Xmin.FtToMillimeters() &&
                                       pt.X.FtToMillimeters() <= Xmax.FtToMillimeters()
                                       select pt).ToList();

                    //Iterate through the load areas
                    for (int i = 0; i < poixInScope.Count - 1; i++) //<- -1 because theres 1 less areas than points
                    {
                        //Determine the X value in the middle of the span to be able to get relevant walls
                        double x1 = poixInScope[i].X;
                        double x2 = poixInScope[i + 1].X;
                        double xC = (x1 + (x2 - x1) / 2).FtToMillimeters();

                        //Determine relevant walls (that means the walls which are crossed by the current Xcentre value iteration)
                        var wallsX = (from FamilyInstance fin in Walls
                                      where StartPoint(fin, trf).X.FtToMillimeters() <= xC &&
                                      EndPoint(fin, trf).X.FtToMillimeters() >= xC
                                      select fin).OrderBy(x => StartPoint(x, trf).Y); //<- Not using Descending because the list is defined from up to down

                        //Determine relevant boundaries (that means the boundaries which are crossed by the current Xcentre value iteration)
                        var boundaryX = (from CurveElement cue in Bd
                                         where StartPoint(cue, trf).X.FtToMillimeters() <= xC &&
                                         EndPoint(cue, trf).X.FtToMillimeters() >= xC
                                         select cue).ToHashSet();

                        //First handle the walls
                        //Create a linked list to be able select previous and next elements in sequence
                        var wallsXlinked = new LinkedList <FamilyInstance>(wallsX);
                        var node         = wallsXlinked.Find(fi);
                        var wallPositive = node?.Next?.Value;
                        var wallNegative = node?.Previous?.Value;

                        //Select boundaries if no walls found at location
                        CurveElement bdPositive = null, bdNegative = null;
                        if (wallPositive == null)
                        {
                            bdPositive = boundaryX.MaxBy(x => StartPoint(x, trf).Y);
                        }
                        if (wallNegative == null)
                        {
                            bdNegative = boundaryX.MinBy(x => StartPoint(x, trf).Y);
                        }

                        //Flow control
                        bool isEdgePositive = false, isEdgeNegative = false; //<-- Indicates if the wall is on the boundary

                        //Detect edge cases
                        if (wallPositive == null && StartPoint(bdPositive, trf).Y.FtToMillimeters().Equals(Ycur.FtToMillimeters()))
                        {
                            isEdgePositive = true;
                        }
                        if (wallNegative == null && StartPoint(bdNegative, trf).Y.FtToMillimeters().Equals(Ycur.FtToMillimeters()))
                        {
                            isEdgeNegative = true;
                        }

                        //Prepare for roof load: if edge case detected select both boundaries
                        if (isEdgePositive || isEdgeNegative)
                        {
                            if (bdPositive == null)
                            {
                                bdPositive = boundaryX.MaxBy(x => StartPoint(x, trf).Y);
                            }
                            if (bdNegative == null)
                            {
                                bdNegative = boundaryX.MinBy(x => StartPoint(x, trf).Y);
                            }

                            double widthRoofLoad = (StartPoint(bdPositive, trf).Y - StartPoint(bdNegative, trf).Y) / 2;
                            double roofLoadArea  = (widthRoofLoad * (x2 - x1)).SqrFeetToSqrMeters();
                            double roofLoad      = roofLoadIntensity * roofLoadArea;
                            load += roofLoad; //Write to the overall load variable
                        }

                        //Process the positive and negative side
                        //Declare Y values
                        double yP, yN;

                        //Declare combining list for vertices
                        List <XYZ> vertices = new List <XYZ>();
                        //Add points along the wall if one is edge case
                        if (isEdgePositive || isEdgeNegative)
                        {
                            vertices.Add(NormPoint(x1.Round4(), Ycur.Round4(), trfO, LoadData.GS_View));
                            vertices.Add(NormPoint(x2.Round4(), Ycur.Round4(), trfO, LoadData.GS_View));
                        }


                        #region Positive side

                        if (!isEdgePositive)
                        {
                            //Calculate Y values
                            if (wallPositive != null)
                            {
                                yP = Ycur + (StartPoint(wallPositive, trf).Y - Ycur) / 2;
                            }
                            else
                            {
                                yP = Ycur + (StartPoint(bdPositive, trf).Y - Ycur) / 2;
                            }

                            //Create points from the X and Y values
                            XYZ PxP1 = NormPoint(x1.Round4(), yP.Round4(), trfO, LoadData.GS_View);
                            XYZ PxP2 = NormPoint(x2.Round4(), yP.Round4(), trfO, LoadData.GS_View);

                            //Create a list of vertices to feed the solid builder
                            vertices.Add(PxP1);
                            vertices.Add(PxP2);

                            nrTotal++;
                        }

                        #endregion


                        #region Negative side

                        if (!isEdgeNegative)
                        {
                            if (wallNegative != null)
                            {
                                yN = StartPoint(wallNegative, trf).Y + (Ycur - StartPoint(wallNegative, trf).Y) / 2;
                            }
                            else
                            {
                                yN = StartPoint(bdNegative, trf).Y + (Ycur - StartPoint(bdNegative, trf).Y) / 2;
                            }

                            //Create points from the X and Y values
                            XYZ PxN1 = NormPoint(x1.Round4(), yN.Round4(), trfO, LoadData.GS_View);
                            XYZ PxN2 = NormPoint(x2.Round4(), yN.Round4(), trfO, LoadData.GS_View);

                            //Create a list of vertices to feed the solid builder
                            vertices.Add(PxN1);
                            vertices.Add(PxN2);

                            nrTotal++;
                        }
                        #endregion

                        //Create a list of vertices
                        vertices = vertices.DistinctBy(xyz => new { X = xyz.X.Round4(), Y = xyz.Y.Round4() }).ToList();
                        vertices = tr.ConvexHull(vertices);

                        //Create a path from the Clipper framework
                        Path wallLoadPath = CreatePath(vertices);
                        //The defined precision of the Clipper objects
                        long precision = 10000;

                        //Debug
                        //debug.Append((Clipper.Area(wallLoadPath) / (precision * precision)).SqrFeetToSqrMeters() + "+\n");

                        //Iterate through the load areas and intersect them with wall load areas
                        foreach (LoadArea la in LoadAreas)
                        {
                            Paths   solution = new Paths();
                            Clipper c        = new Clipper();
                            c.AddPath(wallLoadPath, PolyType.ptClip, true);
                            c.AddPath(la.Path, PolyType.ptSubject, true);
                            c.Execute(ClipType.ctIntersection, solution);
                            foreach (Path path in solution)
                            {
                                double intArea = (Clipper.Area(path) / (precision * precision)).SqrFeetToSqrMeters();
                                //debug.Append(intArea + " " + la.Load + " " + la.Load * intArea + "\n");
                                //debug.Append((Clipper.Area(la.Path)/(precision*precision)).SqrFeetToSqrMeters()+"\n");
                                load      += intArea * la.Load;
                                totalArea += intArea;
                            }
                        }
                    }
                    fi.LookupParameter("GS_Load").Set(load / length);
                    debug.Append(length + " " + totalArea + " " + load + "\n" + load / length + "\n");
                }

                totalLoops = nrTotal;
                return(Result.Succeeded);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw new Exception(e.Message);
                //return Result.Succeeded;
            }
        }
예제 #2
0
        public Result DrawLoadAreas(Document doc)
        {
            try
            {
                //Get the transform
                Transform trfO = Origo.GetTransform();
                Transform trf  = trfO.Inverse;

                //Get the list of boundaries and walls (to simplify the synthax)
                HashSet <CurveElement>   Bd    = BoundaryData.BoundaryLines;
                HashSet <FamilyInstance> Walls = WallsAlong.WallSymbols.ToHashSet();

                //The analysis proceeds in steps
                double step = ((double)mySettings.Default.integerStepSize).MmToFeet();

                foreach (FamilyInstance fi in Walls)
                {
                    //Determine the start X
                    double Xmin = StartPoint(fi, trf).X;

                    //Determine the end X
                    double Xmax = EndPoint(fi, trf).X;

                    //The y of the wall
                    double Ycur = StartPoint(fi, trf).Y;

                    ////Divide the largest X value by the step value to determine the number iterations in X direction
                    int nrOfX = (int)Math.Floor((Xmax - Xmin) / step);

                    //Debug
                    double[] X, Y; X = new double[4]; Y = new double[4];

                    //Iterate through the length of the current wall analyzing the load
                    for (int i = 0; i < nrOfX; i++)
                    {
                        //Current x value
                        double x1 = Xmin + i * step;
                        double x2 = Xmin + (i + 1) * step;
                        double xC = x1 + step / 2;

                        //Debug
                        if (i == 0)
                        {
                            X[0] = x1;
                            X[2] = x1;
                        }
                        X[1] = x2;
                        X[3] = x2;

                        //Determine relevant walls (that means the walls which are crossed by the current X value iteration)
                        var wallsX = (from FamilyInstance fin in Walls
                                      where StartPoint(fin, trf).X <= xC && EndPoint(fin, trf).X >= xC
                                      select fin).OrderBy(x => StartPoint(x, trf).Y); //<- Not using Descending because the list is defined from up to down

                        //Determine relevant walls (that means the walls which are crossed by the current X value iteration)
                        var boundaryX = (from CurveElement cue in Bd
                                         where StartPoint(cue, trf).X <= xC && EndPoint(cue, trf).X >= xC
                                         select cue).ToHashSet();

                        //First handle the walls
                        var wallsXlinked = new LinkedList <FamilyInstance>(wallsX);
                        var listNode1    = wallsXlinked.Find(fi);
                        var wallPositive = listNode1?.Next?.Value;
                        var wallNegative = listNode1?.Previous?.Value;

                        //Select boundaries if no walls found at location
                        CurveElement bdPositive = null, bdNegative = null;
                        if (wallPositive == null)
                        {
                            bdPositive = boundaryX.MaxBy(x => StartPoint(x, trf).Y);
                        }
                        if (wallNegative == null)
                        {
                            bdNegative = boundaryX.MinBy(x => StartPoint(x, trf).Y);
                        }

                        //Flow control
                        bool isEdgePositive = false, isEdgeNegative = false; //<-- Indicates if the wall is on the boundary

                        //Detect edge cases
                        if (wallPositive == null && StartPoint(bdPositive, trf).Y.FtToMillimeters().Equals(Ycur.FtToMillimeters()))
                        {
                            isEdgePositive = true;
                        }
                        if (wallNegative == null && StartPoint(bdNegative, trf).Y.FtToMillimeters().Equals(Ycur.FtToMillimeters()))
                        {
                            isEdgeNegative = true;
                        }

                        //Init loop counters
                        int nrOfYPos, nrOfYNeg;

                        //Determine number of iterations in Y direction POSITIVE handling all cases
                        //The 2* multiplier on step makes sure that iteration only happens on the half of the span
                        if (wallPositive != null)
                        {
                            nrOfYPos = (int)Math.Floor((StartPoint(wallPositive, trf).Y - Ycur) / (2 * step));
                        }
                        else if (isEdgePositive)
                        {
                            nrOfYPos = 0;
                        }
                        else
                        {
                            nrOfYPos = (int)Math.Floor((StartPoint(bdPositive, trf).Y - Ycur) / (2 * step));
                        }

                        //Determine number of iterations in Y direction NEGATIVE handling all cases
                        //The 2* multiplier on step makes sure that iteration only happens on the half of the span
                        if (wallNegative != null)
                        {
                            nrOfYNeg = (int)Math.Floor((-StartPoint(wallNegative, trf).Y + Ycur) / (2 * step));
                        }
                        else if (isEdgeNegative)
                        {
                            nrOfYNeg = 0;
                        }
                        else
                        {
                            nrOfYNeg = (int)Math.Floor((-StartPoint(bdNegative, trf).Y + Ycur) / (2 * step));
                        }

                        //Iterate through the POSITIVE side
                        for (int j = 0; j < nrOfYPos; j++)
                        {
                            //Current y value
                            double y1 = Ycur + j * step;
                            double y2 = Ycur + (j + 1) * step;

                            //Debug
                            if (i == 0 && j == nrOfYPos - 1)
                            {
                                Y[0] = y2;
                            }
                            if (j == nrOfYPos - 1)
                            {
                                Y[1] = y2;
                                if (!Y[0].FtToMillimeters().Equals(Y[1].FtToMillimeters()))
                                {
                                    CreateLoadAreaBoundaries(doc, X[0], X[1], Y[0], trfO);
                                    X[0] = x1; Y[0] = y2;
                                }
                                if (i == nrOfX - 1)
                                {
                                    CreateLoadAreaBoundaries(doc, X[0], X[1], Y[0], trfO);
                                }
                            }
                        }

                        //Iterate through the NEGATIVE side
                        for (int k = 0; k < nrOfYNeg; k++)
                        {
                            //Current y value
                            double y1 = Ycur - k * step;
                            double y2 = Ycur - (k + 1) * step;

                            //Debug
                            if (i == 0 && k == nrOfYNeg - 1)
                            {
                                Y[2] = y2;
                            }
                            if (k == nrOfYNeg - 1)
                            {
                                Y[3] = y2;
                                if (!Y[2].FtToMillimeters().Equals(Y[3].FtToMillimeters()))
                                {
                                    CreateLoadAreaBoundaries(doc, X[2], X[3], Y[2], trfO);
                                    X[2] = x1; Y[2] = y2;
                                }
                                if (i == nrOfX - 1)
                                {
                                    CreateLoadAreaBoundaries(doc, X[2], X[3], Y[2], trfO);
                                }
                            }
                        }
                    }
                }
                return(Result.Succeeded);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw new Exception(e.Message);
            }
        }