public void AddElement(Element elm) { if (_pointStree == null) { return; } var elmid = elm.Id.IntegerValue; HashSet <GeometrySegment> segList; if (SegmentCache.ContainsKey(elmid)) { segList = SegmentCache[elmid]; } else { segList = new HashSet <GeometrySegment>(); } if (elm.Location is LocationPoint) { var lpoint = elm.Location as LocationPoint; PointGeometrySegment psg = null; if (elm is FamilyInstance) { var fi = elm as FamilyInstance; psg = new PointGeometrySegment(elm.Id, lpoint.Point, fi.FacingOrientation, fi.HandOrientation, fi.FacingFlipped, fi.HandFlipped); } else { psg = new PointGeometrySegment(elm.Id, lpoint.Point); } _pointStree.Add(psg, lpoint.Point); } else if (elm.Location is LocationCurve) { var curve = elm.Location as LocationCurve; if (curve == null) { return; } var cseg = new CurveGeometrySegment(curve.Curve, elm); segList.Add(cseg); _pointStree.Add(cseg, cseg.MidPoint); } if (!SegmentCache.ContainsKey(elmid)) { SegmentCache.Add(elmid, segList); } }
public virtual void ParseFrom(Element elm, MEPRevitGraphWriter writer) { 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 elmStack = new Stack <Tuple <Element, XYZ> >(); elmStack.Push(new Tuple <Element, XYZ>(elm, null)); var previouseConnections = new HashSet <Connector>(); while (elmStack.Count >= 1) { var currentElementAndpt = elmStack.Pop(); var currentElement = currentElementAndpt.Item1; var orgPoint = currentElementAndpt.Item2; scannedElements.Add(currentElement.Id.IntegerValue); ConnectorManager currentCm = Utils.MEPUtils.GetConnectionManager(currentElement); if (currentCm == null) { continue; } var connStack = new Stack <Connector>(); foreach (var conn in currentCm.Connectors.OfType <Connector>().Where(cn => cn.ConnectorType == ConnectorType.End || cn.ConnectorType == ConnectorType.Curve))// && !previouseConnections.Any(pc => pc.IsConnectedTo(cn)))) { connStack.Push(conn); } XYZ nextOrigin = null; while (connStack.Count >= 1) { var currentConn = connStack.Pop(); Connector nextConnector = null; Element nextElement = null; nextOrigin = currentConn.Origin; MEPRevitEdge edge = null; var meps = GetSectionForConnctor(currentConn); var edgeType = MEPGraph.Model.MEPEdgeTypes.FLOWS_TO; switch (currentConn.Domain) { case Autodesk.Revit.DB.Domain.DomainCableTrayConduit: edgeType = MEPGraph.Model.MEPEdgeTypes.CABLETRAY_FLOW_TO; break; case Autodesk.Revit.DB.Domain.DomainElectrical: edgeType = MEPGraph.Model.MEPEdgeTypes.ELECTRICAL_FLOW_TO; break; case Autodesk.Revit.DB.Domain.DomainPiping: edgeType = MEPGraph.Model.MEPEdgeTypes.HYDRONIC_FLOW_TO; break; case Autodesk.Revit.DB.Domain.DomainHvac: edgeType = MEPGraph.Model.MEPEdgeTypes.AIR_FLOW_TO; break; case Autodesk.Revit.DB.Domain.DomainUndefined: edgeType = MEPGraph.Model.MEPEdgeTypes.FLOWS_TO; break; } if (currentConn.IsConnected) { //var ci = currentConn.GetMEPConnectorInfo(); //connection search nextConnector = currentConn.AllRefs.OfType <Connector>().Where(cn => (cn.ConnectorType == ConnectorType.End || cn.ConnectorType == ConnectorType.Curve) && cn.IsConnectedTo(currentConn) && cn.Owner.Id.IntegerValue != currentElement.Id.IntegerValue).FirstOrDefault(); if (nextConnector != null) { previouseConnections.Add(currentConn); edge = graph.AddConnection(currentConn, nextConnector, MEPPathConnectionType.Phyiscal, edgeType); nextElement = nextConnector.Owner; } } if (nextConnector == null) { //geometry search var connPoint = currentConn.Origin; var nearPoints = cpTree.GetNearby(connPoint, 1F); var nearPointsOrdered = nearPoints.Where(el => el.OriginatingElement.IntegerValue != currentElement.Id.IntegerValue).OrderBy(d => d.Point.DistanceTo(connPoint)).ToList(); var nearest = nearPointsOrdered.FirstOrDefault(); if (nearest != null) { var distance = nearest.Point.DistanceTo(connPoint); if (distance < 0.01F) { var nearElm = elm.Document.GetElement(nearest.OriginatingElement); if (nearElm != null) { var mepm = MEPUtils.GetConnectionManager(nearElm); #if REVIT2016 nextConnector = (mepm != null) ? mepm.Connectors.OfType <Connector>().Where(cn => (cn.ConnectorType == ConnectorType.End || cn.ConnectorType == ConnectorType.Curve) && cn.Id == nearest.ConnectorIndex).FirstOrDefault() : null; #else throw new Exception("Only supported in Revit 2016 onwards"); #endif if (nextConnector != null) { previouseConnections.Add(currentConn); edge = graph.AddConnection(currentConn, nextConnector, MEPPathConnectionType.Proximity, edgeType); nextElement = nextConnector.Owner; //nextOrigin = nextConnector.Origin; } } } } if (nextConnector == null && geoTree != null) { //todo: curve - point intersection check var colBox = new HLBoundingBoxXYZ(connPoint, new XYZ(0.1, 0.1, 0.1)); var nearbyCurves = geoTree.GetColliding(colBox); var nearbyCurve = nearbyCurves.OfType <CurveGeometrySegment>().Where(nb => nb.OriginatingElement.IntegerValue != currentConn.Owner.Id.IntegerValue).OrderBy(nd => nd.Geometry.Distance(connPoint)).FirstOrDefault(); if (nearbyCurve != null) { var distance = nearbyCurve.Geometry.Distance(connPoint); //check if connector is sitting near or with extent of the mepcurve var tolerence = 0.01; if (distance < tolerence || nearbyCurve.Radius > 0.001 && distance <= (nearbyCurve.Radius + tolerence) || nearbyCurve.Width > 0.001 && distance <= (nearbyCurve.Width + tolerence) || nearbyCurve.Height > 0.001 && distance <= (nearbyCurve.Height + tolerence)) { //how to add this connection to the graph with no next connector?? var orgElme = elm.Document.GetElement(nearbyCurve.OriginatingElement); edge = graph.AddConnection(currentConn, connPoint, orgElme, MEPPathConnectionType.ProximityNoConnector, edgeType); nextElement = orgElme; //nextOrigin = connPoint; } } } } if (edge != null && edge.Length < 0.1) { if (meps != null) { edge.Length = meps.TotalCurveLength; edge.SetWeight("Roughness", meps.Roughness); edge.SetWeight("ReynoldsNumber", meps.ReynoldsNumber); edge.SetWeight("Velocity", meps.Velocity); edge.SetWeight("VelocityPressure", meps.VelocityPressure); edge.SetWeight("Flow", meps.Flow); } else if (orgPoint != null && nextOrigin != null) { var length = Math.Abs(orgPoint.DistanceTo(nextOrigin)); //very crude way to get length, should really be using MEPSection if (length >= 0.1) { edge.Length = length; } } } ScanSpacesFromElement(currentConn, graph, scannedElements, nextElement == null); var currentDepth = elmStack.Count; if (nextElement != null && (maxDepth == -1 || currentDepth < maxDepth) && !scannedElements.Contains(nextElement.Id.IntegerValue))// && !graph.ContainsElement(nextElement)) { elmStack.Push(new Tuple <Element, XYZ>(nextElement, nextOrigin)); //ScanFromElement(elm, graph, cpTree, maxDepth, currentDepth++); } } //check curve for nearby unconnected points if (cpTree != null && currentElement is MEPCurve) { //point - curve intersection check var curveElm = currentElement as MEPCurve; var locCurve = curveElm.Location as LocationCurve; var curve = locCurve.Curve; var nearbyCurve = new CurveGeometrySegment(curve, currentElement); var P1 = curve.GetEndPoint(0); var P2 = curve.GetEndPoint(1); var curveAsLine = curve is Line ? curve as Line : Line.CreateBound(P1, P2); var nearbyCurves = cpTree.GetNearby(curveAsLine, (float)nearbyCurve.MaxDimension); foreach (var cb in nearbyCurves) { if (cb.OriginatingElement.IntegerValue == currentElement.Id.IntegerValue) { continue; } if (P1.DistanceTo(cb.Point) < 0.01) { continue; } if (P2.DistanceTo(cb.Point) < 0.01) { continue; } var tolerence = 0.01; var cnpoint = curveAsLine.Project(cb.Point); var distance = cnpoint.Distance; //distance check is a crude way to check this element is sitting in the duct/pipe, could be nearby but intended to be connected. if (distance < (nearbyCurve.MaxDimension / 2) + tolerence) { var orgElme = elm.Document.GetElement(cb.OriginatingElement); if (orgElme == null) { continue; } var cmgr = MEPUtils.GetConnectionManager(orgElme); if (cmgr == null) { continue; } #if REVIT2016 var nc = cmgr.Connectors.OfType <Connector>().FirstOrDefault(cn => cn.Id == cb.ConnectorIndex); #else Connector nc = null; #endif if (nc == null || nc.IsConnected) { continue; } //further check that direction of point intersects curve var prjInX = nc.CoordinateSystem.OfPoint(new XYZ(0, 0, 5)); var prjInnX = nc.CoordinateSystem.OfPoint(new XYZ(0, 0, -5)); var prjLine = Line.CreateBound(prjInnX, prjInX); var ix = curveAsLine.Intersect(prjLine); if (ix != SetComparisonResult.Overlap) { continue; } var edge = graph.AddConnection(nc, cnpoint.XYZPoint, currentElement, MEPPathConnectionType.ProximityNoConnector, MEPGraph.Model.MEPEdgeTypes.FLOWS_TO); if (orgPoint != null) { edge.Length = Math.Abs(orgPoint.DistanceTo(cnpoint.XYZPoint)); } if (!scannedElements.Contains(orgElme.Id.IntegerValue) && !elmStack.Any(el => el.Item1 == orgElme))// && !graph.ContainsElement(nextElement)) { elmStack.Push(new Tuple <Element, XYZ>(orgElme, cnpoint.XYZPoint)); } } } } ScanSpacesFromElement(currentElement, graph, scannedElements); } }
public void AddElement(Element elm, bool includeGeometry, Transform tx = null) { if (_boundsStree == null || elm == null) { return; } var elmid = elm.Id.IntegerValue; HashSet <GeometrySegment> segList; if (SegmentCache.ContainsKey(elmid)) { segList = SegmentCache[elmid]; } else { segList = new HashSet <GeometrySegment>(); } if (includeGeometry || elm is FamilyInstance) { var gop = defaultGeomOptions; if (elm.Category != null && _geoOptionsOverrides.ContainsKey(elm.Category.Id.IntegerValue)) { gop = _geoOptionsOverrides[elm.Category.Id.IntegerValue]; } var egeo = elm.get_Geometry(gop); if (egeo == null) { return; } if (tx != null) { egeo = egeo.GetTransformed(tx); } var allSolids = GeoUtils.GetAllSolidsInGeometry(egeo); foreach (var sld in allSolids) { if (!solidIsValid(sld)) { continue; } var hlbbox = GeoUtils.GetGeoBoundingBox(sld, Transform.Identity); if (hlbbox == null) { continue; } var geoSegment = new SolidGeometrySegment(sld, elm, hlbbox); segList.Add(geoSegment); _boundsStree.Add(geoSegment, hlbbox); } } if (elm.Location is LocationCurve) { var curve = elm.Location as LocationCurve; if (curve == null) { return; } var acCurve = curve.Curve; if (tx != null) { acCurve = acCurve.CreateTransformed(tx); } var cseg = new CurveGeometrySegment(acCurve, elm); segList.Add(cseg); _boundsStree.Add(cseg, cseg.Bounds); } if (!SegmentCache.ContainsKey(elmid)) { SegmentCache.Add(elmid, segList); } }