개정판 54eedb38
issue #622: 사용자가 도면을 닫을때 도면의 데이타가 변경되었을 경우 저장 여부를 확인하는 창을 띄운다
Change-Id: I9225fde70ec295babd31d6c7b9e2fd76808660bb
DTI_PID/DTI_PID/App.py | ||
---|---|---|
18 | 18 |
|
19 | 19 |
class App(QApplication): |
20 | 20 |
""" This is App class inherits from QApplication """ |
21 |
|
|
22 |
NAME = 'Digital P&ID' |
|
23 |
|
|
21 | 24 |
def __init__(self, args): |
22 | 25 |
import locale |
23 | 26 |
|
DTI_PID/DTI_PID/Commands/SaveWorkCommand.py | ||
---|---|---|
7 | 7 |
from PyQt5.QtGui import * |
8 | 8 |
from PyQt5.QtWidgets import * |
9 | 9 |
|
10 |
|
|
10 | 11 |
class SaveWorkCommand(QThread): |
11 | 12 |
display_message = pyqtSignal(Enum, str) |
12 | 13 |
show_progress = pyqtSignal(int) |
... | ... | |
42 | 43 |
if item.area == titleBlockProp[0]: |
43 | 44 |
titleBlockItems.append(item) |
44 | 45 |
|
45 |
db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and type(item) is not QGraphicsBoundingBoxItem and type(item) is not QEngineeringErrorItem and type(item) is not QEngineeringLineNoTextItem] |
|
46 |
db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and type( |
|
47 |
item) is not QGraphicsBoundingBoxItem and type(item) is not QEngineeringErrorItem and type( |
|
48 |
item) is not QEngineeringLineNoTextItem] |
|
46 | 49 |
db_items.extend([item for item in items if type(item) is QEngineeringLineNoTextItem]) |
47 | 50 |
db_items.extend([line for line in appDocData.tracerLineNos if type(line) is QEngineeringTrimLineNoTextItem]) |
48 | 51 |
db_items.extend(titleBlockItems) |
... | ... | |
59 | 62 |
except Exception as ex: |
60 | 63 |
from AppDocData import MessageType |
61 | 64 |
|
62 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
65 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
66 |
sys.exc_info()[-1].tb_lineno) |
|
63 | 67 |
self.display_message.emit(MessageType.Error, message) |
64 | 68 |
|
65 | 69 |
@staticmethod |
... | ... | |
70 | 74 |
|
71 | 75 |
app_doc_data = AppDocData.instance() |
72 | 76 |
path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml') |
73 |
result = xg.writeXmlOnScene(path, app_doc_data.activeDrawing.width, app_doc_data.activeDrawing.height, app_doc_data.allItems, app_doc_data.tracerLineNos) |
|
74 |
|
|
77 |
result = xg.writeXmlOnScene(path, app_doc_data.activeDrawing.width, app_doc_data.activeDrawing.height, |
|
78 |
app_doc_data.allItems, app_doc_data.tracerLineNos) |
|
79 |
|
|
75 | 80 |
resultStr = '[저장 결과]' |
76 | 81 |
|
77 | 82 |
for item in result.items(): |
DTI_PID/DTI_PID/Drawing.py | ||
---|---|---|
20 | 20 |
from EngineeringUnknownItem import QEngineeringUnknownItem |
21 | 21 |
from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem |
22 | 22 |
|
23 |
|
|
23 | 24 |
class Source: |
24 | 25 |
""" This is Source class """ |
26 |
|
|
25 | 27 |
def __init__(self, source): |
26 | 28 |
if type(source) is np.ndarray: |
27 | 29 |
self.source = Image.fromarray(source) |
... | ... | |
31 | 33 |
self.source = Image.fromqimage(source) |
32 | 34 |
elif type(source) is QPixmap: |
33 | 35 |
self.source = Image.fromqpixmap(source) |
34 |
|
|
36 |
|
|
35 | 37 |
''' |
36 | 38 |
@history 2018.05.18 Jeongwoo When Parameter [rect] is None, return whole image |
37 | 39 |
''' |
38 |
def getPyImageOnRect(self, rect = None): |
|
40 |
|
|
41 |
def getPyImageOnRect(self, rect=None): |
|
39 | 42 |
if rect is not None: |
40 | 43 |
return self.source.copy().crop((rect.left(), rect.top(), rect.right(), rect.bottom())) |
41 | 44 |
else: |
42 | 45 |
return self.source.copy() |
43 | 46 |
|
44 |
def getQImageOnRect(self, rect = None):
|
|
47 |
def getQImageOnRect(self, rect=None):
|
|
45 | 48 |
image = ImageQt(self.getPyImageOnRect(rect)) |
46 | 49 |
return image.convertToFormat(QImage.Format_RGBA8888) |
47 | 50 |
|
51 |
|
|
48 | 52 |
class Drawing: |
49 | 53 |
''' |
50 | 54 |
@brief construction |
51 | 55 |
@author humkyung |
52 | 56 |
@date 2018.07.07 |
53 | 57 |
''' |
58 |
|
|
54 | 59 |
def __init__(self, uid, name, datetime): |
55 | 60 |
import uuid |
56 | 61 |
app_doc_data = AppDocData.instance() |
... | ... | |
68 | 73 |
|
69 | 74 |
self.width = 0 |
70 | 75 |
self.height = 0 |
71 |
self._attrs = [['Drawing No', ''], ['Rev No', ''], ['Unit', '']] # attributes |
|
76 |
self._attrs = [['Drawing No', ''], ['Rev No', ''], ['Unit', '']] # attributes |
|
77 |
self._modified = False |
|
72 | 78 |
|
73 | 79 |
def __del__(self): |
74 | 80 |
""" destructor """ |
... | ... | |
89 | 95 |
@author humkyung |
90 | 96 |
@date 2018.07.07 |
91 | 97 |
''' |
98 |
|
|
92 | 99 |
@property |
93 | 100 |
def attrs(self): |
94 | 101 |
return self._attrs |
... | ... | |
98 | 105 |
@author humkyung |
99 | 106 |
@date 2018.07.07 |
100 | 107 |
''' |
108 |
|
|
101 | 109 |
@attrs.setter |
102 | 110 |
def attrs(self, value): |
103 | 111 |
self._attrs = value |
... | ... | |
107 | 115 |
self.width, self.height = image.size |
108 | 116 |
self.currentPidSource = Source(image) |
109 | 117 |
|
118 |
@property |
|
119 |
def modified(self): |
|
120 |
"""getter of modified""" |
|
121 |
return self._modified |
|
122 |
|
|
123 |
@modified.setter |
|
124 |
def modified(self, value): |
|
125 |
"""setter of modified""" |
|
126 |
self._modified = value |
|
127 |
|
|
110 | 128 |
''' |
111 | 129 |
@brief set attribute |
112 | 130 |
@author humkyung |
113 | 131 |
@date 2018.07.07 |
114 | 132 |
''' |
133 |
|
|
115 | 134 |
def setAttr(self, name, value): |
116 | 135 |
attrs = [attr for attr in self._attrs if attr[0] == name] |
117 | 136 |
if attrs: |
... | ... | |
123 | 142 |
|
124 | 143 |
def from_database(self): |
125 | 144 |
""" load all components of drawing """ |
126 |
|
|
145 |
|
|
127 | 146 |
items = [] |
128 | 147 |
tracer_line_nos = [] |
129 | 148 |
app_doc_data = AppDocData.instance() |
... | ... | |
136 | 155 |
if item: items.append(item) |
137 | 156 |
|
138 | 157 |
# parse texts |
139 |
for text in [component for component in components if component['Name'] == 'Text' and component['SymbolType_UID'] == -1]: |
|
158 |
for text in [component for component in components if |
|
159 |
component['Name'] == 'Text' and component['SymbolType_UID'] == -1]: |
|
140 | 160 |
item = QEngineeringTextItem.from_database(text) |
141 | 161 |
if item: |
142 | 162 |
item.uid = text['UID'] |
... | ... | |
144 | 164 |
items.append(item) |
145 | 165 |
|
146 | 166 |
# note |
147 |
for note in [component for component in components if component['Name'] == 'Note' and component['SymbolType_UID'] == -1]: |
|
167 |
for note in [component for component in components if |
|
168 |
component['Name'] == 'Note' and component['SymbolType_UID'] == -1]: |
|
148 | 169 |
item = QEngineeringTextItem.from_database(note) |
149 | 170 |
if item is not None: |
150 | 171 |
item.uid = note['UID'] |
151 | 172 |
items.append(item) |
152 | 173 |
|
153 |
for line in [component for component in components if component['Name'] == 'Line' and component['SymbolType_UID'] == -1]: |
|
174 |
for line in [component for component in components if |
|
175 |
component['Name'] == 'Line' and component['SymbolType_UID'] == -1]: |
|
154 | 176 |
item = QEngineeringLineItem.from_database(line) |
155 | 177 |
if item: items.append(item) |
156 | 178 |
|
157 |
for unknown in [component for component in components if component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]: |
|
179 |
for unknown in [component for component in components if |
|
180 |
component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]: |
|
158 | 181 |
item = QEngineeringUnknownItem.from_database(unknown) |
159 | 182 |
if item: items.append(item) |
160 | 183 |
|
161 |
for component in [component for component in components if component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]: |
|
184 |
for component in [component for component in components if |
|
185 |
component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]: |
|
162 | 186 |
line_no = QEngineeringLineNoTextItem.from_database(component) |
163 | 187 |
if type(line_no) is QEngineeringLineNoTextItem: |
164 | 188 |
runs = app_doc_data.get_pipe_runs(str(line_no.uid)) |
... | ... | |
175 | 199 |
line_run.owner = line_no |
176 | 200 |
line_no.runs.append(line_run) |
177 | 201 |
|
178 |
for component in [component for component in components if component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]: |
|
202 |
for component in [component for component in components if |
|
203 |
component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]: |
|
179 | 204 |
tracer_line_no = QEngineeringTrimLineNoTextItem() |
180 | 205 |
tracer_line_no.uid = uuid.UUID(component['UID']) |
181 | 206 |
|
... | ... | |
191 | 216 |
matches[0].owner = tracer_line_no |
192 | 217 |
line_run.items.append(matches[0]) |
193 | 218 |
tracer_line_no.runs.append(line_run) |
194 |
|
|
219 |
|
|
195 | 220 |
tracer_line_nos.append(tracer_line_no) |
196 | 221 |
|
197 |
for component in [component for component in components if component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]: |
|
222 |
for component in [component for component in components if |
|
223 |
component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]: |
|
198 | 224 |
item = QEngineeringVendorItem.from_database(component) |
199 | 225 |
if item: items.append(item) |
200 | 226 |
except Exception as ex: |
201 | 227 |
from App import App |
202 | 228 |
from AppDocData import MessageType |
203 | 229 |
|
204 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
230 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
231 |
sys.exc_info()[-1].tb_lineno) |
|
205 | 232 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
206 | 233 |
finally: |
207 |
return items,tracer_line_nos |
|
234 |
return items, tracer_line_nos
|
|
208 | 235 |
|
209 | 236 |
def export(self, path): |
210 | 237 |
""" save items of drawing to given xml file """ |
211 | 238 |
import XmlGenerator as xg |
212 | 239 |
|
213 |
items,tracer_line_nos = self.from_database() |
|
240 |
items, tracer_line_nos = self.from_database()
|
|
214 | 241 |
xg.writeXmlOnScene(path, self.width, self.height, items, tracer_line_nos) |
215 | 242 |
|
216 | 243 |
def transfer(self, database): |
... | ... | |
226 | 253 |
cursor.execute(sql, (self.name,)) |
227 | 254 |
sql = database.to_sql('delete from INSTRUMENT_DATA_LIST where PNID_NO=?') |
228 | 255 |
cursor.execute(sql, (self.name,)) |
229 |
sql = database.to_sql('delete from TitleBlockValues where Drawings_UID=(select UID from Drawings where [Name]=?)') |
|
256 |
sql = database.to_sql( |
|
257 |
'delete from TitleBlockValues where Drawings_UID=(select UID from Drawings where [Name]=?)') |
|
230 | 258 |
cursor.execute(sql, (self.name,)) |
231 |
sql = database.to_sql('delete from LineNoAttributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
259 |
sql = database.to_sql( |
|
260 |
'delete from LineNoAttributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
232 | 261 |
cursor.execute(sql, (self.name,)) |
233 |
sql = database.to_sql('delete from Attributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
262 |
sql = database.to_sql( |
|
263 |
'delete from Attributes where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
234 | 264 |
cursor.execute(sql, (self.name,)) |
235 |
sql = database.to_sql('delete from Associations where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
265 |
sql = database.to_sql( |
|
266 |
'delete from Associations where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
236 | 267 |
cursor.execute(sql, (self.name,)) |
237 |
sql = database.to_sql('delete from Points where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
268 |
sql = database.to_sql( |
|
269 |
'delete from Points where Components_UID in (select UID from Components where Drawings_UID=(select UID from Drawings where Name=?))') |
|
238 | 270 |
cursor.execute(sql, (self.name,)) |
239 |
sql = database.to_sql('delete from PipeRunItems where PipeRuns_UID in (select UID from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?))') |
|
271 |
sql = database.to_sql( |
|
272 |
'delete from PipeRunItems where PipeRuns_UID in (select UID from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?))') |
|
240 | 273 |
cursor.execute(sql, (self.name,)) |
241 | 274 |
sql = database.to_sql('delete from PipeRuns where Drawings_UID=(select UID from Drawings where Name=?)') |
242 | 275 |
cursor.execute(sql, (self.name,)) |
243 |
sql = database.to_sql('delete from Components where Drawings_UID=(select UID from Drawings where Name=?)') |
|
276 |
sql = database.to_sql( |
|
277 |
'delete from Components where Drawings_UID=(select UID from Drawings where Name=?)') |
|
244 | 278 |
cursor.execute(sql, (self.name,)) |
245 | 279 |
sql = database.to_sql('delete from Drawings where Name=?') |
246 | 280 |
cursor.execute(sql, (self.name,)) |
... | ... | |
252 | 286 |
for component in components: |
253 | 287 |
sql = database.to_sql('insert into Components(UID,Drawings_UID,Symbol_UID,X,Y,Width,Height,Rotation,Area,Value,Owner,[From],[To],Connected,[Supplied By],SpecialItemTypes_UID, OriginIndex) \ |
254 | 288 |
values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)') |
255 |
cursor.execute(sql, (component['UID'], component['Drawings_UID'], component['Symbol_UID'], |
|
256 |
component['X'], component['Y'], component['Width'], component['Height'], component['Rotation'], component['Area'], |
|
257 |
component['Value'], component['Owner'], component['From'], component['To'], component['Connected'], |
|
258 |
component['Supplied By'], component['SpecialItemTypes_UID'], component['OriginIndex'])) |
|
289 |
cursor.execute(sql, (component['UID'], component['Drawings_UID'], component['Symbol_UID'], |
|
290 |
component['X'], component['Y'], component['Width'], component['Height'], |
|
291 |
component['Rotation'], component['Area'], |
|
292 |
component['Value'], component['Owner'], component['From'], component['To'], |
|
293 |
component['Connected'], |
|
294 |
component['Supplied By'], component['SpecialItemTypes_UID'], |
|
295 |
component['OriginIndex'])) |
|
259 | 296 |
|
260 | 297 |
for component in components: |
261 | 298 |
pipe_runs = app_doc_data.get_pipe_runs(component['UID']) |
262 | 299 |
for pipe_run in pipe_runs: |
263 |
sql = database.to_sql('insert into PipeRuns(UID,Drawings_UID,Type,Owner,[Index]) values(?,?,?,?,?)') |
|
300 |
sql = database.to_sql( |
|
301 |
'insert into PipeRuns(UID,Drawings_UID,Type,Owner,[Index]) values(?,?,?,?,?)') |
|
264 | 302 |
cursor.execute(sql, (pipe_run[0], pipe_run[1], pipe_run[2], pipe_run[3], pipe_run[4])) |
265 | 303 |
pipe_run_items = app_doc_data.get_pipe_run_items(pipe_run[0]) |
266 | 304 |
for pipe_run_item in pipe_run_items: |
267 |
sql = database.to_sql('insert into PipeRunItems(UID,PipeRuns_UID,[Index],Components_UID) values(?,?,?,?)') |
|
268 |
cursor.execute(sql, (pipe_run_item[0], pipe_run_item[1], pipe_run_item[2], pipe_run_item[3])) |
|
305 |
sql = database.to_sql( |
|
306 |
'insert into PipeRunItems(UID,PipeRuns_UID,[Index],Components_UID) values(?,?,?,?)') |
|
307 |
cursor.execute(sql, |
|
308 |
(pipe_run_item[0], pipe_run_item[1], pipe_run_item[2], pipe_run_item[3])) |
|
269 | 309 |
|
270 | 310 |
connectors = app_doc_data.get_component_connectors(component['UID']) |
271 | 311 |
for connector in connectors: |
272 |
sql = database.to_sql('insert into Points(Components_UID,[Index],X,Y,Connected,Connected_At) values(?,?,?,?,?,?)') |
|
273 |
cursor.execute(sql, (connector['Components_UID'], connector['Index'], connector['X'], connector['Y'], connector['Connected'], connector['Connected_At'])) |
|
312 |
sql = database.to_sql( |
|
313 |
'insert into Points(Components_UID,[Index],X,Y,Connected,Connected_At) values(?,?,?,?,?,?)') |
|
314 |
cursor.execute(sql, ( |
|
315 |
connector['Components_UID'], connector['Index'], connector['X'], connector['Y'], |
|
316 |
connector['Connected'], connector['Connected_At'])) |
|
274 | 317 |
|
275 | 318 |
associations = app_doc_data.get_component_associations(component['UID']) |
276 | 319 |
for assoc in associations: |
277 |
sql = database.to_sql('insert into Associations(UID,[Type],Components_UID,Association) values(?,?,?,?)') |
|
278 |
cursor.execute(sql, (assoc['UID'], assoc['Type'], assoc['Components_UID'], assoc['Association'])) |
|
320 |
sql = database.to_sql( |
|
321 |
'insert into Associations(UID,[Type],Components_UID,Association) values(?,?,?,?)') |
|
322 |
cursor.execute(sql, |
|
323 |
(assoc['UID'], assoc['Type'], assoc['Components_UID'], assoc['Association'])) |
|
279 | 324 |
|
280 | 325 |
attributes = app_doc_data.get_component_attributes(component['UID']) |
281 | 326 |
for attr in attributes: |
282 |
sql = database.to_sql('insert into Attributes(UID,Components_UID,SymbolAttribute_UID,Value) values(?,?,?,?)') |
|
283 |
cursor.execute(sql, (attr['UID'], attr['Components_UID'], attr['SymbolAttribute_UID'], attr['Value'])) |
|
327 |
sql = database.to_sql( |
|
328 |
'insert into Attributes(UID,Components_UID,SymbolAttribute_UID,Value) values(?,?,?,?)') |
|
329 |
cursor.execute(sql, ( |
|
330 |
attr['UID'], attr['Components_UID'], attr['SymbolAttribute_UID'], attr['Value'])) |
|
284 | 331 |
|
285 | 332 |
conn.commit() |
286 | 333 |
# Catch the exception |
... | ... | |
290 | 337 |
|
291 | 338 |
print(sql) |
292 | 339 |
from App import App |
293 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
294 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
340 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
341 |
sys.exc_info()[-1].tb_lineno) |
|
342 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
91 | 91 |
''' |
92 | 92 |
|
93 | 93 |
def __init__(self): |
94 |
from App import App |
|
94 | 95 |
from LineTypeConditions import LineTypeConditions |
95 | 96 |
|
96 | 97 |
super(self.__class__, self).__init__() |
... | ... | |
120 | 121 |
_translate = QCoreApplication.translate |
121 | 122 |
version = QCoreApplication.applicationVersion() |
122 | 123 |
# set title |
123 |
self.setWindowTitle(_translate("Digital P&ID({}) - {}".format(version, project.name),
|
|
124 |
"Digital P&ID({}) - {}".format(version, project.name)))
|
|
124 |
self.setWindowTitle(_translate(f"{App.NAME}({version}) - {project.name}",
|
|
125 |
f"{App.NAME}({version}) - {project.name}"))
|
|
125 | 126 |
|
126 | 127 |
self.lineComboBox = QComboBox(self.toolBar) |
127 | 128 |
for condition in LineTypeConditions.items(): |
... | ... | |
318 | 319 |
self.tableWidgetInconsistency.setSortingEnabled(True) |
319 | 320 |
|
320 | 321 |
def eventFilter(self, source, event): |
321 |
""" |
|
322 |
display mouse position of graphics view |
|
323 |
""" |
|
322 |
"""display mouse position of graphics view""" |
|
324 | 323 |
if (event.type() == QEvent.MouseMove): |
325 | 324 |
pos = self.graphicsView.mapToScene(event.pos()) |
326 | 325 |
self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y()))) |
... | ... | |
328 | 327 |
return QWidget.eventFilter(self, source, event) |
329 | 328 |
|
330 | 329 |
def closeEvent(self, event): |
331 |
""" close main window """ |
|
330 |
"""ask user to save drawing which is modified""" |
|
331 |
|
|
332 |
self.save_drawing_if_necessary() |
|
332 | 333 |
AppDocData.instance().clear() |
334 |
event.accept() |
|
333 | 335 |
|
334 | 336 |
def inconsistencyTableKeyPressEvent(self, event): |
335 | 337 |
try: |
... | ... | |
654 | 656 |
sys.exc_info()[-1].tb_lineno) |
655 | 657 |
self.addMessage.emit(MessageType.Error, message) |
656 | 658 |
|
659 |
def save_drawing_if_necessary(self): |
|
660 |
"""ask to user to save drawing or not when drawing is modified""" |
|
661 |
|
|
662 |
app_doc_data = AppDocData.instance() |
|
663 |
if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified: |
|
664 |
if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"), |
|
665 |
self.tr("Do you want to save drawing?"), |
|
666 |
QMessageBox.Yes | QMessageBox.No): |
|
667 |
self.actionSaveCliked() |
|
668 |
|
|
657 | 669 |
''' |
658 | 670 |
@brief action save click event |
659 | 671 |
@author kyouho |
... | ... | |
666 | 678 |
''' |
667 | 679 |
|
668 | 680 |
def actionSaveCliked(self): |
669 |
from datetime import datetime |
|
670 | 681 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
671 | 682 |
from SaveWorkCommand import SaveWorkCommand |
672 | 683 |
|
673 | 684 |
try: |
674 |
appDocData = AppDocData.instance()
|
|
675 |
if appDocData.imgName is None:
|
|
685 |
app_doc_data = AppDocData.instance()
|
|
686 |
if app_doc_data.imgName is None:
|
|
676 | 687 |
self.showImageSelectionMessageBox() |
677 | 688 |
return |
678 | 689 |
|
679 |
appDocData.clearItemList(False)
|
|
690 |
app_doc_data.clearItemList(False)
|
|
680 | 691 |
|
681 | 692 |
items = self.graphicsView.scene.items() |
682 | 693 |
for item in items: |
683 | 694 |
if issubclass(type(item), QEngineeringAbstractItem): |
684 |
appDocData.allItems.append(item)
|
|
695 |
app_doc_data.allItems.append(item)
|
|
685 | 696 |
if issubclass(type(item), QEngineeringTextItem): |
686 |
appDocData.texts.append(item)
|
|
697 |
app_doc_data.texts.append(item)
|
|
687 | 698 |
|
688 | 699 |
itemTypes = [] |
689 | 700 |
for item in items: |
... | ... | |
701 | 712 |
self._save_work_cmd.finished.connect(self.save_finished) |
702 | 713 |
|
703 | 714 |
self._save_work_cmd.start() |
704 |
|
|
705 | 715 |
except Exception as ex: |
706 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
|
716 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
|
|
707 | 717 |
sys.exc_info()[-1].tb_lineno) |
708 | 718 |
self.addMessage.emit(MessageType.Error, message) |
709 | 719 |
|
710 | 720 |
def save_finished(self): |
711 | 721 |
"""reload drawing list""" |
722 |
|
|
712 | 723 |
self._save_work_cmd.show_progress.emit(100) |
713 | 724 |
QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr) |
714 | 725 |
self.load_drawing_list() |
715 | 726 |
|
727 |
app_doc_data = AppDocData.instance() |
|
728 |
app_doc_data.activeDrawing.modified = False |
|
729 |
title = self.windowTitle() |
|
730 |
self.setWindowTitle(title[:-1] if title[-1] == '*' else title) |
|
731 |
|
|
716 | 732 |
''' |
717 | 733 |
@brief refresh resultPropertyTableWidget |
718 | 734 |
@author kyouho |
... | ... | |
832 | 848 |
self.graphicsView.useDefaultCommand() |
833 | 849 |
self.graphicsView.zoomImageInit() |
834 | 850 |
|
851 |
def scene_changed(self): |
|
852 |
"""update modified flag""" |
|
853 |
|
|
854 |
app_doc_data = AppDocData.instance() |
|
855 |
app_doc_data.activeDrawing.modified = True |
|
856 |
title = self.windowTitle() |
|
857 |
self.setWindowTitle(title if title[-1] == '*' else title + '*') |
|
858 |
|
|
835 | 859 |
def onConvertPDFToImage(self): |
836 | 860 |
""" |
837 | 861 |
@brief convert to selected pdf to image |
... | ... | |
1251 | 1275 |
|
1252 | 1276 |
def onOpenImageDrawing(self, path=None): |
1253 | 1277 |
from Drawing import Drawing |
1254 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
|
1255 | 1278 |
|
1256 | 1279 |
try: |
1280 |
self.save_drawing_if_necessary() |
|
1281 |
if hasattr(self, '_save_work_cmd'): |
|
1282 |
self._save_work_cmd.wait() |
|
1283 |
|
|
1257 | 1284 |
app_doc_data = AppDocData.instance() |
1285 |
|
|
1258 | 1286 |
project = app_doc_data.getCurrentProject() |
1259 | 1287 |
|
1260 | 1288 |
self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), |
... | ... | |
1283 | 1311 |
|
1284 | 1312 |
try: |
1285 | 1313 |
self.show_Progress_bar() |
1314 |
|
|
1315 |
# disconnect scene changed if signal is connected |
|
1316 |
if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0: |
|
1317 |
self.graphicsView.scene.contents_changed.disconnect() |
|
1318 |
|
|
1286 | 1319 |
# Load data |
1287 | 1320 |
path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml') |
1288 | 1321 |
configs = app_doc_data.getConfigs('Data Load', 'Xml First') |
... | ... | |
1290 | 1323 |
self.loadRecognitionResultFromXml(path) |
1291 | 1324 |
else: |
1292 | 1325 |
self.load_drawing(app_doc_data.activeDrawing) |
1326 |
|
|
1327 |
# connect scene changed signal |
|
1328 |
self.graphicsView.scene.contents_changed.connect(self.scene_changed) |
|
1293 | 1329 |
finally: |
1294 | 1330 |
if hasattr(self, 'progress'): |
1295 | 1331 |
self.progress.setValue(self.progress.maximum()) |
DTI_PID/DTI_PID/Shapes/EngineeringLineItem.py | ||
---|---|---|
11 | 11 |
except ImportError: |
12 | 12 |
try: |
13 | 13 |
from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
14 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QGraphicsLineItem |
|
14 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, \ |
|
15 |
QGraphicsLineItem |
|
15 | 16 |
except ImportError: |
16 | 17 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
17 | 18 |
|
... | ... | |
19 | 20 |
import shapely |
20 | 21 |
from LineTypeConditions import LineTypeConditions |
21 | 22 |
|
23 |
|
|
22 | 24 |
class QEngineeringLineItem(QGraphicsLineItem, QEngineeringAbstractItem): |
23 | 25 |
""" This is engineering line item """ |
24 | 26 |
|
... | ... | |
32 | 34 |
2018.05.15 Jeongwoo Change method to call parent's __init__ |
33 | 35 |
humkyung 2018.06.21 add vertices to parameter |
34 | 36 |
''' |
37 |
|
|
35 | 38 |
def __init__(self, vertices=[], thickness=None, parent=None, uid=None): |
36 | 39 |
import uuid |
37 | 40 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
... | ... | |
45 | 48 |
self.uid = uuid.uuid4() if uid is None else uuid.UUID(uid) |
46 | 49 |
self.thickness = thickness |
47 | 50 |
|
48 |
self.setPen(QPen(Qt.blue, 4, Qt.SolidLine)) # set default pen |
|
49 |
self.isCreated = True
|
|
51 |
self.setPen(QPen(Qt.blue, 4, Qt.SolidLine)) # set default pen
|
|
52 |
self.isCreated = True |
|
50 | 53 |
|
51 | 54 |
self._owner = None |
52 | 55 |
self._flowMark = None |
53 | 56 |
configs = AppDocData.instance().getConfigs('Line', 'Default Type') |
54 | 57 |
self._lineType = None |
55 |
self.lineType = configs[0].value if 1 == len(configs) else 'Secondary' # defulat line type is 'Secondary' |
|
58 |
self.lineType = configs[0].value if 1 == len(configs) else 'Secondary' # defulat line type is 'Secondary'
|
|
56 | 59 |
|
57 | 60 |
self._properties = \ |
58 |
{\ |
|
59 |
SymbolProp(None, 'Size', 'Size Text Item', Expression='self.EvaluatedSize'):None,\
|
|
60 |
SymbolProp(None, 'Flow Mark', 'Size Text Item', Expression='self.EvaluatedSize'):None |
|
61 |
{ \
|
|
62 |
SymbolProp(None, 'Size', 'Size Text Item', Expression='self.EvaluatedSize'): None, \
|
|
63 |
SymbolProp(None, 'Flow Mark', 'Size Text Item', Expression='self.EvaluatedSize'): None
|
|
61 | 64 |
} |
62 | 65 |
|
63 |
self.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable)
|
|
66 |
self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
|
|
64 | 67 |
|
65 | 68 |
self.setAcceptHoverEvents(True) |
66 | 69 |
self.setAcceptTouchEvents(True) |
... | ... | |
70 | 73 |
|
71 | 74 |
if vertices: |
72 | 75 |
self.setLine(vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]) |
73 |
|
|
76 |
|
|
74 | 77 |
index = 0 |
75 | 78 |
for vertex in vertices: |
76 |
connector = QEngineeringConnectorItem(parent=self, index=index+1)
|
|
79 |
connector = QEngineeringConnectorItem(parent=self, index=index + 1)
|
|
77 | 80 |
connector.setPos(vertex) |
78 | 81 |
connector.setParentItem(self) |
79 | 82 |
# connector의 connectPoint, sceneConnectPoint를 vertex로 함 추후 좀 알아봐서 수정 필요 |
... | ... | |
81 | 84 |
connector.sceneConnectPoint = vertex |
82 | 85 |
|
83 | 86 |
# add connector move able |
84 |
connector.setFlags(QGraphicsItem.ItemIsSelectable|QGraphicsItem.ItemIsFocusable)
|
|
87 |
connector.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsFocusable)
|
|
85 | 88 |
connector.setAcceptTouchEvents(True) |
86 | 89 |
connector.transfer.onPosChanged.connect(self.onConnectorPosChaned) |
87 | 90 |
|
... | ... | |
90 | 93 |
index = index + 1 |
91 | 94 |
|
92 | 95 |
self.update_arrow() |
93 |
|
|
94 |
tooltip = '<b>{}</b><br>({},{})-({},{})'.format(str(self.uid), vertices[0][0], vertices[0][1], vertices[1][0], vertices[1][1]) |
|
96 |
|
|
97 |
tooltip = '<b>{}</b><br>({},{})-({},{})'.format(str(self.uid), vertices[0][0], vertices[0][1], |
|
98 |
vertices[1][0], vertices[1][1]) |
|
95 | 99 |
self.setToolTip(tooltip) |
96 | 100 |
except Exception as ex: |
97 | 101 |
from App import App |
98 | 102 |
from AppDocData import MessageType |
99 | 103 |
|
100 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
104 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
105 |
sys.exc_info()[-1].tb_lineno) |
|
101 | 106 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
102 | 107 |
|
103 | 108 |
def __str__(self): |
... | ... | |
109 | 114 |
""" getter of flow mark """ |
110 | 115 |
import uuid |
111 | 116 |
|
112 |
for prop,value in self._properties.items(): |
|
117 |
for prop, value in self._properties.items():
|
|
113 | 118 |
if prop.is_selectable and type(value) is uuid.UUID and self.scene(): |
114 | 119 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)] |
115 | 120 |
if matches: self._properties[prop] = matches[0] |
116 |
|
|
121 |
|
|
117 | 122 |
if prop.Expression: self._properties[prop] = eval(prop.Expression) |
118 |
|
|
123 |
|
|
119 | 124 |
return self._properties |
120 | 125 |
|
121 | 126 |
def set_property(self, property, value): |
122 | 127 |
""" set property with given value """ |
123 | 128 |
if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0) |
124 |
matches = [prop for prop,_ in self._properties.items() if prop.Attribute == property] |
|
129 |
matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
|
|
125 | 130 |
if matches: self._properties[matches[0]] = value |
126 | 131 |
|
127 | 132 |
def prop(self, name): |
128 | 133 |
""" return the value of given property with name """ |
129 |
matches = [(prop,value) for prop,value in self.properties.items() if prop.Attribute == name]
|
|
134 |
matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name]
|
|
130 | 135 |
if matches: return matches[0][1] |
131 | 136 |
|
132 | 137 |
return None |
... | ... | |
135 | 140 |
def Size(self): |
136 | 141 |
""" always return None """ |
137 | 142 |
return None |
138 |
|
|
143 |
|
|
139 | 144 |
@property |
140 | 145 |
def EvaluatedSize(self): |
141 | 146 |
from EngineeringReducerItem import QEngineeringReducerItem |
... | ... | |
147 | 152 |
at = matches[0].items.index(self) |
148 | 153 |
upstream = matches[0].items[:at] |
149 | 154 |
upstream.reverse() |
150 |
prev = self
|
|
155 |
prev = self |
|
151 | 156 |
for item in upstream: |
152 | 157 |
if type(item) is QEngineeringReducerItem: |
153 |
if item.connectors[0].connectedItem is prev: ### Main Size
|
|
158 |
if item.connectors[0].connectedItem is prev: ### Main Size |
|
154 | 159 |
if item.MainSubSize: return item.MainSubSize[0] |
155 | 160 |
elif item.connectors[1].connectedItem is prev: ### Sub Size |
156 | 161 |
if item.MainSubSize: return item.MainSubSize[1] |
... | ... | |
162 | 167 |
prev = self |
163 | 168 |
for item in downstream: |
164 | 169 |
if type(item) is QEngineeringReducerItem: |
165 |
if item.connectors[0].connectedItem is prev: ### Main Size
|
|
170 |
if item.connectors[0].connectedItem is prev: ### Main Size |
|
166 | 171 |
if item.MainSubSize: return item.MainSubSize[0] |
167 | 172 |
elif item.connectors[1].connectedItem is prev: ### Sub Size |
168 | 173 |
if item.MainSubSize: return item.MainSubSize[1] |
... | ... | |
173 | 178 |
if 'Drain' == matches[0].Type: |
174 | 179 |
from AppDocData import AppDocData |
175 | 180 |
return AppDocData.instance().drain_size |
176 |
|
|
181 |
|
|
177 | 182 |
return self.owner.Size |
178 | 183 |
|
179 | 184 |
return None |
... | ... | |
183 | 188 |
@author humkyung |
184 | 189 |
@date 2018.05.10 |
185 | 190 |
''' |
191 |
|
|
186 | 192 |
@property |
187 | 193 |
def owner(self): |
188 | 194 |
import uuid |
... | ... | |
190 | 196 |
if self._owner and type(self._owner) is uuid.UUID: |
191 | 197 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self._owner)] |
192 | 198 |
if matches: self._owner = matches[0] |
193 |
|
|
199 |
|
|
194 | 200 |
if type(self._owner) is not uuid.UUID and type(self._owner) is not str: |
195 | 201 |
return self._owner |
196 | 202 |
else: |
... | ... | |
203 | 209 |
@date 2018.05.10 |
204 | 210 |
@history 2018.05.17 Jeongwoo Add Calling setColor |
205 | 211 |
''' |
212 |
|
|
206 | 213 |
@owner.setter |
207 | 214 |
def owner(self, value): |
208 | 215 |
self._owner = value |
... | ... | |
216 | 223 |
@author humkyung |
217 | 224 |
@date 2018.06.21 |
218 | 225 |
''' |
226 |
|
|
219 | 227 |
@property |
220 | 228 |
def flowMark(self): |
221 | 229 |
return self._flowMark |
... | ... | |
225 | 233 |
@author humkyung |
226 | 234 |
@date 2018.06.21 |
227 | 235 |
''' |
236 |
|
|
228 | 237 |
@flowMark.setter |
229 | 238 |
def flowMark(self, value): |
230 | 239 |
self._flowMark = value |
... | ... | |
234 | 243 |
@author humkyung |
235 | 244 |
@date 2018.06.27 |
236 | 245 |
''' |
246 |
|
|
237 | 247 |
@property |
238 | 248 |
def lineType(self): |
239 | 249 |
return self._lineType |
240 |
|
|
250 |
|
|
241 | 251 |
''' |
242 | 252 |
@brief setter of lineType |
243 | 253 |
@author humkyung |
244 | 254 |
@date 2018.06.27 |
245 | 255 |
''' |
256 |
|
|
246 | 257 |
@lineType.setter |
247 | 258 |
def lineType(self, value): |
248 | 259 |
from AppDocData import AppDocData |
... | ... | |
252 | 263 |
docData = AppDocData.instance() |
253 | 264 |
configs = docData.getLineTypeConfig(self._lineType) |
254 | 265 |
if configs: |
255 |
_pen = self.pen()
|
|
266 |
_pen = self.pen() |
|
256 | 267 |
_pen.setWidth(configs[2]) |
257 | 268 |
_pen.setStyle(configs[3]) |
258 | 269 |
self.setPen(_pen) |
... | ... | |
265 | 276 |
''' |
266 | 277 |
@brief clone an object |
267 | 278 |
''' |
279 |
|
|
268 | 280 |
def clone(self): |
269 | 281 |
clone = QEngineeringLineItem() |
270 |
#clone._vertices = copy.deepcopy(self._vertices) |
|
271 |
#for vertex in clone._vertices: |
|
282 |
# clone._vertices = copy.deepcopy(self._vertices)
|
|
283 |
# for vertex in clone._vertices:
|
|
272 | 284 |
# clone._pol.append(QPointF(vertex[0], vertex[1])) |
273 | 285 |
clone.buildItem() |
274 | 286 |
clone.isCreated = self.isCreated |
... | ... | |
287 | 299 |
@author humkyung |
288 | 300 |
@date 2018.04.16 |
289 | 301 |
''' |
302 |
|
|
290 | 303 |
def startPoint(self): |
291 | 304 |
at = self.line().p1() |
292 | 305 |
return (at.x(), at.y()) |
... | ... | |
296 | 309 |
@author humkyung |
297 | 310 |
@date 2018.04.16 |
298 | 311 |
''' |
312 |
|
|
299 | 313 |
def endPoint(self): |
300 | 314 |
at = self.line().p2() |
301 | 315 |
return (at.x(), at.y()) |
... | ... | |
305 | 319 |
@author humkyung |
306 | 320 |
@date 2018.04.14 |
307 | 321 |
''' |
322 |
|
|
308 | 323 |
def dotProduct(self, lhs, rhs): |
309 |
return sum([lhs[i]*rhs[i] for i in range(len(lhs))])
|
|
324 |
return sum([lhs[i] * rhs[i] for i in range(len(lhs))])
|
|
310 | 325 |
|
311 | 326 |
''' |
312 | 327 |
@brief distance between line and point |
313 | 328 |
@author humkyung |
314 | 329 |
@date 2018.04.16 |
315 | 330 |
''' |
331 |
|
|
316 | 332 |
def distanceTo(self, pt): |
317 | 333 |
from shapely.geometry import Point, LineString |
318 | 334 |
|
... | ... | |
328 | 344 |
@author humkyung |
329 | 345 |
@date 2018.04.21 |
330 | 346 |
''' |
347 |
|
|
331 | 348 |
def perpendicular(self): |
332 | 349 |
import math |
333 | 350 |
|
334 | 351 |
dx = self.endPoint()[0] - self.startPoint()[0] |
335 | 352 |
dy = self.endPoint()[1] - self.startPoint()[1] |
336 |
dx,dy = -dy,dx
|
|
337 |
length = math.sqrt(dx*dx + dy*dy)
|
|
353 |
dx, dy = -dy, dx
|
|
354 |
length = math.sqrt(dx * dx + dy * dy)
|
|
338 | 355 |
dx /= length |
339 | 356 |
dy /= length |
340 | 357 |
|
341 |
return (dx,dy) |
|
358 |
return (dx, dy)
|
|
342 | 359 |
|
343 | 360 |
''' |
344 | 361 |
@brief return angle of line in radian |
345 | 362 |
@author humkyung |
346 | 363 |
@date 2018.04.22 |
347 | 364 |
''' |
365 |
|
|
348 | 366 |
def angle(self): |
349 | 367 |
import math |
350 | 368 |
|
... | ... | |
352 | 370 |
endPt = self.endPoint() |
353 | 371 |
dx = endPt[0] - startPt[0] |
354 | 372 |
dy = endPt[1] - startPt[1] |
355 |
dot = self.dotProduct((1,0), (dx, dy)) |
|
356 |
length = math.sqrt(dx*dx + dy*dy)
|
|
357 |
return math.acos(dot/length)
|
|
373 |
dot = self.dotProduct((1, 0), (dx, dy))
|
|
374 |
length = math.sqrt(dx * dx + dy * dy)
|
|
375 |
return math.acos(dot / length)
|
|
358 | 376 |
|
359 | 377 |
''' |
360 | 378 |
@brief return length of line |
361 | 379 |
@author humkyung |
362 | 380 |
@date 2018.05.08 |
363 | 381 |
''' |
382 |
|
|
364 | 383 |
def length(self): |
365 | 384 |
import math |
366 | 385 |
|
... | ... | |
368 | 387 |
endPt = self.endPoint() |
369 | 388 |
dx = endPt[0] - startPt[0] |
370 | 389 |
dy = endPt[1] - startPt[1] |
371 |
return math.sqrt(dx*dx + dy*dy)
|
|
390 |
return math.sqrt(dx * dx + dy * dy)
|
|
372 | 391 |
|
373 | 392 |
''' |
374 | 393 |
@brief check if line is horizontal |
375 | 394 |
@author humkyung |
376 | 395 |
@date 2018.04.27 |
377 | 396 |
''' |
397 |
|
|
378 | 398 |
def isHorizontal(self): |
379 | 399 |
import math |
380 | 400 |
|
... | ... | |
390 | 410 |
@author humkyung |
391 | 411 |
@date 2018.04.27 |
392 | 412 |
''' |
413 |
|
|
393 | 414 |
def isVertical(self): |
394 | 415 |
import math |
395 | 416 |
|
... | ... | |
407 | 428 |
@history Jeongwoo 2018.05.15 Add normalize |
408 | 429 |
Jeongwoo 2018.05.16 Add length == 0 check |
409 | 430 |
''' |
431 |
|
|
410 | 432 |
def intersection(self, line): |
411 | 433 |
import math |
412 | 434 |
from shapely.geometry import Point, LineString |
... | ... | |
415 | 437 |
endPt = self.endPoint() |
416 | 438 |
dx = endPt[0] - startPt[0] |
417 | 439 |
dy = endPt[1] - startPt[1] |
418 |
length = math.sqrt(dx*dx + dy*dy)
|
|
440 |
length = math.sqrt(dx * dx + dy * dy)
|
|
419 | 441 |
if length == 0: |
420 | 442 |
return None |
421 | 443 |
dx /= length |
422 | 444 |
dy /= length |
423 |
lhs = LineString([(startPt[0] - dx*20, startPt[1] - dy*20), (endPt[0] + dx*20, endPt[1] + dy*20)])
|
|
445 |
lhs = LineString([(startPt[0] - dx * 20, startPt[1] - dy * 20), (endPt[0] + dx * 20, endPt[1] + dy * 20)])
|
|
424 | 446 |
rhs = LineString(line) |
425 | 447 |
return lhs.intersection(rhs) |
426 | 448 |
|
... | ... | |
438 | 460 |
import math |
439 | 461 |
|
440 | 462 |
try: |
441 |
vectors = [(self.endPoint()[0]-self.startPoint()[0], self.endPoint()[1]-self.startPoint()[1]), (rhs.endPoint()[0]-rhs.startPoint()[0], rhs.endPoint()[1]-rhs.startPoint()[1])] |
|
463 |
vectors = [(self.endPoint()[0] - self.startPoint()[0], self.endPoint()[1] - self.startPoint()[1]), |
|
464 |
(rhs.endPoint()[0] - rhs.startPoint()[0], rhs.endPoint()[1] - rhs.startPoint()[1])] |
|
442 | 465 |
angle = self.getAngle(rhs) |
443 | 466 |
if (angle == 0) or (angle == math.pi): return True |
444 | 467 |
except ZeroDivisionError: |
... | ... | |
453 | 476 |
@history Jeongwoo 18.05.15 Add check pt's type |
454 | 477 |
Jeongwoo 18.05.16 Add length == 0 check |
455 | 478 |
''' |
479 |
|
|
456 | 480 |
def is_connectable(self, line, toler=20): |
457 | 481 |
import math |
458 | 482 |
|
... | ... | |
461 | 485 |
|
462 | 486 |
dx = endPt[0] - startPt[0] |
463 | 487 |
dy = endPt[1] - startPt[1] |
464 |
length = math.sqrt(dx*dx + dy*dy)
|
|
488 |
length = math.sqrt(dx * dx + dy * dy)
|
|
465 | 489 |
if length == 0: |
466 | 490 |
return False |
467 | 491 |
dx /= length |
468 | 492 |
dy /= length |
469 |
extendedLine = [(startPt[0] - dx*toler, startPt[1] - dy*toler), (endPt[0] + dx*toler, endPt[1] + dy*toler)] |
|
493 |
extendedLine = [(startPt[0] - dx * toler, startPt[1] - dy * toler), |
|
494 |
(endPt[0] + dx * toler, endPt[1] + dy * toler)] |
|
470 | 495 |
pt = self.intersection(extendedLine) |
471 | 496 |
|
472 | 497 |
return (pt is not None) and (type(pt) == shapely.geometry.point.Point) |
... | ... | |
476 | 501 |
@date 2018.06.26 |
477 | 502 |
@history humkyung 2018.07.03 allow item to be line or symbol |
478 | 503 |
''' |
504 |
|
|
479 | 505 |
def is_connected(self, item, at=QEngineeringAbstractItem.CONNECTED_AT_PT): |
480 | 506 |
""" check if given item is connected to self """ |
481 | 507 |
|
482 |
_connectors = [connector for connector in self.connectors if (connector.connectedItem == item and connector._connected_at == at)] |
|
508 |
_connectors = [connector for connector in self.connectors if |
|
509 |
(connector.connectedItem == item and connector._connected_at == at)] |
|
483 | 510 |
return len(_connectors) > 0 |
484 | 511 |
|
485 | 512 |
''' |
... | ... | |
487 | 514 |
@author kyouho |
488 | 515 |
@date 2018.07.25 |
489 | 516 |
''' |
490 |
def joinTo(self, item = None): |
|
517 |
|
|
518 |
def joinTo(self, item=None): |
|
491 | 519 |
import math |
492 | 520 |
from SymbolSvgItem import SymbolSvgItem |
493 | 521 |
|
... | ... | |
503 | 531 |
for i in range(len(pts)): |
504 | 532 |
dx = pts[i][0] - selected[0] |
505 | 533 |
dy = pts[i][1] - selected[1] |
506 |
if math.sqrt(dx*dx + dy*dy) < 10: |
|
507 |
line = QLineF(QPointF(pts[i][0], pts[i][1]), QPointF(endPoint[0], endPoint[1])) if self._selectedIndex == 0 else QLineF(QPointF(startPoint[0], startPoint[1]), QPointF(pts[i][0], pts[i][1])) |
|
534 |
if math.sqrt(dx * dx + dy * dy) < 10: |
|
535 |
line = QLineF(QPointF(pts[i][0], pts[i][1]), |
|
536 |
QPointF(endPoint[0], endPoint[1])) if self._selectedIndex == 0 else QLineF( |
|
537 |
QPointF(startPoint[0], startPoint[1]), QPointF(pts[i][0], pts[i][1])) |
|
508 | 538 |
self.setLine(line) |
509 | 539 |
self.update() |
510 | 540 |
break |
... | ... | |
525 | 555 |
elif endPoint[0] == connector2Point[0] and endPoint[1] == connector2Point[1]: |
526 | 556 |
self.connectors[1].connectedItem = item |
527 | 557 |
|
528 |
|
|
529 | 558 |
''' |
530 | 559 |
@brief arrange vertex order |
531 | 560 |
@author humkyung |
532 | 561 |
@date 2018.07.04 |
533 | 562 |
''' |
563 |
|
|
534 | 564 |
def arrangeVertexOrder(self, arranged): |
535 | 565 |
import math |
536 | 566 |
|
... | ... | |
545 | 575 |
index += 1 |
546 | 576 |
dx = _pt[0] - pt[0] |
547 | 577 |
dy = _pt[1] - pt[1] |
548 |
dist = math.sqrt(dx*dx + dy*dy)
|
|
578 |
dist = math.sqrt(dx * dx + dy * dy)
|
|
549 | 579 |
if minDist is None or dist < minDist: |
550 | 580 |
minDist = dist |
551 | 581 |
indexed = index |
552 |
|
|
582 |
|
|
553 | 583 |
if indexed == 1 or indexed == 4: |
554 | 584 |
self.reverse() |
555 | 585 |
|
... | ... | |
559 | 589 |
@date 2018.06.25 |
560 | 590 |
@history humkyung 2018.06.27 check line type |
561 | 591 |
''' |
592 |
|
|
562 | 593 |
def isExtendable(self, line, toler=5): |
563 | 594 |
import math |
564 | 595 |
from SymbolSvgItem import SymbolSvgItem |
565 | 596 |
|
566 | 597 |
if self.lineType == line.lineType: |
567 | 598 |
if self.isHorizontal() and line.isHorizontal(): |
568 |
flag = (line.connectors[0].connectedItem is not None and issubclass(type(line.connectors[0].connectedItem), SymbolSvgItem)) or (line.connectors[1].connectedItem is not None and issubclass(type(line.connectors[1].connectedItem), SymbolSvgItem)) |
|
599 |
flag = (line.connectors[0].connectedItem is not None and issubclass( |
|
600 |
type(line.connectors[0].connectedItem), SymbolSvgItem)) or ( |
|
601 |
line.connectors[1].connectedItem is not None and issubclass( |
|
602 |
type(line.connectors[1].connectedItem), SymbolSvgItem)) |
|
569 | 603 |
return (flag and (math.fabs(self.startPoint()[1] - line.startPoint()[1]) < toler)) |
570 | 604 |
elif self.isVertical() and line.isVertical(): |
571 |
flag = (line.connectors[0].connectedItem is not None and issubclass(type(line.connectors[0].connectedItem), SymbolSvgItem)) or (line.connectors[1].connectedItem is not None and issubclass(type(line.connectors[1].connectedItem), SymbolSvgItem)) |
|
605 |
flag = (line.connectors[0].connectedItem is not None and issubclass( |
|
606 |
type(line.connectors[0].connectedItem), SymbolSvgItem)) or ( |
|
607 |
line.connectors[1].connectedItem is not None and issubclass( |
|
608 |
type(line.connectors[1].connectedItem), SymbolSvgItem)) |
|
572 | 609 |
return (flag and (math.fabs(self.startPoint()[0] - line.startPoint()[0]) < toler)) |
573 |
|
|
610 |
|
|
574 | 611 |
return False |
575 |
|
|
612 |
|
|
576 | 613 |
def is_external_point(self, pt): |
577 | 614 |
""" check given pt is located outside of line """ |
578 | 615 |
import math |
... | ... | |
581 | 618 |
dx = self.endPoint()[0] - self.startPoint()[0] |
582 | 619 |
dy = self.endPoint()[1] - self.startPoint()[1] |
583 | 620 |
lineLength = math.sqrt(dx * dx + dy * dy) |
584 |
|
|
621 |
|
|
585 | 622 |
dx = pt.x - self.startPoint()[0] |
586 | 623 |
dy = pt.y - self.startPoint()[1] |
587 | 624 |
length = math.sqrt(dx * dx + dy * dy) |
... | ... | |
596 | 633 |
|
597 | 634 |
return False |
598 | 635 |
except Exception as ex: |
599 |
from App import App
|
|
636 |
from App import App |
|
600 | 637 |
from AppDocData import MessageType |
601 | 638 |
|
602 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
639 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
640 |
sys.exc_info()[-1].tb_lineno) |
|
603 | 641 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
604 | 642 |
|
605 | 643 |
''' |
... | ... | |
608 | 646 |
@history humkyung 2018.05.08 check if line is possible to be connected |
609 | 647 |
Jeongwoo 2018.05.15 Split if-statement and Connect each symbol and line |
610 | 648 |
''' |
649 |
|
|
611 | 650 |
def connect_if_possible(self, obj, toler=20): |
612 | 651 |
""" connect line or symbol is able to be connected and return symbol or line connected to connectors """ |
613 | 652 |
""" this method not update item's position """ |
... | ... | |
618 | 657 |
|
619 | 658 |
res = [] |
620 | 659 |
|
621 |
startPt = self.startPoint()
|
|
660 |
startPt = self.startPoint() |
|
622 | 661 |
endPt = self.endPoint() |
623 | 662 |
|
624 | 663 |
try: |
... | ... | |
627 | 666 |
pt = obj.connectors[i].sceneConnectPoint |
628 | 667 |
if (Point(startPt[0], startPt[1]).distance(Point(pt[0], pt[1])) < toler): |
629 | 668 |
if self.connectors[0].connectedItem is None and obj.connectors[i].connectedItem is None: |
630 |
self.connectors[0].connect(obj)
|
|
669 |
self.connectors[0].connect(obj) |
|
631 | 670 |
obj.connectors[i].connect(self) |
632 | 671 |
res.append(obj) |
633 | 672 |
res.append(obj.connectors[i].sceneConnectPoint) |
... | ... | |
641 | 680 |
_startPt = obj.startPoint() |
642 | 681 |
_endPt = obj.endPoint() |
643 | 682 |
if self.distanceTo(_startPt) < toler: |
644 |
if((Point(startPt[0], startPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)): |
|
683 |
if ((Point(startPt[0], startPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
|
|
645 | 684 |
self.connectors[0].connect(obj) |
646 | 685 |
obj.connectors[0].connect(self) |
647 | 686 |
res.append(obj) |
648 |
elif((Point(endPt[0], endPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)): |
|
687 |
elif ((Point(endPt[0], endPt[1]).distance(Point(_startPt[0], _startPt[1])) < toler)):
|
|
649 | 688 |
self.connectors[1].connect(obj) |
650 | 689 |
obj.connectors[0].connect(self) |
651 | 690 |
res.append(obj) |
... | ... | |
664 | 703 |
else: |
665 | 704 |
obj.connectors[1].connect(self, at=QEngineeringAbstractItem.CONNECTED_AT_BODY) |
666 | 705 |
except Exception as ex: |
667 |
from App import App
|
|
706 |
from App import App |
|
668 | 707 |
from AppDocData import MessageType |
669 | 708 |
|
670 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
709 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
710 |
sys.exc_info()[-1].tb_lineno) |
|
671 | 711 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
672 | 712 |
|
673 | 713 |
return res |
... | ... | |
677 | 717 |
@author kyouho |
678 | 718 |
@date 2018.08.30 |
679 | 719 |
''' |
720 |
|
|
680 | 721 |
def disconnectedItemAtConnector(self, connector): |
681 | 722 |
for conn in self.connectors: |
682 | 723 |
if conn.isOverlapConnector(connector): |
... | ... | |
686 | 727 |
""" reverse if from is connected to second connector """ |
687 | 728 |
if not _from: raise ValueError |
688 | 729 |
|
689 |
if self.connectors[1].connectedItem == _from: self.reverse()
|
|
730 |
if self.connectors[1].connectedItem == _from: self.reverse() |
|
690 | 731 |
|
691 | 732 |
''' |
692 | 733 |
@brief reverse line |
693 | 734 |
@author humkyung |
694 | 735 |
@date 2018.07.03 |
695 | 736 |
''' |
737 |
|
|
696 | 738 |
def reverse(self): |
697 | 739 |
line = self.line() |
698 | 740 |
self.setLine(QLineF(line.p2(), line.p1())) |
... | ... | |
706 | 748 |
@date 2018.05.08 |
707 | 749 |
@history 2018.05.24 Jeongwoo Modifying Draw Flow Arrow |
708 | 750 |
''' |
751 |
|
|
709 | 752 |
def addFlowArrow(self): |
710 | 753 |
import numpy as np |
711 | 754 |
import cv2 |
... | ... | |
715 | 758 |
from shapely.geometry import Point |
716 | 759 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
717 | 760 |
from AppDocData import AppDocData |
718 |
|
|
761 |
|
|
719 | 762 |
try: |
720 | 763 |
docData = AppDocData.instance() |
721 | 764 |
area = docData.getArea('Drawing') |
... | ... | |
739 | 782 |
docData = AppDocData.instance() |
740 | 783 |
area = docData.getArea('Drawing') |
741 | 784 |
img = np.array(AppDocData.instance().getCurrentPidSource().getPyImageOnRect(rect)) |
742 |
|
|
785 |
|
|
743 | 786 |
imgLine = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1] |
744 | 787 |
# remove noise |
745 | 788 |
imgLine = cv2.bitwise_not(imgLine) |
... | ... | |
749 | 792 |
if contours: |
750 | 793 |
contours = sorted(contours, key=cv2.contourArea, reverse=True) |
751 | 794 |
[x, y, w, h] = cv2.boundingRect(contours[0]) |
752 |
if w > 10 and w < 100 and h > 10 and h < 100: # check arrow mark size
|
|
753 |
imgArrowMark = imgLine[y:y+h, x:x+w]
|
|
795 |
if w > 10 and w < 100 and h > 10 and h < 100: # check arrow mark size |
|
796 |
imgArrowMark = imgLine[y:y + h, x:x + w]
|
|
754 | 797 |
|
755 | 798 |
# DEBUG - display flow arrow area |
756 | 799 |
''' |
... | ... | |
764 | 807 |
# up to here |
765 | 808 |
|
766 | 809 |
edges = cv2.Canny(imgArrowMark, 50, 150, apertureSize=3) |
767 |
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 10, minLineLength=10, maxLineGap=5)
|
|
810 |
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 10, minLineLength=10, maxLineGap=5)
|
|
768 | 811 |
|
769 | 812 |
####### HoughLinesP |
770 | 813 |
if lines is not None: |
... | ... | |
775 | 818 |
dx = x2 - x1 |
776 | 819 |
dy = y2 - y1 |
777 | 820 |
selected = line |
778 |
length = math.sqrt(dx*dx + dy*dy)
|
|
821 |
length = math.sqrt(dx * dx + dy * dy)
|
|
779 | 822 |
if maxLength is None or length > maxLength: |
780 | 823 |
maxLength = length |
781 | 824 |
selected = line |
... | ... | |
783 | 826 |
for x1, y1, x2, y2 in selected: |
784 | 827 |
dx = math.fabs(x2 - x1) |
785 | 828 |
dy = math.fabs(y2 - y1) |
786 |
length = math.sqrt(dx*dx + dy*dy)
|
|
829 |
length = math.sqrt(dx * dx + dy * dy)
|
|
787 | 830 |
dx /= length |
788 | 831 |
dy /= length |
789 |
if (self.isVertical() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)) or (self.isHorizontal() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)): continue |
|
832 |
if (self.isVertical() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)) or ( |
|
833 |
self.isHorizontal() and (dx < 0.001 or math.fabs(dx - 1) < 0.001)): continue |
|
790 | 834 |
dist1 = self.distanceTo((rect.left() + x + x1, rect.top() + y + y1)) |
791 | 835 |
dist2 = self.distanceTo((rect.left() + x + x2, rect.top() + y + y2)) |
792 |
if dist1 > dist2: # point which's distance is longer would be start point
|
|
836 |
if dist1 > dist2: # point which's distance is longer would be start point |
|
793 | 837 |
_start = (rect.left() + x + x1, rect.top() + y + y1) |
794 | 838 |
_end = (rect.left() + x + x2, rect.top() + y + y2) |
795 | 839 |
else: |
796 | 840 |
_start = (rect.left() + x + x2, rect.top() + y + y2) |
797 | 841 |
_end = (rect.left() + x + x1, rect.top() + y + y1) |
798 |
|
|
842 |
|
|
799 | 843 |
# DEBUG display detected line |
800 | 844 |
''' |
801 | 845 |
poly = QEngineeringPolylineItem() |
... | ... | |
810 | 854 |
dist1 = Point(startPt[0], startPt[1]).distance(Point(_start[0], _start[1])) |
811 | 855 |
dist2 = Point(startPt[0], startPt[1]).distance(Point(_end[0], _end[1])) |
812 | 856 |
if dist1 > dist2: |
813 |
startPt,endPt = endPt,startPt
|
|
814 |
direction[0],direction[1] = -direction[0],-direction[1]
|
|
857 |
startPt, endPt = endPt, startPt
|
|
858 |
direction[0], direction[1] = -direction[0], -direction[1]
|
|
815 | 859 |
self.reverse() |
816 |
|
|
860 |
|
|
817 | 861 |
''' |
818 | 862 |
center = [(startPt[0]+endPt[0])*0.5, (startPt[1]+endPt[1])*0.5] |
819 | 863 |
arrow = QEngineeringFlowArrowItem(center, direction) |
... | ... | |
827 | 871 |
else: |
828 | 872 |
pass |
829 | 873 |
except Exception as ex: |
830 |
from App import App
|
|
874 |
from App import App |
|
831 | 875 |
from AppDocData import MessageType |
832 | 876 |
|
833 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
877 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
878 |
sys.exc_info()[-1].tb_lineno) |
|
834 | 879 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
835 | 880 |
|
836 | 881 |
''' |
... | ... | |
839 | 884 |
@date 2018.04.22 |
840 | 885 |
@history kyouho 2018.07.24 add symbol angle, transform rotateRadians(-angle -> angle) |
841 | 886 |
''' |
887 |
|
|
842 | 888 |
def insertSymbol(self, symbol, pos): |
843 | 889 |
import math |
844 | 890 |
from shapely.geometry import Point |
845 | 891 |
from shapely import affinity |
846 | 892 |
|
847 | 893 |
vec = self.perpendicular() |
848 |
line = [(pos.x() - vec[0]*20, pos.y() - vec[1]*20),(pos.x() + vec[0]*20, pos.y() + vec[1]*20)]
|
|
894 |
line = [(pos.x() - vec[0] * 20, pos.y() - vec[1] * 20), (pos.x() + vec[0] * 20, pos.y() + vec[1] * 20)]
|
|
849 | 895 |
origin = self.intersection(line) |
850 | 896 |
transform = QTransform() |
851 | 897 |
transform.translate(origin.x, origin.y) |
... | ... | |
853 | 899 |
transform.rotateRadians(-angle) |
854 | 900 |
transform.translate(-symbol.symbolOrigin[0], -symbol.symbolOrigin[1]) |
855 | 901 |
symbol.setTransform(transform) |
856 |
#save angle |
|
902 |
# save angle
|
|
857 | 903 |
symbol.angle = round(angle, 2) |
858 |
if 2 == len(symbol.connectors): # 2 way component
|
|
904 |
if 2 == len(symbol.connectors): # 2 way component |
|
859 | 905 |
for i in range(len(symbol.connectors)): |
860 |
rotatedPt = affinity.rotate(Point(symbol.connectors[i].connectPoint[0] - symbol.symbolOrigin[0], symbol.connectors[i].connectPoint[1] - symbol.symbolOrigin[1]), -angle, Point(0, 0), use_radians=True) |
|
861 |
symbol.connectors[i].sceneConnectPoint = (origin.x+rotatedPt.x, origin.y+rotatedPt.y) |
|
906 |
rotatedPt = affinity.rotate(Point(symbol.connectors[i].connectPoint[0] - symbol.symbolOrigin[0], |
|
907 |
symbol.connectors[i].connectPoint[1] - symbol.symbolOrigin[1]), |
|
908 |
-angle, Point(0, 0), use_radians=True) |
|
909 |
symbol.connectors[i].sceneConnectPoint = (origin.x + rotatedPt.x, origin.y + rotatedPt.y) |
|
862 | 910 |
|
863 | 911 |
dx1 = symbol.connectors[0].sceneConnectPoint[0] - self.startPoint()[0] |
864 | 912 |
dy1 = symbol.connectors[0].sceneConnectPoint[1] - self.startPoint()[1] |
865 |
length1 = math.sqrt(dx1*dx1 + dy1*dy1)
|
|
913 |
length1 = math.sqrt(dx1 * dx1 + dy1 * dy1)
|
|
866 | 914 |
dx2 = symbol.connectors[1].sceneConnectPoint[0] - self.startPoint()[0] |
867 | 915 |
dy2 = symbol.connectors[1].sceneConnectPoint[1] - self.startPoint()[1] |
868 |
length2 = math.sqrt(dx2*dx2 + dy2*dy2)
|
|
916 |
length2 = math.sqrt(dx2 * dx2 + dy2 * dy2)
|
|
869 | 917 |
|
870 | 918 |
if length1 < length2: |
871 | 919 |
processLine = QEngineeringLineItem([symbol.connectors[1].sceneConnectPoint, self.endPoint()]) |
... | ... | |
873 | 921 |
processLine.connectors[1].connectedItem = self.connectors[1].connectedItem |
874 | 922 |
self.scene().addItem(processLine) |
875 | 923 |
|
876 |
line = QLineF(self.line().p1(), QPointF(symbol.connectors[0].sceneConnectPoint[0], symbol.connectors[0].sceneConnectPoint[1])) |
|
924 |
line = QLineF(self.line().p1(), QPointF(symbol.connectors[0].sceneConnectPoint[0], |
|
925 |
symbol.connectors[0].sceneConnectPoint[1])) |
|
877 | 926 |
self.setLine(line) |
878 | 927 |
self.connectors[1].connectedItem = symbol |
879 | 928 |
|
... | ... | |
885 | 934 |
processLine.connectors[1].connectedItem = self.connectors[1].connectedItem |
886 | 935 |
self.scene().addItem(processLine) |
887 | 936 |
|
888 |
line = QLineF(self.line().p1(), QPointF(symbol.connectors[1].sceneConnectPoint[0], symbol.connectors[1].sceneConnectPoint[1])) |
|
937 |
line = QLineF(self.line().p1(), QPointF(symbol.connectors[1].sceneConnectPoint[0], |
|
938 |
symbol.connectors[1].sceneConnectPoint[1])) |
|
889 | 939 |
self.setLine(line) |
890 | 940 |
self.connectors[1].connectedItem = symbol |
891 | 941 |
|
892 | 942 |
symbol.connectors[0].connectedItem = processLine |
893 | 943 |
symbol.connectors[1].connectedItem = self |
894 |
|
|
895 | 944 |
|
896 | 945 |
self.joinTo(symbol) |
897 | 946 |
processLine.joinTo(symbol) |
898 | 947 |
self.update() |
899 |
|
|
948 |
|
|
900 | 949 |
symbol.loc = [origin.x - symbol.symbolOrigin[0], origin.y - symbol.symbolOrigin[1]] |
901 | 950 |
symbol.size = [symbol.boundingRect().width(), symbol.boundingRect().height()] |
902 | 951 |
self.scene().addItem(symbol) |
903 |
|
|
952 |
|
|
904 | 953 |
''' |
905 | 954 |
@brief redraw symbol |
906 | 955 |
@author kyouho |
907 | 956 |
@date 2018.07.25 |
908 | 957 |
''' |
958 |
|
|
909 | 959 |
def reDrawLine(self, symbol, point): |
910 | 960 |
for index in range(len(self.connectors)): |
911 | 961 |
if self.connectors[index].connectedItem == symbol: |
912 |
#startPoint |
|
962 |
# startPoint
|
|
913 | 963 |
if index == 0: |
914 | 964 |
line = QLineF(QPointF(point[0], point[1]), self.line().p2()) |
915 | 965 |
self.setLine(line) |
916 | 966 |
self.connectors[0].setPos([point[0], point[1]]) |
917 |
#endpoint |
|
967 |
# endpoint
|
|
918 | 968 |
else: |
919 | 969 |
line = QLineF(self.line().p1(), QPointF(point[0], point[1])) |
920 | 970 |
self.setLine(line) |
921 | 971 |
self.connectors[1].setPos([point[0], point[1]]) |
922 |
|
|
923 | 972 |
|
924 |
|
|
925 | 973 |
## startPoint에 symbol |
926 |
#if self.connectors[0].connectedItem == symbol: |
|
974 |
# if self.connectors[0].connectedItem == symbol:
|
|
927 | 975 |
# if self.startPoint()[0] == symbol.connectors[0].sceneConnectPoint[0] and self.startPoint()[1] == symbol.connectors[0].sceneConnectPoint[1]: |
928 | 976 |
# line = QLineF(QPointF(changedConnPoint1[0], changedConnPoint1[1]), self.line().p2()) |
929 | 977 |
# self.setLine(line) |
... | ... | |
931 | 979 |
# line = QLineF(QPointF(changedConnPoint2[0], changedConnPoint2[1]), self.line().p2()) |
932 | 980 |
# self.setLine(line) |
933 | 981 |
## endPoint에 symbol |
934 |
#elif self.connectors[1].connectedItem == symbol: |
|
982 |
# elif self.connectors[1].connectedItem == symbol:
|
|
935 | 983 |
# if self.endPoint()[0] == symbol.connectors[0].sceneConnectPoint[0] and self.endPoint()[1] == symbol.connectors[0].sceneConnectPoint[1]: |
936 | 984 |
# line = QLineF(self.line().p1(), QPointF(changedConnPoint1[0], changedConnPoint1[1])) |
937 | 985 |
# self.setLine(line) |
... | ... | |
946 | 994 |
@author humkyung |
947 | 995 |
@date 2018.04.23 |
948 | 996 |
''' |
997 |
|
|
949 | 998 |
def removeSymbol(self, symbol): |
950 | 999 |
import math |
951 | 1000 |
|
952 | 1001 |
if 2 == len(symbol.connectors): # 2-way component |
953 |
connected = symbol.connectors[0].connectedItem if symbol.connectors[0].connectedItem is not self else symbol.connectors[1].connectedItem |
|
954 |
|
|
1002 |
connected = symbol.connectors[0].connectedItem if symbol.connectors[0].connectedItem is not self else \ |
|
1003 |
symbol.connectors[1].connectedItem |
|
1004 |
|
|
955 | 1005 |
pts = [] |
956 | 1006 |
pts.append(self.startPoint()) |
957 | 1007 |
pts.append(self.endPoint()) |
... | ... | |
964 | 1014 |
end = None |
965 | 1015 |
maxDist = None |
966 | 1016 |
for i in range(len(pts)): |
967 |
for j in range(i+1,len(pts)):
|
|
1017 |
for j in range(i + 1, len(pts)):
|
|
968 | 1018 |
dx = pts[i][0] - pts[j][0] |
969 | 1019 |
dy = pts[i][1] - pts[j][1] |
970 |
dist = math.sqrt(dx*dx + dy*dy)
|
|
1020 |
dist = math.sqrt(dx * dx + dy * dy)
|
|
971 | 1021 |
if maxDist is None: |
972 | 1022 |
maxDist = dist |
973 | 1023 |
start = pts[i] |
... | ... | |
977 | 1027 |
start = pts[i] |
978 | 1028 |
end = pts[j] |
979 | 1029 |
|
980 |
if (pts[0] == end) or (pts[1] == start): start,end = end,start
|
|
1030 |
if (pts[0] == end) or (pts[1] == start): start, end = end, start
|
|
981 | 1031 |
|
982 | 1032 |
line = QLineF(QPointF(start[0], start[1]), QPointF(end[0], end[1])) |
983 | 1033 |
self.setLine(line) |
984 |
#self.buildItem() |
|
1034 |
# self.buildItem()
|
|
985 | 1035 |
self.update() |
986 | 1036 |
|
987 | 1037 |
def validate(self): |
... | ... | |
1021 | 1071 |
errors.append(error) |
1022 | 1072 |
|
1023 | 1073 |
# check line to symbol |
1024 |
elif issubclass(type(connector.connectedItem), SymbolSvgItem) and type(connector.connectedItem) is not QEngineeringEquipmentItem: |
|
1074 |
elif issubclass(type(connector.connectedItem), SymbolSvgItem) and type( |
|
1075 |
connector.connectedItem) is not QEngineeringEquipmentItem: |
|
1025 | 1076 |
matches = [conn for conn in connector.connectedItem.connectors if conn.connectedItem is self] |
1026 | 1077 |
# check if two items are connected each other |
1027 | 1078 |
if not matches: |
... | ... | |
1051 | 1102 |
|
1052 | 1103 |
indices = [0, 0] |
1053 | 1104 |
indices[0] = 1 if QPointF(center[0], center[1]) == self.line().p1() else 2 |
1054 |
matches = [conn for conn in connector.connectedItem.connectors if conn.connectedItem == self and conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT] |
|
1105 |
matches = [conn for conn in connector.connectedItem.connectors if |
|
1106 |
conn.connectedItem == self and conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT] |
|
1055 | 1107 |
if matches: |
1056 |
indices[1] = 1 if QPointF(matches[0].center()[0], matches[0].center()[1]) == connector.connectedItem.line().p1() else 2 |
|
1108 |
indices[1] = 1 if QPointF(matches[0].center()[0], matches[0].center()[ |
|
1109 |
1]) == connector.connectedItem.line().p1() else 2 |
|
1057 | 1110 |
|
1058 |
if indices[0] == indices[1]:
|
|
1111 |
if indices[0] == indices[1]: |
|
1059 | 1112 |
error = SymbolSvgItem.createItem('Error', dataPath) |
1060 | 1113 |
error.setPosition(connector.center()) |
1061 | 1114 |
error.parent = self |
... | ... | |
1089 | 1142 |
errors.append(error) |
1090 | 1143 |
|
1091 | 1144 |
except Exception as ex: |
1092 |
from App import App
|
|
1145 |
from App import App |
|
1093 | 1146 |
from AppDocData import MessageType |
1094 | 1147 |
|
1095 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
1148 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
1149 |
sys.exc_info()[-1].tb_lineno) |
|
1096 | 1150 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
1097 |
|
|
1151 |
|
|
1098 | 1152 |
return errors |
1099 | 1153 |
|
1100 | 1154 |
''' |
... | ... | |
1102 | 1156 |
@author humkyung |
1103 | 1157 |
@date 2018.07.05 |
1104 | 1158 |
''' |
1159 |
|
|
1105 | 1160 |
def update_line_type(self): |
1106 | 1161 |
import uuid |
1107 | 1162 |
from LineTypeConditions import LineTypeConditions |
1108 | 1163 |
|
1109 | 1164 |
try: |
1110 |
pool,visited,items = [self],[],[]
|
|
1165 |
pool, visited, items = [self], [], []
|
|
1111 | 1166 |
while pool: |
1112 | 1167 |
obj = pool.pop() |
1113 | 1168 |
visited.append(obj) |
1114 | 1169 |
|
1115 | 1170 |
""" connected items """ |
1116 |
connected = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and not type(connector.connectedItem) is uuid.UUID] |
|
1171 |
connected = [connector.connectedItem for connector in obj.connectors if |
|
1172 |
connector.connectedItem and not type(connector.connectedItem) is uuid.UUID] |
|
1117 | 1173 |
""" connected lines at point """ |
1118 |
lines = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and type(connector.connectedItem) is QEngineeringLineItem and connector._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT] |
|
1174 |
lines = [connector.connectedItem for connector in obj.connectors if connector.connectedItem and type( |
|
1175 |
connector.connectedItem) is QEngineeringLineItem and connector._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT] |
|
1119 | 1176 |
""" add items not in 'connected' to items list """ |
1120 | 1177 |
items.extend([item for item in connected if item not in lines]) |
1121 | 1178 |
""" add items not visited to pool """ |
... | ... | |
1126 | 1183 |
self.lineType = condition.name |
1127 | 1184 |
break |
1128 | 1185 |
except Exception as ex: |
1129 |
from App import App |
|
1186 |
from App import App |
내보내기 Unified diff