pyTransmission_Graphic/graphic.py

184 lines
5.6 KiB
Python
Raw Permalink 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 ezdxf.math import UCS
from type3d import Vector3D
import numpy as np
import transformation
from typing import List, Union, Tuple
def draw_text(msp, text, text_point):
text_entity = msp.add_text(
text=text,
dxfattribs={
# text rotation angle in degrees in OCS
"thickness": 0.333,
"color": 1,
"style": "TXT",
"height": 2,
},
)
# set text position in OCS
text_entity.set_pos(text_point, align="MIDDLE_CENTER")
class Line:
def __init__(
self,
msp,
start_p: Vector3D,
end_p: Vector3D,
tension_k: float,
n_point: int,
):
self._msp = msp
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,draw=False)->List:
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轴的角度画弧垂。先沿Z轴旋转到xz平面的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
if draw:
msp = self._msp
msp.add_polyline3d(points)
return points
def sag(self,draw=False):
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
p_sag_points = [
[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],
] # 旋转前的值
sag_points = rotation.rotate(p_sag_points)
sag_value = start_p.z + middle_span * height / span - middle_z
if draw:
msp = self._msp
msp.add_polyline3d(sag_points)
draw_text(msp, f'sag {sag_value}', sag_points[1])
return sag_points
def swing(self, angel,draw=False)->List:
if not self._points:
self.curve()
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)
if draw:
msp = self._msp
msp.add_polyline3d(swing_point)
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
doc.styles.new("TXT", dxfattribs={"font": "romans.shx"})
def draw(self, points):
msp = self.msp
msp.add_polyline3d(points)
def save(self, file_path):
doc = self._doc
doc.saveas(file_path)
class Ruler:
def __init__(self, curve_points1: List, curve_points2: List):
self._curve_points1 = curve_points1
self._curve_points2 = curve_points2
def closest_distance(self):
curve_points1 = self._curve_points1
curve_points2 = self._curve_points2
closest = 999999999999
closest_poc1 = 0
closest_poc2 = 0
for foo in range(len(curve_points1)):
poc1 = curve_points1[foo] # point of curve 1
for bar in range(len(curve_points2)):
poc2 = curve_points2[bar]
distance = np.sum(np.power((np.array(poc1) - np.array(poc2)), 2)) ** 0.5
if distance < closest:
closest_poc1 = poc1
closest_poc2 = poc2
closest = distance
return closest, closest_poc1, closest_poc2