stbkit 0.1.0a9.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stbkit/__main__.py +10 -0
- stbkit/api/__init__.py +48 -0
- stbkit/api/experimental/__init__.py +19 -0
- stbkit/api/experimental/repository/__init__.py +30 -0
- stbkit/api/py.typed +0 -0
- stbkit/api/stb_latest.py +7 -0
- stbkit/api/stb_v2_0_2.py +11 -0
- stbkit/api/stb_v2_1_1.py +9 -0
- stbkit/cli/__init__.py +17 -0
- stbkit/cli/_internal/cli_main.py +114 -0
- stbkit/cli/_internal/common.py +126 -0
- stbkit/cli/_internal/constants_exit_code.py +59 -0
- stbkit/cli/_internal/converter.py +693 -0
- stbkit/cli/_internal/diff.py +213 -0
- stbkit/cli/_internal/entry_points.py +25 -0
- stbkit/cli/_internal/global_parent.py +70 -0
- stbkit/cli/_internal/show_versions.py +36 -0
- stbkit/cli/_internal/validate.py +310 -0
- stbkit/cli/commands/convert.py +16 -0
- stbkit/cli/commands/diff.py +16 -0
- stbkit/cli/commands/validate.py +16 -0
- stbkit/cli/py.typed +0 -0
- stbkit/tools/__init__.py +12 -0
- stbkit/tools/_internal/__init__.py +5 -0
- stbkit/tools/_internal/constants.py +21 -0
- stbkit/tools/_internal/data_model/building_geometry.py +1208 -0
- stbkit/tools/_internal/data_model/building_geometry_web.py +106 -0
- stbkit/tools/_internal/data_model/element_data.py +93 -0
- stbkit/tools/_internal/data_model/ifc_data/entity_data.py +67 -0
- stbkit/tools/_internal/data_model/ifc_data/entity_names.py +32 -0
- stbkit/tools/_internal/data_model/shape_data.py +1089 -0
- stbkit/tools/_internal/diff/__init__.py +5 -0
- stbkit/tools/_internal/diff/common.py +50 -0
- stbkit/tools/_internal/diff/diff_xml.py +796 -0
- stbkit/tools/_internal/matrix.py +51 -0
- stbkit/tools/_internal/optional_dependencies/__init__.py +5 -0
- stbkit/tools/_internal/optional_dependencies/ifc_common.py +28 -0
- stbkit/tools/_internal/optional_dependencies/ifc_exporter/ifc_entity_exporter.py +473 -0
- stbkit/tools/_internal/optional_dependencies/ifc_exporter/ifc_profile_exporter.py +267 -0
- stbkit/tools/_internal/optional_dependencies/ifc_exporter/ifc_representation_exporter.py +178 -0
- stbkit/tools/_internal/optional_dependencies/ifc_pipeline.py +133 -0
- stbkit/tools/_internal/optional_dependencies/ifc_to_building_geometry.py +64 -0
- stbkit/tools/_internal/stb_io.py +116 -0
- stbkit/tools/_internal/stb_repair/_common.py +24 -0
- stbkit/tools/_internal/stb_repair/_stb_repair.py +197 -0
- stbkit/tools/_internal/stb_repair/_stb_v2_0_2_repair.py +53 -0
- stbkit/tools/_internal/stb_repair/_stb_v2_1_0_repair.py +109 -0
- stbkit/tools/_internal/stb_repair/_stb_v2_1_1_repair.py +109 -0
- stbkit/tools/_internal/studio_report.py +49 -0
- stbkit/tools/_internal/utils/atomic_writer.py +57 -0
- stbkit/tools/_internal/utils/float_rounding.py +49 -0
- stbkit/tools/_internal/utils/girder_utils.py +91 -0
- stbkit/tools/_internal/utils/guid_utils.py +30 -0
- stbkit/tools/_internal/utils/mesh_utils.py +1305 -0
- stbkit/tools/_internal/utils/node_utils.py +50 -0
- stbkit/tools/_internal/utils/unit_utils.py +23 -0
- stbkit/tools/_internal/vectors.py +222 -0
- stbkit/tools/converters/__init__.py +39 -0
- stbkit/tools/converters/_internal/__init__.py +5 -0
- stbkit/tools/converters/_internal/building_geometry_to_ply_text.py +32 -0
- stbkit/tools/converters/_internal/coord_converter.py +151 -0
- stbkit/tools/converters/_internal/element_data_to_building_geometry.py +549 -0
- stbkit/tools/converters/_internal/ifc_to_ply_text.py +21 -0
- stbkit/tools/converters/_internal/name_converter.py +23 -0
- stbkit/tools/converters/_internal/pipeline/__init__.py +5 -0
- stbkit/tools/converters/_internal/pipeline/data.py +188 -0
- stbkit/tools/converters/_internal/pipeline/execution.py +569 -0
- stbkit/tools/converters/_internal/pipeline/ply_pipeline.py +52 -0
- stbkit/tools/converters/_internal/pipeline/stb_pipeline.py +226 -0
- stbkit/tools/converters/_internal/pipeline/stb_pipeline_latest.py +39 -0
- stbkit/tools/converters/_internal/pipeline/step.py +139 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/__init__.py +17 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/_stb_latest_to_element_data.py +186 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/member/member_footing.py +49 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/member/member_line.py +533 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/member/member_pile.py +100 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/member/member_plane.py +103 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/open.py +70 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec.py +214 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_beam_rc.py +67 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_beam_s.py +97 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_beam_src.py +28 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_brace_s.py +49 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_column_cft.py +217 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_column_rc.py +41 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_column_s.py +127 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_column_src.py +173 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_foundation.py +225 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_parapet_rc.py +53 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_pile_rc.py +106 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_pile_s.py +100 -0
- stbkit/tools/converters/_internal/stb_latest_to_element_data/section/sec_steel.py +432 -0
- stbkit/tools/converters/_internal/stb_to_building_geometry.py +44 -0
- stbkit/tools/converters/_internal/stb_to_ifc_data/__init__.py +5 -0
- stbkit/tools/converters/_internal/stb_to_ifc_data/_stb_to_ifc_data.py +59 -0
- stbkit/tools/converters/_internal/stb_to_ifc_data/convert_option.py +22 -0
- stbkit/tools/converters/_internal/stb_to_ply_text.py +22 -0
- stbkit/tools/py.typed +0 -0
- stbkit/tools/upgrade/__init__.py +13 -0
- stbkit/tools/upgrade/_internal/__init__.py +5 -0
- stbkit/tools/upgrade/_internal/common.py +205 -0
- stbkit/tools/upgrade/_internal/upgrade.py +228 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/__init__.py +60 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_common.py +62 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_joint_beam_shape_h.py +44 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_sec_pile_rc.py +101 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_sec_pile_s.py +78 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_sec_slab_deck.py +56 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/hook_sec_slab_rc.py +128 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/post_girder.py +126 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/post_open.py +110 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/post_sec_beam_rc.py +227 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hook_funcs/post_sec_beam_s.py +1153 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/hooks.py +22 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/post.py +42 -0
- stbkit/tools/upgrade/_internal/v2_0_2_to_v2_1_0/tables.py +99 -0
- stbkit/tools/upgrade/_internal/v2_1_0_to_v2_1_1/__init__.py +58 -0
- stbkit/tools/upgrade/_internal/v2_1_0_to_v2_1_1/hooks.py +32 -0
- stbkit/tools/upgrade/_internal/v2_1_0_to_v2_1_1/tables.py +56 -0
- stbkit-0.1.0a9.dev1.dist-info/METADATA +196 -0
- stbkit-0.1.0a9.dev1.dist-info/RECORD +125 -0
- stbkit-0.1.0a9.dev1.dist-info/WHEEL +5 -0
- stbkit-0.1.0a9.dev1.dist-info/entry_points.txt +2 -0
- stbkit-0.1.0a9.dev1.dist-info/licenses/LICENSE +373 -0
- stbkit-0.1.0a9.dev1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright 2025-2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
from typing import Protocol
|
|
8
|
+
|
|
9
|
+
from stbkit.core.data_model import (
|
|
10
|
+
stb_v2_0_0,
|
|
11
|
+
stb_v2_0_1,
|
|
12
|
+
stb_v2_0_2,
|
|
13
|
+
stb_v2_1_0,
|
|
14
|
+
stb_v2_1_1,
|
|
15
|
+
)
|
|
16
|
+
from stbkit.core.data_model.common import StBridgeRoot
|
|
17
|
+
from stbkit.core.stb_exceptions import (
|
|
18
|
+
ReferenceElementNotFoundError,
|
|
19
|
+
UnsupportedStbVersionError,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from ..vectors import Vector3d
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class HasXyz(Protocol):
|
|
26
|
+
@property
|
|
27
|
+
def x(self) -> float: ...
|
|
28
|
+
@property
|
|
29
|
+
def y(self) -> float: ...
|
|
30
|
+
@property
|
|
31
|
+
def z(self) -> float: ...
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_node_coordinate(stb: StBridgeRoot, id: int) -> Vector3d:
|
|
35
|
+
if not isinstance(
|
|
36
|
+
stb,
|
|
37
|
+
(
|
|
38
|
+
stb_v2_0_0.StBridge,
|
|
39
|
+
stb_v2_0_1.StBridge,
|
|
40
|
+
stb_v2_0_2.StBridge,
|
|
41
|
+
stb_v2_1_0.StBridge,
|
|
42
|
+
stb_v2_1_1.StBridge,
|
|
43
|
+
),
|
|
44
|
+
):
|
|
45
|
+
raise UnsupportedStbVersionError(stb.version)
|
|
46
|
+
|
|
47
|
+
for node in stb.stb_model.stb_nodes.stb_node:
|
|
48
|
+
if node.id == id:
|
|
49
|
+
return Vector3d.from_stb_node(node)
|
|
50
|
+
raise ReferenceElementNotFoundError(f"StbNode id={id}が見つかりません")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2025-2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def mm_to_m(value: float) -> float:
|
|
11
|
+
return value / 1000.0
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def m_to_mm(value: float) -> float:
|
|
15
|
+
return value * 1000.0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def radian_to_degree(value: float) -> float:
|
|
19
|
+
return math.degrees(value)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def degree_to_radian(value: float) -> float:
|
|
23
|
+
return math.radians(value)
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Copyright 2025-2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import math
|
|
10
|
+
from collections.abc import Iterator, Sequence
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from math import sqrt
|
|
13
|
+
from typing import TYPE_CHECKING, overload
|
|
14
|
+
|
|
15
|
+
from stbkit.core.stb_exceptions import SchemaError
|
|
16
|
+
|
|
17
|
+
from .utils.unit_utils import degree_to_radian, mm_to_m
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from .utils.node_utils import HasXyz
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True, slots=True)
|
|
24
|
+
class Vector2d(Sequence[float]):
|
|
25
|
+
x: float = 0.0
|
|
26
|
+
y: float = 0.0
|
|
27
|
+
|
|
28
|
+
def mm_to_m(self) -> Vector2d:
|
|
29
|
+
return Vector2d(mm_to_m(self.x), mm_to_m(self.y))
|
|
30
|
+
|
|
31
|
+
def to_vector3d(self, z: float = 0.0) -> Vector3d:
|
|
32
|
+
return Vector3d(self.x, self.y, z)
|
|
33
|
+
|
|
34
|
+
@overload
|
|
35
|
+
def __getitem__(self, index: int) -> float: ...
|
|
36
|
+
|
|
37
|
+
@overload
|
|
38
|
+
def __getitem__(self, index: slice) -> Sequence[float]: ...
|
|
39
|
+
|
|
40
|
+
def __getitem__(self, index: int | slice) -> float | Sequence[float]:
|
|
41
|
+
if isinstance(index, int):
|
|
42
|
+
if index == 0:
|
|
43
|
+
return self.x
|
|
44
|
+
elif index == 1:
|
|
45
|
+
return self.y
|
|
46
|
+
else:
|
|
47
|
+
raise IndexError("インデックスは0から1の範囲で指定してください")
|
|
48
|
+
elif isinstance(index, slice):
|
|
49
|
+
# スライスの場合はリストで返す
|
|
50
|
+
return [self.x, self.y][index]
|
|
51
|
+
else:
|
|
52
|
+
raise TypeError("インデックスは整数またはスライスで指定してください")
|
|
53
|
+
|
|
54
|
+
def __len__(self) -> int:
|
|
55
|
+
return 2
|
|
56
|
+
|
|
57
|
+
def __add__(self, other: Vector2d) -> Vector2d:
|
|
58
|
+
return Vector2d(self.x + other.x, self.y + other.y)
|
|
59
|
+
|
|
60
|
+
def __sub__(self, other: Vector2d) -> Vector2d:
|
|
61
|
+
return Vector2d(self.x - other.x, self.y - other.y)
|
|
62
|
+
|
|
63
|
+
def __neg__(self) -> Vector2d:
|
|
64
|
+
return Vector2d(-self.x, -self.y)
|
|
65
|
+
|
|
66
|
+
def __iter__(self) -> Iterator[float]:
|
|
67
|
+
yield self.x
|
|
68
|
+
yield self.y
|
|
69
|
+
|
|
70
|
+
def clone(self) -> Vector2d:
|
|
71
|
+
return Vector2d(self.x, self.y)
|
|
72
|
+
|
|
73
|
+
def distance_to(self, other: Vector2d) -> float:
|
|
74
|
+
return math.hypot(other.y - self.y, other.x - self.x)
|
|
75
|
+
|
|
76
|
+
def rotate(self, angle_degree: float) -> Vector2d:
|
|
77
|
+
if angle_degree == 0.0:
|
|
78
|
+
return self.clone()
|
|
79
|
+
theta: float = degree_to_radian(angle_degree)
|
|
80
|
+
cos_theta: float = math.cos(theta)
|
|
81
|
+
sin_theta: float = math.sin(theta)
|
|
82
|
+
x_new: float = cos_theta * self.x - sin_theta * self.y
|
|
83
|
+
y_new: float = sin_theta * self.x + cos_theta * self.y
|
|
84
|
+
return Vector2d(x_new, y_new)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def zero() -> Vector2d:
|
|
88
|
+
return Vector2d(0.0, 0.0)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(frozen=True, slots=True)
|
|
92
|
+
class Vector3d(Sequence[float]):
|
|
93
|
+
x: float = 0.0
|
|
94
|
+
y: float = 0.0
|
|
95
|
+
z: float = 0.0
|
|
96
|
+
|
|
97
|
+
def __add__(self, other: Vector3d) -> Vector3d:
|
|
98
|
+
return Vector3d(self.x + other.x, self.y + other.y, self.z + other.z)
|
|
99
|
+
|
|
100
|
+
@overload
|
|
101
|
+
def __getitem__(self, index: int) -> float: ...
|
|
102
|
+
|
|
103
|
+
@overload
|
|
104
|
+
def __getitem__(self, index: slice) -> Sequence[float]: ...
|
|
105
|
+
|
|
106
|
+
def __getitem__(self, index: int | slice) -> float | Sequence[float]:
|
|
107
|
+
if isinstance(index, int):
|
|
108
|
+
if index == 0:
|
|
109
|
+
return self.x
|
|
110
|
+
elif index == 1:
|
|
111
|
+
return self.y
|
|
112
|
+
elif index == 2:
|
|
113
|
+
return self.z
|
|
114
|
+
else:
|
|
115
|
+
raise IndexError("インデックスは0から2の範囲で指定してください")
|
|
116
|
+
elif isinstance(index, slice):
|
|
117
|
+
# スライスの場合はリストで返す
|
|
118
|
+
return [self.x, self.y, self.z][index]
|
|
119
|
+
else:
|
|
120
|
+
raise TypeError("インデックスは整数またはスライスで指定してください")
|
|
121
|
+
|
|
122
|
+
def __len__(self) -> int:
|
|
123
|
+
return 3
|
|
124
|
+
|
|
125
|
+
def __rmul__(self, other: float) -> Vector3d:
|
|
126
|
+
return Vector3d(other * self.x, other * self.y, other * self.z)
|
|
127
|
+
|
|
128
|
+
def __sub__(self, other: Vector3d) -> Vector3d:
|
|
129
|
+
return Vector3d(self.x - other.x, self.y - other.y, self.z - other.z)
|
|
130
|
+
|
|
131
|
+
def __neg__(self) -> Vector3d:
|
|
132
|
+
return Vector3d(-self.x, -self.y, -self.z)
|
|
133
|
+
|
|
134
|
+
def clone(self) -> Vector3d:
|
|
135
|
+
return Vector3d(self.x, self.y, self.z)
|
|
136
|
+
|
|
137
|
+
def cross(self, other: Vector3d) -> Vector3d:
|
|
138
|
+
return Vector3d(
|
|
139
|
+
self.y * other.z - self.z * other.y,
|
|
140
|
+
self.z * other.x - self.x * other.z,
|
|
141
|
+
self.x * other.y - self.y * other.x,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def distance_to(self, other: Vector3d) -> float:
|
|
145
|
+
return sqrt(
|
|
146
|
+
(self.x - other.x) ** 2 + (self.y - other.y) ** 2 + (self.z - other.z) ** 2
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def dot(self, other: Vector3d) -> float:
|
|
150
|
+
return self.x * other.x + self.y * other.y + self.z * other.z
|
|
151
|
+
|
|
152
|
+
def length(self) -> float:
|
|
153
|
+
return sqrt(self.x**2 + self.y**2 + self.z**2)
|
|
154
|
+
|
|
155
|
+
def mm_to_m(self) -> Vector3d:
|
|
156
|
+
return mm_to_m(1.0) * self
|
|
157
|
+
|
|
158
|
+
def normalize(self) -> Vector3d:
|
|
159
|
+
length = self.length()
|
|
160
|
+
if length == 0:
|
|
161
|
+
raise ValueError("零ベクトルは正規化できません")
|
|
162
|
+
return Vector3d(self.x / length, self.y / length, self.z / length)
|
|
163
|
+
|
|
164
|
+
def perpendicular_vector_on_plane(self, def_plane_vec: Vector3d) -> Vector3d:
|
|
165
|
+
# vec1 を正規化
|
|
166
|
+
vec1_normalized: Vector3d = self.normalize()
|
|
167
|
+
|
|
168
|
+
# vec2 の vec1 への射影を計算
|
|
169
|
+
projection_length: float = def_plane_vec.dot(vec1_normalized)
|
|
170
|
+
projection_vector: Vector3d = projection_length * vec1_normalized
|
|
171
|
+
|
|
172
|
+
# vec2 から射影ベクトルを引いて、vec1 に垂直なベクトルを得る
|
|
173
|
+
result: Vector3d = def_plane_vec - projection_vector
|
|
174
|
+
result = result.normalize()
|
|
175
|
+
return result
|
|
176
|
+
|
|
177
|
+
def rotate_around_axis(self, angle_degree: float, axis_vec: Vector3d) -> Vector3d:
|
|
178
|
+
if angle_degree == 0.0:
|
|
179
|
+
return self.clone()
|
|
180
|
+
theta = degree_to_radian(angle_degree)
|
|
181
|
+
a: Vector3d = axis_vec.normalize()
|
|
182
|
+
vec1: Vector3d = math.cos(theta) * self
|
|
183
|
+
vec2: Vector3d = (1.0 - math.cos(theta)) * (self.dot(a)) * a
|
|
184
|
+
vec3: Vector3d = math.sin(theta) * a.cross(self)
|
|
185
|
+
return vec1 + vec2 + vec3
|
|
186
|
+
|
|
187
|
+
def to_tuple(self) -> tuple[float, float, float]:
|
|
188
|
+
return (self.x, self.y, self.z)
|
|
189
|
+
|
|
190
|
+
@staticmethod
|
|
191
|
+
def from_collection(
|
|
192
|
+
collection: Sequence[float],
|
|
193
|
+
) -> Vector3d:
|
|
194
|
+
if len(collection) != 3:
|
|
195
|
+
raise ValueError("3次元のコレクションとしてください")
|
|
196
|
+
return Vector3d(x=collection[0], y=collection[1], z=collection[2])
|
|
197
|
+
|
|
198
|
+
@staticmethod
|
|
199
|
+
def from_stb_node(
|
|
200
|
+
stb_node: HasXyz,
|
|
201
|
+
) -> Vector3d:
|
|
202
|
+
if stb_node.x is None or stb_node.y is None or stb_node.z is None:
|
|
203
|
+
raise SchemaError(
|
|
204
|
+
f"{stb_node._name_for_logger()} x,y,zの値が設定されていません"
|
|
205
|
+
)
|
|
206
|
+
return Vector3d(stb_node.x, stb_node.y, stb_node.z)
|
|
207
|
+
|
|
208
|
+
@staticmethod
|
|
209
|
+
def unit_x() -> Vector3d:
|
|
210
|
+
return Vector3d(1.0, 0.0, 0.0)
|
|
211
|
+
|
|
212
|
+
@staticmethod
|
|
213
|
+
def unit_y() -> Vector3d:
|
|
214
|
+
return Vector3d(0.0, 1.0, 0.0)
|
|
215
|
+
|
|
216
|
+
@staticmethod
|
|
217
|
+
def unit_z() -> Vector3d:
|
|
218
|
+
return Vector3d(0.0, 0.0, 1.0)
|
|
219
|
+
|
|
220
|
+
@staticmethod
|
|
221
|
+
def zero() -> Vector3d:
|
|
222
|
+
return Vector3d(0.0, 0.0, 0.0)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Copyright 2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
from logging import Logger
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from stbkit.core.data_model.common import StBridgeRoot
|
|
11
|
+
from stbkit.core.stb_reporting import Reporter, get_reporter
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
import ifcopenshell.file
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def to_ifc(
|
|
18
|
+
stb: StBridgeRoot, *, logger: Logger | None = None, reporter: Reporter | None = None
|
|
19
|
+
) -> "ifcopenshell.file":
|
|
20
|
+
"""ST-BridgeをIFCへ変換します。
|
|
21
|
+
|
|
22
|
+
この関数を利用するためにはifcopenshellが必要です。
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
stb: ST-Bridgeモデル
|
|
26
|
+
logger: 出力用のLogger。
|
|
27
|
+
reporter: 出力用のReporter。
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
ifcopenshell.file: 生成されたIFCモデル
|
|
31
|
+
"""
|
|
32
|
+
from .._internal.data_model.ifc_data.entity_data import IfcModel
|
|
33
|
+
from ..upgrade import upgrade_to_latest
|
|
34
|
+
from ._internal.stb_to_ifc_data._stb_to_ifc_data import stb_to_ifc_data
|
|
35
|
+
|
|
36
|
+
reporter = get_reporter(logger, reporter)
|
|
37
|
+
stb = upgrade_to_latest(stb, reporter=reporter)
|
|
38
|
+
ifc_model: IfcModel = stb_to_ifc_data(stb, reporter=reporter)
|
|
39
|
+
return ifc_model.to_ifc(reporter=reporter)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Copyright 2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright 2025-2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
from ..._internal.data_model.building_geometry import BuildingGeometry
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def building_geometry_to_ply_text(geom: BuildingGeometry) -> str:
|
|
11
|
+
result: list[str] = []
|
|
12
|
+
result.append("ply")
|
|
13
|
+
result.append("format ascii 1.0")
|
|
14
|
+
result.append(f"element vertex {geom.mesh.vertex_count}")
|
|
15
|
+
result.append("property float x")
|
|
16
|
+
result.append("property float y")
|
|
17
|
+
result.append("property float z")
|
|
18
|
+
result.append(f"element face {geom.mesh.face_count}")
|
|
19
|
+
result.append("property list uchar int vertex_index")
|
|
20
|
+
result.append("end_header")
|
|
21
|
+
positions = geom.mesh.positions
|
|
22
|
+
for i in range(geom.mesh.vertex_count):
|
|
23
|
+
result.append(
|
|
24
|
+
f"{round(positions[i * 3], 5)} {round(positions[i * 3 + 1], 5)} {round(positions[i * 3 + 2], 5)}"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
face_offsets = geom.mesh.face_offsets
|
|
28
|
+
for i in range(geom.mesh.face_count):
|
|
29
|
+
face = geom.mesh.face_vertex_indices[face_offsets[i] : face_offsets[i + 1]]
|
|
30
|
+
result.append(f"{len(face)} {' '.join(map(str, face))}")
|
|
31
|
+
|
|
32
|
+
return "\n".join(result)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Copyright 2025-2026 TAISEI CORPORATION
|
|
2
|
+
# SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
from stbkit.core.stb_exceptions import (
|
|
8
|
+
ZeroLengthMemberError,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from ..._internal.data_model.element_data import ElementType
|
|
12
|
+
from ..._internal.matrix import RotationMatrix
|
|
13
|
+
from ..._internal.vectors import Vector3d
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def rotation_matrix(
|
|
17
|
+
point: Vector3d, vx: Vector3d, vy: Vector3d, vz: Vector3d
|
|
18
|
+
) -> RotationMatrix:
|
|
19
|
+
return RotationMatrix(point, vx, vy, vz)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def rotation_matrix_by_element_type(
|
|
23
|
+
point_start: Vector3d, point_end: Vector3d, angle: float, element_type: ElementType
|
|
24
|
+
) -> RotationMatrix:
|
|
25
|
+
match element_type:
|
|
26
|
+
case (
|
|
27
|
+
ElementType.GIRDER
|
|
28
|
+
| ElementType.BEAM
|
|
29
|
+
| ElementType.BRACE
|
|
30
|
+
| ElementType.STRIP_FOOTING
|
|
31
|
+
| ElementType.PARAPET
|
|
32
|
+
):
|
|
33
|
+
return rotation_matrix_beam(point_start, point_end, angle)
|
|
34
|
+
case (
|
|
35
|
+
ElementType.COLUMN
|
|
36
|
+
| ElementType.POST
|
|
37
|
+
| ElementType.FOOTING
|
|
38
|
+
| ElementType.PILE
|
|
39
|
+
| ElementType.FOUNDATION_COLUMN
|
|
40
|
+
):
|
|
41
|
+
return rotation_matrix_column(point_start, point_end, angle)
|
|
42
|
+
case _:
|
|
43
|
+
raise NotImplementedError(f"要素タイプ{element_type}の回転行列は未実装です")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def axis_vector_by_element_type(
|
|
47
|
+
point_start: Vector3d, point_end: Vector3d, angle: float, element_type: ElementType
|
|
48
|
+
) -> tuple[Vector3d, Vector3d, Vector3d]:
|
|
49
|
+
match element_type:
|
|
50
|
+
case (
|
|
51
|
+
ElementType.GIRDER
|
|
52
|
+
| ElementType.BEAM
|
|
53
|
+
| ElementType.BRACE
|
|
54
|
+
| ElementType.STRIP_FOOTING
|
|
55
|
+
| ElementType.PARAPET
|
|
56
|
+
):
|
|
57
|
+
return axis_vector_beam(point_start, point_end, angle)
|
|
58
|
+
case (
|
|
59
|
+
ElementType.COLUMN
|
|
60
|
+
| ElementType.POST
|
|
61
|
+
| ElementType.FOOTING
|
|
62
|
+
| ElementType.PILE
|
|
63
|
+
| ElementType.FOUNDATION_COLUMN
|
|
64
|
+
):
|
|
65
|
+
return axis_vector_column(point_start, point_end, angle)
|
|
66
|
+
case _:
|
|
67
|
+
raise NotImplementedError(
|
|
68
|
+
f"要素タイプ{element_type}の軸ベクトルは未実装です"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def axis_vector_beam(
|
|
73
|
+
point_start: Vector3d, point_end: Vector3d, angle: float
|
|
74
|
+
) -> tuple[Vector3d, Vector3d, Vector3d]:
|
|
75
|
+
vx: Vector3d = (point_end - point_start).normalize()
|
|
76
|
+
pv: Vector3d = vx.perpendicular_vector_on_plane(Vector3d.unit_z())
|
|
77
|
+
vz: Vector3d = pv.rotate_around_axis(angle, vx).normalize()
|
|
78
|
+
vy: Vector3d = vz.cross(vx)
|
|
79
|
+
return (vx, vy, vz)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def rotation_matrix_beam(
|
|
83
|
+
point_start: Vector3d,
|
|
84
|
+
point_end: Vector3d,
|
|
85
|
+
angle: float,
|
|
86
|
+
) -> RotationMatrix:
|
|
87
|
+
(vx, vy, vz) = axis_vector_beam(point_start, point_end, angle)
|
|
88
|
+
return rotation_matrix(point_start, vy, vz, vx)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def axis_vector_column(
|
|
92
|
+
point_start: Vector3d, point_end: Vector3d, angle: float
|
|
93
|
+
) -> tuple[Vector3d, Vector3d, Vector3d]:
|
|
94
|
+
vx: Vector3d = point_end - point_start
|
|
95
|
+
if vx.length() == 0:
|
|
96
|
+
raise ZeroLengthMemberError("柱の始点と終点が同じ位置です")
|
|
97
|
+
vx = vx.normalize()
|
|
98
|
+
pv: Vector3d = vx.perpendicular_vector_on_plane(Vector3d.unit_x())
|
|
99
|
+
vy: Vector3d = pv.rotate_around_axis(angle, vx).normalize()
|
|
100
|
+
vz: Vector3d = vx.cross(vy)
|
|
101
|
+
return (vx, vy, vz)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def rotation_matrix_column(
|
|
105
|
+
point_start: Vector3d,
|
|
106
|
+
point_end: Vector3d,
|
|
107
|
+
angle: float,
|
|
108
|
+
) -> RotationMatrix:
|
|
109
|
+
(vx, vy, vz) = axis_vector_column(point_start, point_end, angle)
|
|
110
|
+
return rotation_matrix(point_start, vy, vz, vx)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def axis_vector_plate(
|
|
114
|
+
points: list[Vector3d],
|
|
115
|
+
) -> tuple[Vector3d, Vector3d, Vector3d]:
|
|
116
|
+
if len(points) < 3:
|
|
117
|
+
raise AssertionError("pointsの数が3以下です")
|
|
118
|
+
vx: Vector3d = (points[1] - points[0]).normalize()
|
|
119
|
+
vy: Vector3d = vx.perpendicular_vector_on_plane(points[-1] - points[0]).normalize()
|
|
120
|
+
vz = vx.cross(vy)
|
|
121
|
+
return (vx, vy, vz)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def rotation_matrix_plate(points: list[Vector3d]) -> RotationMatrix:
|
|
125
|
+
vx, vy, vz = axis_vector_plate(points)
|
|
126
|
+
return rotation_matrix(points[0], vx, vy, vz)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def to_plate_element_coord(points: list[Vector3d]) -> list[Vector3d]:
|
|
130
|
+
matrix = rotation_matrix_plate(points)
|
|
131
|
+
return [matrix.to_local_point(point) for point in points]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def to_global_coord_plate(
|
|
135
|
+
points: list[Vector3d], out_points: list[Vector3d]
|
|
136
|
+
) -> list[Vector3d]:
|
|
137
|
+
matrix = rotation_matrix_plate(out_points)
|
|
138
|
+
return [matrix.to_global_point(point) for point in points]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def to_global_coord(
|
|
142
|
+
points: list[Vector3d],
|
|
143
|
+
point_start: Vector3d,
|
|
144
|
+
point_end: Vector3d,
|
|
145
|
+
angle: float,
|
|
146
|
+
element_type: ElementType,
|
|
147
|
+
) -> list[Vector3d]:
|
|
148
|
+
matrix = rotation_matrix_by_element_type(
|
|
149
|
+
point_start, point_end, angle, element_type
|
|
150
|
+
)
|
|
151
|
+
return [matrix.to_global_point(point) for point in points]
|