我正在尝试使用 Revit API 自动布线管道。我的目标是让我办公室的管道工程师能够简单地指定接收器的位置和一些相关端点(例如厕所和淋浴),并让我的插件将合适的管道从端点路由到接收器。
我读过路由可能是一个 NP 难问题,但我希望可以使用某些启发式方法来提出合理的解决方案,特别是当端点数量相对较低时。
我开始开发一个 POC,只是为了看看是否可以使用 Revit API 将两个平行管道与中间管道连接起来,但事实证明这有点困难。
特别是,我收到错误:
输入连接器之间无法创建配合,因为 它们之间的角度太小或太大。
打印连接器之间的角度时,它们似乎是 45 和 135 的组合(因此 135 是触发错误的值)。 135是180-45,所以我认为存在方向性问题?但我不确定如何指定管道的方向(如果可能的话)。 哦,值得注意的是,显然 wye 连接器(这是我实际需要的)只是 t 连接器的子集,所以显然我正在调用正确的方法。
这是我的代码。任何见解将不胜感激:
using (Transaction t = new Transaction(doc, "create pipes"))
{
t.Start();
XYZ location1_end = new XYZ(location1_start.X, location1_start.Y + 10 * zOffset, location1_start.Z);
Pipe pipe1 = Pipe.Create(doc, systemType.Id, pipeType.Id, level.Id, location1_start, location1_end);
// Insert second pipe parallel to the first, beneath it
XYZ location2_start = new XYZ(location1_start.X, location1_start.Y, location1_start.Z - zOffset);
XYZ location2_end = new XYZ(location1_start.X, location1_start.Y + 10 * zOffset, location1_start.Z - zOffset);
Pipe pipe2 = Pipe.Create(doc, systemType.Id, pipeType.Id, level.Id, location2_start, location2_end);
// pipe3 starts from someplace in the middle of pipe 1, and reaches someplace in the middle of pipe 2.
XYZ location3_start = new XYZ(location1_start.X, location1_start.Y + 10 , location1_start.Z);
XYZ location3_end = new XYZ(location1_start.X, location1_start.Y + 15, location1_start.Z - zOffset);
Pipe pipe3 = Pipe.Create(doc, systemType.Id, pipeType.Id, level.Id, location3_start, location3_end);
// By default there are two connectors for a pipe - one at the starting point, and one at the end.
ConnectorManager cm1 = pipe1.ConnectorManager;
ConnectorManager cm2 = pipe2.ConnectorManager;
ConnectorManager cm3 = pipe3.ConnectorManager;
Connector pipe1Connector = cm1.Connectors.Cast<Connector>().FirstOrDefault();
Connector pipe2Connector = cm2.Connectors.Cast<Connector>().FirstOrDefault();
// Where the third pipe begins (somewhere in the middle of pipe 1)
Connector thirdPipeConnector1 = cm3.Connectors.Cast<Connector>().FirstOrDefault();
// Where the third pipe ends (somewhere in the middle of pipe 2)
Connector thirdPipeConnector2 = cm3.Connectors.Cast<Connector>().LastOrDefault();
// From this point on, I'm not sure if the code is right. Here, I tried splitting pipes 1 and 2 at the locations where pipe 3 started and ended, so
// that new connectors could then be defined at those points, and those connectors could be used to connect to pipe 3.
ElementId pipe1Segment2Id = PlumbingUtils.BreakCurve(doc, pipe1.Id, location3_start);
ElementId pipe2Segment2Id = PlumbingUtils.BreakCurve(doc, pipe2.Id, location3_end);
Pipe pipe1Segment1 = doc.GetElement(pipe1.Id) as Pipe;
Pipe pipe1Segment2 = doc.GetElement(pipe1Segment2Id) as Pipe;
Pipe pipe2Segment1 = doc.GetElement(pipe2.Id) as Pipe;
Pipe pipe2Segment2 = doc.GetElement(pipe2Segment2Id) as Pipe;
// The connector right before the split of pipe 1?
Connector pipe1SplitConnector1 = pipe1Segment1.ConnectorManager.Connectors.Cast<Connector>().LastOrDefault(); // End of first segment
// The connector right after the split of pipe 1?
Connector pipe1SplitConnector2 = pipe1Segment2.ConnectorManager.Connectors.Cast<Connector>().FirstOrDefault(); // Start of second segment
Connector pipe2SplitConnector1 = pipe2Segment1.ConnectorManager.Connectors.Cast<Connector>().LastOrDefault(); // End of first segment
Connector pipe2SplitConnector2 = pipe2Segment2.ConnectorManager.Connectors.Cast<Connector>().FirstOrDefault(); // Start of second segment
// This was to help in debugging.
double ang1_3 = CalculateAngleBetweenConnectors(pipe1SplitConnector1, thirdPipeConnector1);
double ang1_end_3 = CalculateAngleBetweenConnectors(pipe1SplitConnector2, thirdPipeConnector1);
double ang2_3 = CalculateAngleBetweenConnectors(pipe2SplitConnector1, thirdPipeConnector2);
double ang2_end_3 = CalculateAngleBetweenConnectors(pipe2SplitConnector2, thirdPipeConnector2);
TaskDialog.Show("Angles", $"angle between pipe 1 and pipe 3: {ang1_3}, {ang1_end_3}, angle between pipe 2 and pipe 3: {ang2_3},{double ang2_end_3}");
// The errors are triggered by either of the following two lines.
//doc.Create.NewTeeFitting(pipe1SplitConnector1, thirdPipeConnector1, pipe1SplitConnector2);
//doc.Create.NewTeeFitting(pipe2SplitConnector1, thirdPipeConnector2, pipe2SplitConnector2);
t.Commit();
}
这是有道理的,这样的任务是现实的。首先,您可以查看官方 Revit SDK MEP 示例:
AutoRoute 完全可以满足您的需求,但对于管道:此示例演示了如何在基础送风设备和 2 个终端之间布置一组管道和配件。
接下来,你可以看看我的创建滚动偏移的研究和一系列解决方案;与管道一起使用。
参见。 Revit API 讨论论坛中也有相同问题的帖子,主题为 使用 revit api 相互连接管道。