Skip to content

Commit 7d51ef5

Browse files
committed
Move all MEP assets into repo.
1 parent a7bbc1d commit 7d51ef5

File tree

290 files changed

+122829
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

290 files changed

+122829
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<style type="text/css">
2+
img[src*='#center'] {
3+
display: block;
4+
margin: auto;
5+
}
6+
img[alt=center] {
7+
margin:10
8+
}
9+
</style>
10+
11+
# Eccentric reducers creation
12+
13+
The idea of the algorithm is to add AdditionalTransform to the connections.
14+
15+
AdditionalTransform keeps the offset from the centerline (or the line where flow collection nodes are located).
16+
17+
Each reducer keeps the TrunkSideTransform and BranchSideTransform.
18+
19+
These values are used as AdditionalTransform form TrunkSideComponent and BranchSideComponents.
20+
21+
## Reducer on trunk side
22+
23+
![image](images\ReducerOnTrunkSide1.PNG)
24+
25+
1. Insert reducer on trunk side:
26+
27+
Trunk Side offset is 0 ![center](images\Reducer1Description.PNG) Branch Side offset is H
28+
29+
30+
![image](images\ReducerOnTrunkSide2.PNG)
31+
32+
2. Add AdditionalTransform to the pipe and branch connection
33+
34+
![image](images\ReducerOnTrunkSide3.PNG)
35+
36+
## Reducer on branch side
37+
38+
![image](images\ReducerOnBranchSide1.PNG)
39+
40+
1. Insert reducer on branch side:
41+
42+
Trunk Side offset is H ![center](images\Reducer2Description.PNG) Branch Side offset is 0
43+
44+
![image](images\ReducerOnBranchSide2.PNG)
45+
46+
2. Add TrunkSideTransform.Inverted() to the Additionaltransform of reducer and branch side connection
47+
48+
![image](images\ReducerOnBranchSide3.PNG)
49+
50+
## The resize pipe functionality
51+
52+
![image](images\Resize1.PNG)
53+
54+
1. Resize pipe
55+
56+
![image](images\Resize2.PNG)
57+
58+
2. Insert reducer on Trunk side
59+
60+
![image](images\Resize3.PNG)
61+
62+
3. Add AdditionalTransform to the pipe
63+
64+
![image](images\Resize4.PNG)
65+
66+
4. Insert reducer on the Branch side
67+
68+
![image](images\Resize5.PNG)
69+
70+
## Sample
71+
72+
1. Create pipes between 4 connections, one of them is Wye connection
73+
74+
![image](images\Sample1.PNG)
75+
76+
2. Create pipes between Terminal 1 and Wye
77+
78+
![image](images\Sample2.PNG)
79+
80+
3. Add reducer between Terminal 1 and Pipe Segment 1
81+
82+
![image](images\Sample3.PNG)
83+
84+
4. Apply Reducer.BranchSideTransform to Pipe Segment 1 and Wye connection
85+
86+
![image](images\Sample4.PNG)
87+
88+
5. Create pipe between Wye connection and Terminal 2
89+
90+
![image](images\Sample5.PNG)
91+
92+
6. Apply Wye AdditionalTransform to Pipe Segment 2 and Terminal 2 connection
93+
94+
![image](images\Sample6.PNG)
95+
96+
7. Create pipe between Wye connection and Terminal 3
97+
98+
![image](images\Sample7.PNG)
99+
100+
8. Apply Wye AdditionalTransform to Pipe Segment 3 and Terminal 3 connection
101+
102+
![image](images\Sample8.PNG)
103+
104+
9. Create reducer between Pipe Segment 3 and Terminal 3
105+
106+
![image](images\Sample9.PNG)
107+
108+
10. Apply Reducer.TrunsSideTransform.Inverted() to Reducer and Terminal 3 connection
109+
110+
![image](images\Sample10.PNG)
111+
112+
113+
114+
115+
116+

Elements.MEP/Elements.MEP.sln

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.26124.0
5+
MinimumVisualStudioVersion = 15.0.26124.0
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elements.MEP", "src\Elements.MEP.csproj", "{F20FD29C-071C-46E2-AE44-223B7C098684}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elements.MEP.Tests", "test\Elements.MEP.Tests.csproj", "{604CD6E0-FD8F-440F-B027-E24F1B6F5840}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Debug|x64 = Debug|x64
14+
Debug|x86 = Debug|x86
15+
Release|Any CPU = Release|Any CPU
16+
Release|x64 = Release|x64
17+
Release|x86 = Release|x86
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
23+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|Any CPU.Build.0 = Debug|Any CPU
25+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|x64.ActiveCfg = Debug|Any CPU
26+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|x64.Build.0 = Debug|Any CPU
27+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|x86.ActiveCfg = Debug|Any CPU
28+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Debug|x86.Build.0 = Debug|Any CPU
29+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|Any CPU.ActiveCfg = Release|Any CPU
30+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|Any CPU.Build.0 = Release|Any CPU
31+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|x64.ActiveCfg = Release|Any CPU
32+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|x64.Build.0 = Release|Any CPU
33+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|x86.ActiveCfg = Release|Any CPU
34+
{F20FD29C-071C-46E2-AE44-223B7C098684}.Release|x86.Build.0 = Release|Any CPU
35+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|Any CPU.Build.0 = Debug|Any CPU
37+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|x64.ActiveCfg = Debug|Any CPU
38+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|x64.Build.0 = Debug|Any CPU
39+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|x86.ActiveCfg = Debug|Any CPU
40+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Debug|x86.Build.0 = Debug|Any CPU
41+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|Any CPU.ActiveCfg = Release|Any CPU
42+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|Any CPU.Build.0 = Release|Any CPU
43+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|x64.ActiveCfg = Release|Any CPU
44+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|x64.Build.0 = Release|Any CPU
45+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|x86.ActiveCfg = Release|Any CPU
46+
{604CD6E0-FD8F-440F-B027-E24F1B6F5840}.Release|x86.Build.0 = Release|Any CPU
47+
EndGlobalSection
48+
EndGlobal

Elements.MEP/Examples-Create Tree.dib

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!meta
2+
3+
{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":".NET"},{"aliases":["C#","c#"],"languageName":"C#","name":"csharp"},{"aliases":["frontend"],"name":"vscode"}]}}
4+
5+
#!csharp
6+
7+
#r "nuget: Elements.MEP"
8+
9+
#!markdown
10+
11+
The routing basis for MEP systems is Elements.Flow.Tree. The tree is a geometric graph, with Flow.Nodes that are connected by Flow.Connections. The tree is simply meant to represent where the system paths are, where the paths merge/branch and what amount of flow is in each connection. You can optionally provide a diameter for the connections, to get a system that has realistic sizes.
12+
13+
The leaves of the system are called Inlets (purely for historical reasons) and the trunk node is called the Outlet (again, for historical reasons). There is only one Outlet, but there can be many Inlets.
14+
15+
The simplest tree is flat and just has some inlets and some outlets, lets make that now.
16+
17+
#!csharp
18+
19+
using Elements.Flow;
20+
21+
var tree= new Tree(new[] {"Room-101"});
22+
23+
tree.SetOutletPosition((0,-1,0));
24+
25+
tree.AddInlet((-1,1,0 ));
26+
tree.AddInlet((1,5,0));
27+
28+
return tree;
29+
30+
#!markdown
31+
32+
Note that both inlets are connected directly to the outlet, which is not a very interesting system. Let's change this to make it so that the inlets join together before going to the outlet. We'll see some of our first ways in modifying and interacting with the `Tree`.
33+
34+
### TODO Add a description of there being Nodes/Edges in the Tree
35+
36+
#!csharp
37+
38+
using Elements.Flow;
39+
40+
var tree= new Tree(new[] {"Room-101"});
41+
42+
tree.SetOutletPosition((0,-1,0));
43+
44+
var inlet1 = tree.AddInlet((-1,1,0 ));
45+
var connection = tree.GetOutgoingConnection((inlet1));
46+
var node = tree.SplitConnectionThroughPoint(connection, (0,1,0), out _);
47+
48+
// when we add an inlet we can specify a node to connect via
49+
var inlet2 = tree.AddInlet((1,5,0), connectVia: node);
50+
51+
return tree;
52+
53+
#!markdown
54+
55+
Note the small cube that has appeared. These cubes appear at every node where there is more than one incoming connection. They are places where the Tree branches.
56+
57+
The Tree class is designed to let you modify the connections of the system while always maintaining internal connectivity. Let's clean up the connection from our second inlet so that it isn't at an angle.
58+
59+
#!csharp
60+
61+
var inlet2 = tree.Inlets[1];
62+
var connection = tree.GetOutgoingConnection(inlet2);
63+
tree.NormalizeConnectionPath(connection, Vector3.ZAxis, Vector3.XAxis, 90, Tree.NormalizationType.End);
64+
65+
return tree;
66+
67+
#!markdown
68+
69+
Here are some other common Tree manipulation methods:
70+
71+
```csharp
72+
tree.ChamferAtNode(tree.InternalNodes.First(), 0.5, out _, out _);
73+
tree.ConnectVertically(tree.Connections.First(), 0.5);
74+
tree.MergeConnectionsAtPoint(tree.Connections.ToList(), (0,1,0));
75+
tree.ShiftConnectionToNode(tree.Connections.First(), tree.Outlet);
76+
```
77+
78+
#!markdown
79+
80+
Let's build a slightly more complex tree and give it some flow values.
81+
82+
#!csharp
83+
84+
using Elements.Flow;
85+
86+
var tree= new Tree(new[] {"Room-101"});
87+
tree.SetOutletPosition((0,-1,0));
88+
89+
var inlet1 = tree.AddInlet((-1,1,0), 1);
90+
var inlet2 = tree.AddInlet((-1,5,0), 2);
91+
var inlet3 = tree.AddInlet((1,2,0), 3);
92+
93+
var connection1 = tree.GetOutgoingConnection(inlet1);
94+
var connection2 = tree.GetOutgoingConnection(inlet2);
95+
var node= tree.MergeConnectionsAtPoint(new List<Connection> {connection1, connection2}, (0,1,0));
96+
97+
// connection1 is a new connection after the previous change
98+
connection2 = tree.GetOutgoingConnection(inlet2);
99+
var connection3 = tree.GetOutgoingConnection(inlet3);
100+
tree.ShiftConnectionToNode(connection3, node);
101+
tree.MergeConnectionsAtPoint(new List<Connection> {connection2, connection3}, (0,2,0));
102+
103+
connection2 = tree.GetOutgoingConnection(inlet2);
104+
tree.NormalizeConnectionPath(connection2, Vector3.ZAxis, Vector3.XAxis, 90, Tree.NormalizationType.End);
105+
106+
return tree;
107+
108+
#!markdown
109+
110+
Now, you have a tree with some flow values and some branching connections. Let's find the flow at the connections.
111+
112+
#!csharp
113+
114+
tree.UpdateSections();
115+
116+
var connection3 = tree.GetOutgoingConnection(inlet3);
117+
Console.WriteLine($"Flow from inlet1: {tree.GetFlowOfConnection(connection3)}");
118+
119+
var trunk = tree.GetIncomingConnections(tree.Outlet).First();
120+
Console.WriteLine($"Flow from outlet: {tree.GetFlowOfConnection(trunk)}");
121+
122+
#!markdown
123+
124+
The `UpdateSections()` method is used to update the flow values in the connections. It also updates the "Sections" property of the tree, where each section is a list of connections that are connected to each other but without any branching. Let's take a look at what the sections look like.
125+
126+
#!csharp
127+
128+
var sections = tree.GetSections();
129+
Console.WriteLine($"Number of connections: {tree.Connections.Count()}");
130+
Console.WriteLine($"Number of sections: {sections.Count()}");
131+
132+
return sections;
133+
134+
#!markdown
135+
136+
Now lets create fittings for this tree. For that we'll use the `Elements.Fittings` namespace, and we can create fittings with just one one line.
137+
138+
#!csharp
139+
140+
using Elements.Fittings;
141+
142+
var fittings = new FittingTreeRouting(tree).BuildFittingTree(out var errors);
143+
144+
return fittings;
145+
146+
#!markdown
147+
148+
These fitting were created using the default FittingTreeRouting, which you can modify to get different results if we want.
149+
150+
#!csharp
151+
152+
var routing = new FittingTreeRouting(tree);
153+
routing.PipeMaterial = new Material("Pipe", Colors.Aqua, 0.1, 0.1);
154+
var fittings = routing.BuildFittingTree(out var error);// FittingTree.FromFlowNetwork(tree, out var errors, routing);
155+
156+
return fittings;
157+
158+
#!markdown
159+
160+
Besides just color, you can make a custom FittingTreeRouting that implements your own logic for creating fittings. For example, imagine you only have one size of "Terminal" and "Elbow" fittings, and you want to create your Fitting tree using only that one size. You do this by inheriting from the FittingTreeRouting class and overriding the `BranchPipe` and `TerminatePipe` methods.
161+
162+
#!csharp
163+
164+
public class OneSizeToRuleThemAll: FittingTreeRouting
165+
{
166+
public OneSizeToRuleThemAll(Tree tree) : base(tree)
167+
{
168+
}
169+
170+
public override Fitting ChangeDirection(Connection incoming, Connection outgoing)
171+
{
172+
var diameter = 0.1;
173+
var elbow = CreateElbow(diameter, incoming.End.Position, incoming.Direction().Negate(), outgoing.Direction());
174+
return elbow;
175+
}
176+
177+
public override Fitting TerminatePipe(Connection incoming, Connection outgoing, out Node[] absorbed) {
178+
var diameter = 0.1;
179+
absorbed = new Node[0];
180+
if (outgoing != null)
181+
{
182+
var terminal = new Terminal(outgoing.Start.Position, outgoing.Direction(), 0.03, diameter, DefaultFittingMaterial);
183+
return terminal;
184+
}
185+
else if (incoming != null)
186+
{
187+
var terminal = new Terminal(incoming.End.Position, incoming.Direction().Negate(), 0.03, diameter, DefaultFittingMaterial);
188+
return terminal;
189+
}
190+
else
191+
{
192+
throw new ArgumentNullException("Both connections to terminate were null");
193+
}
194+
}
195+
196+
public override IReducer ReduceOrJoin(StraightSegment pipe, bool invert, double newDiameter, double additionalDistance = 0){
197+
var reducer = base.ReduceOrJoin(pipe, invert, newDiameter, additionalDistance);
198+
(reducer as Reducer).Material = new Material("Reducer", Colors.Coral, newDiameter, newDiameter);
199+
return reducer;
200+
}
201+
}
202+
203+
var routing = new OneSizeToRuleThemAll(tree);
204+
routing.PipeMaterial = new Material("Pipe", Colors.Aqua, 0.1, 0.1);
205+
var fittings = routing.BuildFittingTree(out var errors);// FittingTree.FromFlowNetwork(tree, out var errors, routing);
206+
Console.WriteLine($"Total number of reducers: {fittings.FittingsOfType<Reducer>().Count()}");
207+
208+
return fittings;
209+
210+
#!markdown
211+
212+
Cool! Now you have 100mm elbows and terminals. Notice that reducers were automatically added wherever necessary. The other methods you might be interested in modifying are:
213+
214+
```csharp
215+
Fitting BranchPipe(Connection incoming1, Connection incoming2, Connection outgoing) // for single branch nodes.
216+
Fitting ManifoldPipe(IEnumerable<Connection> incoming, Connection outgoing) // for multi-branch nodes.
217+
Fitting ChangePipe(Connection incoming, Connection outgoing) // for nodes with a single incoming and outgoing connection that are aligned.
218+
```

0 commit comments

Comments
 (0)