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,1089 @@
|
|
|
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
|
+
from abc import ABCMeta, abstractmethod
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from typing import Any, Final, Self
|
|
12
|
+
|
|
13
|
+
from ..._internal.constants import UNKNOWN_ELEMENT_SIZE_MM
|
|
14
|
+
from ..utils.unit_utils import degree_to_radian
|
|
15
|
+
from ..vectors import Vector2d
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def rotate_and_offset_points(
|
|
19
|
+
points: list[Vector2d], angle_degree: float | None, offset: Vector2d | None
|
|
20
|
+
) -> list[Vector2d]:
|
|
21
|
+
if angle_degree is None and offset is None:
|
|
22
|
+
return points
|
|
23
|
+
angle_degree = angle_degree or 0.0
|
|
24
|
+
offset = offset or Vector2d.zero()
|
|
25
|
+
angle: float = degree_to_radian(angle_degree)
|
|
26
|
+
cos_a: float = math.cos(angle)
|
|
27
|
+
sin_a: float = math.sin(angle)
|
|
28
|
+
rotated_and_offset_points = [
|
|
29
|
+
Vector2d(x * cos_a - y * sin_a + offset.x, x * sin_a + y * cos_a + offset.y)
|
|
30
|
+
for x, y in points
|
|
31
|
+
]
|
|
32
|
+
return rotated_and_offset_points
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def diagram_core(points: list[Vector2d]) -> Vector2d:
|
|
36
|
+
"""図心を計算する(多角形の重心)"""
|
|
37
|
+
if not points or len(points) < 3:
|
|
38
|
+
raise ValueError("3点以上の多角形が必要です")
|
|
39
|
+
area: float = 0.0
|
|
40
|
+
cx: float = 0.0
|
|
41
|
+
cy: float = 0.0
|
|
42
|
+
n: int = len(points)
|
|
43
|
+
for i in range(n):
|
|
44
|
+
x0, y0 = points[i].x, points[i].y
|
|
45
|
+
x1, y1 = points[(i + 1) % n].x, points[(i + 1) % n].y
|
|
46
|
+
cross: float = x0 * y1 - x1 * y0
|
|
47
|
+
area += cross
|
|
48
|
+
cx += (x0 + x1) * cross
|
|
49
|
+
cy += (y0 + y1) * cross
|
|
50
|
+
area *= 0.5
|
|
51
|
+
if abs(area) < 1e-12:
|
|
52
|
+
raise ValueError("面積がゼロです")
|
|
53
|
+
cx /= 6.0 * area
|
|
54
|
+
cy /= 6.0 * area
|
|
55
|
+
return Vector2d(cx, cy)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ShapePosition(Enum):
|
|
59
|
+
BOTTOM_CENTER = "中央下"
|
|
60
|
+
BOTTOM_LEFT = "左下"
|
|
61
|
+
BOTTOM_RIGHT = "右下"
|
|
62
|
+
CENTER_CENTER = "中央"
|
|
63
|
+
CENTER_LEFT = "左中央"
|
|
64
|
+
CENTER_RIGHT = "右中央"
|
|
65
|
+
TOP_CENTER = "中央上"
|
|
66
|
+
TOP_LEFT = "左上"
|
|
67
|
+
TOP_RIGHT = "右上"
|
|
68
|
+
DIAGRAM_CORE = "図心"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class SlotsMergeMeta(ABCMeta):
|
|
72
|
+
def __new__(
|
|
73
|
+
mcs,
|
|
74
|
+
name: str,
|
|
75
|
+
bases: tuple[type, ...],
|
|
76
|
+
namespace: dict[str, Any],
|
|
77
|
+
**kwargs: Any,
|
|
78
|
+
) -> Any:
|
|
79
|
+
# クラス生成
|
|
80
|
+
cls = super().__new__(mcs, name, bases, namespace)
|
|
81
|
+
# すべての親クラスの __slots__ を集める
|
|
82
|
+
slots: list[str] = []
|
|
83
|
+
for base in bases:
|
|
84
|
+
base_slots = getattr(base, "__slots__", ())
|
|
85
|
+
if isinstance(base_slots, str):
|
|
86
|
+
base_slots = (base_slots,)
|
|
87
|
+
slots.extend(base_slots)
|
|
88
|
+
# dataclassのフィールド名を取得
|
|
89
|
+
if hasattr(cls, "__annotations__"):
|
|
90
|
+
dataclass_fields = cls.__annotations__.keys()
|
|
91
|
+
slots.extend(dataclass_fields)
|
|
92
|
+
# 重複を除去し、tupleに変換
|
|
93
|
+
slots_tuple: tuple[str, ...] = tuple(dict.fromkeys(slots))
|
|
94
|
+
# __slots__をクラスに設定
|
|
95
|
+
cls.__slots__ = slots_tuple # type: ignore
|
|
96
|
+
return cls
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
100
|
+
class Shape(metaclass=SlotsMergeMeta):
|
|
101
|
+
rotate_degree: float | None = None
|
|
102
|
+
offset: Vector2d | None = None
|
|
103
|
+
|
|
104
|
+
# オーバーロード必須メソッド
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
108
|
+
"""座標は形状に外接する長方形の中心点を原点とする"""
|
|
109
|
+
|
|
110
|
+
# 任意でオーバーロードするメソッド
|
|
111
|
+
|
|
112
|
+
def get_in_point2ds(self) -> list[Vector2d] | None:
|
|
113
|
+
"""座標は形状に外接する長方形の中心点を原点とする"""
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
117
|
+
match position:
|
|
118
|
+
case ShapePosition.TOP_LEFT:
|
|
119
|
+
return Vector2d(self._x_min, self._y_max)
|
|
120
|
+
case ShapePosition.TOP_RIGHT:
|
|
121
|
+
return Vector2d(self._x_max, self._y_max)
|
|
122
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
123
|
+
return Vector2d(self._x_min, self._y_min)
|
|
124
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
125
|
+
return Vector2d(self._x_max, self._y_min)
|
|
126
|
+
case ShapePosition.TOP_CENTER:
|
|
127
|
+
return Vector2d(self._x_center, self._y_max)
|
|
128
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
129
|
+
return Vector2d(self._x_center, self._y_min)
|
|
130
|
+
case ShapePosition.CENTER_LEFT:
|
|
131
|
+
return Vector2d(self._x_min, self._y_center)
|
|
132
|
+
case ShapePosition.CENTER_RIGHT:
|
|
133
|
+
return Vector2d(self._x_max, self._y_center)
|
|
134
|
+
case ShapePosition.CENTER_CENTER:
|
|
135
|
+
return Vector2d(self._x_center, self._y_center)
|
|
136
|
+
case ShapePosition.DIAGRAM_CORE:
|
|
137
|
+
core_point: Vector2d = diagram_core(self.get_out_point2ds())
|
|
138
|
+
in_point_2ds: list[Vector2d] | None = self.get_in_point2ds()
|
|
139
|
+
if in_point_2ds:
|
|
140
|
+
core_point -= diagram_core(in_point_2ds)
|
|
141
|
+
return core_point
|
|
142
|
+
case _:
|
|
143
|
+
raise AssertionError(f"{position}:不明な位置指定です")
|
|
144
|
+
|
|
145
|
+
# 基本的にオーバーロード不要メソッド
|
|
146
|
+
|
|
147
|
+
def get_out_point2ds_with_rotate_and_offset(self) -> list[Vector2d]:
|
|
148
|
+
return rotate_and_offset_points(
|
|
149
|
+
self.get_out_point2ds(), self.rotate_degree, self.offset
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def get_in_point2ds_with_rotate_and_offset(self) -> list[Vector2d] | None:
|
|
153
|
+
in_points = self.get_in_point2ds()
|
|
154
|
+
if in_points is None:
|
|
155
|
+
return None
|
|
156
|
+
return rotate_and_offset_points(in_points, self.rotate_degree, self.offset)
|
|
157
|
+
|
|
158
|
+
# プライベートプロパティ
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def _x_min(self) -> float:
|
|
162
|
+
return min(point.x for point in self.get_out_point2ds())
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def _x_max(self) -> float:
|
|
166
|
+
return max(point.x for point in self.get_out_point2ds())
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def _y_min(self) -> float:
|
|
170
|
+
return min(point.y for point in self.get_out_point2ds())
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def _y_max(self) -> float:
|
|
174
|
+
return max(point.y for point in self.get_out_point2ds())
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def _x_center(self) -> float:
|
|
178
|
+
return (self._x_min + self._x_max) / 2.0
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def _y_center(self) -> float:
|
|
182
|
+
return (self._y_min + self._y_max) / 2.0
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclass(repr=False, eq=False, order=False)
|
|
186
|
+
class ShapePair:
|
|
187
|
+
start: Shape
|
|
188
|
+
end: Shape | None = None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
192
|
+
class ShapeAngle(Shape):
|
|
193
|
+
name: str
|
|
194
|
+
a: float
|
|
195
|
+
b: float
|
|
196
|
+
t1: float
|
|
197
|
+
t2: float
|
|
198
|
+
r1: float = 0.0
|
|
199
|
+
r2: float = 0.0
|
|
200
|
+
|
|
201
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
202
|
+
result: list[Vector2d] = [
|
|
203
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0),
|
|
204
|
+
Vector2d(-self.b / 2.0 + self.t1, -self.a / 2.0),
|
|
205
|
+
Vector2d(-self.b / 2.0 + self.t1, self.a / 2.0 - self.t2),
|
|
206
|
+
Vector2d(self.b / 2.0, self.a / 2.0 - self.t2),
|
|
207
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
208
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
209
|
+
]
|
|
210
|
+
return result
|
|
211
|
+
|
|
212
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
213
|
+
if self.rotate_degree is None and self.offset is None:
|
|
214
|
+
match position:
|
|
215
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
216
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
217
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
218
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
219
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
220
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
221
|
+
case ShapePosition.CENTER_CENTER:
|
|
222
|
+
return Vector2d.zero()
|
|
223
|
+
case ShapePosition.CENTER_LEFT:
|
|
224
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
225
|
+
case ShapePosition.CENTER_RIGHT:
|
|
226
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
227
|
+
case ShapePosition.TOP_CENTER:
|
|
228
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
229
|
+
case ShapePosition.TOP_LEFT:
|
|
230
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
231
|
+
case ShapePosition.TOP_RIGHT:
|
|
232
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
233
|
+
case ShapePosition.DIAGRAM_CORE:
|
|
234
|
+
raise NotImplementedError(
|
|
235
|
+
"Angleの図心の計算はサポートされていません"
|
|
236
|
+
)
|
|
237
|
+
else:
|
|
238
|
+
return super().get_position_point(position)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
242
|
+
class ShapeArbitrary(Shape):
|
|
243
|
+
out_points: list[Vector2d] = field(default_factory=list)
|
|
244
|
+
in_points: list[list[Vector2d]] = field(default_factory=list)
|
|
245
|
+
|
|
246
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
247
|
+
return self.out_points
|
|
248
|
+
|
|
249
|
+
def get_in_point2ds(self) -> list[Vector2d] | None:
|
|
250
|
+
if self.in_points:
|
|
251
|
+
return self.in_points[0]
|
|
252
|
+
else:
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
256
|
+
if position == ShapePosition.DIAGRAM_CORE:
|
|
257
|
+
core_point: Vector2d = diagram_core(self.out_points)
|
|
258
|
+
for in_point_2ds in self.in_points:
|
|
259
|
+
core_point -= diagram_core(in_point_2ds)
|
|
260
|
+
return core_point
|
|
261
|
+
return super().get_position_point(position)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
265
|
+
class ShapeBox(Shape):
|
|
266
|
+
name: str
|
|
267
|
+
a: float
|
|
268
|
+
b: float
|
|
269
|
+
t: float
|
|
270
|
+
r: float
|
|
271
|
+
|
|
272
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
273
|
+
result: list[Vector2d] = [
|
|
274
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0),
|
|
275
|
+
Vector2d(self.b / 2.0, -self.a / 2.0),
|
|
276
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
277
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
278
|
+
]
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
282
|
+
match position:
|
|
283
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
284
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
285
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
286
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
287
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
288
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
289
|
+
case ShapePosition.CENTER_LEFT:
|
|
290
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
291
|
+
case ShapePosition.CENTER_RIGHT:
|
|
292
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
293
|
+
case ShapePosition.TOP_CENTER:
|
|
294
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
295
|
+
case ShapePosition.TOP_LEFT:
|
|
296
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
297
|
+
case ShapePosition.TOP_RIGHT:
|
|
298
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
299
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
300
|
+
return Vector2d.zero()
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
304
|
+
class ShapeBuildBox(Shape):
|
|
305
|
+
name: str
|
|
306
|
+
a: float
|
|
307
|
+
b: float
|
|
308
|
+
t1: float
|
|
309
|
+
t2: float
|
|
310
|
+
|
|
311
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
312
|
+
result: list[Vector2d] = [
|
|
313
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0),
|
|
314
|
+
Vector2d(self.b / 2.0, -self.a / 2.0),
|
|
315
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
316
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
317
|
+
]
|
|
318
|
+
return result
|
|
319
|
+
|
|
320
|
+
def get_in_point2ds(self) -> list[Vector2d]:
|
|
321
|
+
result: list[Vector2d] = [
|
|
322
|
+
Vector2d(-self.b / 2.0 + self.t1, -self.a / 2.0 + self.t2),
|
|
323
|
+
Vector2d(self.b / 2.0 - self.t1, -self.a / 2.0 + self.t2),
|
|
324
|
+
Vector2d(self.b / 2.0 - self.t1, self.a / 2.0 - self.t2),
|
|
325
|
+
Vector2d(-self.b / 2.0 + self.t1, self.a / 2.0 - self.t2),
|
|
326
|
+
]
|
|
327
|
+
return result
|
|
328
|
+
|
|
329
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
330
|
+
match position:
|
|
331
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
332
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
333
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
334
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
335
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
336
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
337
|
+
case ShapePosition.CENTER_LEFT:
|
|
338
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
339
|
+
case ShapePosition.CENTER_RIGHT:
|
|
340
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
341
|
+
case ShapePosition.TOP_CENTER:
|
|
342
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
343
|
+
case ShapePosition.TOP_LEFT:
|
|
344
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
345
|
+
case ShapePosition.TOP_RIGHT:
|
|
346
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
347
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
348
|
+
return Vector2d.zero()
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
352
|
+
class ShapeChannel(Shape):
|
|
353
|
+
name: str
|
|
354
|
+
a: float
|
|
355
|
+
b: float
|
|
356
|
+
t1: float
|
|
357
|
+
t2: float
|
|
358
|
+
r1: float = 0.0
|
|
359
|
+
r2: float = 0.0
|
|
360
|
+
|
|
361
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
362
|
+
result: list[Vector2d] = [
|
|
363
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0),
|
|
364
|
+
Vector2d(self.b / 2.0, -self.a / 2.0),
|
|
365
|
+
Vector2d(self.b / 2.0, -self.a / 2.0 + self.t2),
|
|
366
|
+
Vector2d(-self.b / 2.0 + self.t1, -self.a / 2.0 + self.t2),
|
|
367
|
+
Vector2d(-self.b / 2.0 + self.t1, self.a / 2.0 - self.t2),
|
|
368
|
+
Vector2d(self.b / 2.0, self.a / 2.0 - self.t2),
|
|
369
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
370
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
371
|
+
]
|
|
372
|
+
return result
|
|
373
|
+
|
|
374
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
375
|
+
match position:
|
|
376
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
377
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
378
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
379
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
380
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
381
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
382
|
+
case ShapePosition.CENTER_CENTER:
|
|
383
|
+
return Vector2d.zero()
|
|
384
|
+
case ShapePosition.CENTER_LEFT:
|
|
385
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
386
|
+
case ShapePosition.CENTER_RIGHT:
|
|
387
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
388
|
+
case ShapePosition.TOP_CENTER:
|
|
389
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
390
|
+
case ShapePosition.TOP_LEFT:
|
|
391
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
392
|
+
case ShapePosition.TOP_RIGHT:
|
|
393
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
394
|
+
case ShapePosition.DIAGRAM_CORE:
|
|
395
|
+
raise NotImplementedError("Channelの図心の計算はサポートされていません")
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
399
|
+
class ShapeCircle(Shape):
|
|
400
|
+
name: str
|
|
401
|
+
d: float
|
|
402
|
+
number_of_divisions: int = 12
|
|
403
|
+
|
|
404
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
405
|
+
n_div: int = max(self.number_of_divisions, 3)
|
|
406
|
+
unit_angle: float = math.pi * 2.0 / n_div
|
|
407
|
+
r: float = self.d / 2.0
|
|
408
|
+
result: list[Vector2d] = [
|
|
409
|
+
Vector2d(
|
|
410
|
+
r * math.cos(i * unit_angle),
|
|
411
|
+
r * math.sin(i * unit_angle),
|
|
412
|
+
)
|
|
413
|
+
for i in range(n_div)
|
|
414
|
+
]
|
|
415
|
+
return result
|
|
416
|
+
|
|
417
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
418
|
+
i: int
|
|
419
|
+
match position:
|
|
420
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
421
|
+
return Vector2d.zero()
|
|
422
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
423
|
+
i = 6
|
|
424
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
425
|
+
i = 5
|
|
426
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
427
|
+
i = 7
|
|
428
|
+
case ShapePosition.CENTER_LEFT:
|
|
429
|
+
i = 4
|
|
430
|
+
case ShapePosition.CENTER_RIGHT:
|
|
431
|
+
i = 0
|
|
432
|
+
case ShapePosition.TOP_CENTER:
|
|
433
|
+
i = 2
|
|
434
|
+
case ShapePosition.TOP_LEFT:
|
|
435
|
+
i = 1
|
|
436
|
+
case ShapePosition.TOP_RIGHT:
|
|
437
|
+
i = 3
|
|
438
|
+
unit_angle: float = math.pi * 2.0 / 8.0
|
|
439
|
+
r: float = self.d / 2.0
|
|
440
|
+
return Vector2d(
|
|
441
|
+
r * math.cos(i * unit_angle),
|
|
442
|
+
r * math.sin(i * unit_angle),
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
447
|
+
class ShapeCrossH(Shape):
|
|
448
|
+
name: str
|
|
449
|
+
h_h: float
|
|
450
|
+
h_b: float
|
|
451
|
+
h_tw: float
|
|
452
|
+
h_tf: float
|
|
453
|
+
i_h: float
|
|
454
|
+
i_b: float
|
|
455
|
+
i_tw: float
|
|
456
|
+
i_tf: float
|
|
457
|
+
i_offset_x: float = 0.0
|
|
458
|
+
h_offset_y: float = 0.0
|
|
459
|
+
|
|
460
|
+
@property
|
|
461
|
+
def _x_max(self) -> float:
|
|
462
|
+
return self.h_h / 2.0
|
|
463
|
+
|
|
464
|
+
@property
|
|
465
|
+
def _x_min(self) -> float:
|
|
466
|
+
return -self.h_h / 2.0
|
|
467
|
+
|
|
468
|
+
@property
|
|
469
|
+
def _x_center(self) -> float:
|
|
470
|
+
return 0.0
|
|
471
|
+
|
|
472
|
+
@property
|
|
473
|
+
def _y_max(self) -> float:
|
|
474
|
+
return self.i_h / 2.0
|
|
475
|
+
|
|
476
|
+
@property
|
|
477
|
+
def _y_min(self) -> float:
|
|
478
|
+
return -self.i_h / 2.0
|
|
479
|
+
|
|
480
|
+
@property
|
|
481
|
+
def _y_center(self) -> float:
|
|
482
|
+
return 0.0
|
|
483
|
+
|
|
484
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
485
|
+
return [
|
|
486
|
+
Vector2d(-self.i_b / 2.0 + self.i_offset_x, self._y_min),
|
|
487
|
+
Vector2d(self.i_b / 2.0 + self.i_offset_x, self._y_min),
|
|
488
|
+
Vector2d(self.i_b / 2.0 + self.i_offset_x, self._y_min + self.i_tf),
|
|
489
|
+
Vector2d(self.i_tw / 2.0 + self.i_offset_x, self._y_min + self.i_tf),
|
|
490
|
+
Vector2d(
|
|
491
|
+
self.i_tw / 2.0 + self.i_offset_x, -self.h_tw / 2.0 + self.h_offset_y
|
|
492
|
+
),
|
|
493
|
+
Vector2d(self._x_max - self.h_tf, -self.h_tw / 2.0 + self.h_offset_y),
|
|
494
|
+
Vector2d(self._x_max - self.h_tf, -self.h_b / 2.0 + self.h_offset_y),
|
|
495
|
+
Vector2d(self._x_max, -self.h_b / 2.0 + self.h_offset_y),
|
|
496
|
+
Vector2d(self._x_max, self.h_b / 2.0 + self.h_offset_y),
|
|
497
|
+
Vector2d(self._x_max - self.h_tf, self.h_b / 2.0 + self.h_offset_y),
|
|
498
|
+
Vector2d(self._x_max - self.h_tf, self.h_tw / 2.0 + self.h_offset_y),
|
|
499
|
+
Vector2d(
|
|
500
|
+
self.i_tw / 2.0 + self.i_offset_x, self.h_tw / 2.0 + self.h_offset_y
|
|
501
|
+
),
|
|
502
|
+
Vector2d(self.i_tw / 2.0 + self.i_offset_x, self._y_max - self.i_tf),
|
|
503
|
+
Vector2d(self.i_b / 2.0 + self.i_offset_x, self._y_max - self.i_tf),
|
|
504
|
+
Vector2d(self.i_b / 2.0 + self.i_offset_x, self._y_max),
|
|
505
|
+
Vector2d(-self.i_b / 2.0 + self.i_offset_x, self._y_max),
|
|
506
|
+
Vector2d(-self.i_b / 2.0 + self.i_offset_x, self._y_max - self.i_tf),
|
|
507
|
+
Vector2d(-self.i_tw / 2.0 + self.i_offset_x, self._y_max - self.i_tf),
|
|
508
|
+
Vector2d(
|
|
509
|
+
-self.i_tw / 2.0 + self.i_offset_x, self.h_tw / 2.0 + self.h_offset_y
|
|
510
|
+
),
|
|
511
|
+
Vector2d(self._x_min + self.h_tf, self.h_tw / 2.0 + self.h_offset_y),
|
|
512
|
+
Vector2d(self._x_min + self.h_tf, self.h_b / 2.0 + self.h_offset_y),
|
|
513
|
+
Vector2d(self._x_min, self.h_b / 2.0 + self.h_offset_y),
|
|
514
|
+
Vector2d(self._x_min, -self.h_b / 2.0 + self.h_offset_y),
|
|
515
|
+
Vector2d(self._x_min + self.h_tf, -self.h_b / 2.0 + self.h_offset_y),
|
|
516
|
+
Vector2d(self._x_min + self.h_tf, -self.h_tw / 2.0 + self.h_offset_y),
|
|
517
|
+
Vector2d(
|
|
518
|
+
-self.i_tw / 2.0 + self.i_offset_x, -self.h_tw / 2.0 + self.h_offset_y
|
|
519
|
+
),
|
|
520
|
+
Vector2d(-self.i_tw / 2.0 + self.i_offset_x, self._y_min + self.i_tf),
|
|
521
|
+
Vector2d(-self.i_b / 2.0 + self.i_offset_x, self._y_min + self.i_tf),
|
|
522
|
+
]
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
526
|
+
class ShapeEquilateralTriangle(Shape):
|
|
527
|
+
name: str
|
|
528
|
+
width_base: float
|
|
529
|
+
width_chamfer: float = 0.0
|
|
530
|
+
|
|
531
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
532
|
+
if self.width_chamfer == 0.0:
|
|
533
|
+
return [
|
|
534
|
+
Vector2d(self._x_min, self._y_min),
|
|
535
|
+
Vector2d(self._x_max, self._y_min),
|
|
536
|
+
Vector2d(self._x_center, self._y_max),
|
|
537
|
+
]
|
|
538
|
+
else:
|
|
539
|
+
height_chamfer: float = (math.sqrt(3.0) / 2.0) * self.width_chamfer
|
|
540
|
+
return [
|
|
541
|
+
Vector2d(-self.width_base / 2.0, self._y_min),
|
|
542
|
+
Vector2d(self.width_base / 2.0, self._y_min),
|
|
543
|
+
Vector2d(
|
|
544
|
+
self._x_max,
|
|
545
|
+
self._y_min + height_chamfer,
|
|
546
|
+
),
|
|
547
|
+
Vector2d(self.width_chamfer / 2.0, self._y_max),
|
|
548
|
+
Vector2d(-self.width_chamfer / 2.0, self._y_max),
|
|
549
|
+
Vector2d(
|
|
550
|
+
self._x_min,
|
|
551
|
+
self._y_min + height_chamfer,
|
|
552
|
+
),
|
|
553
|
+
]
|
|
554
|
+
|
|
555
|
+
@property
|
|
556
|
+
def _x_max(self) -> float:
|
|
557
|
+
if self.width_chamfer == 0.0:
|
|
558
|
+
return self.width_base / 2.0
|
|
559
|
+
else:
|
|
560
|
+
return self.width_base / 2.0 + self.width_chamfer / 2.0
|
|
561
|
+
|
|
562
|
+
@property
|
|
563
|
+
def _x_min(self) -> float:
|
|
564
|
+
return -self._x_max
|
|
565
|
+
|
|
566
|
+
@property
|
|
567
|
+
def _x_center(self) -> float:
|
|
568
|
+
return 0.0
|
|
569
|
+
|
|
570
|
+
@property
|
|
571
|
+
def _y_max(self) -> float:
|
|
572
|
+
return math.sqrt(3.0) / 2.0 * (self.width_base + self.width_chamfer) / 2.0
|
|
573
|
+
|
|
574
|
+
@property
|
|
575
|
+
def _y_min(self) -> float:
|
|
576
|
+
return -self._y_max
|
|
577
|
+
|
|
578
|
+
@property
|
|
579
|
+
def _y_center(self) -> float:
|
|
580
|
+
return 0.0
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
584
|
+
class ShapeH(Shape):
|
|
585
|
+
name: str
|
|
586
|
+
a: float
|
|
587
|
+
b: float
|
|
588
|
+
t1: float
|
|
589
|
+
t2: float
|
|
590
|
+
r: float
|
|
591
|
+
|
|
592
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
593
|
+
result: list[Vector2d] = [
|
|
594
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0),
|
|
595
|
+
Vector2d(self.b / 2.0, -self.a / 2.0),
|
|
596
|
+
Vector2d(self.b / 2.0, -self.a / 2.0 + self.t2),
|
|
597
|
+
Vector2d(self.t1 / 2.0, -self.a / 2.0 + self.t2),
|
|
598
|
+
Vector2d(self.t1 / 2.0, self.a / 2.0 - self.t2),
|
|
599
|
+
Vector2d(self.b / 2.0, self.a / 2.0 - self.t2),
|
|
600
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
601
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
602
|
+
Vector2d(-self.b / 2.0, self.a / 2.0 - self.t2),
|
|
603
|
+
Vector2d(-self.t1 / 2.0, self.a / 2.0 - self.t2),
|
|
604
|
+
Vector2d(-self.t1 / 2.0, -self.a / 2.0 + self.t2),
|
|
605
|
+
Vector2d(-self.b / 2.0, -self.a / 2.0 + self.t2),
|
|
606
|
+
]
|
|
607
|
+
return result
|
|
608
|
+
|
|
609
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
610
|
+
match position:
|
|
611
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
612
|
+
return Vector2d.zero()
|
|
613
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
614
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
615
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
616
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
617
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
618
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
619
|
+
case ShapePosition.CENTER_LEFT:
|
|
620
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
621
|
+
case ShapePosition.CENTER_RIGHT:
|
|
622
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
623
|
+
case ShapePosition.TOP_CENTER:
|
|
624
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
625
|
+
case ShapePosition.TOP_LEFT:
|
|
626
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
627
|
+
case ShapePosition.TOP_RIGHT:
|
|
628
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
632
|
+
class ShapeLipC(Shape):
|
|
633
|
+
name: str
|
|
634
|
+
h: float
|
|
635
|
+
a: float
|
|
636
|
+
c: float
|
|
637
|
+
t: float
|
|
638
|
+
|
|
639
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
640
|
+
result: list[Vector2d] = [
|
|
641
|
+
Vector2d(-self.a / 2.0, -self.h / 2.0),
|
|
642
|
+
Vector2d(self.a / 2.0, -self.h / 2.0),
|
|
643
|
+
Vector2d(self.a / 2.0, -self.h / 2.0 + self.c),
|
|
644
|
+
Vector2d(self.a / 2.0 - self.t, -self.h / 2.0 + self.c),
|
|
645
|
+
Vector2d(self.a / 2.0 - self.t, -self.h / 2.0 + self.t),
|
|
646
|
+
Vector2d(-self.a / 2.0 + self.t, -self.h / 2.0 + self.t),
|
|
647
|
+
Vector2d(-self.a / 2.0 + self.t, self.h / 2.0 - self.t),
|
|
648
|
+
Vector2d(self.a / 2.0 - self.t, self.h / 2.0 - self.t),
|
|
649
|
+
Vector2d(self.a / 2.0 - self.t, self.h / 2.0 - self.c),
|
|
650
|
+
Vector2d(self.a / 2.0, self.h / 2.0 - self.c),
|
|
651
|
+
Vector2d(self.a / 2.0, self.h / 2.0),
|
|
652
|
+
Vector2d(-self.a / 2.0, self.h / 2.0),
|
|
653
|
+
]
|
|
654
|
+
return result
|
|
655
|
+
|
|
656
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
657
|
+
match position:
|
|
658
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
659
|
+
return Vector2d(0.0, -self.h / 2.0)
|
|
660
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
661
|
+
return Vector2d(-self.a / 2.0, -self.h / 2.0)
|
|
662
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
663
|
+
return Vector2d(self.a / 2.0, -self.h / 2.0)
|
|
664
|
+
case ShapePosition.CENTER_CENTER:
|
|
665
|
+
return Vector2d.zero()
|
|
666
|
+
case ShapePosition.CENTER_LEFT:
|
|
667
|
+
return Vector2d(-self.a / 2.0, 0.0)
|
|
668
|
+
case ShapePosition.CENTER_RIGHT:
|
|
669
|
+
return Vector2d(self.a / 2.0, 0.0)
|
|
670
|
+
case ShapePosition.TOP_CENTER:
|
|
671
|
+
return Vector2d(0.0, self.h / 2.0)
|
|
672
|
+
case ShapePosition.TOP_LEFT:
|
|
673
|
+
return Vector2d(-self.a / 2.0, self.h / 2.0)
|
|
674
|
+
case ShapePosition.TOP_RIGHT:
|
|
675
|
+
return Vector2d(self.a / 2.0, self.h / 2.0)
|
|
676
|
+
case ShapePosition.DIAGRAM_CORE:
|
|
677
|
+
raise NotImplementedError("LipCの図心の計算はサポートされていません")
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
681
|
+
class ShapeOctagon(Shape):
|
|
682
|
+
name: str
|
|
683
|
+
width_x: float
|
|
684
|
+
width_y: float
|
|
685
|
+
width_chamfer_bottom_left_x: float = 0.0
|
|
686
|
+
width_chamfer_bottom_left_y: float = 0.0
|
|
687
|
+
width_chamfer_bottom_right_x: float = 0.0
|
|
688
|
+
width_chamfer_bottom_right_y: float = 0.0
|
|
689
|
+
width_chamfer_top_right_x: float = 0.0
|
|
690
|
+
width_chamfer_top_right_y: float = 0.0
|
|
691
|
+
width_chamfer_top_left_x: float = 0.0
|
|
692
|
+
width_chamfer_top_left_y: float = 0.0
|
|
693
|
+
|
|
694
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
695
|
+
result: list[Vector2d] = []
|
|
696
|
+
if (
|
|
697
|
+
self.width_chamfer_bottom_left_x == 0.0
|
|
698
|
+
or self.width_chamfer_bottom_left_y == 0.0
|
|
699
|
+
):
|
|
700
|
+
result.append(Vector2d(self._x_min, self._y_min))
|
|
701
|
+
else:
|
|
702
|
+
result.append(
|
|
703
|
+
Vector2d(self._x_min + self.width_chamfer_bottom_left_x, self._y_min)
|
|
704
|
+
)
|
|
705
|
+
if (
|
|
706
|
+
self.width_chamfer_bottom_right_x == 0.0
|
|
707
|
+
or self.width_chamfer_bottom_right_y == 0.0
|
|
708
|
+
):
|
|
709
|
+
result.append(Vector2d(self._x_max, self._y_min))
|
|
710
|
+
else:
|
|
711
|
+
result.append(
|
|
712
|
+
Vector2d(self._x_max - self.width_chamfer_bottom_right_x, self._y_min)
|
|
713
|
+
)
|
|
714
|
+
result.append(
|
|
715
|
+
Vector2d(self._x_max, self._y_min + self.width_chamfer_bottom_right_y)
|
|
716
|
+
)
|
|
717
|
+
if (
|
|
718
|
+
self.width_chamfer_top_right_x == 0.0
|
|
719
|
+
or self.width_chamfer_top_right_y == 0.0
|
|
720
|
+
):
|
|
721
|
+
result.append(Vector2d(self._x_max, self._y_max))
|
|
722
|
+
else:
|
|
723
|
+
result.append(
|
|
724
|
+
Vector2d(self._x_max, self._y_max - self.width_chamfer_top_right_y)
|
|
725
|
+
)
|
|
726
|
+
result.append(
|
|
727
|
+
Vector2d(self._x_max - self.width_chamfer_top_right_x, self._y_max)
|
|
728
|
+
)
|
|
729
|
+
if self.width_chamfer_top_left_x == 0.0 or self.width_chamfer_top_left_y == 0.0:
|
|
730
|
+
result.append(Vector2d(self._x_min, self._y_max))
|
|
731
|
+
else:
|
|
732
|
+
result.append(
|
|
733
|
+
Vector2d(self._x_min + self.width_chamfer_top_left_x, self._y_max)
|
|
734
|
+
)
|
|
735
|
+
result.append(
|
|
736
|
+
Vector2d(self._x_min, self._y_max - self.width_chamfer_top_left_y)
|
|
737
|
+
)
|
|
738
|
+
if (
|
|
739
|
+
self.width_chamfer_bottom_left_x == 0.0
|
|
740
|
+
or self.width_chamfer_bottom_left_y == 0.0
|
|
741
|
+
):
|
|
742
|
+
pass
|
|
743
|
+
else:
|
|
744
|
+
result.append(
|
|
745
|
+
Vector2d(self._x_min, self._y_min + self.width_chamfer_bottom_left_y)
|
|
746
|
+
)
|
|
747
|
+
return result
|
|
748
|
+
|
|
749
|
+
@property
|
|
750
|
+
def _x_min(self) -> float:
|
|
751
|
+
return -self.width_x / 2.0
|
|
752
|
+
|
|
753
|
+
@property
|
|
754
|
+
def _x_max(self) -> float:
|
|
755
|
+
return self.width_x / 2.0
|
|
756
|
+
|
|
757
|
+
@property
|
|
758
|
+
def _x_center(self) -> float:
|
|
759
|
+
return 0.0
|
|
760
|
+
|
|
761
|
+
@property
|
|
762
|
+
def _y_min(self) -> float:
|
|
763
|
+
return -self.width_y / 2.0
|
|
764
|
+
|
|
765
|
+
@property
|
|
766
|
+
def _y_max(self) -> float:
|
|
767
|
+
return self.width_y / 2.0
|
|
768
|
+
|
|
769
|
+
@property
|
|
770
|
+
def _y_center(self) -> float:
|
|
771
|
+
return 0.0
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
775
|
+
class ShapePipe(Shape):
|
|
776
|
+
name: str
|
|
777
|
+
d: float
|
|
778
|
+
t: float
|
|
779
|
+
number_of_divisions: int = 12
|
|
780
|
+
|
|
781
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
782
|
+
n_div: int = max(self.number_of_divisions, 3)
|
|
783
|
+
unit_angle: float = math.pi * 2.0 / n_div
|
|
784
|
+
r: float = self.d / 2.0
|
|
785
|
+
result: list[Vector2d] = [
|
|
786
|
+
Vector2d(
|
|
787
|
+
r * math.cos(i * unit_angle),
|
|
788
|
+
r * math.sin(i * unit_angle),
|
|
789
|
+
)
|
|
790
|
+
for i in range(n_div)
|
|
791
|
+
]
|
|
792
|
+
return result
|
|
793
|
+
|
|
794
|
+
def get_in_point2ds(self) -> list[Vector2d]:
|
|
795
|
+
n_div: int = max(self.number_of_divisions, 3)
|
|
796
|
+
unit_angle: float = math.pi * 2.0 / n_div
|
|
797
|
+
r = self.d / 2.0 - self.t
|
|
798
|
+
result: list[Vector2d] = [
|
|
799
|
+
Vector2d(
|
|
800
|
+
r * math.cos(i * unit_angle),
|
|
801
|
+
r * math.sin(i * unit_angle),
|
|
802
|
+
)
|
|
803
|
+
for i in range(n_div)
|
|
804
|
+
]
|
|
805
|
+
return result
|
|
806
|
+
|
|
807
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
808
|
+
i: int
|
|
809
|
+
match position:
|
|
810
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
811
|
+
return Vector2d.zero()
|
|
812
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
813
|
+
i = 6
|
|
814
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
815
|
+
i = 5
|
|
816
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
817
|
+
i = 7
|
|
818
|
+
case ShapePosition.CENTER_LEFT:
|
|
819
|
+
i = 4
|
|
820
|
+
case ShapePosition.CENTER_RIGHT:
|
|
821
|
+
i = 0
|
|
822
|
+
case ShapePosition.TOP_CENTER:
|
|
823
|
+
i = 2
|
|
824
|
+
case ShapePosition.TOP_LEFT:
|
|
825
|
+
i = 1
|
|
826
|
+
case ShapePosition.TOP_RIGHT:
|
|
827
|
+
i = 3
|
|
828
|
+
unit_angle: float = math.pi * 2.0 / 8.0
|
|
829
|
+
r: float = self.d / 2.0
|
|
830
|
+
return Vector2d(
|
|
831
|
+
r * math.cos(i * unit_angle),
|
|
832
|
+
r * math.sin(i * unit_angle),
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
837
|
+
class ShapeRectangle(Shape):
|
|
838
|
+
name: str
|
|
839
|
+
width_x: float
|
|
840
|
+
width_y: float
|
|
841
|
+
|
|
842
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
843
|
+
result: list[Vector2d] = [
|
|
844
|
+
Vector2d(-self.width_x / 2.0, -self.width_y / 2.0),
|
|
845
|
+
Vector2d(self.width_x / 2.0, -self.width_y / 2.0),
|
|
846
|
+
Vector2d(self.width_x / 2.0, self.width_y / 2.0),
|
|
847
|
+
Vector2d(-self.width_x / 2.0, self.width_y / 2.0),
|
|
848
|
+
]
|
|
849
|
+
return result
|
|
850
|
+
|
|
851
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
852
|
+
match position:
|
|
853
|
+
case ShapePosition.CENTER_CENTER | ShapePosition.DIAGRAM_CORE:
|
|
854
|
+
return Vector2d.zero()
|
|
855
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
856
|
+
return Vector2d(0.0, -self.width_y / 2.0)
|
|
857
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
858
|
+
return Vector2d(-self.width_x / 2.0, -self.width_y / 2.0)
|
|
859
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
860
|
+
return Vector2d(self.width_x / 2.0, -self.width_y / 2.0)
|
|
861
|
+
case ShapePosition.CENTER_LEFT:
|
|
862
|
+
return Vector2d(-self.width_x / 2.0, 0.0)
|
|
863
|
+
case ShapePosition.CENTER_RIGHT:
|
|
864
|
+
return Vector2d(self.width_x / 2.0, 0.0)
|
|
865
|
+
case ShapePosition.TOP_CENTER:
|
|
866
|
+
return Vector2d(0.0, self.width_y / 2.0)
|
|
867
|
+
case ShapePosition.TOP_LEFT:
|
|
868
|
+
return Vector2d(-self.width_x / 2.0, self.width_y / 2.0)
|
|
869
|
+
case ShapePosition.TOP_RIGHT:
|
|
870
|
+
return Vector2d(self.width_x / 2.0, self.width_y / 2.0)
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
874
|
+
class ShapeRightTriangle(Shape):
|
|
875
|
+
"""直角三角形
|
|
876
|
+
|
|
877
|
+
左下が直角とする"""
|
|
878
|
+
|
|
879
|
+
name: str
|
|
880
|
+
width_x: float
|
|
881
|
+
width_y: float
|
|
882
|
+
chamfer_x: float = 0.0
|
|
883
|
+
chamfer_y: float = 0.0
|
|
884
|
+
|
|
885
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
886
|
+
result: list[Vector2d] = [
|
|
887
|
+
Vector2d(-self.width_x / 2.0, -self.width_y / 2.0),
|
|
888
|
+
Vector2d(self.width_x / 2.0, -self.width_y / 2.0),
|
|
889
|
+
]
|
|
890
|
+
if self.chamfer_y > 0.0:
|
|
891
|
+
result.append(
|
|
892
|
+
Vector2d(self.width_x / 2.0, -self.width_y / 2.0 + self.chamfer_y)
|
|
893
|
+
)
|
|
894
|
+
if self.chamfer_x > 0.0:
|
|
895
|
+
result.append(
|
|
896
|
+
Vector2d(-self.width_x / 2.0 + self.chamfer_x, self.width_y / 2.0)
|
|
897
|
+
)
|
|
898
|
+
result.append(
|
|
899
|
+
Vector2d(-self.width_x / 2.0, self.width_y / 2.0),
|
|
900
|
+
)
|
|
901
|
+
return result
|
|
902
|
+
|
|
903
|
+
@property
|
|
904
|
+
def _x_max(self) -> float:
|
|
905
|
+
return self.width_x / 2.0
|
|
906
|
+
|
|
907
|
+
@property
|
|
908
|
+
def _x_min(self) -> float:
|
|
909
|
+
return -self.width_x / 2.0
|
|
910
|
+
|
|
911
|
+
@property
|
|
912
|
+
def _x_center(self) -> float:
|
|
913
|
+
return 0.0
|
|
914
|
+
|
|
915
|
+
@property
|
|
916
|
+
def _y_max(self) -> float:
|
|
917
|
+
return self.width_y / 2.0
|
|
918
|
+
|
|
919
|
+
@property
|
|
920
|
+
def _y_min(self) -> float:
|
|
921
|
+
return -self.width_y / 2.0
|
|
922
|
+
|
|
923
|
+
@property
|
|
924
|
+
def _y_center(self) -> float:
|
|
925
|
+
return 0.0
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
929
|
+
class ShapeT(Shape):
|
|
930
|
+
name: str
|
|
931
|
+
a: float
|
|
932
|
+
b: float
|
|
933
|
+
t1: float
|
|
934
|
+
t2: float
|
|
935
|
+
r: float
|
|
936
|
+
|
|
937
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
938
|
+
result: list[Vector2d] = [
|
|
939
|
+
Vector2d(-self.t1 / 2.0, -self.a / 2.0),
|
|
940
|
+
Vector2d(self.t1 / 2.0, -self.a / 2.0),
|
|
941
|
+
Vector2d(self.t1 / 2.0, self.a / 2.0 - self.t2),
|
|
942
|
+
Vector2d(self.b / 2.0, self.a / 2.0 - self.t2),
|
|
943
|
+
Vector2d(self.b / 2.0, self.a / 2.0),
|
|
944
|
+
Vector2d(-self.b / 2.0, self.a / 2.0),
|
|
945
|
+
Vector2d(-self.b / 2.0, self.a / 2.0 - self.t2),
|
|
946
|
+
Vector2d(-self.t1 / 2.0, self.a / 2.0 - self.t2),
|
|
947
|
+
]
|
|
948
|
+
return result
|
|
949
|
+
|
|
950
|
+
def get_position_point(self, position: ShapePosition) -> Vector2d:
|
|
951
|
+
match position:
|
|
952
|
+
case ShapePosition.BOTTOM_CENTER:
|
|
953
|
+
return Vector2d(0.0, -self.a / 2.0)
|
|
954
|
+
case ShapePosition.BOTTOM_LEFT:
|
|
955
|
+
return Vector2d(-self.b / 2.0, -self.a / 2.0)
|
|
956
|
+
case ShapePosition.BOTTOM_RIGHT:
|
|
957
|
+
return Vector2d(self.b / 2.0, -self.a / 2.0)
|
|
958
|
+
case ShapePosition.CENTER_CENTER:
|
|
959
|
+
return Vector2d.zero()
|
|
960
|
+
case ShapePosition.CENTER_LEFT:
|
|
961
|
+
return Vector2d(-self.b / 2.0, 0.0)
|
|
962
|
+
case ShapePosition.CENTER_RIGHT:
|
|
963
|
+
return Vector2d(self.b / 2.0, 0.0)
|
|
964
|
+
case ShapePosition.TOP_CENTER:
|
|
965
|
+
return Vector2d(0.0, self.a / 2.0)
|
|
966
|
+
case ShapePosition.TOP_LEFT:
|
|
967
|
+
return Vector2d(-self.b / 2.0, self.a / 2.0)
|
|
968
|
+
case ShapePosition.TOP_RIGHT:
|
|
969
|
+
return Vector2d(self.b / 2.0, self.a / 2.0)
|
|
970
|
+
case ShapePosition.DIAGRAM_CORE:
|
|
971
|
+
raise NotImplementedError("T形鋼の図心の計算はサポートされていません")
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
@dataclass(eq=False, order=False, kw_only=True)
|
|
975
|
+
class ShapeTSrc(Shape):
|
|
976
|
+
name: str
|
|
977
|
+
h_h: float
|
|
978
|
+
h_b: float
|
|
979
|
+
h_tw: float
|
|
980
|
+
h_tf: float
|
|
981
|
+
t_h: float
|
|
982
|
+
t_b: float
|
|
983
|
+
t_tw: float
|
|
984
|
+
t_tf: float
|
|
985
|
+
t_offset_x: float = 0.0
|
|
986
|
+
|
|
987
|
+
@property
|
|
988
|
+
def _x_max(self) -> float:
|
|
989
|
+
return self.h_h / 2.0
|
|
990
|
+
|
|
991
|
+
@property
|
|
992
|
+
def _x_min(self) -> float:
|
|
993
|
+
return -self.h_h / 2.0
|
|
994
|
+
|
|
995
|
+
@property
|
|
996
|
+
def _x_center(self) -> float:
|
|
997
|
+
return 0.0
|
|
998
|
+
|
|
999
|
+
@property
|
|
1000
|
+
def _y_max(self) -> float:
|
|
1001
|
+
return (self.t_h + self.h_b / 2.0) / 2.0
|
|
1002
|
+
|
|
1003
|
+
@property
|
|
1004
|
+
def _y_min(self) -> float:
|
|
1005
|
+
return -self._y_max
|
|
1006
|
+
|
|
1007
|
+
@property
|
|
1008
|
+
def _y_center(self) -> float:
|
|
1009
|
+
return 0.0
|
|
1010
|
+
|
|
1011
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
1012
|
+
return [
|
|
1013
|
+
Vector2d(-self.t_b / 2.0 + self.t_offset_x, self._y_min),
|
|
1014
|
+
Vector2d(self.t_b / 2.0 + self.t_offset_x, self._y_min),
|
|
1015
|
+
Vector2d(self.t_b / 2.0 + self.t_offset_x, self._y_min + self.t_tf),
|
|
1016
|
+
Vector2d(self.t_tw / 2.0 + self.t_offset_x, self._y_min + self.t_tf),
|
|
1017
|
+
Vector2d(
|
|
1018
|
+
self.t_tw / 2.0 + self.t_offset_x,
|
|
1019
|
+
self._y_max - self.h_b / 2.0 - self.h_tw / 2.0,
|
|
1020
|
+
),
|
|
1021
|
+
Vector2d(
|
|
1022
|
+
self._x_max - self.h_tf, self._y_max - self.h_b / 2.0 - self.h_tw / 2.0
|
|
1023
|
+
),
|
|
1024
|
+
Vector2d(self._x_max - self.h_tf, self._y_max - self.h_b),
|
|
1025
|
+
Vector2d(self._x_max, self._y_max - self.h_b),
|
|
1026
|
+
Vector2d(self._x_max, self._y_max),
|
|
1027
|
+
Vector2d(self._x_max - self.h_tf, self._y_max),
|
|
1028
|
+
Vector2d(
|
|
1029
|
+
self._x_max - self.h_tf, self._y_max - self.h_b / 2.0 + self.h_tw / 2.0
|
|
1030
|
+
),
|
|
1031
|
+
Vector2d(
|
|
1032
|
+
self._x_min + self.h_tf, self._y_max - self.h_b / 2.0 + self.h_tw / 2.0
|
|
1033
|
+
),
|
|
1034
|
+
Vector2d(self._x_min + self.h_tf, self._y_max),
|
|
1035
|
+
Vector2d(self._x_min, self._y_max),
|
|
1036
|
+
Vector2d(self._x_min, self._y_max - self.h_b),
|
|
1037
|
+
Vector2d(self._x_min + self.h_tf, self._y_max - self.h_b),
|
|
1038
|
+
Vector2d(
|
|
1039
|
+
self._x_min + self.h_tf, self._y_max - self.h_b / 2.0 - self.h_tw / 2.0
|
|
1040
|
+
),
|
|
1041
|
+
Vector2d(
|
|
1042
|
+
-self.t_tw / 2.0 + self.t_offset_x,
|
|
1043
|
+
self._y_max - self.h_b / 2.0 - self.h_tw / 2.0,
|
|
1044
|
+
),
|
|
1045
|
+
Vector2d(-self.t_tw / 2.0 + self.t_offset_x, self._y_min + self.t_tf),
|
|
1046
|
+
Vector2d(-self.t_b / 2.0 + self.t_offset_x, self._y_min + self.t_tf),
|
|
1047
|
+
]
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
class ShapeUnknown(Shape):
|
|
1051
|
+
_instance: Shape | None = None
|
|
1052
|
+
|
|
1053
|
+
def __new__(cls) -> Self:
|
|
1054
|
+
if cls._instance is None:
|
|
1055
|
+
cls._instance = ShapeRectangle(
|
|
1056
|
+
name="Unknown",
|
|
1057
|
+
width_x=UNKNOWN_ELEMENT_SIZE_MM,
|
|
1058
|
+
width_y=UNKNOWN_ELEMENT_SIZE_MM,
|
|
1059
|
+
)
|
|
1060
|
+
return cls._instance # type:ignore[return-value]
|
|
1061
|
+
|
|
1062
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
1063
|
+
if self._instance is None:
|
|
1064
|
+
raise RuntimeError("UnknownShape instance is not initialized.")
|
|
1065
|
+
return self._instance.get_out_point2ds()
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
class ShapeUndefined(Shape):
|
|
1069
|
+
_instance: Shape | None = None
|
|
1070
|
+
|
|
1071
|
+
def __new__(cls) -> Any:
|
|
1072
|
+
if cls._instance is None:
|
|
1073
|
+
cls._instance = ShapeRectangle(
|
|
1074
|
+
name="Undefined",
|
|
1075
|
+
width_x=UNKNOWN_ELEMENT_SIZE_MM,
|
|
1076
|
+
width_y=UNKNOWN_ELEMENT_SIZE_MM,
|
|
1077
|
+
)
|
|
1078
|
+
return cls._instance
|
|
1079
|
+
|
|
1080
|
+
def get_out_point2ds(self) -> list[Vector2d]:
|
|
1081
|
+
if self._instance is None:
|
|
1082
|
+
raise RuntimeError("UndefinedShape instance is not initialized.")
|
|
1083
|
+
return self._instance.get_out_point2ds()
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
SHAPE_PAIR_UNKNOWN: Final[ShapePair] = ShapePair(start=ShapeUnknown(), end=None)
|
|
1087
|
+
SHAPE_PAIRS_UNKNOWN: Final[list[ShapePair]] = [SHAPE_PAIR_UNKNOWN]
|
|
1088
|
+
SHAPE_PAIR_UNDEFINED: Final[ShapePair] = ShapePair(start=ShapeUndefined(), end=None)
|
|
1089
|
+
SHAPE_PAIRS_UNDEFINED: Final[list[ShapePair]] = [SHAPE_PAIR_UNDEFINED]
|