개정판 62df6e0a
issue #1601: stream line 생성
Change-Id: I52075695f28fc28225f18f2cb87666b92c6ed62b
HYTOS/HYTOS/Commands/PlaceStreamlineCommand.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
""" This is place stream line module """ |
|
3 |
|
|
4 |
import os.path |
|
5 |
import AbstractCommand |
|
6 |
try: |
|
7 |
from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QT_VERSION_STR |
|
8 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor, QTransform |
|
9 |
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog |
|
10 |
except ImportError: |
|
11 |
try: |
|
12 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR |
|
13 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor |
|
14 |
except ImportError: |
|
15 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
|
16 |
|
|
17 |
class PlaceStreamlineCommand(AbstractCommand.AbstractCommand): |
|
18 |
""" This is place line class """ |
|
19 |
|
|
20 |
onSuccess = pyqtSignal() |
|
21 |
onRejected = pyqtSignal(AbstractCommand.AbstractCommand) |
|
22 |
|
|
23 |
def __init__(self, imageViewer): |
|
24 |
super(PlaceStreamlineCommand, self).__init__(imageViewer) |
|
25 |
self.name = 'PlaceLine' |
|
26 |
self.imageViewer.setCursor(QCursor(Qt.CrossCursor)) |
|
27 |
|
|
28 |
self._streamline = None |
|
29 |
|
|
30 |
''' |
|
31 |
@brief reset command status |
|
32 |
@author humkyung |
|
33 |
@date 2018.07.23 |
|
34 |
''' |
|
35 |
def reset(self): |
|
36 |
self._streamline = None |
|
37 |
|
|
38 |
''' |
|
39 |
@brief place a line |
|
40 |
@author humkyung |
|
41 |
@date 2018.07.23 |
|
42 |
''' |
|
43 |
def execute(self, param): |
|
44 |
import shapely |
|
45 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
|
46 |
from SymbolSvgItem import SymbolSvgItem |
|
47 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
|
48 |
|
|
49 |
self.isTreated = False |
|
50 |
|
|
51 |
event = param[1] |
|
52 |
if 'mousePressEvent' == param[0] and event.button() == Qt.LeftButton: |
|
53 |
if self._streamline is None: |
|
54 |
selected = self.imageViewer.scene.itemAt(param[2], QTransform()) |
|
55 |
if selected is not None and type(selected) is QEngineeringConnectorItem: |
|
56 |
self._streamline = QEngineeringStreamlineItem() |
|
57 |
self._streamline._vertices.append(selected.center()) |
|
58 |
self.imageViewer.scene.addItem(self._streamline) |
|
59 |
self.imageViewer.scene.setFocusItem(self._streamline) |
|
60 |
else: |
|
61 |
try: |
|
62 |
QGraphicsView.mouseReleaseEvent(self.imageViewer, event) |
|
63 |
self._streamline.update() |
|
64 |
self.onSuccess.emit() |
|
65 |
finally: |
|
66 |
pass |
|
67 |
elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.RightButton: |
|
68 |
self.onRejected.emit(self) |
|
69 |
elif 'mouseMoveEvent' == param[0] and self._streamline is not None: |
|
70 |
self._streamline.onMouseMoved(event, param[2]) |
|
71 |
elif 'keyPressEvent' == param[0]: |
|
72 |
if event.key() == Qt.Key_Escape: |
|
73 |
self.onRejected.emit(self) |
|
74 |
self.isTreated = False |
|
75 |
|
|
76 |
def undo(self): |
|
77 |
pass |
|
78 |
|
|
79 |
def redo(self): |
|
80 |
pass |
HYTOS/HYTOS/MainWindow.py | ||
---|---|---|
1287 | 1287 |
@history Jeongwoo 2018.05.10 Change method for Checkable action |
1288 | 1288 |
''' |
1289 | 1289 |
def onPlaceLine(self): |
1290 |
import PlaceStreamlineCommand |
|
1291 |
|
|
1292 |
""" |
|
1290 | 1293 |
if not self.graphicsView.hasImage(): |
1291 | 1294 |
self.actionLine.setChecked(False) |
1292 | 1295 |
self.showImageSelectionMessageBox() |
1293 | 1296 |
return |
1297 |
""" |
|
1294 | 1298 |
|
1295 | 1299 |
self.actionLine.setChecked(True) |
1296 | 1300 |
if not hasattr(self.actionLine, 'tag'): |
1297 |
self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
|
|
1301 |
self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
|
|
1298 | 1302 |
self.actionLine.tag.onSuccess.connect(self.onLineCreated) |
1299 | 1303 |
self.actionLine.tag.onRejected.connect(self.onCommandRejected) |
1300 | 1304 |
|
HYTOS/HYTOS/Shapes/EngineeringStreamlineItem.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
""" |
|
3 |
This is Polyline item module |
|
4 |
""" |
|
5 |
|
|
6 |
import sys |
|
7 |
import os.path |
|
8 |
import copy |
|
9 |
try: |
|
10 |
from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QObject, QT_VERSION_STR |
|
11 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QBrush, QPen, QPolygonF, QColor, QTransform |
|
12 |
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QGraphicsItem, QAbstractGraphicsShapeItem, QGraphicsPathItem |
|
13 |
except ImportError: |
|
14 |
try: |
|
15 |
from PyQt4.QtCore import Qt, QRectF, QObject, pyqtSignal, QT_VERSION_STR |
|
16 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QColor |
|
17 |
except ImportError: |
|
18 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
|
19 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
|
20 |
|
|
21 |
class QEngineeringStreamlineItem(QGraphicsPathItem, QEngineeringAbstractItem): |
|
22 |
""" This is EngineeringPolylineItem Class """ |
|
23 |
|
|
24 |
onRemoved = pyqtSignal(QGraphicsItem) |
|
25 |
|
|
26 |
''' |
|
27 |
@history 2018.05.11 Jeongwoo Declare variable self.pen |
|
28 |
2018.05.15 Jeongwoo Change method to call parent's __init__ |
|
29 |
2018.05.25 Jeongwoo Change self.pen's default color (red → blue) |
|
30 |
''' |
|
31 |
def __init__(self, uid=None, parent=None): |
|
32 |
import uuid |
|
33 |
|
|
34 |
try: |
|
35 |
QGraphicsPathItem.__init__(self, parent) |
|
36 |
QEngineeringAbstractItem.__init__(self) |
|
37 |
self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable) |
|
38 |
|
|
39 |
self.uid = uuid.uuid4() if uid is None else uid |
|
40 |
self._vertices = [] |
|
41 |
self.isCreated = False |
|
42 |
self._pt = None |
|
43 |
self.setPen(QPen(Qt.blue, 2, Qt.SolidLine)) # set default pen |
|
44 |
|
|
45 |
self.transfer = Transfer() |
|
46 |
except Exception as ex: |
|
47 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
48 |
|
|
49 |
@property |
|
50 |
def drawing_mode(self): |
|
51 |
return self._drawing_mode |
|
52 |
|
|
53 |
@drawing_mode.setter |
|
54 |
def drawing_mode(self, value): |
|
55 |
self._drawing_mode = value |
|
56 |
|
|
57 |
''' |
|
58 |
@brief construct a polyline |
|
59 |
''' |
|
60 |
def process(self, param): |
|
61 |
if ('mousePressEvent' == param[0]) and (param[1].button() == Qt.LeftButton): |
|
62 |
self._vertices.append(param[2]) |
|
63 |
elif ('mouseMoveEvent' == param[0]): |
|
64 |
self._pt = param[2] |
|
65 |
elif ('mouseReleaseEvent' == param[0]) and (param[1].button() == Qt.RightButton): |
|
66 |
self.isCreated = True |
|
67 |
|
|
68 |
''' |
|
69 |
@brief clone an object |
|
70 |
''' |
|
71 |
def clone(self): |
|
72 |
clone = QEngineeringStreamlineItem() |
|
73 |
clone._vertices = copy.deepcopy(self._vertices) |
|
74 |
clone.isCreated = self.isCreated |
|
75 |
|
|
76 |
return clone |
|
77 |
|
|
78 |
def init(self): |
|
79 |
self._vertices = [] |
|
80 |
self._pt = None |
|
81 |
self.isCreated = False |
|
82 |
|
|
83 |
''' |
|
84 |
@build build path |
|
85 |
@author humkyung |
|
86 |
@date 2018.04.23 |
|
87 |
''' |
|
88 |
def buildItem(self): |
|
89 |
path = QPainterPath() |
|
90 |
path.moveTo(self._vertices[0][0], self._vertices[0][1]) |
|
91 |
for i in range(1, len(self._vertices)): |
|
92 |
path.lineTo(self._vertices[i][0], self._vertices[i][1]) |
|
93 |
self.setPath(path) |
|
94 |
self.isCreated = True |
|
95 |
|
|
96 |
''' |
|
97 |
@brief return bouding rectangle of polyline |
|
98 |
@author humkyung |
|
99 |
@date 2018.07.23 |
|
100 |
''' |
|
101 |
def boundingRect(self): |
|
102 |
rect = QRectF() |
|
103 |
|
|
104 |
if self.isCreated: |
|
105 |
rect = self.path().boundingRect() |
|
106 |
rect = QRectF(rect.left() - 5, rect.top() - 5, rect.width() + 10, rect.height() + 10) |
|
107 |
else: |
|
108 |
minX = None |
|
109 |
minY = None |
|
110 |
maxX = None |
|
111 |
maxY = None |
|
112 |
for pt in self._vertices: |
|
113 |
if minX is None or pt[0] < minX: |
|
114 |
minX = pt[0] |
|
115 |
if minY is None or pt[1] < minY: |
|
116 |
minY = pt[1] |
|
117 |
|
|
118 |
if maxX is None or pt[0] > maxX: |
|
119 |
maxX = pt[0] |
|
120 |
if maxY is None or pt[1] > maxY: |
|
121 |
maxY = pt[1] |
|
122 |
|
|
123 |
if self._pt is not None: |
|
124 |
if minX is None or self._pt[0] < minX: |
|
125 |
minX = self._pt[0] |
|
126 |
if minY is None or self._pt[1] < minY: |
|
127 |
minY = self._pt[1] |
|
128 |
|
|
129 |
if maxX is None or self._pt[0] > maxX: |
|
130 |
maxX = self._pt[0] |
|
131 |
if maxY is None or self._pt[1] > maxY: |
|
132 |
maxY = self._pt[1] |
|
133 |
|
|
134 |
if minX is not None and minY is not None and maxX is not None and maxY is not None: |
|
135 |
rect = QRectF(minX - 5, minY - 5, maxX - minX + 10, maxY - minY + 10) |
|
136 |
|
|
137 |
return rect |
|
138 |
|
|
139 |
''' |
|
140 |
@brief |
|
141 |
@author humkyung |
|
142 |
@date 2018.07.26 |
|
143 |
''' |
|
144 |
def onMouseMoved(self, event, scenePos): |
|
145 |
from SymbolSvgItem import SymbolSvgItem |
|
146 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
|
147 |
|
|
148 |
# get connection point near by mouse point |
|
149 |
pt = (scenePos.x(), scenePos.y()) |
|
150 |
item = self.scene().itemAt(scenePos, QTransform()) |
|
151 |
if (item is not None) and (type(item) is SymbolSvgItem): |
|
152 |
connPt = item.getConnectionPointCloseTo(pt, 5) |
|
153 |
if connPt is not None: pt = connPt |
|
154 |
elif (item is not None) and (type(item) is QEngineeringConnectorItem): |
|
155 |
pt = item.center() |
|
156 |
# up to here |
|
157 |
|
|
158 |
del self._vertices[1:] |
|
159 |
dx = pt[0] - self._vertices[0][0] |
|
160 |
dy = pt[1] - self._vertices[0][1] |
|
161 |
self._vertices.append((self._vertices[0][0] + dx*0.5, self._vertices[0][1])) |
|
162 |
self._vertices.append((self._vertices[-1][0], self._vertices[-1][1] + dy)) |
|
163 |
self._vertices.append(pt) |
|
164 |
|
|
165 |
self.buildItem() |
|
166 |
self.update() |
|
167 |
|
|
168 |
''' |
|
169 |
@brief Return real item position |
|
170 |
@authro Jeongwoo |
|
171 |
@date 2018.05.29 |
|
172 |
''' |
|
173 |
def boundingRectOnScene(self): |
|
174 |
rect = self.boundingRect() |
|
175 |
sp = self.startPoint() |
|
176 |
rect.moveTo(sp[0], sp[1]) |
|
177 |
return rect |
|
178 |
|
|
179 |
''' |
|
180 |
@brief Set Color. Override QEngineeringAbstractItem's |
|
181 |
@author Jeongwoo |
|
182 |
@date 2018.05.11 |
|
183 |
@history 2018.05.11 Jeongwoo Add self.setPen() Method |
|
184 |
@history humkyung 2018.05.13 call setPen method to apply changed color |
|
185 |
''' |
|
186 |
def setColor(self, color): |
|
187 |
c = QColor() |
|
188 |
c.setNamedColor(color) |
|
189 |
_pen = self.pen() |
|
190 |
_pen.setColor(c) |
|
191 |
self.setPen(_pen) |
|
192 |
self.update() |
|
193 |
|
|
194 |
''' |
|
195 |
@brief The class transfer pyqtSignal Event. Cause Subclass of QGraphicsRectItem can't use pyqtSignal |
|
196 |
@author Jeongwoo |
|
197 |
@date 2018.06.18 |
|
198 |
''' |
|
199 |
class Transfer(QObject): |
|
200 |
onRemoved = pyqtSignal(QGraphicsItem) |
|
201 |
|
|
202 |
def __init__(self, parent = None): |
|
203 |
QObject.__init__(self, parent) |
내보내기 Unified diff