Exemplo n.º 1
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);
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates the element in the model
        /// </summary>
        /// <param name="doc"></param>
        public void CreateLocal(StreamMessage message)
        {
            //insert at position?
            //find space it's in?
            //find family symbol/type?
            _dispatcher.QueueAction((uiapp) =>
            {
                var doc = uiapp.ActiveUIDocument.Document;

                var node        = message.After.AsNode();
                var nodeElement = doc.GetElement(node.Id);

                using (var updatetx = new Transaction(doc, "Update from stream"))
                {
                    updatetx.Start("Update from stream");

                    if (node.Labels.Contains("FanCoilUnit"))
                    {
                        if (nodeElement == null)
                        {
                            //create node
                            //
                            //get the space it's in

                            var query = @"
query($fcuid:ID!){
 FanCoilUnit (Id:$fcuid){
   Id
   ModelElements{
      Id
      UniqueId
     }
   Space{
        Id
     }
    ConnectedTo{
      Id
      Apparent_Load
      ModelElements{
       Id
       UniqueId
     }
    }
   }
}";
                            var vars  = new Dictionary <string, object>();
                            vars.Add("fcuid", node.Id);

                            var res = _client.ExecuteQuery(query, vars);

                            if (res.FanCoilUnit != null)
                            {
                                var fcu          = res.FanCoilUnit[0];
                                Element modelElm = null;
                                foreach (var modelelemet in fcu.ModelElements)
                                {
                                    var id   = modelelemet.UniqueId.Value;
                                    modelElm = doc.GetElement((string)id);
                                    if (modelElm != null)
                                    {
                                        break;
                                    }
                                }

                                if (fcu.Space != null)
                                {
                                    var spaceId = fcu.Space.Id.Value;

                                    //find space
                                    var spaceElm = doc.GetElement((string)spaceId) as SpatialElement;
                                    if (spaceElm != null)
                                    {
                                        //find center
                                        MEPRevitNode rv = new MEPRevitNode(spaceElm);

                                        var sbopt = new SpatialElementBoundaryOptions();
                                        sbopt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish;
                                        sbopt.StoreFreeBoundaryFaces         = true;
                                        SpatialElementGeometryCalculator sg  = new SpatialElementGeometryCalculator(doc, sbopt);
                                        var spgets = sg.CalculateSpatialElementGeometry(spaceElm);

                                        var spgeo        = spgets.GetGeometry();
                                        var center       = spgeo.ComputeCentroid();
                                        var bbox         = spgeo.GetBoundingBox();
                                        var heightOfUnit = 1;
                                        var randomOffset = (bbox.Max.X - bbox.Min.X) / 2 * (new Random().NextDouble() - 0.5);
                                        var inspoint     = new XYZ(center.X + randomOffset, center.Y, bbox.Max.Z - heightOfUnit);


                                        FilteredElementCollector famFilter = new FilteredElementCollector(doc);

                                        //this is static for this example. We will need to discover the type and pull the family
                                        //from a family library service.
                                        string familyName = "HL_FanCoilUnit_HotandChilledWaterSoffit3HorizontalRoundConnections";

                                        Family foundFam = famFilter.OfClass(typeof(Family)).ToElements().OfType <Family>().FirstOrDefault(fm => fm.Name == familyName);
                                        var fcuSymbol   = doc.GetElement(foundFam.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;

                                        var newElm = doc.Create.NewFamilyInstance(inspoint, fcuSymbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);


                                        //var props = MEPGraphUtils.GetNodePropsWithElementProps(new Client.Model.ModelElement(), newElm);
                                        //var newnode = _client.Push("ModelElement", props);
                                        //_client.Relate(new PendingNode(node), newnode, Client.Model.MEPEdgeTypes.REALIZED_BY, null);



                                        var nodeparamers = node.ExtendedProperties;
                                        foreach (var param in newElm.Parameters.OfType <Parameter>())
                                        {
                                            if (param.IsReadOnly)
                                            {
                                                continue;
                                            }

                                            var hp        = new HLRevitParameter(param);
                                            var paramName = Utils.GetGraphQLCompatibleFieldName(param.Definition.Name);

                                            if (nodeparamers.ContainsKey(paramName))
                                            {
                                                var incommingValue = nodeparamers[paramName];
                                                var currentValue   = MEPGraphUtils.RevitToGraphValue(hp);

                                                if (incommingValue != currentValue)
                                                {
                                                    hp.Value = incommingValue;
                                                }
                                            }
                                        }

                                        if (fcu.ConnectedTo != null)
                                        {
                                            string fcuName = "FCU";

                                            Family foundfcuFam = famFilter.OfClass(typeof(Family)).ToElements().OfType <Family>().FirstOrDefault(fm => fm.Name == fcuName);
                                            var fcueSymbol     = doc.GetElement(foundFam.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
                                            var fcuEinspt      = inspoint + new XYZ(1, 0, 0);
                                            var newFuceElm     = doc.Create.NewFamilyInstance(fcuEinspt, fcuSymbol, Autodesk.Revit.DB.Structure.StructuralType.NonStructural);


                                            foreach (var param in newFuceElm.Parameters.OfType <Parameter>())
                                            {
                                                if (param.IsReadOnly)
                                                {
                                                    continue;
                                                }

                                                var hp        = new HLRevitParameter(param);
                                                var paramName = Utils.GetGraphQLCompatibleFieldName(param.Definition.Name);

                                                if (fcu.ConnectedTo[paramName] != null)
                                                {
                                                    var incommingValue = fcu.ConnectedTo[paramName].Value;
                                                    var currentValue   = MEPGraphUtils.RevitToGraphValue(hp);

                                                    if (incommingValue != currentValue)
                                                    {
                                                        hp.Value = incommingValue;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    updatetx.Commit();
                }
            });
        }