235 |
235 |
|
236 |
236 |
#connector.setZValue(self.zValue() + 1)
|
237 |
237 |
self.connectors.append(connector)
|
238 |
|
if len(connected) > index:
|
239 |
|
connected_item_uid = connected[index]
|
240 |
|
if connected_item_uid:
|
241 |
|
target = QEngineeringConnectorItem.find_connector(connected_item_uid)
|
242 |
|
connector.connect(target)
|
243 |
|
if target:
|
244 |
|
target.connect(connector)
|
245 |
|
targets.append(target)
|
|
238 |
if connected:
|
|
239 |
if len(connected) > index:
|
|
240 |
connected_item_uid = connected[index]
|
|
241 |
if connected_item_uid:
|
|
242 |
target = QEngineeringConnectorItem.find_connector(connected_item_uid)
|
|
243 |
connector.connect(target)
|
|
244 |
if target:
|
|
245 |
target.connect(connector)
|
|
246 |
targets.append(target)
|
246 |
247 |
|
247 |
248 |
index = index + 1
|
248 |
249 |
|
... | ... | |
788 |
789 |
sys.exc_info()[-1].tb_lineno)
|
789 |
790 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
790 |
791 |
|
|
792 |
def distance_to(self, pt: QPointF) -> float:
|
|
793 |
from shapely.geometry import Point, LineString
|
|
794 |
|
|
795 |
res = sys.float_info.max
|
|
796 |
|
|
797 |
try:
|
|
798 |
pts = []
|
|
799 |
for idx in range(self.path().elementCount()):
|
|
800 |
ele = self.path().elementAt(idx)
|
|
801 |
if ele.isMoveTo():
|
|
802 |
pts.clear()
|
|
803 |
pts.append((ele.x, ele.y))
|
|
804 |
elif ele.isLineTo():
|
|
805 |
if len(pts) > 1:
|
|
806 |
pts.pop(0)
|
|
807 |
|
|
808 |
pts.append((ele.x, ele.y))
|
|
809 |
|
|
810 |
line = LineString([(pts[0][0], pts[0][1]), (pts[1][0], pts[1][1])])
|
|
811 |
dist = line.distance(Point(pt.x(), pt.y()))
|
|
812 |
if dist < res:
|
|
813 |
res = dist
|
|
814 |
except Exception as ex:
|
|
815 |
from App import App
|
|
816 |
from AppDocData import MessageType
|
|
817 |
|
|
818 |
message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
|
|
819 |
f"{sys.exc_info()[-1].tb_lineno}"
|
|
820 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
|
821 |
|
|
822 |
return res
|
|
823 |
|
|
824 |
def insert_symbol(self, symbol, pos: QPointF):
|
|
825 |
"""split line and join symbol and line"""
|
|
826 |
import math
|
|
827 |
from App import App
|
|
828 |
from shapely.geometry import Point, LineString
|
|
829 |
from shapely import affinity
|
|
830 |
|
|
831 |
def perpendicular(pts):
|
|
832 |
import math
|
|
833 |
|
|
834 |
dx, dy = pts[1][0] - pts[0][0], pts[1][1] - pts[0][1]
|
|
835 |
dx, dy = -dy, dx
|
|
836 |
length = math.sqrt(dx * dx + dy * dy)
|
|
837 |
dx /= length
|
|
838 |
dy /= length
|
|
839 |
|
|
840 |
return (dx, dy)
|
|
841 |
|
|
842 |
def intersection(pts, line):
|
|
843 |
import math
|
|
844 |
from shapely.geometry import Point, LineString
|
|
845 |
|
|
846 |
start_pt, end_pt = pts[0], pts[1]
|
|
847 |
dx, dy = end_pt[0] - start_pt[0], end_pt[1] - start_pt[1]
|
|
848 |
length = math.sqrt(dx * dx + dy * dy)
|
|
849 |
if length == 0:
|
|
850 |
return None
|
|
851 |
dx /= length
|
|
852 |
dy /= length
|
|
853 |
lhs = LineString(
|
|
854 |
[(start_pt[0] - dx * 20, start_pt[1] - dy * 20), (end_pt[0] + dx * 20, end_pt[1] + dy * 20)])
|
|
855 |
rhs = LineString(line)
|
|
856 |
return lhs.intersection(rhs)
|
|
857 |
|
|
858 |
def dot_product(lhs, rhs):
|
|
859 |
return sum([lhs[i] * rhs[i] for i in range(len(lhs))])
|
|
860 |
|
|
861 |
def angle(pts):
|
|
862 |
import math
|
|
863 |
|
|
864 |
start_pt, end_pt = pts[0], pts[1]
|
|
865 |
dx, dy = end_pt[0] - start_pt[0], end_pt[1] - start_pt[1]
|
|
866 |
dot = dot_product((1, 0), (dx, dy))
|
|
867 |
length = math.sqrt(dx * dx + dy * dy)
|
|
868 |
return math.acos(dot / length)
|
|
869 |
|
|
870 |
try:
|
|
871 |
pts = []
|
|
872 |
for idx in range(self.path().elementCount()):
|
|
873 |
ele = self.path().elementAt(idx)
|
|
874 |
if ele.isMoveTo():
|
|
875 |
pts.clear()
|
|
876 |
pts.append((ele.x, ele.y))
|
|
877 |
elif ele.isLineTo():
|
|
878 |
if len(pts) > 1:
|
|
879 |
pts.pop(0)
|
|
880 |
|
|
881 |
pts.append((ele.x, ele.y))
|
|
882 |
|
|
883 |
vec = perpendicular(pts)
|
|
884 |
line = [(pos.x() - vec[0] * 20, pos.y() - vec[1] * 20),
|
|
885 |
(pos.x() + vec[0] * 20, pos.y() + vec[1] * 20)]
|
|
886 |
origin = intersection(pts, line)
|
|
887 |
if type(origin) is Point:
|
|
888 |
dx, dy = origin.x - pos.x(), origin.y - pos.y()
|
|
889 |
length = math.sqrt(dx ** 2 + dy ** 2)
|
|
890 |
|
|
891 |
symbol.moveBy(origin.x - pos.x(), origin.y - pos.y())
|
|
892 |
symbol.loc = [round(origin.x - symbol.symbolOrigin[0], 1),
|
|
893 |
round(origin.y - symbol.symbolOrigin[1], 1)]
|
|
894 |
symbol.size = [symbol.boundingRect().width(), symbol.boundingRect().height()]
|
|
895 |
symbol.angle = round(angle(pts), 2)
|
|
896 |
symbol.setRotation(math.radians(-symbol.angle))
|
|
897 |
if 2 == len(symbol.connectors) or symbol.name == "Line_Splitter": # 2 way component
|
|
898 |
symbol_connectors = symbol.connectors
|
|
899 |
if symbol.name == "Line_Splitter":
|
|
900 |
symbol_connectors = list(
|
|
901 |
filter(lambda x: x._direction in ["LEFT", "RIGHT"], symbol.connectors))
|
|
902 |
if not len(symbol_connectors) == 2:
|
|
903 |
return
|
|
904 |
# symbol_connectors = symbol.connectors[0:2]
|
|
905 |
"""
|
|
906 |
for i in range(len(symbol.connectors)):
|
|
907 |
rotatedPt = affinity.rotate(Point(symbol.connectors[i].connectPoint[0] - symbol.symbolOrigin[0],
|
|
908 |
symbol.connectors[i].connectPoint[1] - symbol.symbolOrigin[
|
|
909 |
1]),
|
|
910 |
-angle, Point(0, 0), use_radians=True)
|
|
911 |
"""
|
|
912 |
dx1 = symbol_connectors[0].center()[0] - pts[0][0]
|
|
913 |
dy1 = symbol_connectors[0].center()[1] - pts[0][1]
|
|
914 |
length1 = math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
915 |
dx2 = symbol_connectors[1].center()[0] - pts[0][0]
|
|
916 |
dy2 = symbol_connectors[1].center()[1] - pts[0][1]
|
|
917 |
length2 = math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
918 |
|
|
919 |
if length1 < length2:
|
|
920 |
"""create a new line"""
|
|
921 |
new_line = QEngineeringStreamlineItem()
|
|
922 |
for _idx in range(idx):
|
|
923 |
ele = self.path().elementAt(_idx)
|
|
924 |
new_line._vertices.append((ele.x, ele.y))
|
|
925 |
new_line._vertices.append(symbol_connectors[0].center())
|
|
926 |
new_line.build_path()
|
|
927 |
new_line.build_connectors(connected=None)
|
|
928 |
self.scene().addItem(new_line)
|
|
929 |
|
|
930 |
App.mainWnd().add_hmb_data(new_line)
|
|
931 |
new_line.update_label_contents()
|
|
932 |
new_line.connectors[0].connect(self.connectors[0].connectedItem)
|
|
933 |
if self.connectors[0].connectedItem:
|
|
934 |
self.connectors[0].connectedItem.connect(new_line.connectors[0])
|
|
935 |
|
|
936 |
if self.connectors[1].connectedItem:
|
|
937 |
new_line.connectors[1].connect(symbol_connectors[0])
|
|
938 |
symbol_connectors[0].connect(new_line.connectors[1])
|
|
939 |
new_line.transfer.onRemoved.connect(App.mainWnd().on_item_removed)
|
|
940 |
"""up to here"""
|
|
941 |
|
|
942 |
"""update stream line"""
|
|
943 |
self._vertices.clear()
|
|
944 |
self._vertices.append(symbol_connectors[1].center())
|
|
945 |
for _idx in range(idx, self.path().elementCount()):
|
|
946 |
ele = self.path().elementAt(_idx)
|
|
947 |
if ele.isLineTo():
|
|
948 |
self._vertices.append((ele.x, ele.y))
|
|
949 |
|
|
950 |
self.connectors[0].setPos(symbol_connectors[1].center())
|
|
951 |
self.connectors[0].connect(symbol_connectors[1])
|
|
952 |
symbol_connectors[1].connect(self.connectors[0])
|
|
953 |
self.build_path()
|
|
954 |
|
|
955 |
"""up to here"""
|
|
956 |
return
|
|
957 |
else:
|
|
958 |
"""create a new line"""
|
|
959 |
new_line = QEngineeringStreamlineItem()
|
|
960 |
for _idx in range(idx):
|
|
961 |
ele = self.path().elementAt(_idx)
|
|
962 |
new_line._vertices.append((ele.x, ele.y))
|
|
963 |
new_line._vertices.append(symbol_connectors[1].center())
|
|
964 |
new_line.build_path()
|
|
965 |
new_line.build_connectors(connected=None)
|
|
966 |
self.scene().addItem(new_line)
|
|
967 |
|
|
968 |
App.mainWnd().add_hmb_data(new_line)
|
|
969 |
new_line.update_label_contents()
|
|
970 |
|
|
971 |
new_line.connectors[0].connect(self.connectors[0].connectedItem)
|
|
972 |
if self.connectors[0].connectedItem:
|
|
973 |
self.connectors[0].connectedItem.connect(new_line.connectors[0])
|
|
974 |
|
|
975 |
if self.connectors[1].connectedItem:
|
|
976 |
new_line.connectors[1].connect(symbol_connectors[1])
|
|
977 |
symbol_connectors[1].connect(new_line.connectors[1])
|
|
978 |
|
|
979 |
new_line.transfer.onRemoved.connect(App.mainWnd().on_item_removed)
|
|
980 |
"""up to here"""
|
|
981 |
|
|
982 |
self._vertices.clear()
|
|
983 |
self._vertices.append(symbol_connectors[0].center())
|
|
984 |
for _idx in range(idx, self.path().elementCount()):
|
|
985 |
ele = self.path().elementAt(_idx)
|
|
986 |
if ele.isLineTo():
|
|
987 |
self._vertices.append((ele.x, ele.y))
|
|
988 |
|
|
989 |
self.connectors[0].setPos(symbol_connectors[0].center())
|
|
990 |
self.connectors[0].connect(symbol_connectors[0])
|
|
991 |
symbol_connectors[0].connect(self.connectors[0])
|
|
992 |
self.build_path()
|
|
993 |
|
|
994 |
return
|
|
995 |
self.scene.update()
|
|
996 |
|
|
997 |
"""
|
|
998 |
symbol.loc = [origin.x - symbol.symbolOrigin[0], origin.y - symbol.symbolOrigin[1]]
|
|
999 |
symbol.size = [symbol.boundingRect().width(), symbol.boundingRect().height()]
|
|
1000 |
self.scene().addItem(symbol)
|
|
1001 |
"""
|
|
1002 |
except Exception as ex:
|
|
1003 |
from App import App
|
|
1004 |
from AppDocData import MessageType
|
|
1005 |
|
|
1006 |
message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
|
|
1007 |
f"{sys.exc_info()[-1].tb_lineno}"
|
|
1008 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
791 |
1009 |
'''
|
792 |
1010 |
@brief return bounding rectangle of polyline
|
793 |
1011 |
@author humkyung
|
... | ... | |
842 |
1060 |
else:
|
843 |
1061 |
polygon = QPolygon()
|
844 |
1062 |
for pt in self._vertices:
|
845 |
|
polygon.append(QPointF(pt[0], pt[1]))
|
|
1063 |
polygon.append(QPoint(pt[0], pt[1]))
|
846 |
1064 |
path = QPainterPath()
|
847 |
1065 |
path.addPolygon(polygon)
|
848 |
1066 |
|