Buckets:
| // | |
| // (C) Copyright 2003-2019 by Autodesk, Inc. | |
| // | |
| // Permission to use, copy, modify, and distribute this software in | |
| // object code form for any purpose and without fee is hereby granted, | |
| // provided that the above copyright notice appears in all copies and | |
| // that both that copyright notice and the limited warranty and | |
| // restricted rights notice below appear in all supporting | |
| // documentation. | |
| // | |
| // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. | |
| // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF | |
| // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. | |
| // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE | |
| // UNINTERRUPTED OR ERROR FREE. | |
| // | |
| // Use, duplication, or disclosure by the U.S. Government is subject to | |
| // restrictions set forth in FAR 52.227-19 (Commercial Computer | |
| // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) | |
| // (Rights in Technical Data and Computer Software), as applicable. | |
| // | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Text; | |
| using System.IO; | |
| using System.Diagnostics; | |
| using Autodesk.Revit; | |
| using Autodesk.Revit.ApplicationServices; | |
| using Autodesk.Revit.DB; | |
| using Autodesk.Revit.UI; | |
| using Autodesk.Revit.DB.Mechanical; | |
| using GXYZ = Autodesk.Revit.DB.XYZ; | |
| namespace Revit.SDK.Samples.AutoRoute.CS | |
| { | |
| /// <summary> | |
| /// route a set of ducts and fittings between a base air supply equipment and 2 terminals. | |
| /// </summary> | |
| [] | |
| [] | |
| [] | |
| public class Command : IExternalCommand | |
| { | |
| /// <summary> | |
| /// The revit application | |
| /// </summary> | |
| private static Application m_application; | |
| /// <summary> | |
| /// The current document of the application | |
| /// </summary> | |
| private static Document m_document; | |
| /// <summary> | |
| /// The mechanical system that will be created | |
| /// </summary> | |
| private MechanicalSystem m_mechanicalSystem; | |
| /// <summary> | |
| /// The type of the ducts in the system | |
| /// </summary> | |
| DuctType dtRectangle; | |
| /// <summary> | |
| /// The type id of the duct | |
| /// </summary> | |
| Autodesk.Revit.DB.ElementId ductTypeId = new Autodesk.Revit.DB.ElementId(139191L); | |
| /// <summary> | |
| /// The system type id of the duct | |
| /// </summary> | |
| ElementId systemTypeId = ElementId.InvalidElementId; | |
| /// <summary> | |
| /// The level of the duct | |
| /// </summary> | |
| Level lvl =null; | |
| /// <summary> | |
| /// Minimum length of a fitting | |
| /// </summary> | |
| private const double min1FittingLength = 1; | |
| /// <summary> | |
| /// Minimum length of a duct | |
| /// </summary> | |
| private const double minDuctLength = 0.5; | |
| /// <summary> | |
| /// The vertical offset of the highest connector to the trunk ducts | |
| /// </summary> | |
| private const double verticalTrunkOffset = 15; | |
| /// <summary> | |
| /// Optional distance from trunk to the boundary of system bounding box | |
| /// used when failed to lay out ducts in the region of bounding box | |
| /// </summary> | |
| private const double horizontalOptionalTrunkOffset = 5; | |
| /// <summary> | |
| /// Minimum length of 2 fittings | |
| /// </summary> | |
| private const double min2FittingsLength = min1FittingLength * 2; | |
| /// <summary> | |
| /// The minimum length of 1 duct with 2 fittings | |
| /// </summary> | |
| private const double min1Duct2FittingsLength = min1FittingLength * 2 + minDuctLength; | |
| /// <summary> | |
| /// Implement this method as an external command for Revit. | |
| /// </summary> | |
| /// <param name="commandData">An object that is passed to the external application | |
| /// which contains data related to the command, | |
| /// such as the application object and active view.</param> | |
| /// <param name="message">A message that can be set by the external application | |
| /// which will be displayed if a failure or cancellation is returned by | |
| /// the external command.</param> | |
| /// <param name="elements">A set of elements to which the external application | |
| /// can add elements that are to be highlighted in case of failure or cancellation.</param> | |
| /// <returns>Return the status of the external command. | |
| /// A result of Succeeded means that the API external method functioned as expected. | |
| /// Cancelled can be used to signify that the user cancelled the external operation | |
| /// at some point. Failure should be returned if the application is unable to proceed with | |
| /// the operation.</returns> | |
| public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, | |
| ElementSet elements) | |
| { | |
| // set out default result to Failed. | |
| Autodesk.Revit.UI.Result retRes = Autodesk.Revit.UI.Result.Failed; | |
| m_application = commandData.Application.Application; | |
| m_document = commandData.Application.ActiveUIDocument.Document; | |
| Trace.Listeners.Clear(); | |
| Trace.AutoFlush = true; | |
| //get the system type id of the duct | |
| ElementClassFilter systemTypeFilter = new ElementClassFilter(typeof(MEPSystemType)); | |
| FilteredElementCollector C = new FilteredElementCollector(m_document); | |
| C.WherePasses(systemTypeFilter); | |
| foreach (MEPSystemType type in C) | |
| { | |
| if (type.SystemClassification == MEPSystemClassification.SupplyAir) | |
| { | |
| systemTypeId = type.Id; | |
| break; | |
| } | |
| } | |
| string outputFileName = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "AutoRoute.log"); | |
| if (File.Exists(outputFileName)) | |
| { | |
| File.Delete(outputFileName); | |
| } | |
| TextWriterTraceListener listener = new TextWriterTraceListener(outputFileName); | |
| Trace.Listeners.Add(listener); | |
| Transaction transaction = new Transaction(m_document, "Sample_AutoRoute"); | |
| try | |
| { | |
| transaction.Start(); | |
| //set the level of the duct | |
| lvl = Level.Create(m_document, 0.0); | |
| //Lists to temporarily record the created elements | |
| List<Duct> ducts = new List<Duct>(); | |
| List<GXYZ> points = new List<GXYZ>(); | |
| List<Connector> connectors = new List<Connector>(); | |
| List<Connector> baseConnectors = new List<Connector>(); | |
| //Get the connectors and bounding boxes | |
| List<Autodesk.Revit.DB.ElementId> ids = new List<ElementId>(); | |
| ids.Add(new ElementId(378728L)); | |
| ids.Add(new ElementId(378707L)); | |
| ids.Add(new ElementId(378716L)); | |
| FamilyInstance[] instances = new FamilyInstance[3]; | |
| Autodesk.Revit.DB.BoundingBoxXYZ[] boxes = new Autodesk.Revit.DB.BoundingBoxXYZ[3]; | |
| Connector[] conns = new Connector[3]; | |
| ConnectorSetIterator csi = null; | |
| for (int i = 0; i < ids.Count; ++i) | |
| { | |
| Element element = m_document.GetElement(ids[i]); | |
| if (null == element) | |
| { | |
| message = "Element " + ids[i].ToString() + " can't be found."; | |
| return Autodesk.Revit.UI.Result.Failed; | |
| } | |
| instances[i] = element as FamilyInstance; | |
| csi = ConnectorInfo.GetConnectors(ids[i]).ForwardIterator(); | |
| csi.MoveNext(); | |
| conns[i] = csi.Current as Connector; | |
| boxes[i] = instances[i].get_BoundingBox(m_document.ActiveView); | |
| } | |
| //Find the "Out" and "SupplyAir" connector on the base equipment | |
| csi = ConnectorInfo.GetConnectors(ids[0]).ForwardIterator(); | |
| while (csi.MoveNext()) | |
| { | |
| Connector conn = csi.Current as Connector; | |
| if (conn.Direction == FlowDirectionType.Out && conn.DuctSystemType == DuctSystemType.SupplyAir) | |
| { | |
| conns[0] = conn; | |
| } | |
| } | |
| //Create a mechanical system with a base air supply equipment and 2 terminals. | |
| m_mechanicalSystem = CreateMechanicalSystem( | |
| //[378728][SupplyAir][Out][RectProfile][OST_MechanicalEquipment] | |
| new ConnectorInfo(new ElementId(378728L), conns[0].Origin.X, conns[0].Origin.Y, conns[0].Origin.Z), | |
| new ConnectorInfo[]{ | |
| //[378707][SupplyAir][In][RectProfile] | |
| new ConnectorInfo(new ElementId(378707L), conns[1].Origin.X, conns[1].Origin.Y, conns[1].Origin.Z), | |
| //[378716][SupplyAir][In][RectProfile] | |
| new ConnectorInfo(new ElementId(378716L), conns[2].Origin.X, conns[2].Origin.Y, conns[2].Origin.Z) | |
| }, | |
| DuctSystemType.SupplyAir | |
| ); | |
| //Get the boundary of the system | |
| double minX = conns[0].Origin.X; | |
| double minY = conns[0].Origin.Y; | |
| double maxX = conns[0].Origin.X; | |
| double maxY = conns[0].Origin.Y; | |
| double maxZ = conns[0].Origin.Z; | |
| for (int i = 1; i < boxes.Length; ++i) | |
| { | |
| if (conns[i].Origin.X < minX) | |
| minX = conns[i].Origin.X; | |
| if (conns[i].Origin.Y < minY) | |
| minY = conns[i].Origin.Y; | |
| if (conns[i].Origin.X > maxX) | |
| maxX = conns[i].Origin.X; | |
| if (conns[i].Origin.Y > maxY) | |
| maxY = conns[i].Origin.Y; | |
| if (conns[i].Origin.Z > maxZ) | |
| maxZ = conns[i].Origin.Z; | |
| } | |
| //Calculate the optional values for the trunk ducts | |
| double midX = (minX + maxX) / 2; | |
| double midY = (minY + maxY) / 2; | |
| double[] baseXValues = new double[3] { midX, (minX + midX) / 2, (maxX + midX) / 2 }; | |
| double[] baseYValues = new double[3] { midY, (minY + midY) / 2, (maxY + midY) / 2 }; | |
| //Get the duct type for the ducts to be created | |
| dtRectangle = m_document.GetElement(ductTypeId) as DuctType; | |
| //Create the ducts and elbows that connect the base mechanical equipment | |
| GXYZ connectorDirection = conns[0].CoordinateSystem.BasisZ; | |
| if (0 == connectorDirection.DistanceTo(new GXYZ(-1, 0, 0))) | |
| { | |
| points.Add(new GXYZ(conns[0].Origin.X - min1FittingLength, conns[0].Origin.Y, conns[0].Origin.Z)); | |
| points.Add(new GXYZ(conns[0].Origin.X - min2FittingsLength, conns[0].Origin.Y, conns[0].Origin.Z + min1FittingLength)); | |
| points.Add(new GXYZ(conns[0].Origin.X - min2FittingsLength, conns[0].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| } | |
| else if (0 == connectorDirection.DistanceTo(new GXYZ(1, 0, 0))) | |
| { | |
| points.Add(new GXYZ(conns[0].Origin.X + min1FittingLength, conns[0].Origin.Y, conns[0].Origin.Z)); | |
| points.Add(new GXYZ(conns[0].Origin.X + min2FittingsLength, conns[0].Origin.Y, conns[0].Origin.Z + min1FittingLength)); | |
| points.Add(new GXYZ(conns[0].Origin.X + min2FittingsLength, conns[0].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| } | |
| else if (0 == connectorDirection.DistanceTo(new GXYZ(0, -1, 0))) | |
| { | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y - min1FittingLength, conns[0].Origin.Z)); | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y - min2FittingsLength, conns[0].Origin.Z + min1FittingLength)); | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y - min2FittingsLength, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| } | |
| else if (0 == connectorDirection.DistanceTo(new GXYZ(0, 1, 0))) | |
| { | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y + min1FittingLength, conns[0].Origin.Z)); | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y + min2FittingsLength, conns[0].Origin.Z + min1FittingLength)); | |
| points.Add(new GXYZ(conns[0].Origin.X, conns[0].Origin.Y + min2FittingsLength, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| } | |
| ducts.Add(Duct.Create(m_document, ductTypeId, lvl.Id,conns[0], points[0])); | |
| ducts.Add(Duct.Create(m_document, systemTypeId, ductTypeId, lvl.Id, points[1], points[2])); | |
| connectors.Add(ConnectorInfo.GetConnector(ducts[0].Id, points[0])); | |
| connectors.Add(ConnectorInfo.GetConnector(ducts[1].Id, points[1])); | |
| connectors.Add(ConnectorInfo.GetConnector(ducts[1].Id, points[2])); | |
| connectors[0].ConnectTo(connectors[1]); | |
| m_document.Create.NewElbowFitting(connectors[0], connectors[1]); | |
| baseConnectors.Add(connectors[2]); | |
| //Create the vertical ducts for terminals | |
| points.Clear(); | |
| ducts.Clear(); | |
| points.Add(new GXYZ(conns[1].Origin.X, conns[1].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| points.Add(new GXYZ(conns[2].Origin.X, conns[2].Origin.Y, maxZ + verticalTrunkOffset - min1FittingLength)); | |
| ducts.Add(Duct.Create(m_document, ductTypeId, lvl.Id, conns[1], points[0])); | |
| ducts.Add(Duct.Create(m_document, ductTypeId, lvl.Id, conns[2], points[1])); | |
| baseConnectors.Add(ConnectorInfo.GetConnector(ducts[0].Id, points[0])); | |
| baseConnectors.Add(ConnectorInfo.GetConnector(ducts[1].Id, points[1])); | |
| //Connect the system by creating the trunk line of ducts and connect them to the base connectors | |
| SortConnectorsByX(baseConnectors); | |
| for (int i = 0; i < baseYValues.Length; ++i) | |
| { | |
| if (ConnectSystemOnXAxis(baseConnectors, baseYValues[i])) | |
| { | |
| LogUtility.WriteMechanicalSystem(m_mechanicalSystem); | |
| return Autodesk.Revit.UI.Result.Succeeded; | |
| } | |
| } | |
| SortConnectorsByY(baseConnectors); | |
| for (int i = 0; i < baseXValues.Length; ++i) | |
| { | |
| if (ConnectSystemOnYAxis(baseConnectors, baseXValues[i])) | |
| { | |
| LogUtility.WriteMechanicalSystem(m_mechanicalSystem); | |
| return Autodesk.Revit.UI.Result.Succeeded; | |
| } | |
| } | |
| //If all the cases fail to route the system, try the trunks out of the bounding box | |
| SortConnectorsByX(baseConnectors); | |
| if (ConnectSystemOnXAxis(baseConnectors, maxY + horizontalOptionalTrunkOffset)) | |
| { | |
| LogUtility.WriteMechanicalSystem(m_mechanicalSystem); | |
| return Autodesk.Revit.UI.Result.Succeeded; | |
| } | |
| SortConnectorsByY(baseConnectors); | |
| if (ConnectSystemOnYAxis(baseConnectors, maxX + horizontalOptionalTrunkOffset)) | |
| { | |
| LogUtility.WriteMechanicalSystem(m_mechanicalSystem); | |
| return Autodesk.Revit.UI.Result.Succeeded; | |
| } | |
| //If there's no path for the connection, choose one path and let Revit report the error | |
| connectors.Clear(); | |
| SortConnectorsByX(baseConnectors); | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConnectors[0].Origin.X + min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset), new GXYZ(baseConnectors[1].Origin.X - min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset))); | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConnectors[1].Origin.X + min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset), new GXYZ(baseConnectors[2].Origin.X - min1FittingLength, baseYValues[0], maxZ + verticalTrunkOffset))); | |
| ConnectWithElbowFittingOnXAxis(baseConnectors[0], connectors[0]); | |
| ConnectWithElbowFittingOnXAxis(baseConnectors[2], connectors[3]); | |
| ConnectWithTeeFittingOnXAxis(baseConnectors[1], connectors[1], connectors[2], false); | |
| } | |
| catch (Exception ex) | |
| { | |
| Trace.WriteLine(ex.ToString()); | |
| message = ex.Message; | |
| retRes = Autodesk.Revit.UI.Result.Failed; | |
| } | |
| finally | |
| { | |
| transaction.Commit(); | |
| Trace.Flush(); | |
| listener.Close(); | |
| Trace.Close(); | |
| Trace.Listeners.Remove(listener); | |
| } | |
| return retRes; | |
| } | |
| /// <summary> | |
| /// Connect the system with a trunk line of ducts on X axis | |
| /// </summary> | |
| /// <param name="baseConnectors">the upper connectors of the vertical ducts that derived from the terminals and the base equipment</param> | |
| /// <param name="baseY">the y value of the trunk line</param> | |
| /// <returns> | |
| /// true if the system can be connected | |
| /// false if the system cannot be connected | |
| /// </returns> | |
| private bool ConnectSystemOnXAxis(List<Connector> baseConnectors, double baseY) | |
| { | |
| //Check the count of the base connectors | |
| if (null == baseConnectors || 3 != baseConnectors.Count) | |
| { | |
| return false; | |
| } | |
| for (int i = 0; i < baseConnectors.Count; ++i) | |
| { | |
| //Check the distance of the connector from the trunk | |
| if (baseConnectors[i].Origin.Y != baseY && Math.Abs(baseConnectors[i].Origin.Y - baseY) < min1Duct2FittingsLength) | |
| { | |
| return false; | |
| } | |
| //Check the distance of the connectors on X axis | |
| for (int j = i + 1; j < baseConnectors.Count; ++j) | |
| { | |
| if (baseConnectors[j].Origin.X != baseConnectors[i].Origin.X && baseConnectors[j].Origin.X - baseConnectors[i].Origin.X < min2FittingsLength) | |
| { | |
| return false; | |
| } | |
| } | |
| } | |
| try | |
| { | |
| double baseZ = baseConnectors[0].Origin.Z + min1FittingLength; | |
| //Create the ducts and elbow fittings to connect the vertical ducts and the trunk ducts | |
| List<Connector> connectors = new List<Connector>(); | |
| if (baseConnectors[0].Origin.X == baseConnectors[1].Origin.X) | |
| { | |
| //All 3 connectors are with the same X value | |
| if (baseConnectors[1].Origin.X == baseConnectors[2].Origin.X) | |
| { | |
| return false; | |
| } | |
| else | |
| { | |
| //The 1st and 2nd base connectors are on the same side of the trunk | |
| if (Math.Sign(baseConnectors[0].Origin.Y - baseY) * Math.Sign(baseConnectors[1].Origin.Y - baseY) == 1) | |
| { | |
| return false; | |
| } | |
| //Create the trunk | |
| connectors = CreateDuct(new GXYZ(baseConnectors[0].Origin.X + min1FittingLength, baseY, baseZ), new GXYZ(baseConnectors[2].Origin.X - min1FittingLength, baseY, baseZ)); | |
| //Create a tee fitting connecting the 1st and 2nd base connectors to the trunk | |
| ConnectWithTeeFittingOnXAxis(baseConnectors[0], baseConnectors[1], connectors[0], true); | |
| //Create an elbow fitting connection the 3rd base connector to the trunk | |
| ConnectWithElbowFittingOnXAxis(baseConnectors[2], connectors[1]); | |
| } | |
| } | |
| else | |
| { | |
| //Create the segment of duct on the trunk to be connected to the 1st base connector | |
| connectors = CreateDuct(new GXYZ(baseConnectors[0].Origin.X + min1FittingLength, baseY, baseZ), new GXYZ(baseConnectors[1].Origin.X - min1FittingLength, baseY, baseZ)); | |
| //Create an elbow fitting connection the 1st base connector with the trunk | |
| ConnectWithElbowFittingOnXAxis(baseConnectors[0], connectors[0]); | |
| if (baseConnectors[1].Origin.X == baseConnectors[2].Origin.X) | |
| { | |
| //The 2nd and 3rd connectors are on the same side of the trunk | |
| if (Math.Sign(baseConnectors[1].Origin.Y - baseY) * Math.Sign(baseConnectors[2].Origin.Y - baseY) == 1) | |
| { | |
| return false; | |
| } | |
| //Create a tee fitting connecting the 2nd and 3rd base connectors to the trunk | |
| ConnectWithTeeFittingOnXAxis(baseConnectors[1], baseConnectors[2], connectors[1], true); | |
| } | |
| else | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConnectors[1].Origin.X + min1FittingLength, baseY, baseZ), new GXYZ(baseConnectors[2].Origin.X - min1FittingLength, baseY, baseZ))); | |
| //Create a tee fitting connecting the 2nd base connector to the trunk | |
| ConnectWithTeeFittingOnXAxis(baseConnectors[1], connectors[1], connectors[2], false); | |
| //Create an elbow fitting connection the 3rd base connector to the trunk | |
| ConnectWithElbowFittingOnXAxis(baseConnectors[2], connectors[3]); | |
| } | |
| } | |
| return true; | |
| } | |
| catch | |
| { | |
| return false; | |
| } | |
| } | |
| /// <summary> | |
| /// Connect a base connector to a connector on the trunk with an elbow fitting | |
| /// </summary> | |
| /// <param name="baseConn">the upper connector of the vertical duct that derived from a terminal or the base equipment</param> | |
| /// <param name="conn">the connector of a duct on the trunk</param> | |
| private void ConnectWithElbowFittingOnXAxis(Connector baseConn, Connector conn) | |
| { | |
| double baseY = conn.Origin.Y; | |
| double baseZ = conn.Origin.Z; | |
| List<Connector> connectors = new List<Connector>(); | |
| //If the distance of the two connectors on the Y axis is greater than 2, create a duct on the Y axis and then connect it to the 2 connectors with elbow fittings | |
| if (Math.Abs(baseConn.Origin.Y - baseY) > min1Duct2FittingsLength) | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn.Origin.X, baseConn.Origin.Y - Math.Sign(baseConn.Origin.Y - baseY), baseZ), new GXYZ(baseConn.Origin.X, baseY + Math.Sign(baseConn.Origin.Y - baseY), baseZ))); | |
| connectors[0].ConnectTo(baseConn); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn); | |
| connectors[1].ConnectTo(conn); | |
| m_document.Create.NewElbowFitting(connectors[1], conn); | |
| } | |
| //If the distance of the two connectors on the Y axis is less than 2, connect them with an elbow fitting | |
| else | |
| { | |
| baseConn.ConnectTo(conn); | |
| m_document.Create.NewElbowFitting(baseConn, conn); | |
| } | |
| } | |
| /// <summary> | |
| /// Connect 3 connectors on the trunk with a tee fitting | |
| /// </summary> | |
| /// <param name="conn1">the first connector</param> | |
| /// <param name="conn2">the second connector</param> | |
| /// <param name="conn3">the third connector</param> | |
| /// <param name="flag">a flag to indicate whether there are 2 base connectors or 1 base connector</param> | |
| private void ConnectWithTeeFittingOnXAxis(Connector conn1, Connector conn2, Connector conn3, bool flag) | |
| { | |
| double baseY = conn3.Origin.Y; | |
| double baseZ = conn3.Origin.Z; | |
| List<GXYZ> points = new List<GXYZ>(); | |
| List<Duct> ducts = new List<Duct>(); | |
| List<Connector> connectors = new List<Connector>(); | |
| //Connect two base connectors to a connector on the trunk | |
| if (true == flag) | |
| { | |
| Connector baseConn1 = conn1; | |
| Connector baseConn2 = conn2; | |
| Connector conn = conn3; | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn1.Origin.X, baseConn1.Origin.Y - Math.Sign(baseConn1.Origin.Y - baseY), baseZ), new GXYZ(baseConn1.Origin.X, baseY + Math.Sign(baseConn1.Origin.Y - baseY), baseZ))); | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn2.Origin.X, baseConn2.Origin.Y - Math.Sign(baseConn2.Origin.Y - baseY), baseZ), new GXYZ(baseConn2.Origin.X, baseY + Math.Sign(baseConn2.Origin.Y - baseY), baseZ))); | |
| connectors[0].ConnectTo(baseConn1); | |
| connectors[2].ConnectTo(baseConn2); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn1); | |
| m_document.Create.NewElbowFitting(connectors[2], baseConn2); | |
| connectors[1].ConnectTo(connectors[3]); | |
| connectors[1].ConnectTo(conn); | |
| connectors[3].ConnectTo(conn); | |
| m_document.Create.NewTeeFitting(connectors[1], connectors[3], conn); | |
| } | |
| //Connect a base connector to two connectors on the trunk | |
| else | |
| { | |
| Connector baseConn = conn1; | |
| if (Math.Abs(baseConn.Origin.Y - baseY) > min1Duct2FittingsLength) | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn.Origin.X, baseConn.Origin.Y - Math.Sign(baseConn.Origin.Y - baseY), baseZ), new GXYZ(baseConn.Origin.X, baseY + Math.Sign(baseConn.Origin.Y - baseY), baseZ))); | |
| baseConn.ConnectTo(connectors[0]); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn); | |
| connectors[1].ConnectTo(conn2); | |
| connectors[1].ConnectTo(conn3); | |
| conn2.ConnectTo(conn3); | |
| m_document.Create.NewTeeFitting(conn2, conn3, connectors[1]); | |
| } | |
| else | |
| { | |
| baseConn.ConnectTo(conn2); | |
| baseConn.ConnectTo(conn3); | |
| conn2.ConnectTo(conn3); | |
| m_document.Create.NewTeeFitting(conn2, conn3, baseConn); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Sort the base connectors by their x values | |
| /// </summary> | |
| /// <param name="connectors">the connectors to be sorted</param> | |
| private void SortConnectorsByX(List<Connector> connectors) | |
| { | |
| for (int i = 0; i < connectors.Count; ++i) | |
| { | |
| double min = connectors[i].Origin.X; | |
| int minIndex = i; | |
| for (int j = i; j < connectors.Count; ++j) | |
| { | |
| if (connectors[j].Origin.X < min) | |
| { | |
| min = connectors[j].Origin.X; | |
| minIndex = j; | |
| } | |
| } | |
| Connector t = connectors[i]; | |
| connectors[i] = connectors[minIndex]; | |
| connectors[minIndex] = t; | |
| } | |
| } | |
| /// <summary> | |
| /// Connect the system with a trunk line of ducts on Y axis | |
| /// </summary> | |
| /// <param name="baseConnectors">the upper connectors of the vertical ducts that derived from the terminals and the base equipment</param> | |
| /// <param name="baseX">the x value of the trunk line</param> | |
| /// <returns> | |
| /// true if the system can be connected | |
| /// false if the system cannot be connected | |
| /// </returns> | |
| private bool ConnectSystemOnYAxis(List<Connector> baseConnectors, double baseX) | |
| { | |
| //Check the count of the base connectors | |
| if (null == baseConnectors || 3 != baseConnectors.Count) | |
| { | |
| return false; | |
| } | |
| for (int i = 0; i < baseConnectors.Count; ++i) | |
| { | |
| //Check the distance of the connector from the trunk | |
| if (baseConnectors[i].Origin.X != baseX && Math.Abs(baseConnectors[i].Origin.X - baseX) < min1Duct2FittingsLength) | |
| { | |
| return false; | |
| } | |
| //Check the distance of the connectors on Y axis | |
| for (int j = i + 1; j < baseConnectors.Count; ++j) | |
| { | |
| if (baseConnectors[j].Origin.Y != baseConnectors[i].Origin.Y && baseConnectors[j].Origin.Y - baseConnectors[i].Origin.Y < min2FittingsLength) | |
| { | |
| return false; | |
| } | |
| } | |
| } | |
| try | |
| { | |
| double baseZ = baseConnectors[0].Origin.Z + min1FittingLength; | |
| //Create the ducts and elbow fittings to connect the vertical ducts and the trunk ducts | |
| List<Connector> connectors = new List<Connector>(); | |
| if (baseConnectors[0].Origin.Y == baseConnectors[1].Origin.Y) | |
| { | |
| //All 3 connectors are with the same Y value | |
| if (baseConnectors[1].Origin.Y == baseConnectors[2].Origin.Y) | |
| { | |
| return false; | |
| } | |
| else | |
| { | |
| //The 1st and 2nd base connectors are on the same side of the trunk | |
| if (Math.Sign(baseConnectors[0].Origin.X - baseX) * Math.Sign(baseConnectors[1].Origin.X - baseX) == 1) | |
| { | |
| return false; | |
| } | |
| //Create the trunk | |
| connectors = CreateDuct(new GXYZ(baseX, baseConnectors[0].Origin.Y + min1FittingLength, baseZ), new GXYZ(baseX, baseConnectors[2].Origin.Y - min1FittingLength, baseZ)); | |
| //Create a tee fitting connecting the 1st and 2nd base connectors to the trunk | |
| ConnectWithTeeFittingOnYAxis(baseConnectors[0], baseConnectors[1], connectors[0], true); | |
| //Create an elbow fitting connection the 3rd base connector to the trunk | |
| ConnectWithElbowFittingOnYAxis(baseConnectors[2], connectors[1]); | |
| } | |
| } | |
| else | |
| { | |
| //Create the segment of duct on the trunk to be connected to the 1st base connector | |
| connectors = CreateDuct(new GXYZ(baseX, baseConnectors[0].Origin.Y + min1FittingLength, baseZ), new GXYZ(baseX, baseConnectors[1].Origin.Y - min1FittingLength, baseZ)); | |
| //Create an elbow fitting connection the 1st base connector with the trunk | |
| ConnectWithElbowFittingOnYAxis(baseConnectors[0], connectors[0]); | |
| if (baseConnectors[1].Origin.Y == baseConnectors[2].Origin.Y) | |
| { | |
| //The 2nd and 3rd connectors are on the same side of the trunk | |
| if (Math.Sign(baseConnectors[1].Origin.X - baseX) * Math.Sign(baseConnectors[2].Origin.X - baseX) == 1) | |
| { | |
| return false; | |
| } | |
| //Create a tee fitting connecting the 2nd and 3rd base connectors to the trunk | |
| ConnectWithTeeFittingOnYAxis(baseConnectors[1], baseConnectors[2], connectors[1], true); | |
| } | |
| else | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseX, baseConnectors[1].Origin.Y + min1FittingLength, baseZ), new GXYZ(baseX, baseConnectors[2].Origin.Y - min1FittingLength, baseZ))); | |
| //Create a tee fitting connecting the 2nd base connector to the trunk | |
| ConnectWithTeeFittingOnYAxis(baseConnectors[1], connectors[1], connectors[2], false); | |
| //Create an elbow fitting connection the 3rd base connector to the trunk | |
| ConnectWithElbowFittingOnYAxis(baseConnectors[2], connectors[3]); | |
| } | |
| } | |
| return true; | |
| } | |
| catch | |
| { | |
| return false; | |
| } | |
| } | |
| /// <summary> | |
| /// Connect a base connector to a connector on the trunk with an elbow fitting | |
| /// </summary> | |
| /// <param name="baseConn">the upper connector of the vertical duct that derived from a terminal or the base equipment</param> | |
| /// <param name="conn">the connector of a duct on the trunk</param> | |
| private void ConnectWithElbowFittingOnYAxis(Connector baseConn, Connector conn) | |
| { | |
| double baseX = conn.Origin.X; | |
| double baseZ = conn.Origin.Z; | |
| List<Connector> connectors = new List<Connector>(); | |
| //If the distance of the two connectors on the X axis is greater than 2, create a duct on the X axis and then connect it to the 2 connectors with elbow fittings | |
| if (Math.Abs(baseConn.Origin.X - baseX) > min1Duct2FittingsLength) | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn.Origin.X - Math.Sign(baseConn.Origin.X - baseX), baseConn.Origin.Y, baseZ), new GXYZ(baseX + Math.Sign(baseConn.Origin.X - baseX), baseConn.Origin.Y, baseZ))); | |
| connectors[0].ConnectTo(baseConn); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn); | |
| connectors[1].ConnectTo(conn); | |
| m_document.Create.NewElbowFitting(connectors[1], conn); | |
| } | |
| //If the distance of the two connectors on the X axis is less than 2, connect them with an elbow fitting | |
| else | |
| { | |
| baseConn.ConnectTo(conn); | |
| m_document.Create.NewElbowFitting(baseConn, conn); | |
| } | |
| } | |
| /// <summary> | |
| /// Connect 3 connectors on the trunk with a tee fitting | |
| /// </summary> | |
| /// <param name="conn1">the first connector</param> | |
| /// <param name="conn2">the second connector</param> | |
| /// <param name="conn3">the third connector</param> | |
| /// <param name="flag">a flag to indicate whether there are 2 base connectors or 1 base connector</param> | |
| private void ConnectWithTeeFittingOnYAxis(Connector conn1, Connector conn2, Connector conn3, bool flag) | |
| { | |
| double baseX = conn3.Origin.X; | |
| double baseZ = conn3.Origin.Z; | |
| List<GXYZ> points = new List<GXYZ>(); | |
| List<Duct> ducts = new List<Duct>(); | |
| List<Connector> connectors = new List<Connector>(); | |
| //Connect two base connectors to a connector on the trunk | |
| if (true == flag) | |
| { | |
| Connector baseConn1 = conn1; | |
| Connector baseConn2 = conn2; | |
| Connector conn = conn3; | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn1.Origin.X - Math.Sign(baseConn1.Origin.X - baseX), baseConn1.Origin.Y, baseZ), new GXYZ(baseX + Math.Sign(baseConn1.Origin.X - baseX), baseConn1.Origin.Y, baseZ))); | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn2.Origin.X - Math.Sign(baseConn2.Origin.X - baseX), baseConn2.Origin.Y, baseZ), new GXYZ(baseX + Math.Sign(baseConn2.Origin.X - baseX), baseConn2.Origin.Y, baseZ))); | |
| connectors[0].ConnectTo(baseConn1); | |
| connectors[2].ConnectTo(baseConn2); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn1); | |
| m_document.Create.NewElbowFitting(connectors[2], baseConn2); | |
| connectors[1].ConnectTo(connectors[3]); | |
| connectors[1].ConnectTo(conn); | |
| connectors[3].ConnectTo(conn); | |
| m_document.Create.NewTeeFitting(connectors[1], connectors[3], conn); | |
| } | |
| //Connect a base connector to two connectors on the trunk | |
| else | |
| { | |
| Connector baseConn = conn1; | |
| if (Math.Abs(baseConn.Origin.X - baseX) > min1Duct2FittingsLength) | |
| { | |
| connectors.AddRange(CreateDuct(new GXYZ(baseConn.Origin.X - Math.Sign(baseConn.Origin.X - baseX), baseConn.Origin.Y, baseZ), new GXYZ(baseX + Math.Sign(baseConn.Origin.X - baseX), baseConn.Origin.Y, baseZ))); | |
| baseConn.ConnectTo(connectors[0]); | |
| m_document.Create.NewElbowFitting(connectors[0], baseConn); | |
| connectors[1].ConnectTo(conn2); | |
| connectors[1].ConnectTo(conn3); | |
| conn2.ConnectTo(conn3); | |
| m_document.Create.NewTeeFitting(conn2, conn3, connectors[1]); | |
| } | |
| else | |
| { | |
| baseConn.ConnectTo(conn2); | |
| baseConn.ConnectTo(conn3); | |
| conn2.ConnectTo(conn3); | |
| m_document.Create.NewTeeFitting(conn2, conn3, baseConn); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Sort the base connectors by their y values | |
| /// </summary> | |
| /// <param name="connectors">the connectors to be sorted</param> | |
| private void SortConnectorsByY(List<Connector> connectors) | |
| { | |
| for (int i = 0; i < connectors.Count; ++i) | |
| { | |
| double min = connectors[i].Origin.Y; | |
| int minIndex = i; | |
| for (int j = i; j < connectors.Count; ++j) | |
| { | |
| if (connectors[j].Origin.Y < min) | |
| { | |
| min = connectors[j].Origin.Y; | |
| minIndex = j; | |
| } | |
| } | |
| Connector t = connectors[i]; | |
| connectors[i] = connectors[minIndex]; | |
| connectors[minIndex] = t; | |
| } | |
| } | |
| /// <summary> | |
| /// Create a duct with two points | |
| /// </summary> | |
| /// <param name="point1">the first point</param> | |
| /// <param name="point2">the second point</param> | |
| /// <returns></returns> | |
| private List<Connector> CreateDuct(GXYZ point1, GXYZ point2) | |
| { | |
| List<Connector> connectors = new List<Connector>(); | |
| Duct duct = Duct.Create(m_document, systemTypeId, ductTypeId, lvl.Id, point1, point2); | |
| connectors.Add(ConnectorInfo.GetConnector(duct.Id, point1)); | |
| connectors.Add(ConnectorInfo.GetConnector(duct.Id, point2)); | |
| return connectors; | |
| } | |
| /// <summary> | |
| /// Create a mechanical system | |
| /// </summary> | |
| /// <param name="baseConnector">the base connector of the mechanical system</param> | |
| /// <param name="connectors">the connectors of the mechanical system</param> | |
| /// <param name="systemType">the system type of the mechanical system</param> | |
| /// <returns>the created mechanical system</returns> | |
| private MechanicalSystem CreateMechanicalSystem(ConnectorInfo baseConnector, ConnectorInfo[] connectors, DuctSystemType systemType) | |
| { | |
| ConnectorSet cset = null; | |
| if (connectors != null) | |
| { | |
| cset = new ConnectorSet(); | |
| foreach (ConnectorInfo ci in connectors) | |
| { | |
| cset.Insert(ci.Connector); | |
| } | |
| } | |
| MechanicalSystem mechanicalSystem = m_document.Create.NewMechanicalSystem(baseConnector == null ? null : baseConnector.Connector, cset, systemType); | |
| return mechanicalSystem; | |
| } | |
| /// <summary> | |
| /// information of a connector | |
| /// </summary> | |
| public class ConnectorInfo | |
| { | |
| /// <summary> | |
| /// The owner's element ID | |
| /// </summary> | |
| ElementId m_ownerId; | |
| /// <summary> | |
| /// The origin of the connector | |
| /// </summary> | |
| GXYZ m_origin; | |
| /// <summary> | |
| /// The Connector object | |
| /// </summary> | |
| Connector m_connector; | |
| /// <summary> | |
| /// The connector this object represents | |
| /// </summary> | |
| public Connector Connector | |
| { | |
| get { return m_connector; } | |
| set { m_connector = value; } | |
| } | |
| /// <summary> | |
| /// The owner ID of the connector | |
| /// </summary> | |
| public ElementId OwnerId | |
| { | |
| get { return m_ownerId; } | |
| set { m_ownerId = value; } | |
| } | |
| /// <summary> | |
| /// The origin of the connector | |
| /// </summary> | |
| public GXYZ Origin | |
| { | |
| get { return m_origin; } | |
| set { m_origin = value; } | |
| } | |
| /// <summary> | |
| /// The constructor that finds the connector with the owner ID and origin | |
| /// </summary> | |
| /// <param name="ownerId">the ownerID of the connector</param> | |
| /// <param name="origin">the origin of the connector</param> | |
| public ConnectorInfo(ElementId ownerId, GXYZ origin) | |
| { | |
| m_ownerId = ownerId; | |
| m_origin = origin; | |
| m_connector = ConnectorInfo.GetConnector(m_ownerId, origin); | |
| } | |
| /// <summary> | |
| /// The constructor that finds the connector with the owner ID and the values of the origin | |
| /// </summary> | |
| /// <param name="ownerId">the ownerID of the connector</param> | |
| /// <param name="x">the X value of the connector</param> | |
| /// <param name="y">the Y value of the connector</param> | |
| /// <param name="z">the Z value of the connector</param> | |
| public ConnectorInfo(ElementId ownerId, double x, double y, double z) | |
| : this(ownerId, new GXYZ(x, y, z)) | |
| { | |
| } | |
| /// <summary> | |
| /// Get the connector of the owner at the specific origin | |
| /// </summary> | |
| /// <param name="ownerId">the owner ID of the connector</param> | |
| /// <param name="connectorOrigin">the origin of the connector</param> | |
| /// <returns>if found, return the connector, or else return null</returns> | |
| public static Connector GetConnector(ElementId ownerId, GXYZ connectorOrigin) | |
| { | |
| ConnectorSet connectors = GetConnectors(ownerId); | |
| foreach (Connector conn in connectors) | |
| { | |
| if (conn.ConnectorType == ConnectorType.Logical) | |
| continue; | |
| if (conn.Origin.IsAlmostEqualTo(connectorOrigin)) | |
| return conn; | |
| } | |
| return null; | |
| } | |
| /// <summary> | |
| /// Get all the connectors of an element with a specific ID | |
| /// </summary> | |
| /// <param name="ownerId">the owner ID of the connector</param> | |
| /// <returns>the connector set which includes all the connectors found</returns> | |
| public static ConnectorSet GetConnectors(ElementId ownerId) | |
| { | |
| Element element = m_document.GetElement(ownerId); | |
| return GetConnectors(element); | |
| } | |
| /// <summary> | |
| /// Get all the connectors of a specific element | |
| /// </summary> | |
| /// <param name="element">the owner of the connector</param> | |
| /// <returns>if found, return all the connectors found, or else return null</returns> | |
| public static ConnectorSet GetConnectors(Autodesk.Revit.DB.Element element) | |
| { | |
| if (element == null) return null; | |
| FamilyInstance fi = element as FamilyInstance; | |
| if (fi != null && fi.MEPModel != null) | |
| { | |
| return fi.MEPModel.ConnectorManager.Connectors; | |
| } | |
| MEPSystem system = element as MEPSystem; | |
| if (system != null) | |
| { | |
| return system.ConnectorManager.Connectors; | |
| } | |
| MEPCurve duct = element as MEPCurve; | |
| if (duct != null) | |
| { | |
| return duct.ConnectorManager.Connectors; | |
| } | |
| return null; | |
| } | |
| /// <summary> | |
| /// Find the two connectors of the specific ConnectorManager at the two locations | |
| /// </summary> | |
| /// <param name="connMgr">The ConnectorManager of the connectors to be found</param> | |
| /// <param name="ptn1">the location of the first connector</param> | |
| /// <param name="ptn2">the location of the second connector</param> | |
| /// <returns>The two connectors found</returns> | |
| public static Connector[] FindConnectors(ConnectorManager connMgr, GXYZ pnt1, GXYZ pnt2) | |
| { | |
| Connector[] result = new Connector[2]; | |
| ConnectorSet conns = connMgr.Connectors; | |
| foreach (Connector conn in conns) | |
| { | |
| if (conn.Origin.IsAlmostEqualTo(pnt1)) | |
| { | |
| result[0] = conn; | |
| } | |
| else if (conn.Origin.IsAlmostEqualTo(pnt2)) | |
| { | |
| result[1] = conn; | |
| } | |
| } | |
| return result; | |
| } | |
| }; | |
| } | |
| public class LogUtility | |
| { | |
| /// <summary> | |
| /// Invalid string. | |
| /// </summary> | |
| public const string InvalidString = "[!]"; | |
| /// <summary> | |
| /// Write the information of an element to the log file | |
| /// </summary> | |
| /// <param name="element">the element whose information is to be written</param> | |
| public static void WriteElement(Element element) | |
| { | |
| WriteElement(element, true); | |
| } | |
| /// <summary> | |
| /// Write the information of an element to the log file | |
| /// </summary> | |
| /// <param name="element">the element whose information is to be written</param> | |
| /// <param name="writeId">whether the id will be outputted</param> | |
| public static void WriteElement(Element element, bool writeId) | |
| { | |
| if (element == null) | |
| { | |
| Trace.WriteLine("null"); return; | |
| } | |
| ElementId elementId = element.Id; | |
| ElementId familyId = element.get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsElementId(); | |
| string familyName = LogUtility.InvalidString; | |
| Element objectType = GetElement<Element>(element.Document, familyId); | |
| string elementName = LogUtility.InvalidString; | |
| try { elementName = element.Name; } | |
| catch { } | |
| if (objectType != null) | |
| { | |
| Parameter familyNameParameter = objectType.get_Parameter(BuiltInParameter.ALL_MODEL_FAMILY_NAME); | |
| if (familyNameParameter != null) | |
| familyName = familyNameParameter.AsString(); | |
| } | |
| BuiltInCategory category = element.Category.BuiltInCategory; | |
| Trace.WriteLine("Type: " + element.GetType().FullName); | |
| Trace.WriteLine("Name: " + familyName + ":" + elementName); | |
| if (writeId) Trace.WriteLine("Id: " + elementId.ToString()); | |
| Trace.WriteLine("Category: " + category); | |
| Trace.WriteLine("FamilyId: " + familyId.ToString()); | |
| } | |
| /// <summary> | |
| /// Write the information of a mechanical system to the log file | |
| /// </summary> | |
| /// <param name="system">the mechanical system whose information is to be written</param> | |
| public static void WriteMechanicalSystem(MechanicalSystem system) | |
| { | |
| string flow = InvalidString; | |
| try { flow = system.GetFlow().ToString(); } | |
| catch (Exception) { } | |
| Trace.WriteLine("Flow: " + flow); | |
| Trace.WriteLine("IsWellConnected: " + system.IsWellConnected); | |
| Trace.WriteLine("SystemType: " + system.SystemType); | |
| Trace.WriteLine("+DuctNetwork"); | |
| Trace.Indent(); | |
| foreach (Element element in system.DuctNetwork) | |
| { | |
| LogUtility.WriteElement(element, false); | |
| Trace.WriteLine(""); | |
| } | |
| Trace.Unindent(); | |
| WriteMEPSystem(system); | |
| } | |
| /// <summary> | |
| /// Get element by its id and cast it to the specified type | |
| /// </summary> | |
| /// <param name="document">the owner document of the element</param> | |
| /// <param name="eid">the id of the element</param> | |
| /// <returns>the element of the specified type</returns> | |
| public static T GetElement<T>(Document document, ElementId eid) where T : Autodesk.Revit.DB.Element | |
| { | |
| return document.GetElement(eid) as T; | |
| } | |
| /// <summary> | |
| /// Write the information of a MEPSystem to the log file. | |
| /// </summary> | |
| /// <param name="system">the MEP system whose information is to be written</param> | |
| public static void WriteMEPSystem(MEPSystem system) | |
| { | |
| WriteElement(system.BaseEquipment); | |
| Trace.Unindent(); | |
| Trace.WriteLine("+BaseEquipmentConnector"); | |
| Trace.Indent(); | |
| WriteConnector(system.BaseEquipmentConnector); | |
| Trace.Unindent(); | |
| Trace.WriteLine("+Elements"); | |
| Trace.Indent(); | |
| foreach (Element element in system.Elements) | |
| { | |
| WriteElement(element); | |
| Trace.WriteLine(""); | |
| } | |
| Trace.Unindent(); | |
| Trace.WriteLine("+ConnectorManager"); | |
| Trace.Indent(); | |
| WriteConnectorManager(system.ConnectorManager); | |
| Trace.Unindent(); | |
| } | |
| /// <summary> | |
| /// Write the information of a connector to the log file | |
| /// </summary> | |
| /// <param name="connector">the connector whose information is to be written</param> | |
| public static void WriteConnector(Connector connector) | |
| { | |
| if (connector == null) | |
| { | |
| Trace.WriteLine("null"); return; | |
| } | |
| object connType = InvalidString; | |
| object connDirection = InvalidString; | |
| object connShape = InvalidString; | |
| try { connShape = connector.Shape; } | |
| catch { } | |
| object connSize = InvalidString; | |
| try { connSize = GetShapeInfo(connector); } | |
| catch { } | |
| object connLocation = GetLocation(connector); | |
| object connAType = connector.ConnectorType; | |
| object connIsConnected = InvalidString; | |
| switch (connector.Domain) | |
| { | |
| case Domain.DomainElectrical: | |
| connType = connector.ElectricalSystemType; | |
| break; | |
| case Domain.DomainHvac: | |
| connType = connector.DuctSystemType; | |
| connDirection = connector.Direction; | |
| connIsConnected = connector.IsConnected; | |
| break; | |
| case Domain.DomainPiping: | |
| connType = connector.PipeSystemType; | |
| connDirection = connector.Direction; | |
| connIsConnected = connector.IsConnected; | |
| break; | |
| case Domain.DomainUndefined: | |
| default: | |
| connType = Domain.DomainUndefined; | |
| break; | |
| } | |
| Trace.WriteLine("Type: " + connAType); | |
| Trace.WriteLine("SystemType: " + connType); | |
| Trace.WriteLine("Direction: " + connDirection); | |
| Trace.WriteLine("Shape: " + connShape); | |
| Trace.WriteLine("Size: " + connSize); | |
| Trace.WriteLine("Location: " + connLocation); | |
| Trace.WriteLine("IsConnected: " + connIsConnected); | |
| } | |
| /// <summary> | |
| /// Write the information of a ConnectorManager to the log file | |
| /// </summary> | |
| /// <param name="connectorManager">the ConnectorManager whose information is to be written</param> | |
| public static void WriteConnectorManager(ConnectorManager connectorManager) | |
| { | |
| Trace.WriteLine("+Connectors"); | |
| Trace.Indent(); | |
| WriteConnectorSet2(connectorManager.Connectors); | |
| Trace.Unindent(); | |
| Trace.WriteLine("+UnusedConnectors"); | |
| Trace.Indent(); | |
| WriteConnectorSet2(connectorManager.UnusedConnectors); | |
| Trace.Unindent(); | |
| } | |
| /// <summary> | |
| /// Get the information string of a connector | |
| /// </summary> | |
| /// <param name="connector">the connector to be read</param> | |
| /// <returns>the information string of the connector</returns> | |
| public static string GetConnectorId(Connector connector) | |
| { | |
| if (connector == null) | |
| { | |
| return "null"; | |
| } | |
| ElementId ownerId = connector.Owner.Id; | |
| string systemId = InvalidString; | |
| try { systemId = connector.MEPSystem.Id.ToString(); } | |
| catch { } | |
| object connType = InvalidString; | |
| object connDirection = InvalidString; | |
| object connShape = InvalidString; | |
| try { connShape = connector.Shape; } | |
| catch { } | |
| object connSize = InvalidString; | |
| try { connSize = GetShapeInfo(connector); } | |
| catch { } | |
| object connLocation = GetLocation(connector); | |
| object connAType = connector.ConnectorType; | |
| object connIsConnected = InvalidString; | |
| switch (connector.Domain) | |
| { | |
| case Domain.DomainElectrical: | |
| connType = connector.ElectricalSystemType; | |
| break; | |
| case Domain.DomainHvac: | |
| connType = connector.DuctSystemType; | |
| connDirection = connector.Direction; | |
| connIsConnected = connector.IsConnected; | |
| break; | |
| case Domain.DomainPiping: | |
| connType = connector.PipeSystemType; | |
| connDirection = connector.Direction; | |
| connIsConnected = connector.IsConnected; | |
| break; | |
| case Domain.DomainUndefined: | |
| default: | |
| connType = Domain.DomainUndefined; | |
| break; | |
| } | |
| return string.Format("[{0}]\t[{1}]\t[{2}]\t[{3}]\t[{4}]\t[{5}]\t[{6}]\t[{7}]\t[{8}]\t", | |
| ownerId.ToString(), connType, connDirection, connShape, connSize, connLocation, | |
| connAType, connIsConnected, systemId); | |
| } | |
| /// <summary> | |
| /// Get the shape information string of a connector | |
| /// </summary> | |
| /// <param name="conn">the element to be read</param> | |
| /// <returns>the shape information string of the connector</returns> | |
| private static string GetShapeInfo(Connector conn) | |
| { | |
| switch (conn.Shape) | |
| { | |
| case ConnectorProfileType.Invalid: | |
| break; | |
| case ConnectorProfileType.Oval: | |
| break; | |
| case ConnectorProfileType.Rectangular: | |
| return string.Format("{0}\" x {1}\"", conn.Width, conn.Height); | |
| case ConnectorProfileType.Round: | |
| return string.Format("{0}\"", conn.Radius); | |
| default: | |
| break; | |
| } | |
| return InvalidString; | |
| } | |
| /// <summary> | |
| /// Get the location string of a connector | |
| /// </summary> | |
| /// <param name="conn">the connector to be read</param> | |
| /// <returns>the location information string of the connector</returns> | |
| private static object GetLocation(Connector conn) | |
| { | |
| if (conn.ConnectorType == ConnectorType.Logical) | |
| { | |
| return InvalidString; | |
| } | |
| Autodesk.Revit.DB.XYZ origin = conn.Origin; | |
| return string.Format("{0},{1},{2}", origin.X, origin.Y, origin.Z); | |
| } | |
| /// <summary> | |
| /// Write the information of a ConnectorSet to the log file. | |
| /// </summary> | |
| /// <param name="connectorSet">the ConnectorSet whose information is to be written</param> | |
| private static void WriteConnectorSet2(ConnectorSet connectorSet) | |
| { | |
| SortedDictionary<string, List<Connector>> connectors = new SortedDictionary<string, List<Connector>>(); | |
| foreach (Connector conn in connectorSet) | |
| { | |
| string connId = GetConnectorId(conn); | |
| if (conn.ConnectorType == ConnectorType.Logical) | |
| { | |
| foreach (Connector logLinkConn in conn.AllRefs) | |
| { | |
| connId += GetConnectorId(logLinkConn); | |
| } | |
| } | |
| if (!connectors.ContainsKey(connId)) | |
| { | |
| connectors.Add(connId, new List<Connector>()); | |
| } | |
| connectors[connId].Add(conn); | |
| } | |
| foreach (string key in connectors.Keys) | |
| { | |
| foreach (Connector conn in connectors[key]) | |
| { | |
| WriteConnector(conn); | |
| Trace.WriteLine("+AllRefs"); | |
| Trace.Indent(); | |
| WriteConnectorSet(conn.AllRefs); | |
| Trace.Unindent(); | |
| Trace.WriteLine(""); | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// Write the information of a ConnectorSet to the log file. | |
| /// </summary> | |
| /// <param name="connectorSet">the mechanical system whose information is to be written</param> | |
| private static void WriteConnectorSet(ConnectorSet connectorSet) | |
| { | |
| SortedDictionary<string, List<Connector>> connectors = new SortedDictionary<string, List<Connector>>(); | |
| foreach (Connector conn in connectorSet) | |
| { | |
| string connId = GetConnectorId(conn); | |
| if (conn.ConnectorType == ConnectorType.Logical) | |
| { | |
| foreach (Connector logLinkConn in conn.AllRefs) | |
| { | |
| connId += GetConnectorId(logLinkConn); | |
| } | |
| } | |
| if (!connectors.ContainsKey(connId)) | |
| { | |
| connectors.Add(connId, new List<Connector>()); | |
| } | |
| connectors[connId].Add(conn); | |
| } | |
| foreach (string key in connectors.Keys) | |
| { | |
| foreach (Connector conn in connectors[key]) | |
| { | |
| WriteConnector(conn); | |
| Trace.WriteLine(""); | |
| } | |
| } | |
| } | |
| } | |
| } | |
Xet Storage Details
- Size:
- 62.1 kB
- Xet hash:
- 18863c4ca0cc93d748031a8cb9674ad5f5368677fc0fe59fca6d237171c2a093
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.