using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using Nice3point.Revit.Toolkit.External; using System; using System.Linq; namespace Szmedi.RvKits.MEPTools { [Transaction(TransactionMode.Manual)] public class CableLayoutCmd : ExternalCommand { private readonly IList elems = new List(); public override void Execute() { CableLayoutWin win = new(Document); if (win.ShowDialog() != true) { Result = Result.Cancelled; return; } var count = win.ViewModel.Count; var conduitType = win.ViewModel.SelectedConduitType; var size = win.ViewModel.Size; using Transaction trans = new(Document, "敷设电缆"); try { //Reference refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter(), "请选择桥架"); //var ct = uidoc.doc.GetElement(refer) as CableTray; Reference refer = UiDocument.Selection.PickObject(ObjectType.Element, new GenericFilter(), "请选择需要敷设桥架"); var ct = UiDocument.Document.GetElement(refer) as MEPCurve; XYZ xyz = refer.GlobalPoint; //Curve curve = (ct.Location as LocationCurve).Curve; //XYZ project = curve.Project(xyz).XYZPoint; elems.Add(ct); Connector connector = GetNearConnector(ct, xyz); GetAlrefsElementOrdered(connector); trans.Start(); Dictionary> dictionary = new(); List firstConduits = new(); double interval = size.OuterDiameter; foreach (var elem in elems) { if (elem is MEPCurve mepCurve) { var loc = mepCurve.Location as LocationCurve; Conduit conduit = Conduit.Create( Document, conduitType.Id, loc.Curve.GetEndPoint(0), loc.Curve.GetEndPoint(1), mepCurve.LevelId ); firstConduits.Add(conduit); } } dictionary.Add(0, firstConduits); if (count > 2) { for (int i = 0; i < count; i++) { List conduits = new(); var x = Math.Pow(-1, i); var y = Math.Ceiling(i / 2.0); var offest = x * y * interval; if (count % 2 == 0) { offest += interval / 2; } foreach (var conduit in firstConduits) { var loc = conduit.Location as LocationCurve; var line = loc.Curve as Line; var direction = line.Direction.CrossProduct(XYZ.BasisZ); var id = ElementTransformUtils.CopyElement(Document, conduit.Id, direction * offest).FirstOrDefault(); var conduitCopied = Document.GetElement(id) as Conduit; conduits.Add(conduitCopied); } dictionary.Add(i + 1, conduits); } Document.Regenerate(); } for (int i = 0; i < dictionary.Count; i++) { var conduits = dictionary[i]; for (var j = 0; j < conduits.Count - 1; j++) { var conduit = conduits[j]; var conduit1 = conduits[j + 1]; var list = GetNearestConnector(conduit, conduit1); if (list[0] != null && list[1] != null) { Document.Create.NewElbowFitting(list[0], list[1]); } } } if (count % 2 == 0) { Document.Delete(firstConduits.Select(e => e.Id).ToList()); } trans.Commit(); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { if (trans.GetStatus() == TransactionStatus.Started) { trans.Commit(); } } catch (Exception ex) { ErrorMessage = ex.Message; if (trans.GetStatus() == TransactionStatus.Started) { trans.Commit(); } Result = Result.Failed; } } public static List GetNearestConnector(Element element1, Element element2) { List list = new(); Connector conn1 = null; Connector conn2 = null; var conns = ConnectorsUnused(element1).ForwardIterator(); var conns1 = ConnectorsUnused(element2).ForwardIterator(); double distance = double.MaxValue; while (conns.MoveNext()) { var connTemp1 = conns.Current as Connector; conns1.Reset(); while (conns1.MoveNext()) { var connTemp2 = conns1.Current as Connector; double tempDistance = connTemp1.Origin.DistanceTo(connTemp2.Origin); if (distance > tempDistance) { distance = tempDistance; conn1 = connTemp1; conn2 = connTemp2; } } } list.Add(conn1); list.Add(conn2); return list; } public static ConnectorSet ConnectorsUnused(Element element) { if (element == null) { return null; } ConnectorSet connectorSet = null; if (element is FamilyInstance familyInstance && familyInstance.MEPModel != null) { connectorSet = familyInstance.MEPModel.ConnectorManager?.UnusedConnectors; } if (element is MEPCurve mepcurve) { connectorSet = mepcurve.ConnectorManager.UnusedConnectors; } if (element is FabricationPart fabricationPart) { connectorSet = fabricationPart.ConnectorManager.UnusedConnectors; } return connectorSet ?? null; } /// /// 获取选择点最近的连接件 /// /// 管线 /// /// private Connector GetNearConnector(Element elem, XYZ xyz) { if (elem is not MEPCurve mep) { throw new ArgumentException("元素不是管线"); } SortedDictionary dictionary = new(); ConnectorSetIterator connectorSetIterator = mep.ConnectorManager.Connectors.ForwardIterator(); while (connectorSetIterator.MoveNext()) { Connector connector = connectorSetIterator.Current as Connector; if (connector.AllRefs.Size > 0) { dictionary.Add(connector.Origin.DistanceTo(xyz), connector); } } return dictionary.Values.ElementAt(0); } private void GetAlrefsElementOrdered(Connector startConnector) { //连接的元素 Element elem = null; //得到与当前连接件连接的连接件 ConnectorSetIterator connectorSetIterator = startConnector.AllRefs.ForwardIterator(); while (connectorSetIterator.MoveNext()) { Connector currentConn = connectorSetIterator.Current as Connector; if (currentConn.Origin.IsAlmostEqualTo(startConnector.Origin)) { elem = currentConn.Owner; break; } } elems.Add(elem); Connector connectorConnected = GetConnectorConnected(elem, startConnector); if (connectorConnected.IsConnected) { GetAlrefsElementOrdered(connectorConnected); } } private Connector GetConnectorConnected(Element elem, Connector conn) { Connector connConnected = null; ConnectorSet set = null; if (elem is MEPCurve) { MEPCurve mep = elem as MEPCurve; set = mep.ConnectorManager.Connectors; } else if (elem is FamilyInstance) { FamilyInstance isntance = elem as FamilyInstance; set = isntance.MEPModel.ConnectorManager.Connectors; } if (set != null) { ConnectorSetIterator connectorSetIterator = set.ForwardIterator(); while (connectorSetIterator.MoveNext()) { Connector currentConn = connectorSetIterator.Current as Connector; if (currentConn.AllRefs.Size > 0) { if (!currentConn.Origin.IsAlmostEqualTo(conn.Origin)) { connConnected = currentConn; break; } } } } return connConnected; } } }