Загрузка данных
Понял систему координат так: `X Axis` — ось гиба. Центр первого фланца лежит в плоскости `XZ` (зеркало) на расстоянии `Радиус` от `X`. Дуга лежит в плоскости `YZ`, а `Y Axis` параллельна оси первого фланца. В построении я использую только это: рёбра фланцев, плоскость `YZ` (дуга горизонтальна) и направление `Y Axis`. От `XY` ничего не зависит.
Ниже — построение второго патрубка и кольца. Функции `AddNozzle / AddConnectionPipe / AddDryPipe` меняются почти целиком (появляется номер патрубка), поэтому их привожу полностью. Остальное — точечные правки.
---
### Патч 1 — константы имён
Заменить блок `' --- имена компонентов …` (от `NOZZLE` до `TEE`) на:
vb
```vb
' --- общие компоненты (один комплект на РВС) ---
Private Const VERT As String = "Сухотруб верт ГПСС:1"
Private Const TEE As String = "Сухотруб тройник:1"
' --- файлы ---
Private Const DRY_FILE As String = "сухотруб подключения ГПСС.iam"
Private Const DRY_FILE_MIRROR As String = "сухотруб подключения ГПСС-01.iam" ' ← проверь имя
Private Const RING_FILE As String = "Труба вальцованная ГПСС.iam"
' --- вальцованные трубы: калибруются на модели ---
Private Const RING_TURN_1 As Double = 0 ' угол YZ трубы к XZ РВС, сторона патрубка 1
Private Const RING_TURN_2 As Double = 180 ' то же, сторона патрубка 2
Private Const RING_INSERT_GAP As Double = -2 ' зазор под прокладку между зеркалами
```
Имена компонентов патрубка теперь даёт класс `GpssNames` (патч 6). У патрубка №1 имена прежние, поэтому управляемая группа его не пересоздаёт.
### Патч 2 — `Main`, блок построения
Заменить блок от `ThisAssembly.BeginManage` до `ThisAssembly.EndManage` включительно:
vb
```vb
ThisAssembly.BeginManage(Group)
If enabled Then
Dim g1 As New GpssNames(1)
AddGpss(g1, gpssAngle)
Dim g2 As GpssNames = Nothing
If count >= 2 Then
g2 = New GpssNames(2)
AddGpss(g2, gpssAngle + 180) ' второй — напротив
End If
AddVerticalDryPipe() ' один на РВС (при 2 ГПСС — на α + 90°)
If count >= 2 Then
Try
Dim ring As RingPlan = CalcRing()
AddRing(g1, ring, RING_TURN_1)
AddRing(g2, ring, RING_TURN_2)
Catch ex As Exception
errors.Add("Кольцо: " & ex.Message)
End Try
End If
End If
ThisAssembly.EndManage(Group) ' всё, что не добавлено в этом запуске, удаляется
```
### Патч 3 — заменить `AddNozzle`, `AddConnectionPipe`, `AddDryPipe` целиком
vb
```vb
' Один патрубок со всей своей цепочкой
Sub AddGpss(g As GpssNames, angle As Double)
AddNozzle(g, angle)
AddConnectionPipe(g)
AddDryPipe(g)
End Sub
' ============================================================================
' 1. ПАТРУБОК, ПЕНОГЕНЕРАТОР, УКРЕПЛИСТ
' ============================================================================
Sub AddNozzle(g As GpssNames, angle As Double)
Components.Add(g.Nozzle, "Патрубок для ГПСС.iam")
Components.Add(g.Foam, "Пеногенератор ГПСС.ipt")
Components.Add(g.Seal, "Прокладка под ГПСС.ipt")
Components.Add(g.Plate, "Укреп лист на ГПСС.ipt")
Parameter(g.Nozzle, "Материал") = material
Parameter(g.Plate, "Толщина") = shellS
Parameter(g.Plate, "Диаметр") = tankD + 2 * shellS
Parameter(g.Plate, "Полный") = (gpssH < tankH - 450) ' 450 = −20 + 100 + 370 (как в исходном коде)
Dim c As String = g.Tag & " "
' --- укреплист на стенке РВС: ось, высота, угол ---
Constraints.AddMate(c & "Укреплист и РВС", g.Plate, "Y Axis", "", "Y Axis",
solutionType := MateConstraintSolutionTypeEnum.kAlignedSolutionType)
Constraints.AddFlush(c & "Укреплист и РВС 2", g.Plate, "XZ Plane", "", "XZ Plane", -gpssH)
Constraints.AddAngle(c & "Укреплист и РВС 3", g.Plate, "YZ Plane", "", "YZ Plane", 180 град + angle,
AngleConstraintSolutionTypeEnum.kReferenceVectorSolution, "", "Y Axis")
' --- патрубок на укреплисте ---
Constraints.AddMate(c & "Патрубок и укреплист", g.Plate, "XZ Plane", g.Nozzle, "XY Plane")
Constraints.AddMate(c & "Патрубок и укреплист 2", g.Plate, "YZ Plane", g.Nozzle, "YZ Plane")
Constraints.AddMate(c & "Патрубок и укреплист 3", g.Nozzle, "XZ Plane", g.Plate, "XY Plane",
tankD / 2 + 330 мм)
' --- пеногенератор на патрубке ---
Constraints.AddMate(c & "ось патр и пеногена", g.Nozzle, "Y Axis", g.Foam, "Z Axis",
solutionType := MateConstraintSolutionTypeEnum.kAlignedSolutionType)
Constraints.AddFlush(c & "Патрубок и пеногена", g.Foam, "XY Plane", g.Nozzle, "XZ Plane", 12 мм)
Constraints.AddMate(c & "Патрубок и пеногена 2", g.Foam, "XZ Plane", g.Nozzle, "XY Plane")
' --- прокладка пеногенератора ---
Constraints.AddMate(c & "Пеногена и прокладка", g.Seal, "ЦентрОсь", g.Foam, "Z Axis",
solutionType := MateConstraintSolutionTypeEnum.kAlignedSolutionType)
Constraints.AddFlush(c & "Пеногена и прокладка 2", g.Seal, "XZ Plane", g.Foam, "XY Plane", -10 мм)
Constraints.AddAngle(c & "Пеногена и прокладка 3", g.Seal, "XY Plane", g.Foam, "XZ Plane", 0 град,
AngleConstraintSolutionTypeEnum.kReferenceVectorSolution, g.Foam, "Y Axis")
' --- крепёж пеногенератора: две стороны, сетка 3 × 2 (шаг 170, между рядами 510) ---
Dim off As Double = NutOffset(22)
Fasten(g.Tag & "_ПГ1", g.Foam, "Ребро0", 55, 80, off,
Sub(kit) RectPattern("Метизы " & g.Tag & "_ПГ1:1", kit, 3, 170, g.Foam, "Ребро3", False,
2, 510, g.Foam, "Ребро2", True))
Fasten(g.Tag & "_ПГ2", g.Foam, "Ребро1", 55, 80, off,
Sub(kit) RectPattern("Метизы " & g.Tag & "_ПГ2:1", kit, 3, 170, g.Foam, "Ребро2", True,
2, 510, g.Foam, "Ребро3", False))
End Sub
' ============================================================================
' 2. ТРУБОПРОВОД ПОДКЛЮЧЕНИЯ
' ============================================================================
Sub AddConnectionPipe(g As GpssNames)
Components.Add(g.Pipe, "Трубопровод подключения ГПСС.iam")
Parameter(g.Pipe, "Коррозия") = corrosion
Parameter(g.Pipe, "Материал") = material
Parameter(g.Pipe, "Тип") = flangeType
Dim c As String = g.Tag & " "
Constraints.AddMate(c & "Трубопровод подключения:1", g.Pipe, "Y Axis", g.Foam, "Z Axis",
solutionType := MateConstraintSolutionTypeEnum.kAlignedSolutionType)
Constraints.AddFlush(c & "Трубопровод подключения:2", g.Pipe, "YZ Plane", g.Foam, "YZ Plane")
Constraints.AddFlush(c & "Трубопровод подключения:3", g.Pipe, "XZ Plane", g.Foam, "XY Plane", 592 мм)
AddGasket("Прокладка " & g.Tag & "_Подкл:1", {g.Pipe, "Фланец"})
' Здесь всегда болты (как в исходном коде). Смещение гайки 55,3 — фиксированное.
' ПРОВЕРИТЬ: возможно, должно быть NutOffset(flangeS).
Fasten(g.Tag & "_Подкл", {g.Pipe, "Фланец"}, "Proxy:Ребро1", 65, 0, -55.3,
Sub(kit) CircPattern("Метизы " & g.Tag & "_Подкл:1", kit, 4, 90, g.Pipe, "Y Axis"),
boltOnly := True, washerEdge := "Ребро3")
End Sub
' ============================================================================
' 3. СУХОТРУБ (у 2-го патрубка — зеркальная сборка -01)
' ============================================================================
Sub AddDryPipe(g As GpssNames)
Components.Add(g.Dry, If(g.N = 1, DRY_FILE, DRY_FILE_MIRROR))
Parameter(g.Dry, "Материал") = material
Parameter(g.Dry, "Коррозия") = corrosion
Parameter(g.Dry, "Направление2") = dryDirection
Parameter(g.Dry, "Тип") = flangeType
Dim c As String = g.Tag & " "
Constraints.AddMate(c & "Сухотруб:1", g.Dry, "XZ Plane", g.Pipe, "XY Plane", 602 мм)
Constraints.AddFlush(c & "Сухотруб:2", g.Dry, "YZ Plane", g.Pipe, "YZ Plane")
Constraints.AddFlush(c & "Сухотруб:3", g.Dry, "XY Plane", g.Pipe, "XZ Plane", 350 мм)
AddGasket("Прокладка " & g.Tag & "_Сух1:1", {g.Dry, "Фланец"})
AddGasket("Прокладка " & g.Tag & "_Сух2:1", {g.Dry, "Фланец2"})
' трубопровод подключения ↔ сухотруб
Fasten(g.Tag & "_Сух1", {g.Pipe, "Фланец2"}, "РеброДляВставки", 65, 90, NutOffset(flangeS),
Sub(kit) CircPattern("Метизы " & g.Tag & "_Сух1:1", kit, 4, 90, g.Dry, "Y Axis"))
' сухотруб ↔ вертикальный сухотруб (1 ГПСС) или первая вальцованная труба (2 ГПСС)
Fasten(g.Tag & "_Сух2", {g.Dry, "Фланец2"}, "РеброДляВставки", 65, 90, NutOffset(flangeS),
Sub(kit) CircPattern("Метизы " & g.Tag & "_Сух2:1", kit, 4, 90, {g.Dry, "Фланец2"}, "X Axis"))
End Sub
```
Имена всех зависимостей теперь начинаются с `g.Tag`, иначе у двух патрубков они бы совпали. Старые зависимости патрубка №1 группа один раз удалит и создаст под новыми именами — это безопасно.
### Патч 4 — `AddRing`
Вставить после `AddTee`:
vb
```vb
' ============================================================================
' КОЛЬЦО ОДНОЙ СТОРОНЫ: N вальцованных труб цепочкой от сухотруба к тройнику
' Каждая труба: «Фланец» — в зеркало предыдущего фланца (зазор под прокладку)
' + угол её YZ (плоскость дуги) к XZ РВС — фиксирует поворот вокруг оси.
' К тройнику последнюю не привязываем: замкнутого контура нет, стык сходится
' по расчёту CalcRing. Прокладка и крепёж — на «Фланец2» каждой трубы.
' ============================================================================
Sub AddRing(g As GpssNames, r As RingPlan, turn As Double)
Dim prev As String() = {g.Dry, "Фланец2"}
For k As Integer = 1 To r.N
Dim seg As String = g.Ring(k)
Components.Add(seg, RING_FILE)
Parameter(seg, "Радиус") = r.Rho
Parameter(seg, "Угол") = r.ThetaDeg
Parameter(seg, "Тип") = flangeType
Parameter(seg, "Материал") = material
Parameter(seg, "Коррозия") = corrosion
Constraints.AddInsert("Вставка " & seg, {seg, "Фланец"}, "Proxy:Ребро2", prev, "Proxy:Ребро2",
axesOpposed := True, distance := RING_INSERT_GAP)
Constraints.AddAngle("Угол " & seg, seg, "YZ Plane", "", "XZ Plane", turn,
AngleConstraintSolutionTypeEnum.kReferenceVectorSolution, seg, "Y Axis")
' дальний фланец: стык со следующей трубой или с тройником
Dim far As String() = {seg, "Фланец2"}
Dim joint As String = g.Tag & "_Кольцо" & k
AddGasket("Прокладка " & joint & ":1", far)
Fasten(joint, far, "РеброДляВставки", 65, 90, NutOffset(flangeS),
Sub(kit) CircPattern("Метизы " & joint & ":1", kit, 4, 90, far, "X Axis"))
prev = far
Next
End Sub
```
### Патч 5 — класс `GpssNames`
Добавить в конец правила, рядом с `RingPlan`:
vb
```vb
' Имена компонентов одного патрубка. №1 — прежние (их отслеживает группа),
' №2 — с номером. Tag — префикс соединений, массивов и зависимостей.
Class GpssNames
Public N As Integer
Public Tag As String
Public Nozzle As String, Foam As String, Seal As String, Plate As String
Public Pipe As String, Dry As String
Public Sub New(index As Integer)
N = index
Dim sfx As String = If(index = 1, "", " " & index)
Tag = If(index = 1, "ГПСС", "ГПСС" & index)
Nozzle = "Патрубок ГПСС" & sfx
Foam = "Пеногенератор ГПСС" & sfx
Seal = "Прокладка ГПСС" & sfx
Plate = "Укреплист ГПСС" & sfx
Pipe = "Трубопровод подключения ГПСС" & sfx
Dry = "Сухотруб ГПСС:" & index
End Sub
Public Function Ring(k As Integer) As String
Return "Труба вальцованная " & Tag & ":" & k
End Function
End Class
```
`AddVerticalDryPipe` и `AddTee` не меняются: они уже ставят вертикальный сухотруб на `gpssAngle + dryAngle` (+90° при 2 ГПСС).
---
### Калибровка на первом прогоне (как с отводами змеевика)
1. **Труба гнётся наружу, от стенки** — поменять `RING_TURN_1` (или `_2` для второй стороны) на 0 ↔ 180.
2. **Фланцы «влезли» друг в друга, а не стоят с зазором 2 мм** — поменять знак `RING_INSERT_GAP`.
3. **Последняя труба не попадает во фланец тройника.** Если невязка в проверочном окне ≈ 0, значит модели не совпадают с константами. Проверь `RING_STRAIGHT` (300 у сухотруба и у тройника) и `RING_AXIS_GAP` (ось сухотруба = ось вертикального).
### Нужно подтвердить
- Имя файла зеркального сухотруба — у меня `сухотруб подключения ГПСС-01.iam`. Фланцы в нём тоже называются `Фланец` и `Фланец2`?
- В сборке вальцованной трубы фланец на плоскости `XZ` называется именно `Фланец`, а дальний — `Фланец2`? Параметры называются `Радиус`, `Угол`, `Тип`, `Материал`, `Коррозия`?
- Модели сухотруба и тройника уже переделаны под 300, или пока стоят старые 600 / 350? Если старые, кольцо не сойдётся с тройником — тогда временно поставь `RING_STRAIGHT = 600` и проверяй только сторону сухотруба.