public static SpaceBoundary[] SpaceBoundaryFromRevitArea(ADSK.Area area, Document doc, View view = null)
        {
            if (view == null)
            {
                view = GetViewWhereElemIsVisible(doc, area);
            }

            var geom = area.get_Geometry(new Options()
            {
                View = view
            });
            var solid = geom.Where(g => typeof(ADSK.Solid) == g.GetType()).Cast <ADSK.Solid>().Where(s => s != null);
            var face  = solid.First().Faces.get_Item(0) as PlanarFace;

            var boundaries = new List <SpaceBoundary>();

            foreach (var p in face.GetProfiles(true))
            {
                var boundary = new SpaceBoundary(p,
                                                 new Elements.Geometry.Transform(),
                                                 BuiltInMaterials.Default,
                                                 null,
                                                 false,
                                                 Guid.NewGuid(),
                                                 "");
                boundaries.Add(boundary);
            }
            return(boundaries.ToArray());
        }
Пример #2
0
        private static void SplitZones(SpacePlanningZonesInputs input, double corridorWidth, LevelVolume lvl, List <Element> spaceBoundaries, List <Profile> corridorProfiles, Vector3 pt, bool addCorridor = true)
        {
            var containingBoundary = spaceBoundaries.OfType <SpaceBoundary>().FirstOrDefault(b => b.Boundary.Contains(pt));

            if (containingBoundary != null)
            {
                if (input.Overrides != null)
                {
                    var spaceOverrides = input.Overrides.ProgramAssignments.FirstOrDefault(s => s.Identity.IndividualCentroid.IsAlmostEqualTo(containingBoundary.Boundary.Perimeter.Centroid()));
                    if (spaceOverrides != null)
                    {
                        containingBoundary.Name = spaceOverrides.Value.ProgramType;
                    }
                }
                spaceBoundaries.Remove(containingBoundary);
                var perim = containingBoundary.Boundary.Perimeter;
                pt.DistanceTo(perim, out var cp);
                var            line      = new Line(pt, cp);
                var            extension = line.ExtendTo(containingBoundary.Boundary);
                List <Profile> newSbs    = new List <Profile>();
                if (addCorridor)
                {
                    var corridorShape             = extension.ToPolyline(1).Offset(corridorWidth / 2, EndType.Square);
                    var csAsProfiles              = corridorShape.Select(s => new Profile(s));
                    var corridorShapesIntersected = Profile.Intersection(new[] { containingBoundary.Boundary }, csAsProfiles);
                    corridorProfiles.AddRange(corridorShapesIntersected);
                    newSbs = Profile.Difference(new[] { containingBoundary.Boundary }, csAsProfiles);
                }
                else
                {
                    newSbs = Profile.Split(new[] { containingBoundary.Boundary }, new[] { extension.ToPolyline(1) }, Vector3.EPSILON);
                }
                spaceBoundaries.AddRange(newSbs.Select(p => SpaceBoundary.Make(p, containingBoundary.Name, containingBoundary.Transform, lvl.Height)));
            }
        }
Пример #3
0
        public static SpaceBoundary[] SpaceBoundaries(this List <BHE.Panel> spaceBoundaries, List <BHE.Panel> uniqueBEs)
        {
            List <Polyloop>     pLoops = new List <Polyloop>();
            List <BHG.Polyline> panels = spaceBoundaries.Select(x => x.Polyline()).ToList();

            foreach (BHG.Polyline pLine in panels)
            {
                if (BH.Engine.Environment.Query.NormalAwayFromSpace(pLine, spaceBoundaries))
                {
                    pLoops.Add(BH.Engine.XML.Convert.ToGBXML(pLine));
                }
                else
                {
                    pLoops.Add(BH.Engine.XML.Convert.ToGBXML(pLine.Flip()));
                }
            }

            SpaceBoundary[] boundaries = new SpaceBoundary[pLoops.Count];

            for (int x = 0; x < pLoops.Count; x++)
            {
                PlanarGeometry planarGeom = new PlanarGeometry();
                planarGeom.PolyLoop = pLoops[x];
                planarGeom.ID       = "pGeom" + Guid.NewGuid().ToString().Replace("-", "").Substring(0, 10);
                boundaries[x]       = new SpaceBoundary {
                    PlanarGeometry = planarGeom
                };

                //Get the ID from the referenced element
                boundaries[x].SurfaceIDRef = "Panel-" + uniqueBEs.FindIndex(i => i.BHoM_Guid == spaceBoundaries[x].BHoM_Guid).ToString();
            }

            return(boundaries);
        }
Пример #4
0
 static public SpaceBoundary MakeSpaceBoundary(SpaceBoundary sb, List <List <double> > points, int surfacecount)
 {
     sb.surfaceIdRef            = "su-" + surfacecount.ToString();
     sb.PlanarGeometry          = new PlanarGeometry();
     sb.PlanarGeometry.PolyLoop = new PolyLoop();
     sb.PlanarGeometry.PolyLoop = makePolyLoopsFromDbleList(sb.PlanarGeometry.PolyLoop, points);
     return(sb);
 }
Пример #5
0
        public static SpaceBoundary TogbXML_SpaceBoundary(this Panel panel, double tolerance = Core.Tolerance.MicroDistance)
        {
            if (panel == null)
            {
                return(null);
            }

            Geometry.Spatial.Face3D face3D = panel.PlanarBoundary3D.GetFace3D();
            if (face3D == null)
            {
                return(null);
            }

            SpaceBoundary spaceBoundary = new SpaceBoundary();

            spaceBoundary.surfaceIdRef   = Core.gbXML.Query.Id(panel, typeof(Surface));
            spaceBoundary.PlanarGeometry = face3D.TogbXML(tolerance);

            return(spaceBoundary);
        }
        public static List <Space> MakeSpacesFromEPObj(List <EPObj.MemorySafe_Spaces> myspace)
        {
            List <Space> retspaces  = new List <Space>();
            int          spacecount = 0;

            foreach (EPObj.MemorySafe_Spaces space in myspace)
            {
                //foreach Space space in your ListofSpaces
                Space zespace = new Space();
                zespace.id = "Space-1";
                zespace.lightScheduleIdRef     = "lightSchedule-1";
                zespace.equipmentScheduleIdRef = "equipmentSchedule-1";
                zespace.peopleScheduleIdRef    = "peopleSchedule-1";
                zespace.conditionType          = "HeatedAndCooled";
                zespace.buildingStoreyIdRef    = "bldg-story-1";
                zespace.Name            = "Test Space-" + spacecount;
                zespace.peoplenum       = 12;
                zespace.totalpeoplegain = 450;
                zespace.senspeoplegain  = 250;
                zespace.latpeoplegain   = 200;
                zespace.PeopleHeatGains = new PeopleHeatGain[3];
                zespace.lpd             = 1.2;
                zespace.epd             = 1.5;
                zespace.Area            = 2450;
                zespace.Volume          = 24500;
                zespace.PlanarGeo       = new PlanarGeometry();
                zespace.ShellGeo        = new ShellGeometry();


                PeopleNumber pn = new PeopleNumber();
                pn.unit = peopleNumberUnitEnum.NumberOfPeople;

                string people = gb.FormatDoubleToString(zespace.peoplenum);
                pn.valuefield        = people;
                zespace.PeopleNumber = pn;

                PeopleHeatGain phg = new PeopleHeatGain();
                phg.unit         = peopleHeatGainUnitEnum.BtuPerHourPerson;
                phg.heatGainType = peopleHeatGainTypeEnum.Total;
                string totalpopload = gb.FormatDoubleToString(zespace.totalpeoplegain);
                phg.value = totalpopload;
                zespace.PeopleHeatGains[0] = phg;

                PeopleHeatGain shg = new PeopleHeatGain();
                shg.unit         = peopleHeatGainUnitEnum.BtuPerHourPerson;
                shg.heatGainType = peopleHeatGainTypeEnum.Sensible;
                string senspopload = gb.FormatDoubleToString(zespace.senspeoplegain);
                shg.value = senspopload;
                zespace.PeopleHeatGains[1] = shg;

                PeopleHeatGain lhg = new PeopleHeatGain();
                lhg.unit         = peopleHeatGainUnitEnum.BtuPerHourPerson;
                lhg.heatGainType = peopleHeatGainTypeEnum.Latent;
                string latpopload = gb.FormatDoubleToString(zespace.latpeoplegain);
                lhg.value = latpopload;
                zespace.PeopleHeatGains[2] = lhg;

                LightPowerPerArea lpd = new LightPowerPerArea();
                lpd.unit = powerPerAreaUnitEnum.WattPerSquareFoot;
                lpd.lpd  = gb.FormatDoubleToString(zespace.lpd);
                zespace.LightPowerPerArea = lpd;

                EquipPowerPerArea epd = new EquipPowerPerArea();
                epd.unit = powerPerAreaUnitEnum.WattPerSquareFoot;
                epd.epd  = gb.FormatDoubleToString(zespace.epd);
                zespace.EquipPowerPerArea = epd;

                Area spacearea = new Area();
                spacearea.val     = gb.FormatDoubleToString(zespace.Area);
                zespace.spacearea = spacearea;

                Volume spacevol = new Volume();
                spacevol.val     = gb.FormatDoubleToString(zespace.Volume);
                zespace.spacevol = spacevol;

                //same as the planar geometry of the floor planes above
                PlanarGeometry spaceplpoly = new PlanarGeometry();
                //get a list of points that makes up the polyloop
                List <List <double> > spacepoints = prod.MakeFakeList(3);
                //make polyloop with points
                spaceplpoly.PolyLoop = new PolyLoop();
                spaceplpoly.PolyLoop = prod.makePolyLoopsFromDbleList(spaceplpoly.PolyLoop, spacepoints);
                zespace.PlanarGeo    = spaceplpoly;
                //@@
                //ShellGeometry
                //similar to planar geometry, but with more planes
                ShellGeometry sg = new ShellGeometry();
                sg.unit        = lengthUnitEnum.Feet;
                sg.id          = "sg" + space.name;
                sg.ClosedShell = new ClosedShell();
                //up to 100 surfaces per space?  base on the space instance surfaces
                sg.ClosedShell.PolyLoops = new PolyLoop[space.spaceSurfaces.Count()];
                //I would have a list of surface elements that make up the space surfaces.
                //each surface would consist of a series of points that defines the surface.
                for (int i = 0; i < space.spaceSurfaces.Count(); i++)
                {
                    //get points from the space surfaces
                    List <List <double> > epluspoints = new List <List <double> >();
                    epluspoints = EnergyPlusClass.GetCoordinDoubles(space.spaceSurfaces[i].SurfaceCoords);
                    sg.ClosedShell.PolyLoops[i] = new PolyLoop();
                    sg.ClosedShell.PolyLoops[i] = prod.makePolyLoopsFromDbleList(sg.ClosedShell.PolyLoops[i], epluspoints);
                }
                zespace.ShellGeo = sg;

                zespace.cadid    = new CADObjectId();
                zespace.cadid.id = "990099-" + spacecount;
                //make surface boundaries..special code needed so that space boundaries are not duplicated...
                //option 1 : the surfaces already declared as internal somehow and how shared.
                //option 2:  the api tries to figure it out
                zespace.spbound = new SpaceBoundary[space.spaceSurfaces.Count()];
                int psurfacecount = 0;
                for (int i = 0; i < space.spaceSurfaces.Count(); i++)
                {
                    //get points from the space surfaces
                    List <List <double> > epluspoints = new List <List <double> >();
                    epluspoints = EnergyPlusClass.GetCoordinDoubles(space.spaceSurfaces[i].SurfaceCoords);
                    //if surface is exterior
                    SpaceBoundary sb = new SpaceBoundary();
                    zespace.spbound[i] = prod.MakeSpaceBoundary(sb, epluspoints, psurfacecount);

                    psurfacecount++;
                    //else if surface is interior and it has not been listed before
                    //then do the same
                    //else do nothing because it is interior and it has already been listed


                    //I also would like to keep track of all the surfaces that I create to better prepare me for the surface definition
                    uniquesurf.Add(zespace.spbound[i].PlanarGeometry);
                    //make a dictionary that stores the name of a surface and its planar geometry?
                    uniqueplanes.Add(zespace.spbound[i].surfaceIdRef, zespace.spbound[i].PlanarGeometry);
                    //make a dictionary that stores the name of a surface and create a surface as the value

                    Surface newsurface = new Surface();
                    //this took a lot of customization...a user would have to make their own code to attach to my object here
                    newsurface = prod.SetUpSurfaceFromIDF(space.spaceSurfaces[i], zespace.spbound[i].PlanarGeometry);
                    uniquesurfaces.Add(zespace.spbound[i].surfaceIdRef, newsurface);
                }


                retspaces.Add(zespace);
                spacecount++;
            }
            return(retspaces);
        }
Пример #7
0
        /// <summary>
        /// The OpenOfficeLayout function.
        /// </summary>
        /// <param name="model">The input model.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A OpenOfficeLayoutOutputs instance containing computed results and the model with any new elements.</returns>
        public static OpenOfficeLayoutOutputs Execute(Dictionary <string, Model> inputModels, OpenOfficeLayoutInputs input)
        {
            var catalog = JsonConvert.DeserializeObject <ContentCatalog>(File.ReadAllText("./catalog.json"));

            var spacePlanningZones = inputModels["Space Planning Zones"];
            var levels             = spacePlanningZones.AllElementsOfType <LevelElements>();
            var deskCount          = 0;

            var configJson    = File.ReadAllText("OpenOfficeDeskConfigurations.json");
            var configs       = JsonConvert.DeserializeObject <SpaceConfiguration>(configJson);
            var defaultConfig = configs[Hypar.Model.Utilities.GetStringValueFromEnum(input.DeskType)];

            var desksPerInstance = input.DeskType == OpenOfficeLayoutInputsDeskType.Enclosed_Pair || input.DeskType == OpenOfficeLayoutInputsDeskType.Double_Desk ? 2 : 1;

            var output = new OpenOfficeLayoutOutputs();

            var overridesByCentroid = new Dictionary <Guid, SpaceSettingsOverride>();

            foreach (var spaceOverride in input.Overrides?.SpaceSettings ?? new List <SpaceSettingsOverride>())
            {
                var matchingBoundary = levels.SelectMany(l => l.Elements).OfType <SpaceBoundary>().OrderBy(ob => ((JObject)ob.AdditionalProperties["ParentCentroid"]).ToObject <Vector3>().DistanceTo(spaceOverride.Identity.ParentCentroid)).First();
                if (overridesByCentroid.ContainsKey(matchingBoundary.Id))
                {
                    var mbCentroid = ((JObject)matchingBoundary.AdditionalProperties["ParentCentroid"]).ToObject <Vector3>();
                    if (overridesByCentroid[matchingBoundary.Id].Identity.ParentCentroid.DistanceTo(mbCentroid) > spaceOverride.Identity.ParentCentroid.DistanceTo(mbCentroid))
                    {
                        overridesByCentroid[matchingBoundary.Id] = spaceOverride;
                    }
                }
                else
                {
                    overridesByCentroid.Add(matchingBoundary.Id, spaceOverride);
                }
            }

            foreach (var lvl in levels)
            {
                var corridors        = lvl.Elements.OfType <Floor>();
                var corridorSegments = corridors.SelectMany(p => p.Profile.Segments());
                var officeBoundaries = lvl.Elements.OfType <SpaceBoundary>().Where(z => z.Name == "Open Office");
                foreach (var ob in officeBoundaries)
                {
                    // create a boundary we can use to override individual groups of desks. It's sunk slightly so that, if floors are on, you don't see it.
                    var overridableBoundary = new SpaceBoundary(ob.Boundary, ob.Cells, ob.Transform.Concatenated(new Transform(0, 0, -0.05)), ob.Material, new Representation(new[] { new Lamina(ob.Boundary.Perimeter, false) }), false, Guid.NewGuid(), "DeskArea");
                    overridableBoundary.AdditionalProperties.Add("ParentCentroid", (ob.AdditionalProperties["ParentCentroid"] as JObject).ToObject <Vector3>());
                    overridableBoundary.AdditionalProperties.Add("Desk Type", Hypar.Model.Utilities.GetStringValueFromEnum(input.DeskType));
                    output.Model.AddElement(overridableBoundary);
                    var  spaceBoundary        = ob.Boundary;
                    Line orientationGuideEdge = FindEdgeAdjacentToCorridor(spaceBoundary.Perimeter, corridorSegments);
                    var  orientationTransform = new Transform(Vector3.Origin, orientationGuideEdge.Direction(), Vector3.ZAxis);
                    var  boundaryCurves       = new List <Polygon>();
                    boundaryCurves.Add(spaceBoundary.Perimeter);
                    boundaryCurves.AddRange(spaceBoundary.Voids ?? new List <Polygon>());
                    Grid2d grid;
                    try
                    {
                        grid = new Grid2d(boundaryCurves, orientationTransform);
                    }
                    catch
                    {
                        Console.WriteLine("Something went wrong creating a grid.");
                        continue;
                    }

                    var selectedConfig = defaultConfig;
                    if (overridesByCentroid.ContainsKey(ob.Id))
                    {
                        var spaceOverride = overridesByCentroid[ob.Id];
                        selectedConfig = configs[Hypar.Model.Utilities.GetStringValueFromEnum(spaceOverride.Value.DeskType)];
                        overridableBoundary.AdditionalProperties["Desk Type"] = Hypar.Model.Utilities.GetStringValueFromEnum(spaceOverride.Value.DeskType);
                    }

                    var aisleWidth = 1.0;
                    grid.V.DivideByPattern(new[] { ("Desk", selectedConfig.Width), ("Desk", selectedConfig.Width), ("Desk", selectedConfig.Width), ("Desk", selectedConfig.Width), ("Aisle", aisleWidth) }, PatternMode.Cycle, FixedDivisionMode.RemainderAtBothEnds);
Пример #8
0
        public static List<SpaceBoundary> GetSpaceBoundaryList(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm)
        {

            
            List<SpaceBoundary> sbList = new List<SpaceBoundary>();
            try
            {
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:SpaceBoundary", gbXMLnsm);
                foreach (XmlNode node in nodes)
                {
                    SpaceBoundary sb = new SpaceBoundary();
                    string spaceboundaryId;
                    spaceboundaryId = node.Attributes[0].Value.ToString();
                    sb.surfaceIdRef = spaceboundaryId;

                    XmlNodeList sbchilds = node.ChildNodes;
                    foreach (XmlNode sbpnode in sbchilds)
                    {
                        if (sbpnode.Name == "PlanarGeometry")
                        {
                            sb.sbplane = new PlanarGeometry();
                            XmlNodeList pgchilds = sbpnode.ChildNodes;
                            MakeSBPlanarGeometry(sb, pgchilds);
                        }
                    }

                    sbList.Add(sb);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return sbList;
        }
Пример #9
0
        public static List<gbXMLSpaces> getSimpleSpaces(XmlDocument xmldoc, XmlNamespaceManager xmlns)
        {
            List<gbXMLSpaces> retspaces = new List<gbXMLSpaces>();
            try
            {
                XmlNodeList nodes = xmldoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", xmlns);

                foreach (XmlNode spaceNode in nodes)
                {
                    //initialize a new instance of the class
                    gbXMLSpaces space = new gbXMLSpaces();
                    space.spacebounds = new List<SpaceBoundary>();
                    //get id and space
                    XmlAttributeCollection spaceAtts = spaceNode.Attributes;
                    foreach (XmlAttribute at in spaceAtts)
                    {
                        if (at.Name == "id")
                        {
                            space.id = at.Value;
                            break;
                        }
                    }
                    if (spaceNode.HasChildNodes)
                    {
                        XmlNodeList childNodes = spaceNode.ChildNodes;
                        foreach (XmlNode node in childNodes)
                        {
                            if (node.Name == "PlanarGeometry")
                            {
                                space.pg = new PlanarGeometry();
                                XmlNodeList childnodes = node.ChildNodes;
                                foreach (XmlNode node2 in childnodes)
                                {
                                    if (node2.Name == "PolyLoop")
                                    {
                                        space.pg.pl = new PolyLoop();
                                        space.pg.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();

                                        XmlNodeList cartPoints = node2.ChildNodes;
                                        foreach (XmlNode point in cartPoints)
                                        {
                                            if (point.Name == "CartesianPoint")
                                            {
                                                Vector.CartCoord coord = new Vector.CartCoord();
                                                XmlNodeList val = point.ChildNodes;
                                                int pointcount = 1;
                                                foreach (XmlNode cpoint in val)
                                                {
                                                    switch (pointcount)
                                                    {
                                                        case 1:
                                                            coord.X = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                        case 2:
                                                            coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                        case 3:
                                                            coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                            break;
                                                    }
                                                    pointcount++;
                                                }
                                                Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                space.pg.pl.plcoords.Add(memsafecoord);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (node.Name == "ShellGeometry")
                            {
                                space.sg = new ShellGeometry();
                                XmlAttributeCollection sgAtts = spaceNode.Attributes;
                                foreach (XmlAttribute at in sgAtts)
                                {
                                    if (at.Name == "id")
                                    {
                                        space.sg.id = at.Value;
                                        break;
                                    }
                                }

                                XmlNodeList childnodes = node.ChildNodes;
                                foreach (XmlNode sgnode in childnodes)
                                {
                                    if (sgnode.Name == "ClosedShell")
                                    {
                                        space.sg.cs = new ClosedShell();
                                        space.sg.cs.ploops = new List<PolyLoop>();

                                        foreach (XmlNode pl in sgnode)
                                        {
                                            if (pl.Name == "PolyLoop")
                                            {
                                                PolyLoop sgpl = new PolyLoop();
                                                sgpl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                                                XmlNodeList cartPoints = pl.ChildNodes;
                                                foreach (XmlNode point in cartPoints)
                                                {
                                                    if (point.Name == "CartesianPoint")
                                                    {
                                                        Vector.CartCoord coord = new Vector.CartCoord();
                                                        XmlNodeList val = point.ChildNodes;
                                                        int pointcount = 1;
                                                        foreach (XmlNode cpoint in val)
                                                        {
                                                            switch (pointcount)
                                                            {
                                                                case 1:
                                                                    coord.X = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 2:
                                                                    coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 3:
                                                                    coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                            }
                                                            pointcount++;
                                                        }
                                                        Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                        sgpl.plcoords.Add(memsafecoord);
                                                    }
                                                }
                                                space.sg.cs.ploops.Add(sgpl);
                                            }
                                        }
                                    }
                                }
                            }
                            else if (node.Name == "SpaceBoundary")
                            {
                                SpaceBoundary sb = new SpaceBoundary();
                                XmlAttributeCollection spbatts = node.Attributes;
                                foreach (XmlAttribute at in spbatts)
                                {
                                    if (at.Name == "surfaceIdRef")
                                    {
                                        sb.surfaceIdRef = at.Value;
                                        break;
                                    }
                                }
                                XmlNodeList sbchilds = node.ChildNodes;
                                foreach (XmlNode sbpnode in sbchilds)
                                {
                                    if (sbpnode.Name == "PlanarGeometry")
                                    {
                                        sb.sbplane = new PlanarGeometry();
                                        XmlNodeList pgchilds = sbpnode.ChildNodes;
                                        foreach (XmlNode pgchild in pgchilds)
                                        {
                                            if (pgchild.Name == "PolyLoop")
                                            {
                                                sb.sbplane.pl = new PolyLoop();

                                                sb.sbplane.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                                                XmlNodeList cartPoints = pgchild.ChildNodes;
                                                foreach (XmlNode point in cartPoints)
                                                {
                                                    if (point.Name == "CartesianPoint")
                                                    {
                                                        Vector.CartCoord coord = new Vector.CartCoord();
                                                        XmlNodeList val = point.ChildNodes;
                                                        int pointcount = 1;
                                                        foreach (XmlNode cpoint in val)
                                                        {
                                                            switch (pointcount)
                                                            {
                                                                case 1:
                                                                    coord.X = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 2:
                                                                    coord.Y = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                                case 3:
                                                                    coord.Z = Convert.ToDouble(cpoint.InnerText);
                                                                    break;
                                                            }
                                                            pointcount++;
                                                        }
                                                        Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                                        sb.sbplane.pl.plcoords.Add(memsafecoord);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                //finally, add the thing here
                                space.spacebounds.Add(sb);
                            }
                        }
                    }
                    else
                    {
                        //throw something
                    }
                    retspaces.Add(space);
                }
            }
            catch (Exception e)
            {

            }
            return retspaces;
        }
Пример #10
0
        private static SpaceBoundary MakeSBPlanarGeometry(SpaceBoundary sb, XmlNodeList pgchilds)
        {
            try
            {

                foreach (XmlNode pgchild in pgchilds)
                {
                    if (pgchild.Name == "PolyLoop")
                    {
                        sb.sbplane.pl = new PolyLoop();

                        sb.sbplane.pl.plcoords = new List<Vector.MemorySafe_CartCoord>();
                        XmlNodeList cartPoints = pgchild.ChildNodes;
                        foreach (XmlNode point in cartPoints)
                        {
                            if (point.Name == "CartesianPoint")
                            {
                                Vector.CartCoord coord = new Vector.CartCoord();
                                XmlNodeList val = point.ChildNodes;
                                int pointcount = 1;
                                foreach (XmlNode cpoint in val)
                                {
                                    switch (pointcount)
                                    {
                                        case 1:
                                            coord.X = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                        case 2:
                                            coord.Y = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                        case 3:
                                            coord.Z = Convert.ToDouble(cpoint.InnerText);
                                            break;
                                    }
                                    pointcount++;
                                }
                                Vector.MemorySafe_CartCoord memsafecoord = Vector.convertToMemorySafeCoord(coord);
                                sb.sbplane.pl.plcoords.Add(memsafecoord);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {

            }
            return sb;
        }
Пример #11
0
        /// <summary>
        /// The SpacePlanningZones function.
        /// </summary>
        /// <param name="model">The input model.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A SpacePlanningZonesOutputs instance containing computed results and the model with any new elements.</returns>
        public static SpacePlanningZonesOutputs Execute(Dictionary <string, Model> inputModels, SpacePlanningZonesInputs input)
        {
            var corridorWidth = input.CorridorWidth;
            var corridorMat   = SpaceBoundary.MaterialDict["Circulation"];

            var output       = new SpacePlanningZonesOutputs();
            var levelsModel  = inputModels["Levels"];
            var levelVolumes = levelsModel.AllElementsOfType <LevelVolume>();

            inputModels.TryGetValue("Floors", out var floorsModel);
            var hasCore = inputModels.TryGetValue("Core", out var coresModel);
            var cores   = coresModel?.AllElementsOfType <ServiceCore>() ?? new List <ServiceCore>();

            var random        = new Random(5);
            var levels        = new List <LevelElements>();
            var levelMappings = new Dictionary <Guid, (SpaceBoundary boundary, LevelElements level)>();

            if (levelVolumes.Count() == 0)
            {
                throw new Exception("This function requires LevelVolumes, produced by functions like \"Simple Levels by Envelope\". Try using a different levels function.");
            }
            foreach (var lvl in levelVolumes)
            {
                if (floorsModel != null)
                {
                    var floorAtLevel = floorsModel.AllElementsOfType <Floor>().FirstOrDefault(f => Math.Abs(lvl.Transform.Origin.Z - f.Transform.Origin.Z) < (f.Thickness * 1.1));
                    if (floorAtLevel != null)
                    {
                        lvl.Height -= floorAtLevel.Thickness;
                        var floorFaceOffset = (floorAtLevel.Transform.Origin.Z + floorAtLevel.Thickness) - lvl.Transform.Origin.Z;
                        if (floorFaceOffset > 0.001)
                        {
                            lvl.Transform.Concatenate(new Transform(0, 0, floorFaceOffset));
                            lvl.Height -= floorFaceOffset;
                        }
                    }
                }
                var levelBoundary   = new Profile(lvl.Profile.Perimeter, lvl.Profile.Voids, Guid.NewGuid(), null);
                var coresInBoundary = cores.Where(c => levelBoundary.Contains(c.Centroid)).ToList();
                foreach (var core in coresInBoundary)
                {
                    levelBoundary.Voids.Add(new Polygon(core.Profile.Perimeter.Vertices).Reversed());
                    levelBoundary.OrientVoids();
                }

                var            spaceBoundaries  = new List <Element>();
                List <Profile> corridorProfiles = new List <Profile>();
                if (input.CirculationMode == SpacePlanningZonesInputsCirculationMode.Automatic)
                {
                    var perimeter         = levelBoundary.Perimeter;
                    var perimeterSegments = perimeter.Segments();

                    IdentifyShortEdges(perimeter, perimeterSegments, out var shortEdges, out var shortEdgeIndices);

                    // Single Loaded Zones
                    var singleLoadedZones = CalculateSingleLoadedZones(input, corridorWidth, perimeterSegments, shortEdgeIndices);

                    GenerateEndZones(input, corridorWidth, lvl, corridorProfiles, perimeterSegments, shortEdges, singleLoadedZones, out var thickenedEnds, out var thickerOffsetProfiles, out var innerOffsetMinusThickenedEnds, out var exclusionRegions);

                    // join single loaded zones to each other (useful in bent-bar case)
                    var allCenterLines = JoinSingleLoaded(singleLoadedZones);

                    // thicken and extend single loaded
                    ThickenAndExtendSingleLoaded(corridorWidth, corridorProfiles, coresInBoundary, thickenedEnds, innerOffsetMinusThickenedEnds, allCenterLines);

                    CorridorsFromCore(corridorWidth, corridorProfiles, levelBoundary, coresInBoundary, innerOffsetMinusThickenedEnds, exclusionRegions);

                    SplitCornersAndGenerateSpaceBoundaries(spaceBoundaries, input, lvl, corridorProfiles, levelBoundary, thickerOffsetProfiles);
                }
                else if (input.CirculationMode == SpacePlanningZonesInputsCirculationMode.Manual)
                {
                    if (input.Corridors != null && input.Corridors.Count > 0)
                    {
                        var corridorProfilesForUnion = new List <Profile>();
                        foreach (var corridorPolyline in input.Corridors)
                        {
                            if (corridorPolyline == null || corridorPolyline.Polyline == null)
                            {
                                continue;
                            }
                            var corrPgons = corridorPolyline.Polyline.OffsetOnSide(corridorPolyline.Width, corridorPolyline.Flip);
                            corridorProfilesForUnion.AddRange(corrPgons.Select(p => new Profile(p)));
                        }
                        corridorProfiles = Profile.UnionAll(corridorProfilesForUnion);
                    }
                    SplitCornersAndGenerateSpaceBoundaries(spaceBoundaries, input, lvl, corridorProfiles, levelBoundary);
                }

                // Construct Level
                var level = new LevelElements(new List <Element>(), Guid.NewGuid(), lvl.Name);
                levels.Add(level);

                // Manual Corridor Splits
                foreach (var pt in input.AdditionalCorridorLocations)
                {
                    SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt);
                }

                // Manual Split Locations
                foreach (var pt in input.ManualSplitLocations)
                {
                    SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt, false);
                }

                foreach (SpaceBoundary b in spaceBoundaries)
                {
                    levelMappings.Add(b.Id, (b, level));
                }
                corridorProfiles.Select(p => new Floor(p, 0.1, lvl.Transform, corridorMat)).ToList().ForEach(f => level.Elements.Add(f));
            }
            List <SpaceBoundary> SubdividedBoundaries = new List <SpaceBoundary>();

            // merge overrides
            if (input.Overrides != null && input.Overrides.MergeZones != null && input.Overrides.MergeZones.Count > 0)
            {
                var spaceBoundaries = levelMappings.Select(kvp => kvp.Value);
                foreach (var mz in input.Overrides.MergeZones)
                {
                    var identitiesToMerge = mz.Identities;
                    var matchingSbs       = identitiesToMerge.Select(mzI => spaceBoundaries.FirstOrDefault(
                                                                         sb => ((Vector3)sb.boundary.AdditionalProperties["ParentCentroid"]).DistanceTo(mzI.ParentCentroid) < 1.0)).Where(s => s != (null, null)).ToList();
                    foreach (var msb in matchingSbs)
                    {
                        levelMappings.Remove(msb.boundary.Id);
                    }
                    var sbsByLevel = matchingSbs.GroupBy(sb => sb.level?.Id ?? Guid.Empty);
                    foreach (var lvlGrp in sbsByLevel)
                    {
                        var level    = lvlGrp.First().level;
                        var profiles = lvlGrp.Select(sb => sb.boundary.Boundary);
                        var baseobj  = lvlGrp.FirstOrDefault(n => n.boundary.Name != null && n.boundary.Name != "unspecified");
                        if (baseobj == default)
                        {
                            baseobj = lvlGrp.First();
                        }
                        var baseSB = baseobj.boundary;
                        var union  = Profile.UnionAll(profiles);
                        foreach (var newProfile in union)
                        {
                            var rep = baseSB.Representation.SolidOperations.OfType <Extrude>().First();

                            var newSB = SpaceBoundary.Make(newProfile, baseSB.Name, baseSB.Transform, rep.Height, (Vector3)baseSB.AdditionalProperties["ParentCentroid"], (Vector3)baseSB.AdditionalProperties["ParentCentroid"]);
                            newSB.SetProgram(baseSB.Name);
                            levelMappings.Add(newSB.Id, (newSB, level));
                        }
                    }
                }
            }
            // assignment overrides
            if (input.Overrides != null && input.Overrides.ProgramAssignments != null && input.Overrides.ProgramAssignments.Count > 0)
            {
                var spaceBoundaries = levelMappings.Select(kvp => kvp.Value).ToList();
                // overrides where it is its own parent
                Console.WriteLine(JsonConvert.SerializeObject(input.Overrides.ProgramAssignments));
                foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid)))
                {
                    var centroid   = overrideValue.Identity.ParentCentroid;
                    var matchingSB = spaceBoundaries
                                     .OrderBy(sb => ((Vector3)sb.boundary.AdditionalProperties["IndividualCentroid"]).DistanceTo(centroid))
                                     .FirstOrDefault(sb => ((Vector3)sb.boundary.AdditionalProperties["IndividualCentroid"]).DistanceTo(centroid) < 2.0);
                    // var allMatchingSBs = spaceBoundaries
                    //     .OrderBy(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid))
                    //     .Where(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid) < 2.0);
                    if (matchingSB.boundary != null)
                    {
                        if (overrideValue.Value.Split <= 1)
                        {
                            matchingSB.boundary.SetProgram(overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment);
                            Identity.AddOverrideIdentity(matchingSB.boundary, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                        }
                        else
                        {
                            levelMappings.Remove(matchingSB.boundary.Id);
                            var boundaries = new List <Polygon>(matchingSB.boundary.Boundary.Voids)
                            {
                                matchingSB.boundary.Boundary.Perimeter
                            };
                            var guideVector    = GetDominantAxis(boundaries.SelectMany(b => b.Segments()));
                            var alignmentXform = new Transform(boundaries[0].Start, guideVector, Vector3.ZAxis);
                            var grid           = new Grid2d(boundaries, alignmentXform);
                            grid.U.DivideByCount(Math.Max(overrideValue.Value.Split, 1));
                            foreach (var cell in grid.GetCells().SelectMany(c => c.GetTrimmedCellGeometry()))
                            {
                                var rep       = matchingSB.boundary.Representation.SolidOperations.OfType <Extrude>().First();
                                var newCellSb = SpaceBoundary.Make(cell as Polygon, overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment, matchingSB.boundary.Transform, rep.Height, matchingSB.boundary.AdditionalProperties["ParentCentroid"] as Vector3?);
                                Identity.AddOverrideIdentity(newCellSb, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                                newCellSb.AdditionalProperties["Split"] = overrideValue.Value.Split;
                                SubdividedBoundaries.Add(newCellSb);
                                levelMappings.Add(newCellSb.Id, (newCellSb, matchingSB.level));
                            }
                        }
                    }
                }
                // overrides where it's not its own parent
                foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => !o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid)))
                {
                    var matchingCell = SubdividedBoundaries.FirstOrDefault(b => (b.AdditionalProperties["IndividualCentroid"] as Vector3?)?.DistanceTo(overrideValue.Identity.IndividualCentroid) < 0.01);
                    if (matchingCell != null)
                    {
                        Identity.AddOverrideIdentity(matchingCell, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                        matchingCell.SetProgram(overrideValue.Value.ProgramType);
                    }
                }
            }

            foreach (var levelMapping in levelMappings)
            {
                levelMapping.Value.level.Elements.Add(levelMapping.Value.boundary);
            }
            Dictionary <string, AreaTally> areas = new Dictionary <string, AreaTally>();

            foreach (var sb in levels.SelectMany(lev => lev.Elements.OfType <SpaceBoundary>()))
            {
                var area = sb.Boundary.Area();
                if (sb.Name == null)
                {
                    continue;
                }
                if (!areas.ContainsKey(sb.Name))
                {
                    areas[sb.Name] = new AreaTally(sb.Name, sb.Material.Color, area, area, 1, null, Guid.NewGuid(), sb.Name);
                }
                else
                {
                    var existingTally = areas[sb.Name];
                    existingTally.AchievedArea += area;
                    existingTally.AreaTarget   += area;
                    existingTally.DistinctAreaCount++;
                }
                output.Model.AddElements(sb.Boundary.ToModelCurves(sb.Transform.Concatenated(new Transform(0, 0, 0.03))));
            }
            output.Model.AddElements(areas.Select(kvp => kvp.Value).OrderByDescending(a => a.AchievedArea));
            output.Model.AddElements(levels);

            return(output);
        }
Пример #12
0
        /// <summary>
        /// The SpacePlanningZones function.
        /// </summary>
        /// <param name="model">The input model.</param>
        /// <param name="input">The arguments to the execution.</param>
        /// <returns>A SpacePlanningZonesOutputs instance containing computed results and the model with any new elements.</returns>
        public static SpacePlanningZonesOutputs Execute(Dictionary <string, Model> inputModels, SpacePlanningZonesInputs input)
        {
            var corridorWidth = input.CorridorWidth;
            var corridorMat   = SpaceBoundary.MaterialDict["Circulation"];

            var output       = new SpacePlanningZonesOutputs();
            var levelsModel  = inputModels["Levels"];
            var levelVolumes = levelsModel.AllElementsOfType <LevelVolume>();

            inputModels.TryGetValue("Floors", out var floorsModel);
            var coresModel    = inputModels["Core"];
            var cores         = coresModel.AllElementsOfType <ServiceCore>();
            var random        = new Random(5);
            var levels        = new List <LevelElements>();
            var levelMappings = new Dictionary <Guid, (SpaceBoundary boundary, LevelElements level)>();

            if (levelVolumes.Count() == 0)
            {
                throw new Exception("This function requires LevelVolumes, produced by functions like \"Simple Levels by Envelope\". Try using a different levels function.");
            }
            if (cores.Count() == 0)
            {
                throw new Exception("No ServiceCore elements were found in the model.");
            }
            foreach (var lvl in levelVolumes)
            {
                var spaceBoundaries = new List <Element>();
                if (floorsModel != null)
                {
                    var floorAtLevel = floorsModel.AllElementsOfType <Floor>().FirstOrDefault(f => Math.Abs(lvl.Transform.Origin.Z - f.Transform.Origin.Z) < (f.Thickness * 1.1));
                    if (floorAtLevel != null)
                    {
                        lvl.Height -= floorAtLevel.Thickness;
                        var floorFaceOffset = (floorAtLevel.Transform.Origin.Z + floorAtLevel.Thickness) - lvl.Transform.Origin.Z;
                        if (floorFaceOffset > 0.001)
                        {
                            lvl.Transform.Concatenate(new Transform(0, 0, floorFaceOffset));
                            lvl.Height -= floorFaceOffset;
                        }
                    }
                }
                List <Profile> corridorProfiles = new List <Profile>();
                var            TOO_SHORT        = 9;
                var            levelBoundary    = new Profile(lvl.Profile.Perimeter, lvl.Profile.Voids, Guid.NewGuid(), null);
                var            coresInBoundary  = cores.Where(c => levelBoundary.Contains(c.Centroid)).ToList();
                foreach (var core in coresInBoundary)
                {
                    levelBoundary.Voids.Add(new Polygon(core.Profile.Perimeter.Vertices).Reversed());
                    levelBoundary.OrientVoids();
                }

                var perimeter         = levelBoundary.Perimeter;
                var perimeterSegments = perimeter.Segments();
                var perimeterAngles   = new List <double>();
                for (int i = 0; i < perimeter.Vertices.Count; i++)
                {
                    var nextIndex = (i + 1) % perimeter.Vertices.Count;
                    var prevIndex = (i + perimeter.Vertices.Count - 1) % perimeter.Vertices.Count;
                    var prevVec   = perimeter.Vertices[i] - perimeter.Vertices[prevIndex];
                    var nextVec   = perimeter.Vertices[nextIndex] - perimeter.Vertices[i];
                    var angle     = prevVec.PlaneAngleTo(nextVec);
                    perimeterAngles.Add(angle);
                }
                var allLengths       = perimeterSegments.Select(s => s.Length());
                var validLengths     = allLengths.Where(l => l > TOO_SHORT)?.OrderBy(l => l);
                var shortLength      = (validLengths?.FirstOrDefault() ?? 35 / 1.2) * 1.2;
                var longLength       = Math.Min(validLengths.SkipLast(1).Last(), 50);
                var shortEdges       = new List <Line>();
                var shortEdgeIndices = new List <int>();
                for (int i = 0; i < perimeterSegments.Count(); i++)
                {
                    var start = perimeterAngles[i];
                    var end   = perimeterAngles[(i + 1) % perimeterAngles.Count];
                    if (start > 80 && start < 100 && end > 80 && end < 100 && perimeterSegments[i].Length() < longLength)
                    {
                        shortEdges.Add(perimeterSegments[i]);
                        shortEdgeIndices.Add(i);
                    }
                }


                // Single Loaded Zones

                var singleLoadedZones           = new List <(Polygon hull, Line centerLine)>();
                var singleLoadedLengthThreshold = input.OuterBandDepth * 2 + corridorWidth * 2 + 5; // (two offsets, two corridors, and a usable space width)
                foreach (var sei in shortEdgeIndices)
                {
                    var ps = perimeterSegments;
                    if (ps[sei].Length() < singleLoadedLengthThreshold)
                    {
                        var legSegments = new[] {
                            ps[(sei + ps.Length - 1) % ps.Length],
                            ps[sei],
                            ps[(sei + 1) % ps.Length]
                        };
                        var legLength = Math.Min(legSegments[0].Length(), legSegments[2].Length());
                        legSegments[0] = new Line(ps[sei].Start, ps[sei].Start + legLength * (legSegments[0].Direction() * -1));
                        legSegments[2] = new Line(ps[sei].End, ps[sei].End + legLength * (legSegments[2].Direction()));
                        var hull       = ConvexHull.FromPolylines(legSegments.Select(l => l.ToPolyline(1)));
                        var centerLine = new Line((legSegments[0].Start + legSegments[2].Start) / 2, (legSegments[0].End + legSegments[2].End) / 2);

                        singleLoadedZones.Add((hull, centerLine));
                    }
                }

                var shortEdgesExtended = shortEdges.Select(l => new Line(l.Start - l.Direction() * 0.2, l.End + l.Direction() * 0.2));
                var longEdges          = perimeterSegments.Except(shortEdges);
                var shortEdgeDepth     = Math.Max(input.DepthAtEnds, input.OuterBandDepth);
                var longEdgeDepth      = input.OuterBandDepth;


                var perimeterMinusSingleLoaded = new List <Profile>();
                perimeterMinusSingleLoaded.AddRange(Profile.Difference(new[] { lvl.Profile }, singleLoadedZones.Select(p => new Profile(p.hull))));
                var innerOffset           = perimeterMinusSingleLoaded.SelectMany(p => p.Perimeter.Offset(-longEdgeDepth));
                var thickerOffsets        = shortEdgesExtended.SelectMany(s => s.ToPolyline(1).Offset(shortEdgeDepth, EndType.Butt)).ToList();
                var thickerOffsetProfiles = thickerOffsets.Select(o => new Profile(o.Offset(0.01))).ToList();
                var endOffsetSegments     = thickerOffsets.SelectMany(o => o.Segments()).Where(l => innerOffset.Any(o => o.Contains(l.PointAt(0.5))));

                var innerOffsetMinusThicker = innerOffset.SelectMany(i => Polygon.Difference(new[] { i }, thickerOffsets));

                var outerband = new Profile(lvl.Profile.Perimeter, innerOffsetMinusThicker.ToList(), Guid.NewGuid(), null);

                var outerbandLongEdges = Profile.Difference(new List <Profile> {
                    outerband
                }, thickerOffsetProfiles);
                var ends = Profile.Intersection(new List <Profile> {
                    outerband
                }, thickerOffsets.Select(o => new Profile(o)).ToList());
                var coreSegments = coresInBoundary.SelectMany(c => c.Profile.Perimeter.Offset((corridorWidth / 2) * 0.999).FirstOrDefault()?.Segments());


                var corridorInset = innerOffsetMinusThicker.Select(p => new Profile(p, p.Offset(-corridorWidth), Guid.NewGuid(), "Corridor"));
                corridorProfiles.AddRange(corridorInset);

                // join single loaded zones to each other (useful in bent-bar case)
                var allCenterLines    = singleLoadedZones.ToArray();
                var distanceThreshold = 10.0;
                for (int i = 0; i < allCenterLines.Count(); i++)
                {
                    var crvA = allCenterLines[i].centerLine;
                    for (int j = 0; j < i; j++)
                    {
                        var crvB          = allCenterLines[j].centerLine;
                        var doesIntersect = crvA.Intersects(crvB, out var intersection, true, true);
                        Console.WriteLine($"DOES INTERSECT: " + doesIntersect.ToString());

                        var nearPtA = intersection.ClosestPointOn(crvA);
                        var nearPtB = intersection.ClosestPointOn(crvB);
                        if (nearPtA.DistanceTo(intersection) + nearPtB.DistanceTo(intersection) < distanceThreshold)
                        {
                            if (nearPtA.DistanceTo(crvA.Start) < 0.01)
                            {
                                allCenterLines[i] = (allCenterLines[i].hull, new Line(intersection, crvA.End));
                            }
                            else
                            {
                                allCenterLines[i] = (allCenterLines[i].hull, new Line(crvA.Start, intersection));
                            }
                            if (nearPtB.DistanceTo(crvB.Start) < 0.01)
                            {
                                allCenterLines[j] = (allCenterLines[j].hull, new Line(intersection, crvB.End));
                            }
                            else
                            {
                                allCenterLines[j] = (allCenterLines[j].hull, new Line(crvB.Start, intersection));
                            }
                        }
                    }
                }


                // thicken and extend single loaded
                foreach (var singleLoadedZone in allCenterLines)
                {
                    var         cl          = singleLoadedZone.centerLine;
                    List <Line> centerlines = new List <Line> {
                        cl
                    };
                    foreach (var core in coresInBoundary)
                    {
                        List <Line> linesRunning = new List <Line>();
                        foreach (var curve in centerlines)
                        {
                            curve.Trim(core.Profile.Perimeter, out var linesTrimmedByCore);
                            linesRunning.AddRange(linesTrimmedByCore);
                        }
                        centerlines = linesRunning;
                    }
                    cl = centerlines.OrderBy(l => l.Length()).Last();
                    foreach (var clCandidate in centerlines)
                    {
                        var extended = clCandidate.ExtendTo(innerOffsetMinusThicker.SelectMany(p => p.Segments())).ToPolyline(1);
                        if (extended.Length() == cl.Length() && innerOffsetMinusThicker.Count() > 0)
                        {
                            var     end       = extended.End;
                            var     dist      = double.MaxValue;
                            Vector3?runningPt = null;
                            foreach (var boundary in innerOffsetMinusThicker)
                            {
                                var closestDist = end.DistanceTo(boundary, out var pt);
                                if (closestDist < dist)
                                {
                                    dist      = closestDist;
                                    runningPt = pt;
                                }
                            }
                            extended = new Polyline(new[] { extended.Start, extended.End, runningPt.Value });
                        }
                        //TODO - verify that newly constructed line is contained within building perimeter
                        var thickenedCorridor = extended.Offset(corridorWidth / 2.0, EndType.Square);
                        corridorProfiles.AddRange(Profile.Difference(thickenedCorridor.Select(c => new Profile(c)), thickerOffsets.Select(c => new Profile(c))));
                    }
                }

                foreach (var core in coresInBoundary)
                {
                    if (singleLoadedZones.Any(z => z.hull.Covers(core.Profile.Perimeter)))
                    {
                        continue;
                    }
                    var boundary            = core.Profile.Perimeter.Offset(corridorWidth / 2.0).FirstOrDefault();
                    var outerOffset         = boundary.Offset(corridorWidth).FirstOrDefault();
                    var coreWrap            = new Profile(outerOffset, boundary);
                    var coreWrapWithinFloor = Profile.Intersection(new[] { coreWrap }, new[] { levelBoundary });
                }

                var extendedLines    = new List <Line>();
                var corridorRegions  = new List <Polygon>();
                var exclusionRegions = innerOffsetMinusThicker.SelectMany(r => r.Offset(2 * corridorWidth, EndType.Square));
                foreach (var enclosedRegion in innerOffsetMinusThicker)
                {
                    foreach (var segment in coreSegments)
                    {
                        enclosedRegion.Contains(segment.Start, out var startContainment);
                        enclosedRegion.Contains(segment.End, out var endContainment);
                        if (endContainment == Containment.Outside && startContainment == Containment.Outside)
                        {
                            continue;
                        }
                        var extendedSegment = segment.ExtendTo(new Profile(enclosedRegion));
                        if (extendedSegment.Length() - segment.Length() < 2 * 8)
                        {
                            continue;
                        }
                        extendedLines.Add(extendedSegment);
                        var thickenedCorridor = extendedSegment.ToPolyline(1).Offset(corridorWidth / 2.0, EndType.Butt);
                        var difference        = new List <Profile>();

                        difference = Profile.Difference(corridorProfiles, exclusionRegions.Select(r => new Profile(r)));

                        if (difference.Count > 0 && difference.Sum(d => d.Perimeter.Area()) > 10)
                        {
                            corridorProfiles.AddRange(Profile.Intersection(thickenedCorridor.Select(c => new Profile(c)), new[] { levelBoundary }));
                        }
                    }
                }

                var remainingSpaces = Profile.Difference(new[] { levelBoundary }, corridorProfiles);
                foreach (var remainingSpace in remainingSpaces)
                {
                    try
                    {
                        if (remainingSpace.Perimeter.Vertices.Any(v => v.DistanceTo(levelBoundary.Perimeter) < 0.1))
                        {
                            var endCapZones = Profile.Intersection(new[] { remainingSpace }, thickerOffsetProfiles);
                            var linearZones = Profile.Difference(new[] { remainingSpace }, thickerOffsetProfiles);
                            foreach (var linearZone in linearZones)
                            {
                                var segmentsExtended = new List <Polyline>();
                                foreach (var line in linearZone.Segments())
                                {
                                    if (line.Length() < 2)
                                    {
                                        continue;
                                    }
                                    var l             = new Line(line.Start - line.Direction() * 0.1, line.End + line.Direction() * 0.1);
                                    var extended      = l.ExtendTo(linearZone);
                                    var endDistance   = extended.End.DistanceTo(l.End);
                                    var startDistance = extended.Start.DistanceTo(l.Start);
                                    var maxExtension  = Math.Max(input.OuterBandDepth, input.DepthAtEnds) * 1.6;
                                    if (startDistance > 0.1 && startDistance < maxExtension)
                                    {
                                        var startLine = new Line(extended.Start, line.Start);
                                        segmentsExtended.Add(startLine.ToPolyline(1));
                                    }
                                    if (endDistance > 0.1 && endDistance < maxExtension)
                                    {
                                        var endLine = new Line(extended.End, line.End);
                                        segmentsExtended.Add(endLine.ToPolyline(1));
                                    }
                                }
                                Console.WriteLine(JsonConvert.SerializeObject(linearZone.Perimeter));
                                Console.WriteLine(JsonConvert.SerializeObject(linearZone.Voids));
                                Console.WriteLine(JsonConvert.SerializeObject(segmentsExtended));
                                var splits = Profile.Split(new[] { linearZone }, segmentsExtended, Vector3.EPSILON);
                                spaceBoundaries.AddRange(splits.Select(s => SpaceBoundary.Make(s, input.DefaultProgramAssignment, lvl.Transform, lvl.Height)));
                            }
                            spaceBoundaries.AddRange(endCapZones.Select(s => SpaceBoundary.Make(s, input.DefaultProgramAssignment, lvl.Transform, lvl.Height)));
                        }
                        else
                        {
                            spaceBoundaries.Add(SpaceBoundary.Make(remainingSpace, input.DefaultProgramAssignment, lvl.Transform, lvl.Height));
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("🚨");
                        Console.WriteLine(e.Message);
                        Console.WriteLine(e.StackTrace);
                        spaceBoundaries.Add(SpaceBoundary.Make(remainingSpace, input.DefaultProgramAssignment, lvl.Transform, lvl.Height));
                    }
                }
                var level = new LevelElements(new List <Element>(), Guid.NewGuid(), lvl.Name);
                levels.Add(level);

                foreach (var pt in input.AdditionalCorridorLocations)
                {
                    SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt);
                }

                foreach (var pt in input.ManualSplitLocations)
                {
                    SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt, false);
                }

                foreach (SpaceBoundary b in spaceBoundaries)
                {
                    levelMappings.Add(b.Id, (b, level));
                    output.Model.AddElements(b.Boundary.ToModelCurves(b.Transform.Concatenated(new Transform(0, 0, 0.03))));
                }
                corridorProfiles.Select(p => new Floor(p, 0.1, lvl.Transform, corridorMat)).ToList().ForEach(f => level.Elements.Add(f));
            }
            List <SpaceBoundary> SubdividedBoundaries = new List <SpaceBoundary>();

            if (input.Overrides != null && input.Overrides.ProgramAssignments.Count > 0)
            {
                var spaceBoundaries = levelMappings.Select(kvp => kvp.Value);
                foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid)))
                {
                    var centroid   = overrideValue.Identity.ParentCentroid;
                    var matchingSB = spaceBoundaries
                                     .OrderBy(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid))
                                     .FirstOrDefault(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid) < 2.0);
                    var allMatchingSBs = spaceBoundaries
                                         .OrderBy(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid))
                                         .Where(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid) < 2.0);
                    if (matchingSB.boundary != null)
                    {
                        if (overrideValue.Value.Split <= 1)
                        {
                            matchingSB.boundary.SetProgram(overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment);
                            Identity.AddOverrideIdentity(matchingSB.boundary, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                        }
                        else
                        {
                            levelMappings.Remove(matchingSB.boundary.Id);
                            var boundaries = new List <Polygon>(matchingSB.boundary.Boundary.Voids)
                            {
                                matchingSB.boundary.Boundary.Perimeter
                            };
                            var guideVector    = GetDominantAxis(boundaries.SelectMany(b => b.Segments()));
                            var alignmentXform = new Transform(boundaries[0].Start, guideVector, Vector3.ZAxis);
                            var grid           = new Grid2d(boundaries, alignmentXform);
                            grid.U.DivideByCount(Math.Max(overrideValue.Value.Split, 1));
                            output.Model.AddElements(grid.GetCellSeparators(GridDirection.V, false).Select(c => new ModelCurve(c as Line, new Material("Grey", new Color(0.3, 0.3, 0.3, 1)), matchingSB.boundary.Transform.Concatenated(new Transform(0, 0, 0.02)))));
                            foreach (var cell in grid.GetCells().SelectMany(c => c.GetTrimmedCellGeometry()))
                            {
                                var rep       = matchingSB.boundary.Representation.SolidOperations.OfType <Extrude>().First();
                                var newCellSb = SpaceBoundary.Make(cell as Polygon, overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment, matchingSB.boundary.Transform, rep.Height, matchingSB.boundary.AdditionalProperties["ParentCentroid"] as Vector3?);
                                Identity.AddOverrideIdentity(newCellSb, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                                newCellSb.AdditionalProperties["Split"] = overrideValue.Value.Split;
                                SubdividedBoundaries.Add(newCellSb);
                                levelMappings.Add(newCellSb.Id, (newCellSb, matchingSB.level));
                            }
                        }
                    }
                }

                foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => !o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid)))
                {
                    var matchingCell = SubdividedBoundaries.FirstOrDefault(b => (b.AdditionalProperties["IndividualCentroid"] as Vector3?)?.DistanceTo(overrideValue.Identity.IndividualCentroid) < 0.01);
                    if (matchingCell != null)
                    {
                        Identity.AddOverrideIdentity(matchingCell, "Program Assignments", overrideValue.Id, overrideValue.Identity);
                        matchingCell.SetProgram(overrideValue.Value.ProgramType);
                    }
                }
            }
            foreach (var levelMapping in levelMappings)
            {
                levelMapping.Value.level.Elements.Add(levelMapping.Value.boundary);
            }
            Dictionary <string, AreaTally> areas = new Dictionary <string, AreaTally>();

            foreach (var sb in levels.SelectMany(lev => lev.Elements.OfType <SpaceBoundary>()))
            {
                var area = sb.Boundary.Area();
                if (sb.Name == null)
                {
                    continue;
                }
                if (!areas.ContainsKey(sb.Name))
                {
                    areas[sb.Name] = new AreaTally(sb.Name, sb.Material.Color, area, area, 1, null, Guid.NewGuid(), sb.Name);
                }
                else
                {
                    var existingTally = areas[sb.Name];
                    existingTally.AchievedArea += area;
                    existingTally.AreaTarget   += area;
                    existingTally.DistinctAreaCount++;
                }
            }
            output.Model.AddElements(areas.Select(kvp => kvp.Value).OrderByDescending(a => a.AchievedArea));
            output.Model.AddElements(levels);
            return(output);
        }
Пример #13
0
        public static Building TogbXML(this AdjacencyCluster adjacencyCluster, string name, string description, double tolerance = Tolerance.MicroDistance)
        {
            List <Panel> panels = adjacencyCluster?.GetPanels();

            if (panels == null || panels.Count == 0)
            {
                return(null);
            }

            List <Space> spaces = adjacencyCluster.GetSpaces();

            if (spaces == null)
            {
                return(null);
            }

            //Dictionary of Minimal Elevations and List of Panels
            Dictionary <double, List <Panel> > dictionary_MinElevations = Analytical.Query.MinElevationDictionary(panels, true, Tolerance.MacroDistance);

            //Dictionary of gbXML BuildingStoreys and its elevations
            Dictionary <BuildingStorey, double> dictionary_buildingStoreys = new Dictionary <BuildingStorey, double>();

            //Dictionary of SAM Panels related buildingSorey, minimal elevation and maximal elevation
            Dictionary <Panel, Tuple <BuildingStorey, double, double, double> > dictionary_Panels = new Dictionary <Panel, Tuple <BuildingStorey, double, double, double> >();

            foreach (KeyValuePair <double, List <Panel> > keyValuePair in dictionary_MinElevations)
            {
                BuildingStorey buildingStorey = Architectural.Create.Level(keyValuePair.Key).TogbXML(tolerance);
                dictionary_buildingStoreys[buildingStorey] = keyValuePair.Key;
                foreach (Panel panel in keyValuePair.Value)
                {
                    dictionary_Panels[panel] = new Tuple <BuildingStorey, double, double, double> (buildingStorey, keyValuePair.Key, panel.MinElevation(), panel.MaxElevation());
                }
            }

            List <gbXMLSerializer.Space>     spaces_gbXML = new List <gbXMLSerializer.Space>();
            Dictionary <Guid, SpaceBoundary> dictionary   = new Dictionary <Guid, SpaceBoundary>();

            foreach (Space space in spaces)
            {
                List <Panel> panels_Space = adjacencyCluster.GetRelatedObjects <Panel>(space);
                if (panels_Space == null || panels_Space.Count == 0)
                {
                    continue;
                }

                double         elevation_Level = panels_Space.ConvertAll(x => dictionary_Panels[x].Item2).Min();
                double         elevation_Min   = panels_Space.ConvertAll(x => dictionary_Panels[x].Item3).Min();
                double         elevation_Max   = panels_Space.ConvertAll(x => dictionary_Panels[x].Item4).Max();
                BuildingStorey buildingStorey  = null;
                foreach (KeyValuePair <BuildingStorey, double> keyValuePair in dictionary_buildingStoreys)
                {
                    if (keyValuePair.Value.Equals(elevation_Level))
                    {
                        buildingStorey = keyValuePair.Key;
                        break;
                    }
                }

                if (buildingStorey == null)
                {
                    continue;
                }

                List <Panel> panels_PlanarGeometry = panels_Space.FindAll(x => x.PanelType.PanelGroup() == PanelGroup.Floor || (x.Normal.AlmostSimilar(Vector3D.WorldZ.GetNegated()) && dictionary_Panels[x].Item3 == elevation_Min));
                panels_PlanarGeometry = panels_PlanarGeometry?.MergeCoplanarPanels(Tolerance.MacroDistance, false, false, Tolerance.MacroDistance);
                if (panels_PlanarGeometry == null || panels_PlanarGeometry.Count == 0)
                {
                    continue;
                }

                panels_PlanarGeometry.Sort((x, y) => y.GetArea().CompareTo(x.GetArea()));

                Face3D face3D = panels_PlanarGeometry.First().PlanarBoundary3D?.GetFace3D();
                if (face3D == null)
                {
                    continue;
                }

                double area = face3D.GetArea();
                if (area < Tolerance.MacroDistance)
                {
                    continue;
                }

                double volume = Math.Abs(elevation_Max - elevation_Min) * area;
                if (volume < Tolerance.MacroDistance)
                {
                    continue;
                }

                List <SpaceBoundary> spaceBoundaries = new List <SpaceBoundary>();
                foreach (Panel panel in panels_Space)
                {
                    if (panel == null)
                    {
                        continue;
                    }

                    SpaceBoundary spaceBoundary = null;
                    if (!dictionary.TryGetValue(panel.Guid, out spaceBoundary))
                    {
                        spaceBoundary          = panel.TogbXML_SpaceBoundary(tolerance);
                        dictionary[panel.Guid] = spaceBoundary;
                    }

                    spaceBoundaries.Add(spaceBoundary);
                }

                gbXMLSerializer.Space space_gbXML = new gbXMLSerializer.Space();
                space_gbXML.Name      = space.Name;
                space_gbXML.spacearea = new Area()
                {
                    val = area.ToString()
                };
                space_gbXML.spacevol = new Volume()
                {
                    val = volume.ToString()
                };
                space_gbXML.buildingStoreyIdRef = buildingStorey.id;
                space_gbXML.cadid = new CADObjectId()
                {
                    id = space.Guid.ToString()
                };
                space_gbXML.PlanarGeo = face3D.TogbXML(tolerance);
                space_gbXML.id        = Core.gbXML.Query.Id(space, typeof(gbXMLSerializer.Space));
                space_gbXML.spbound   = spaceBoundaries.ToArray();
                space_gbXML.ShellGeo  = panels_Space.TogbXML(space, tolerance);

                spaces_gbXML.Add(space_gbXML);
            }

            Building building = new Building();

            building.id           = Core.gbXML.Query.Id(adjacencyCluster, typeof(Building));
            building.Name         = name;
            building.Description  = description;
            building.bldgStories  = dictionary_buildingStoreys.Keys.ToArray();
            building.Area         = Analytical.Query.Area(panels, PanelGroup.Floor);
            building.buildingType = buildingTypeEnum.Office;
            building.Spaces       = spaces_gbXML.ToArray();

            return(building);
        }