public void Write(MEPRevitGraph mepGraph, Autodesk.Revit.DB.Document rootDoc)
        {
            var track = new Dictionary <MEPRevitNode, PendingNode>();

            var models = new Dictionary <string, PendingNode>();
            var types  = new Dictionary <string, PendingNode>();
            var levels = new Dictionary <string, PendingNode>();

            var rootModelNode  = new Model.Model();
            var rootModelIdent = DocUtils.GetDocumentIdent(rootDoc);

            rootModelNode.Name = rootDoc.PathName;
            rootModelNode.ExtendedProperties.Add("Identity", rootModelIdent);
            rootModelNode.ExtendedProperties.Add("DateTimeStamp", System.DateTime.Now.ToShortDateString());
            var rootparams = MEPGraphUtils.GetNodePropsWithElementProps(rootModelNode, rootDoc.ProjectInformation);
            var seid       = _gdbClient.Push(rootModelNode, rootparams);

            models.Add(rootModelIdent, seid);

            //add the nodes
            foreach (var mepNode in mepGraph.Nodes)
            {
                var npNode      = mepNode.AsAbstractNode;
                var elmAbParams = npNode.GetAllProperties();


                if (!string.IsNullOrEmpty(mepNode.OrginDocIdent))
                {
                    var elmNode  = mepNode.AsElementNode;
                    var elmParms = elmNode.GetAllProperties();

                    var elmdoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application);
                    var elm    = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.OriginId));
                    if (elm != null)
                    {
                        elmParms    = MEPGraphUtils.GetNodePropsWithElementProps(elmNode, elm);
                        elmAbParams = MEPGraphUtils.GetNodePropsWithElementProps(npNode, elm);
                    }

                    var atid = _gdbClient.Push(npNode, elmAbParams);
                    track.Add(mepNode, atid);

                    var elmid = _gdbClient.Push(elmNode, elmParms);

                    //relate the element node to the abstracted model node
                    _gdbClient.Relate(atid, elmid, Model.MEPEdgeTypes.REALIZED_BY.ToString(), null);


                    PendingNode modelId = null;
                    //create up model nodes
                    if (models.ContainsKey(mepNode.OrginDocIdent))
                    {
                        modelId = models[mepNode.OrginDocIdent];
                    }
                    else
                    {
                        var modelNode = new Model.Model();
                        modelNode.ExtendedProperties.Add("Identity", mepNode.OrginDocIdent);
                        var mparams = modelNode.GetAllProperties();

                        var ldoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application);
                        if (ldoc != null)
                        {
                            mparams = MEPGraphUtils.GetNodePropsWithElementProps(modelNode, ldoc.ProjectInformation);
                        }

                        modelId = _gdbClient.Push(modelNode, mparams);
                        models.Add(mepNode.OrginDocIdent, modelId);
                    }

                    var elmedgeProps = MEPGraphUtils.GetEdgeProps(elm);
                    //connect up model node to element node
                    _gdbClient.Relate(elmid, modelId, Model.MEPEdgeTypes.IS_IN.ToString(), elmedgeProps);

                    Autodesk.Revit.DB.Element typeElm = null;


                    if (elm is Autodesk.Revit.DB.FamilyInstance)
                    {
                        typeElm = (elm as Autodesk.Revit.DB.FamilyInstance).Symbol;
                    }
                    else
                    {
                        var mpType = elm.GetTypeId();
                        typeElm = elmdoc.GetElement(mpType);
                    }



                    //create type nodes
                    if (typeElm != null)
                    {
                        PendingNode tsId = null;
                        if (!types.ContainsKey(typeElm.UniqueId))
                        {
                            var edgeProps = MEPGraphUtils.GetEdgeProps(typeElm);
                            var tsNode    = new Model.ElementType();
                            tsNode.Name = typeElm.Name;
                            var tsprops1 = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm);

                            tsId = _gdbClient.Push(tsNode, tsprops1);
                            types.Add(typeElm.UniqueId, tsId);

                            var tselmNode = new Model.ModelElement();
                            var tsprops2  = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm);
                            var tselmId   = _gdbClient.Push(tselmNode, tsprops2);

                            _gdbClient.Relate(tsId, tselmId, Model.MEPEdgeTypes.REALIZED_BY.ToString(), null);
                            _gdbClient.Relate(tselmId, modelId, Model.MEPEdgeTypes.IS_IN.ToString(), edgeProps);
                        }
                        else
                        {
                            tsId = types[typeElm.UniqueId];
                        }
                        _gdbClient.Relate(atid, tsId, Model.MEPEdgeTypes.IS_OF.ToString(), null);
                    }

                    //create level nodes
                    var lvl = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.LevelId));
                    if (lvl != null)
                    {
                        var         edgeProps = MEPGraphUtils.GetEdgeProps(lvl);
                        PendingNode lvlId     = null;
                        if (!levels.ContainsKey(lvl.UniqueId))
                        {
                            var lvlNode = new Model.Level();
                            lvlNode.Name = lvl.Name;
                            var lvlprops = MEPGraphUtils.GetNodePropsWithElementProps(lvlNode, lvl);
                            lvlId = _gdbClient.Push(lvlNode, lvlprops);
                            levels.Add(lvl.UniqueId, lvlId);
                            _gdbClient.Relate(lvlId, modelId, Model.MEPEdgeTypes.IS_IN.ToString(), edgeProps);
                        }
                        else
                        {
                            lvlId = levels[lvl.UniqueId];
                        }

                        _gdbClient.Relate(atid, lvlId, Model.MEPEdgeTypes.IS_ON.ToString(), null);
                    }
                }
                else
                {
                    var modelId = _gdbClient.Push(npNode, elmAbParams);
                    track.Add(mepNode, modelId);
                }
            }

            //now add the adjacencies
            foreach (var mepEdge in mepGraph.Edges)
            {
                if (!track.ContainsKey(mepEdge.ThisNode))
                {
                    continue;
                }

                if (!track.ContainsKey(mepEdge.NextNode))
                {
                    continue;
                }

                var nid1 = track[mepEdge.ThisNode];
                var nid2 = track[mepEdge.NextNode];

                var edPArams = new Dictionary <string, object>();
                foreach (var wkvp in mepEdge.Weights)
                {
                    edPArams.Add(wkvp.Key, wkvp.Value);
                }


                _gdbClient.Relate(nid1, nid2, mepEdge.AsNodeEdge.EdgeType.ToString(), edPArams);
            }


            //add systems and connections
            foreach (var system in mepGraph.Systems)
            {
                var sysNode = new Model.System();

                var syselm    = rootDoc.GetElement(new Autodesk.Revit.DB.ElementId(system));
                var srops     = MEPGraphUtils.GetNodePropsWithElementProps(sysNode, syselm);
                var sysNodeId = _gdbClient.Push(sysNode, srops);

                var tselmNode = new Model.ModelElement();
                tselmNode.ExtendedProperties.Add("UniqueId", syselm.UniqueId);

                var emprops = MEPGraphUtils.GetNodePropsWithElementProps(tselmNode, syselm);
                var tselmId = _gdbClient.Push(tselmNode, emprops);
                _gdbClient.Relate(sysNodeId, tselmId, Model.MEPEdgeTypes.REALIZED_BY.ToString(), null);
                var edgeProps = MEPGraphUtils.GetEdgeProps(syselm);
                _gdbClient.Relate(tselmId, seid, Model.MEPEdgeTypes.IS_IN.ToString(), edgeProps);


                var stypeId = syselm.GetTypeId();
                var typeElm = rootDoc.GetElement(stypeId);
                if (typeElm != null)
                {
                    PendingNode tsId = null;
                    if (!types.ContainsKey(typeElm.UniqueId))
                    {
                        var stypeedgeProps = MEPGraphUtils.GetEdgeProps(typeElm);
                        var tsNode         = new Model.ElementType();
                        tsNode.Name = typeElm.Name;
                        var tsprops1 = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm);

                        tsId = _gdbClient.Push(tsNode, tsprops1);
                        types.Add(typeElm.UniqueId, tsId);

                        var sysTypeelmNode = new Model.ModelElement();
                        var tsprops2       = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm);
                        var sysTypeelmId   = _gdbClient.Push(sysTypeelmNode, tsprops2);

                        _gdbClient.Relate(tsId, sysTypeelmId, Model.MEPEdgeTypes.REALIZED_BY.ToString(), null);
                        _gdbClient.Relate(tselmId, seid, Model.MEPEdgeTypes.IS_IN.ToString(), stypeedgeProps);
                    }
                    else
                    {
                        tsId = types[typeElm.UniqueId];
                    }

                    _gdbClient.Relate(sysNodeId, tsId, Model.MEPEdgeTypes.IS_OF.ToString(), null);
                }

                var snodes = mepGraph.GetAllNodesForSystem(system);
                foreach (var snd in snodes)
                {
                    if (!track.ContainsKey(snd))
                    {
                        continue;
                    }

                    var rid = track[snd];
                    _gdbClient.Relate(rid, sysNodeId, Model.MEPEdgeTypes.ABSTRACTED_BY.ToString(), null);
                }
            }

            AsyncContext.Run(() => _gdbClient.CommitAsync());
            //var task = Task.Run(() => AsyncContext.Run(() => _gdbClient.CommitAsync()));
            //task.Wait();
        }
예제 #2
0
        public void ParseFrom(Element elm, MEPRevitGraphWriter writer)
        {
            var space = elm as Autodesk.Revit.DB.Mechanical.Space;

            if (space == null)
            {
                return;
            }

            if (space.Volume < 0.5)
            {
                return;
            }

            var scannedElements = writer.Cache.ParsedElements;
            var cpTree          = writer.Cache.connectorsCache;
            var geoTree         = writer.Cache.geoCache;
            var maxDepth        = writer.Cache.MaxDepth;
            var graph           = writer.Graph;

            var lvl = space.Level;

            if (lvl != null)
            {
                graph.AddConnection(elm, lvl, MEPPathConnectionType.Proximity, MEPEdgeTypes.IS_ON);
            }

            //get elements in the space


            //get areas with edges and add to walls

            var sbopt = new SpatialElementBoundaryOptions();

            sbopt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish;
            sbopt.StoreFreeBoundaryFaces         = true;

            //var geoOpt = new Options();
            //var spgeo = space.get_Geometry(geoOpt);

            //get nearby spaces by extending bb of space
            //foreach each face of space geometry
            //split into uv gripd
            //construct line from each point
            //get intersect with faces on nearby faces
            //if it hits increment area count for direction

            var doc = space.Document;
            SpatialElementGeometryCalculator sg = new SpatialElementGeometryCalculator(doc, sbopt);
            var spgets = sg.CalculateSpatialElementGeometry(space);
            var spgeo  = spgets.GetGeometry();
            //var spbb = spgeo.GetBoundingBox();
            var spbb = elm.get_BoundingBox(null);

            //var spbbhl = new HLBoundingBoxXYZ(spbb);
            //spbbhl.Size = spbbhl.Size + new XYZ(2, 2, 4);


            //get faces
            var uvdensity   = 0.75;
            var maxDistance = 4D;
            //var nearbyFaces = nearbySpaces.OfType<SolidGeometrySegment>().Where(spc => spc.OriginatingElement != space.Id).SelectMany(sp => sp.Geometry.Faces.OfType<Face>());

            var rayIncidents = new HashSet <FaceIntersectRay>();


            //get all the faces in the geometry
            var spfaces = spgeo.Faces.OfType <Face>().ToList();

            foreach (var gface in spfaces)
            {
                //extract the faces which bound with other elements (Walls, floors, ceilings, windows etc)
                var sfaceInfos = spgets.GetBoundaryFaceInfo(gface);
                foreach (var sfaceInfo in sfaceInfos)
                {
                    //get the geo face and element of this bounding face
                    var sface = sfaceInfo.GetSubface();

                    var elmId = sfaceInfo.SpatialBoundaryElement;

                    var lelm     = GetElementFromLinkedElement(elmId, doc);
                    var docIdent = string.Empty;
                    //if (lelm == null) continue; //ignore this face if it doesn't resolve to a valid element

                    //find the bounding uv box so we can work out a grid of points
                    var fbb  = sface.GetBoundingBox();
                    var uExt = uvdensity; // (fbb.Max.U - fbb.Min.U) / uvdensity;
                    var vExt = uvdensity; // (fbb.Max.V - fbb.Min.V) / uvdensity;

                    var u = fbb.Min.U;
                    var v = fbb.Min.V;

                    //var sb = new GeoLib.C2DPolygon();

                    //construct grid for ray tracing
                    Stack <UV> gridPoints = new Stack <UV>();
                    while (u <= fbb.Max.U)
                    {
                        v = fbb.Min.V;
                        while (v <= fbb.Max.V)
                        {
                            var uvp = new UV(u, v);
                            v += uvdensity;
                            if (!sface.IsInside(uvp))
                            {
                                continue;                       //only include points that are actually on this face
                            }
                            gridPoints.Push(uvp);
                        }
                        u += uvdensity;
                    }

                    var nerbyCheckCats         = new int[] { };
                    IList <ElementId> hostElms = new List <ElementId>();

                    if (lelm != null && !(lelm is HostObject))
                    {
                        var n = lelm;
                    }

                    if (lelm != null)
                    {
                        docIdent = DocUtils.GetDocumentIdent(lelm.Document);
                        //get cutting elemtns if it's a wall so we can find door and windows
                        if (lelm is HostObject)
                        {
                            var whost = lelm as HostObject;
                            hostElms = whost.FindInserts(true, true, true, true);
                            //build oct tree of hostelems so we can quickly ray trace them later
                            foreach (var hostElm in hostElms)
                            {
                                //ignoring any link and transform for now
                                var ehl = whost.Document.GetElement(hostElm);
                                writer.Cache.geoCacheWriter.AddElement(ehl, true);
                            }
                        }

                        //we need the nearby check to find the cut out elements
                        nerbyCheckCats = new int[] { (int)BuiltInCategory.OST_Doors, (int)BuiltInCategory.OST_Windows };
                    }
                    else
                    {
                        nerbyCheckCats = new int[] { (int)BuiltInCategory.OST_Doors, (int)BuiltInCategory.OST_Windows, (int)BuiltInCategory.OST_Floors, (int)BuiltInCategory.OST_Walls, (int)BuiltInCategory.OST_Roofs };

                        //we need the nearby check to find the bounding element
                        switch (sfaceInfo.SubfaceType)
                        {
                        case SubfaceType.Bottom:
                            nerbyCheckCats = new int[] { (int)BuiltInCategory.OST_Floors };
                            break;

                        case SubfaceType.Top:
                            nerbyCheckCats = new int[] { (int)BuiltInCategory.OST_Roofs, (int)BuiltInCategory.OST_Floors, (int)BuiltInCategory.OST_Windows };
                            break;

                        case SubfaceType.Side:
                            nerbyCheckCats = new int[] { (int)BuiltInCategory.OST_Doors, (int)BuiltInCategory.OST_Windows, (int)BuiltInCategory.OST_Walls };
                            break;
                        }
                    }

                    //option 1 - brute force ray trace
                    //option 2 - construct 2d polygon from edges of each face, translate each face into the same plane, then boolean intersect, get area of each intersect
                    //calc space boundaries at midpoint?
                    Face optLastIntermeidateFace = null;
                    SolidGeometrySegment optLastIntermeidateSegment = null;
                    Face optLastHitFace = null;
                    SolidGeometrySegment optLastHitSegment = null;
                    var arWeight = sface.Area / gridPoints.Count;
                    while (gridPoints.Count > 0)
                    {
                        var pt          = gridPoints.Pop();
                        var rayIncident = new FaceIntersectRay();

                        var nv = sface.ComputeNormal(pt).Normalize();
                        //var mx = sface.ComputeSecondDerivatives(pt).MixedDerivative.Normalize();
                        rayIncident.SourceElement = space;
                        rayIncident.SourceFace    = sface;
                        rayIncident.SourceUV      = pt;

                        rayIncident.RayVecotor          = nv;
                        rayIncident.IntermediatDocIdent = docIdent;
                        rayIncident.IntermeidateElement = lelm != null ? lelm.Id : ElementId.InvalidElementId;
                        rayIncident.AreaWeight          = arWeight;
                        rayIncident.SubFaceType         = sfaceInfo.SubfaceType;
                        rayIncidents.Add(rayIncident);

                        var sp = sface.Evaluate(pt);
                        rayIncident.SourceXYZ = sp;
                        var ray   = Line.CreateBound(sp, sp + nv * 4);
                        var rayBB = new HLBoundingBoxXYZ(sp, (sp + nv * 4), true);
                        //rayBB.Size = rayBB.Size + new XYZ(0.5, 0.5, 0.5);
                        //Plane geoPlane = Plane.c(sp, sp + nv * 5, sp + nv * 5 + (mx * 0.2));
                        //SketchPlane skPlane = SketchPlane.Create(doc, geoPlane);
                        //doc.Create.NewModelCurve(ray, skPlane);

                        //check cache for hit on otherside, if there is one nearby on this face we can ignore it as we're not including both sides
                        //var nearbyrayHits = writer.Cache.rayhitCache.GetNearby(ray, 0.4F);
                        //var validSimilarHit = nearbyrayHits.FirstOrDefault(rh => rh.HittingSegment != null && rh.HittingSegment.OriginatingElement == space.Id && rh.IntermeidateElement == rayIncident.IntermeidateElement);
                        //if (validSimilarHit != null && sface.IsInside(validSimilarHit.HittingUV))
                        //{
                        //    rayIncident.Ignore = true;
                        //    log.Info("Got hit on other side, ignoring");
                        //    continue;
                        // }

                        if (optLastIntermeidateFace != null)
                        {
                            IntersectionResultArray issRes = null;
                            var issGeoHit = getIntersect(pt, optLastIntermeidateFace, sface, maxDistance, out issRes, out double distance, nv, doc);
                            if (issGeoHit)
                            {
                                rayIncident.IntermediatDocIdent = optLastIntermeidateSegment.OriginatingDocIdent;
                                rayIncident.IntermeidateElement = optLastIntermeidateSegment.OriginatingElement;
                            }
                            else
                            {
                                optLastIntermeidateFace    = null;
                                optLastIntermeidateSegment = null;
                            }
                        }

                        GeometrySegment[] nearbyElements = null;

                        if (optLastIntermeidateFace == null)
                        {
                            nearbyElements = geoTree.GetColliding(rayBB);

                            var nearbyCutoutElements = nearbyElements.Where(iel =>
                                                                            (hostElms.Count == 0 || hostElms.Contains(iel.OriginatingElement)) &&
                                                                            nerbyCheckCats.Contains(iel.OriginatingElementCategory.IntegerValue))
                                                       .OfType <SolidGeometrySegment>();


                            IntersectionResultArray isRes = null;
                            bool isGeoHit = false;
                            foreach (var extSegment in nearbyCutoutElements)
                            {
                                foreach (var extFace in extSegment.Geometry.Faces.OfType <Face>())
                                {
                                    isGeoHit = getIntersect(pt, extFace, sface, maxDistance, out isRes, out double distance, nv, doc);
                                    if (isGeoHit)
                                    {
                                        rayIncident.IntermediatDocIdent = extSegment.OriginatingDocIdent;
                                        rayIncident.IntermeidateElement = extSegment.OriginatingElement;
                                        optLastIntermeidateFace         = extFace;
                                        optLastIntermeidateSegment      = extSegment;
                                        break;
                                    }
                                }
                                if (isGeoHit)
                                {
                                    break;
                                }
                            }
                        }



                        if (optLastHitFace != null)
                        {
                            var isHit = getIntersect(pt, optLastHitFace, sface, maxDistance, out var isRe, out double distance, nv, doc);
                            var isRes = isRe;
                            //project point onto other face instead?
                            var srcXYZ   = sface.Evaluate(pt);
                            var otXYZRes = optLastHitFace.Project(srcXYZ);

                            if (isHit)
                            {
                                var itx = isRes.OfType <IntersectionResult>().FirstOrDefault();
                                rayIncident.HittingFace    = optLastHitFace;
                                rayIncident.HittingSegment = optLastHitSegment;
                                rayIncident.HittingUV      = itx.UVPoint;
                                rayIncident.HittingXYZ     = itx.XYZPoint;
                                rayIncident.Distance       = distance;
                                nv = sface.ComputeNormal(pt).Normalize();
                                continue; //shortcut if we find a hit on the same face again
                            }
                            else
                            {
                                optLastHitFace    = null;
                                optLastHitSegment = null;
                            }
                        }


                        if (nearbyElements == null)
                        {
                            nearbyElements = geoTree.GetColliding(rayBB, (ob) => { return(ob.OriginatingElementCategory.IntegerValue == (int)BuiltInCategory.OST_MEPSpaces); });
                        }

                        //BoundingBoxIntersectsFilter bif = new BoundingBoxIntersectsFilter(new Outline(sp - new XYZ(0.1, 0.1, 0.1), (sp + nv * 2) + new XYZ(0.1, 0.1, 0.1)));
                        //var sfv = new FilteredElementCollector(space.Document);
                        //var sepl = sfv.WherePasses(bif).ToElements();

                        var nearbySpaces = nearbyElements.Where(ne => ne.OriginatingElementCategory.IntegerValue == (int)BuiltInCategory.OST_MEPSpaces).OfType <SolidGeometrySegment>().Distinct().ToList();

                        //find the extents of this face which face faces on other nearby faces (whaaat?)
                        //check each face of each nearby space for intersect with ray
                        foreach (var nearSpace in nearbySpaces)
                        {
                            var isHit = false;
                            foreach (var otFace in nearSpace.Geometry.Faces.OfType <Face>())
                            {
                                isHit = getIntersect(pt, otFace, sface, maxDistance, out var isRe, out double distance, nv, doc);
                                var isRes = isRe;
                                //project point onto other face instead?
                                var srcXYZ   = sface.Evaluate(pt);
                                var otXYZRes = otFace.Project(srcXYZ);

                                if (isHit)
                                {
                                    if (nearSpace.OriginatingElement.IntegerValue != elm.Id.IntegerValue)
                                    {
                                        var itx = isRes.OfType <IntersectionResult>().FirstOrDefault();
                                        rayIncident.HittingFace    = otFace;
                                        rayIncident.HittingSegment = nearSpace;
                                        rayIncident.HittingUV      = itx.UVPoint;
                                        rayIncident.HittingXYZ     = itx.XYZPoint;
                                        rayIncident.Distance       = distance;

                                        nv = sface.ComputeNormal(pt).Normalize();

                                        //optimization: check this face again first for the next ray check, since it's likely to be another hit
                                        optLastHitFace    = otFace;
                                        optLastHitSegment = nearSpace;

                                        rayIncident.Ignore = false;
                                    }
                                    else
                                    {
                                        if (distance < 0.1)
                                        {
                                            isHit = false;                 //looks like we hit our own face, ouch!
                                        }
                                        rayIncident.Ignore = true;
                                    }

                                    break;
                                }
                            }
                            if (isHit)
                            {
                                break;
                            }
                        }
                    }
                }

                /*
                 * space
                 * face
                 *    intermediate element (Wall/window/door)
                 *        face (space)
                 * face
                 *
                 *
                 * add connection
                 * this space -> section -> other space
                 * wall ------------^
                 */
            }

            //var ec = new elmComparer();
            var              srcNode        = graph.AddElement(space);
            double           minIncluedArea = 4;
            VectorBucketiser vbw            = new VectorBucketiser(8, 5);

            var includeRays = rayIncidents.Where(r => !r.Ignore);

            var outsideNode = graph.Nodes.FirstOrDefault(n => n.Name == "Outside");
            var groundNode  = graph.Nodes.FirstOrDefault(n => n.Name == "Ground");

            //group by the intermediate element (wall/floor/etc)
            foreach (var docGroup in includeRays.GroupBy(ri => ri.IntermediatDocIdent))//, ec))
            {
                var sdoc = DocUtils.GetDocument(docGroup.Key, elm.Document.Application);

                foreach (var intermediateElemGroup in docGroup.GroupBy(ri => ri.IntermeidateElement.IntegerValue))//, ec))
                {
                    var     selmid = new ElementId(intermediateElemGroup.Key);
                    Element selm   = sdoc != null?sdoc.GetElement(selmid) : null;

                    //group similar vectors into buckets
                    foreach (var rayVectorBuckets in intermediateElemGroup.GroupBy(ri => vbw.GetBucket(ri.RayVecotor)))
                    {
                        var rg = rayVectorBuckets.ToList();

                        var gs = rg.GroupBy(vr => vr.HittingSegment == null ? null : vr.HittingSegment.OriginatingElement).ToList();
                        //group each vector and intermediate element by the element it hits
                        foreach (var orgElmGroup in gs)
                        {
                            //find a section already matching this section
                            //actually easier to treat each path as separate sections
                            //var edNodes = graph.GetEdges(intermediateElemGroup.Key).Where(ed => ed.NextNode.AsAbstractNode.Name == "Surface"
                            //&& ed.NextNode.Connections.Any(cn => cn.NextNode.OriginId == spNode.OriginId)).Where(ed => ed.;

                            var apporxIntersect = orgElmGroup.Sum(et => et.AreaWeight);
                            var vector          = orgElmGroup.First().RayVecotor;
                            if (apporxIntersect < minIncluedArea)
                            {
                                continue;
                            }

                            var direction = VectorBucketiser.GetZeroClamppedPoint(orgElmGroup.First().RayVecotor); //should be rayVectorGroup.Key.AverageVector, but not yet implemented;

                            MEPRevitNode spNode = null;
                            if (orgElmGroup.Key != null)
                            {
                                var otherSpace = doc.GetElement(orgElmGroup.Key);
                                spNode = graph.AddElement(otherSpace);
                            }
                            else
                            {
                                if (selm != null && (selm.Name.ToLower().Contains("exterior") || selm is Autodesk.Revit.DB.Opening || selm.Name.ToLower().Contains("window") || selm is Autodesk.Revit.DB.RoofBase))
                                {
                                    if (outsideNode == null)
                                    {
                                        outsideNode = new MEPRevitNode("Outside", "Boundary", "OutsideBoundary", new MEPGraph.Model.Environment());
                                    }
                                    spNode = outsideNode;
                                }
                                else if (selm != null && (selm.Name.ToLower().Contains("floor") || selm is Autodesk.Revit.DB.Floor))
                                {
                                    if (groundNode == null)
                                    {
                                        groundNode = new MEPRevitNode("Ground", "Boundary", "GroundBoundary", new MEPGraph.Model.Environment());
                                    }
                                    spNode = groundNode;
                                }
                                else
                                {
                                    spNode = new MEPRevitNode("Void", "Boundary", "OtherBoundary", new MEPGraph.Model.VoidVolume());
                                    continue; //ignore void boundaries for now
                                }
                            }


                            var sectionN = graph.NewSection(selm, MEPGraph.Model.MEPEdgeTypes.IS_ON);

                            if (selm == null)
                            {
                                var emptyBondary = new MEPRevitNode();
                                emptyBondary.AsAbstractNode.Name = "OpenBoundary";
                                var cl = graph.AddConnection(emptyBondary, sectionN, MEPPathConnectionType.SectionOf, MEPGraph.Model.MEPEdgeTypes.IS_ON);
                                cl.AsNodeEdge.ExtendedProperties.Add("rvid", intermediateElemGroup.Key);
                            }

                            sectionN.AsAbstractNode.Name = "Surface";
                            var edgesf = graph.AddConnection(srcNode, sectionN, MEPPathConnectionType.Analytical, MEPGraph.Model.MEPEdgeTypes.BOUNDED_BY);

                            //total up intersecting area
                            var sampleIntersect = orgElmGroup.First();


                            edgesf.SetWeight("Area", apporxIntersect);
                            //edgesf.SetWeight("Direction", new HoareLea.MEPGraph.Model.MEPPoint(direction.X, direction.Y, direction.Z));
                            edgesf.SetWeight("DirectionX", direction.X);
                            edgesf.SetWeight("DirectionY", direction.Y);
                            edgesf.SetWeight("DirectionZ", direction.Z);
                            edgesf.SetWeight("SubFaceType", (int)sampleIntersect.SubFaceType);

                            /*
                             * HLBoundingBoxXYZ bb = new HLBoundingBoxXYZ();
                             * foreach (var et in orgElmGroup)
                             * {
                             *  if (et.HittingXYZ != null)
                             *  {
                             *      bb.ExpandToContain(et.HittingXYZ);
                             *  }
                             * }
                             * if (!bb.IsInvalid)
                             * {
                             *  sectionN.BoundingBox = bb;
                             *  var avgCenterPoint = bb.MidPoint;
                             *  var size = bb.Size;
                             *  sectionN.SetProperty("OriginX", avgCenterPoint.X);
                             *  sectionN.SetProperty("OriginY", avgCenterPoint.Y);
                             *  sectionN.SetProperty("OriginZ", avgCenterPoint.Z);
                             *  sectionN.SetProperty("SizeX", size.X);
                             *  sectionN.SetProperty("SizeY", size.Y);
                             *  sectionN.SetProperty("SizeZ", size.Z);
                             * }*/



                            var edgest     = graph.AddConnection(sectionN, spNode, MEPPathConnectionType.Analytical, MEPGraph.Model.MEPEdgeTypes.BOUNDED_BY);
                            var directionn = direction;//.Negate();
                            edgest.SetWeight("Area", apporxIntersect);
                            edgest.SetWeight("DirectionX", directionn.X);
                            edgest.SetWeight("DirectionY", directionn.Y);
                            edgest.SetWeight("DirectionZ", directionn.Z);
                            edgest.SetWeight("SubFaceType", (int)sampleIntersect.SubFaceType);
                        }
                    }
                }
            }
        }
예제 #3
0
        public void Write(MEPRevitGraph mepGraph, BuildingGraphMapping clientMapping, Autodesk.Revit.DB.Document rootDoc)
        {
            var track  = new Dictionary <MEPRevitNode, PendingNode>();
            var models = new Dictionary <string, PendingNode>();
            var types  = new Dictionary <string, PendingNode>();
            var levels = new Dictionary <string, PendingNode>();

            var rootModelNode  = new Model.RevitModel();
            var rootModelIdent = DocUtils.GetDocumentIdent(rootDoc);

            rootModelNode.Name = rootDoc.PathName;
            rootModelNode.ExtendedProperties.Add("Identity", rootModelIdent);
            rootModelNode.ExtendedProperties.Add("DateTimeStamp", System.DateTime.Now.ToShortDateString());

            var schema = _gdbClient.GetSchema();

            //gather data from the graph about nodes which already exist
            string dGather = @"query($modelIdent:String){
  Model (Identity:$modelIdent){
    Identity
    ModelElements {
      UniqueId
      AbstractElement {
        NodeType: __typename
        Name
        ... on Space{
          Number
          Name
          Area
          Id
        }
        ... on Level{
          Name
          Elevation
        }
      }
    }
  }
}";


            var vars = new Dictionary <string, object>();

            vars.Add("modelIdent", rootModelIdent);
            var res = _gdbClient.ExecuteQuery(dGather, vars);

            var     dbModels    = res.Result.Model;
            dynamic dbRootModel = null;
            Dictionary <string, dynamic> modElmCache = new Dictionary <string, dynamic>();

            if (models != null)
            {
                foreach (var model in models)
                {
                    dbRootModel = model;
                    foreach (var modelElement in dbModels.ModelElements)
                    {
                        var meID = modelElement.UniqueId.Value;
                        if (meID == null)
                        {
                            continue;
                        }
                        if (!modElmCache.ContainsKey(meID))
                        {
                            modElmCache.Add(modelElement.UniqueId.Value, modelElement);
                        }
                        else
                        {
                            //there shouldn't be multiple
                            modElmCache[meID] = modelElement;
                        }
                    }
                }
            }



            var         rootparams = MEPGraphUtils.GetNodePropsWithElementProps(rootModelNode, rootDoc.ProjectInformation, schema, clientMapping, true);
            PendingNode seid       = null;

            if (dbRootModel == null)
            {
                seid = _gdbClient.Push(rootModelNode.Label, rootparams);
            }
            else
            {
                seid = _gdbClient.Push(rootModelNode.Label, rootparams);
            }

            models.Add(rootModelIdent, seid);

            var exprops = new Dictionary <string, object>();

            exprops.Add("test", 1);


            //add the nodes
            foreach (var mepNode in mepGraph.Nodes)
            {
                var npNode      = mepNode.AsAbstractNode;
                var elmAbParams = npNode.GetAllProperties();


                if (!string.IsNullOrEmpty(mepNode.OrginDocIdent))
                {
                    var elmNode  = mepNode.AsElementNode;
                    var elmParms = elmNode.GetAllProperties();

                    var elmdoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application);
                    var elm    = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.OriginId));
                    if (elm != null)
                    {
                        elmParms    = MEPGraphUtils.GetNodePropsWithElementProps(elmNode, elm, schema, clientMapping, true);
                        elmAbParams = MEPGraphUtils.GetNodePropsWithElementProps(npNode, elm, schema, clientMapping, true);
                    }

                    var atid = _gdbClient.Push(npNode.Label, elmAbParams);
                    track.Add(mepNode, atid);

                    var elmid = _gdbClient.Push(elmNode.Label, elmParms);

                    //relate the element node to the abstracted model node
                    _gdbClient.Relate(atid, elmid, Model.MEPEdgeTypes.REALIZED_BY, null);


                    PendingNode modelId = null;
                    //create up model nodes
                    if (models.ContainsKey(mepNode.OrginDocIdent))
                    {
                        modelId = models[mepNode.OrginDocIdent];
                    }
                    else
                    {
                        var modelNode = new Model.RevitModel();
                        modelNode.ExtendedProperties.Add("Identity", mepNode.OrginDocIdent);
                        var mparams = modelNode.GetAllProperties();

                        var ldoc = DocUtils.GetDocument(mepNode.OrginDocIdent, rootDoc.Application);
                        if (ldoc != null)
                        {
                            mparams = MEPGraphUtils.GetNodePropsWithElementProps(modelNode, ldoc.ProjectInformation, schema, clientMapping, true);
                        }

                        modelId = _gdbClient.Push(modelNode.Label, mparams);
                        models.Add(mepNode.OrginDocIdent, modelId);
                    }

                    var elmedgeProps = MEPGraphUtils.GetEdgeProps(elm);
                    //connect up model node to element node
                    _gdbClient.Relate(elmid, modelId, Model.MEPEdgeTypes.IS_IN, elmedgeProps);

                    Autodesk.Revit.DB.Element typeElm = null;


                    if (elm is Autodesk.Revit.DB.FamilyInstance)
                    {
                        typeElm = (elm as Autodesk.Revit.DB.FamilyInstance).Symbol;
                    }
                    else
                    {
                        var mpType = elm.GetTypeId();
                        typeElm = elmdoc.GetElement(mpType);
                    }



                    //create type nodes
                    if (typeElm != null)
                    {
                        PendingNode tsId = null;
                        if (!types.ContainsKey(typeElm.UniqueId))
                        {
                            var edgeProps = MEPGraphUtils.GetEdgeProps(typeElm);
                            var tsNode    = new Model.ElementType();
                            tsNode.Name = typeElm.Name;
                            var tsprops1 = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm, schema, clientMapping, true);

                            tsId = _gdbClient.Push(tsNode.Label, tsprops1);
                            types.Add(typeElm.UniqueId, tsId);

                            var tselmNode = new Model.ModelElement();
                            var tsprops2  = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm, schema, clientMapping, true);
                            var tselmId   = _gdbClient.Push(tselmNode.Label, tsprops2);

                            _gdbClient.Relate(tsId, tselmId, Model.MEPEdgeTypes.REALIZED_BY, exprops);
                            _gdbClient.Relate(tselmId, modelId, Model.MEPEdgeTypes.IS_IN, edgeProps);
                        }
                        else
                        {
                            tsId = types[typeElm.UniqueId];
                        }
                        _gdbClient.Relate(atid, tsId, Model.MEPEdgeTypes.IS_OF, exprops);
                    }

                    //create level nodes
                    var lvl = elmdoc.GetElement(new Autodesk.Revit.DB.ElementId(mepNode.LevelId));
                    if (lvl != null)
                    {
                        var         edgeProps = MEPGraphUtils.GetEdgeProps(lvl);
                        PendingNode lvlId     = null;
                        if (!levels.ContainsKey(lvl.UniqueId))
                        {
                            var lvlNode = new Model.Level();
                            lvlNode.Name = lvl.Name;
                            var lvlprops = MEPGraphUtils.GetNodePropsWithElementProps(lvlNode, lvl, schema, clientMapping, true);
                            lvlId = _gdbClient.Push(lvlNode.Label, lvlprops);
                            levels.Add(lvl.UniqueId, lvlId);
                            _gdbClient.Relate(lvlId, modelId, Model.MEPEdgeTypes.IS_IN, edgeProps);
                        }
                        else
                        {
                            lvlId = levels[lvl.UniqueId];
                        }

                        _gdbClient.Relate(atid, lvlId, Model.MEPEdgeTypes.IS_ON, exprops);
                    }
                }
                else
                {
                    var modelId = _gdbClient.Push(npNode.Label, elmAbParams);
                    track.Add(mepNode, modelId);
                }
            }

            //now add the adjacencies
            foreach (var mepEdge in mepGraph.Edges)
            {
                if (!track.ContainsKey(mepEdge.ThisNode))
                {
                    continue;
                }

                if (!track.ContainsKey(mepEdge.NextNode))
                {
                    continue;
                }

                var nid1 = track[mepEdge.ThisNode];
                var nid2 = track[mepEdge.NextNode];

                var edPArams = new Dictionary <string, object>();
                foreach (var wkvp in mepEdge.Weights)
                {
                    edPArams.Add(wkvp.Key, wkvp.Value);
                }


                _gdbClient.Relate(nid1, nid2, mepEdge.AsNodeEdge.EdgeType, edPArams);
            }


            //add systems and connections
            foreach (var system in mepGraph.Systems)
            {
                var sysNode = new Model.System();

                var syselm    = rootDoc.GetElement(new Autodesk.Revit.DB.ElementId(system));
                var srops     = MEPGraphUtils.GetNodePropsWithElementProps(sysNode, syselm, schema, clientMapping, true);
                var sysNodeId = _gdbClient.Push(sysNode.Label, srops);

                var tselmNode = new Model.ModelElement();
                tselmNode.ExtendedProperties.Add("UniqueId", syselm.UniqueId);

                var emprops = MEPGraphUtils.GetNodePropsWithElementProps(tselmNode, syselm, schema, clientMapping, true);
                var tselmId = _gdbClient.Push(tselmNode.Label, emprops);
                _gdbClient.Relate(sysNodeId, tselmId, Model.MEPEdgeTypes.REALIZED_BY, null);
                var edgeProps = MEPGraphUtils.GetEdgeProps(syselm);
                _gdbClient.Relate(tselmId, seid, Model.MEPEdgeTypes.IS_IN, edgeProps);


                var stypeId = syselm.GetTypeId();
                var typeElm = rootDoc.GetElement(stypeId);
                if (typeElm != null)
                {
                    PendingNode tsId = null;
                    if (!types.ContainsKey(typeElm.UniqueId))
                    {
                        var stypeedgeProps = MEPGraphUtils.GetEdgeProps(typeElm);
                        var tsNode         = new Model.ElementType();
                        tsNode.Name = typeElm.Name;
                        var tsprops1 = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm, schema, clientMapping, true);

                        tsId = _gdbClient.Push(tsNode.Label, tsprops1);
                        types.Add(typeElm.UniqueId, tsId);

                        var sysTypeelmNode = new Model.ModelElement();
                        var tsprops2       = MEPGraphUtils.GetNodePropsWithElementProps(tsNode, typeElm, schema, clientMapping, true);
                        var sysTypeelmId   = _gdbClient.Push(sysTypeelmNode.Label, tsprops2);

                        _gdbClient.Relate(tsId, sysTypeelmId, Model.MEPEdgeTypes.REALIZED_BY, null);
                        _gdbClient.Relate(tselmId, seid, Model.MEPEdgeTypes.IS_IN, stypeedgeProps);
                    }
                    else
                    {
                        tsId = types[typeElm.UniqueId];
                    }

                    _gdbClient.Relate(sysNodeId, tsId, Model.MEPEdgeTypes.IS_OF, null);
                }

                var snodes = mepGraph.GetAllNodesForSystem(system);
                foreach (var snd in snodes)
                {
                    if (!track.ContainsKey(snd))
                    {
                        continue;
                    }

                    var rid = track[snd];
                    _gdbClient.Relate(rid, sysNodeId, Model.MEPEdgeTypes.ABSTRACTED_BY, null);
                }
            }

            _gdbClient.Commit();
        }