pyTransmission_Graphic/graphic.py

132 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import copy
import math
import ezdxf
from type3d import Vector3D
import numpy as np
import transformation
from typing import List, Union, Tuple
class Line:
def __init__(
self,
start_p: Vector3D,
end_p: Vector3D,
tension_k: float,
n_point: int,
):
self._start_p: Vector3D = start_p
self._end_p: Vector3D = end_p
self._tension_k: float = tension_k
self._n_point: int = n_point
self._span = 0
self._points = None
self._rotation = None
def curve(self):
if self._points:
return self._points
start_p = self._start_p
end_p = self._end_p
tension_k = self._tension_k
n_point = self._n_point
# 右手坐标系Z朝上
line = Vector3D(end_p.x, end_p.y, end_p.z) - Vector3D(
start_p.x, start_p.y, start_p.z
)
# 计算与X轴的角度
xy_project = copy.deepcopy(line) # 投影到xy平面上
xy_project.z = 0
x_abs_angel = xy_project.angle_to(Vector3D(1, 0, 0))
x_angel = x_abs_angel * np.sign(xy_project.y)
height = end_p.z - start_p.z
span: float = abs(xy_project)
self._span = span
span_l = np.linspace(0, span, n_point) # 档距
z_points: Tuple[float] = (
start_p.z
+ span_l * height / span
- span_l * (span - span_l) * tension_k / math.cos(math.atan(height / span))
)
p_points: List[
Union[List[float, float, float], Tuple[float, float, float]]
] = list() # 未旋转之前的伪坐标
for foo in range(len(span_l)):
p_points.append((span_l[foo] + start_p.x, start_p.y, z_points[foo]))
# 绕Z轴旋转
rotation = transformation.Rotation(
x_angel,
[start_p.x, start_p.y, start_p.z],
[start_p.x, start_p.y, start_p.z + 1],
)
self._rotation = rotation
points = rotation.rotate(
p_points,
)
self._points = points
return points
def sag(self):
# msp.add_polyline3d(
# [(start_p.x, start_p.y, start_p.z), (end_p.x, end_p.y, end_p.z)]
# )
start_p = self._start_p
end_p = self._end_p
span = self._span
height = end_p.z - start_p.z
middle_span = span / 2
points = self._points
n_point = self._n_point
middle_z = points[int(n_point / 2)][2]
rotation = self._rotation
sag_points = rotation.rotate(
[
[start_p.x, start_p.y, start_p.z],
[
middle_span + start_p.x,
start_p.y,
start_p.z + middle_span * height / span,
],
[middle_span + start_p.x, start_p.y, middle_z],
[
middle_span + start_p.x,
start_p.y,
start_p.z + middle_span * height / span,
],
[start_p.x + span, start_p.y, end_p.z],
]
)
return sag_points
def swing(self, angel):
points = self._points
start_p = self._start_p
end_p = self._end_p
swing_rotation = transformation.Rotation(
angel,
[start_p.x, start_p.y, start_p.z],
[end_p.x, end_p.y, end_p.z],
)
swing_point = swing_rotation.rotate(points)
return swing_point
class Canvas:
def __init__(self):
self._doc = None
self._msp = None
def init_canvas(self):
doc = ezdxf.new()
self._doc = doc
msp = doc.modelspace()
self._msp = msp
def draw(self, points):
msp = self._msp
msp.add_polyline3d(points)
def save(self, file_path):
doc = self._doc
doc.saveas(file_path)