프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / DTI_PID / DTI_PID / LineNoTracer.py @ 0b8b80ed

이력 | 보기 | 이력해설 | 다운로드 (30.3 KB)

1
# coding: utf-8
2
""" This is line no tracer module """
3

    
4
import sys
5
import math
6
import shapely
7
from AppDocData import AppDocData, MessageType
8
from EngineeringLineItem import QEngineeringLineItem
9
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
10
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
11
from SymbolSvgItem import SymbolSvgItem
12
from EngineeringTextItem import QEngineeringTextItem
13
from EngineeringUnknownItem import QEngineeringUnknownItem
14
try:
15
    from PyQt5.QtCore import *
16
    from PyQt5.QtGui import *
17
    from PyQt5.QtWidgets import *
18
except ImportError:
19
    try:
20
        from PyQt4.QtCore import *
21
        from PyQt4.QtGui import *
22
    except ImportError:
23
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
24

    
25
class LineNoTracer:
26
    '''
27
        @history    2018.04.26 Jeongwoo Variable name changed (texts → lineNos)
28
    '''
29
    def __init__(self, symbols, lines, lineNos, specBreaks, lineIndicators, vendors, end_breaks):
30
        try:
31
            self._symbols = symbols
32
            self._lines = lines
33
            self._lineNos = lineNos
34
            self._spec_breaks = specBreaks
35
            self._lineIndicator = lineIndicators
36
            self._end_breaks = end_breaks
37
            
38
            """
39
            for spec in self._specBreak:
40
                for attr in spec.attrs:
41
                    if type(attr) is tuple and attr[1] != '':
42
                        self._specBreakUID.append(attr[1])
43
            """
44
        except Exception as ex:
45
            from App import App 
46

    
47
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
48
            App.mainWnd().addMessage.emit(MessageType.Error, message)
49

    
50
    '''
51
        @brief  find primary lines connected to given line no
52
        @author humkyung
53
    '''
54
    def find_primary_lines(self, lineno):
55
        from EngineeringLineItem import QEngineeringLineItem
56
        from EngineeringRunItem import QEngineeringRunItem
57

    
58
        connected_items = []
59
        
60
        _from = lineno.prop('From')
61
        _to = lineno.prop('To')
62
        if _from and _to and lineno.empty():
63
            connected_items = self.find_connected_objects(_from, to=_to, primary=True)
64
            if _from in connected_items and _to in connected_items:
65
                start = connected_items.index(_from)
66
                end = connected_items.index(_to)
67
                if start < end:
68
                    connected_items = connected_items[start:end+1]
69
                else:
70
                    connected_items = connected_items[end:start+1]
71
                    connected_items.reverse()
72
        elif (not _from or not _to) and (1 == len(lineno.conns)):
73
            connected_items = self.find_connected_objects(lineno.conns[0])
74

    
75
        #print(connected_items)
76
        if connected_items:
77
            for item in connected_items: 
78
                item.owner = lineno # set item's owner
79
            
80
            line_run = QEngineeringRunItem()
81
            line_run.items = connected_items
82
            line_run.arrange_flow_direction()
83
            line_run.owner = lineno
84
            lineno.runs.append(line_run)
85

    
86
            lineno.set_property('From', connected_items[0])
87
            lineno.set_property('To', connected_items[-1])
88

    
89
        if _to is not None and connected_items and connected_items[-1] is not _to:
90
            _to.owner = None
91

    
92
        return connected_items
93

    
94
    '''
95
        @brief  find secondary lines
96
        @author humkyung
97
    '''
98
    def find_secondary_lines(self, lines_and_symbols):
99
        from EngineeringAbstractItem import QEngineeringAbstractItem
100
        from EngineeringLineItem import QEngineeringLineItem
101
        from EngineeringRunItem import QEngineeringRunItem
102

    
103
        try:
104
            foundCount = 1
105
            while foundCount:
106
                foundCount = 0
107
                notMatches = []
108
                for line in lines_and_symbols:
109
                    if line.owner is not None: continue
110

    
111
                    line_matches = [x for x in self._lines if x.owner and line.is_connected(x, QEngineeringAbstractItem.CONNECTED_AT_BODY)]
112
                    symbol_matches = [x for x in self._symbols if x.owner and line.is_connected(x) and x.canBeSecondary(line)]
113
                    if line_matches or symbol_matches:
114
                        foundCount += 1
115
                        connected_items = self.find_connected_objects(line)
116
                        
117
                        owner = line_matches[0].owner if line_matches else symbol_matches[0].owner
118
                        for item in connected_items:
119
                            item.owner = owner # set item's owner
120

    
121
                        line_run = QEngineeringRunItem()
122
                        line_run.items = connected_items
123
                        line_run.arrange_flow_direction()
124
                        if line_run.items is not None and len(line_run.items) > 0:
125
                            line_run.owner = owner
126
                            owner.runs.append(line_run)
127
                    else:
128
                        notMatches.append(line)
129
                #lines_and_symbols = notMatches
130
        except Exception as ex:
131
            from App import App 
132

    
133
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
134
            App.mainWnd().addMessage.emit(MessageType.Error, message)
135

    
136
    '''
137
        @brief      trace line no
138
        @author     humkyung
139
        @date       2018.04.16
140
        @history    2018.04.26 Jeongwoo docDatalineNos = self.lineNos, Not For loop
141
                    humkyung 2018.05.08 add flow arrow
142
                    Jeongwoo 2018.05.14 Add [runs] on Primary/Secondary Line - Need to modify Secondary Line
143
                    Jeongwoo 2018.05.15 Make Comments [lineno.conns[0].owner = lineno]
144
                    Jeongwoo 2018.05.17 Modify find secondary lines with 'while'
145
                                        Modify find secondary lines with 'while' used sublist for unconnected line
146
                    humkyung 2018.05.18 set start line's owner before tracing
147
    '''
148
    def execute(self, displayMessage, updateProgress, toler=600):
149
        from EngineeringLineItem import QEngineeringLineItem
150
        from SymbolSvgItem import SymbolSvgItem
151
        from EngineeringRunItem import QEngineeringRunItem
152
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
153

    
154
        try:
155
            docData = AppDocData.instance()
156

    
157
            configs = docData.getConfigs('Line No', 'Delimiter')
158
            if 1 == len(configs):
159
                configs = docData.getConfigs('Line No', 'Configuration')
160

    
161
                for lineno in self._lineNos:
162
                    _from = lineno.prop('From')
163
                    _to = lineno.prop('To')
164

    
165
                    lineno.conns.clear()
166
                    minDist = None
167
                    startLine = None
168
                    for line in self._lines:
169
                        dist = line.distanceTo((lineno.center().x(), lineno.center().y()))
170
                        if (minDist is None) or (dist < minDist):
171
                            minDist = dist
172
                            startLine = line
173
                    if (startLine is not None) and (minDist < toler):
174
                        lineno.conns.append(startLine)
175

    
176
                    if _from and _to and (type(_from) is QEngineeringLineItem or issubclass(type(_from), SymbolSvgItem)) and (type(_to) is QEngineeringLineItem or issubclass(type(_to), SymbolSvgItem)):
177
                        _from.owner = lineno
178
                        _to.owner = lineno
179
                        continue
180
                    else:
181
                        lineno.set_property('From', None)
182
                        lineno.set_property('To', None)
183

    
184
                maxValue = len(self._lineNos) + 1   ## line no's count + secondary line
185

    
186
                # find primary lines
187
                # sort line no with from,to value
188
                self._lineNos.sort(key=lambda line_no:(1 if line_no.prop('From') else 0)+(1 if line_no.prop('To') else 0),reverse=True)
189
                for lineno in self._lineNos:
190
                    if displayMessage: displayMessage.emit('{} {}'.format(lineno.text(), 'Topology Construction'))
191
                    self.find_primary_lines(lineno)
192
                    if updateProgress: updateProgress.emit(maxValue)
193

    
194
                # find secondary lines
195
                lines_and_symbols = self._lines + self._symbols
196
                self.find_secondary_lines(lines_and_symbols)
197

    
198
                # double check conn line cuz startLine may need at first step
199
                for lineno in self._lineNos:
200
                    lineno.conns.clear()
201
                    minDist = None
202
                    startLine = None
203
                    for line in [line for line in lineno.runs[0].items if type(line) is QEngineeringLineItem and (line._lineType == 'Primary' or line._lineType == 'Secondary')]:
204
                        dist = line.distanceTo((lineno.center().x(), lineno.center().y()))
205
                        if (minDist is None) or (dist < minDist):
206
                            minDist = dist
207
                            startLine = line
208
                    if (startLine is not None) and (minDist < toler):
209
                        lineno.conns.append(startLine)
210

    
211
                if updateProgress: updateProgress.emit(maxValue)
212

    
213
            ### make trim lines
214
            updateProgress.emit(-1) # reset progressbar
215
            displayMessage.emit('Unknown line Topology Construction')
216
            orphanLines = [line for line in self._lines if line.owner is None]
217
            orphanSymbols = [symbol for symbol in self._symbols if symbol.owner is None]
218
            if orphanLines + orphanSymbols:
219
                maxValue = len(orphanLines)
220
                orphanLines = sorted(orphanLines, key=lambda param:param.length(), reverse=True)
221
                orphans = orphanLines + orphanSymbols
222
                while len(orphans) > 0:
223
                    trimLineNo = QEngineeringTrimLineNoTextItem()
224
                    trimLineNo.conns.append(orphans[0])
225
                    orphans[0].owner = trimLineNo
226
                    #orphanLines[0].linkedItem = trimLineNo
227

    
228
                    connectedItems = self.find_primary_lines(trimLineNo)
229
                    for item in connectedItems:
230
                        if item in orphanLines:
231
                            orphanLines.remove(item)
232
                            updateProgress.emit(maxValue)
233

    
234
                    self.find_secondary_lines(orphans)
235
                    for item in orphans[:]:
236
                        if item.owner is not None:
237
                            orphans.remove(item)
238
                            updateProgress.emit(maxValue)
239

    
240
                    docData.tracerLineNos.append(trimLineNo)
241

    
242
            #(docData.tracerLineNos))
243
            if updateProgress: updateProgress.emit(maxValue)
244
        except Exception as ex:
245
            from App import App 
246

    
247
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
248
            AppDocData.instance().ex.logger.critical('message')
249
            App.mainWnd().addMessage.emit(MessageType.Error, message)
250

    
251
    '''
252
        @brief      find objects connected to given line while loop
253
        @author     humkyung
254
        @date       2018.04.16
255
        @history    humkyung 2018.05.08 find symbol or line connected to given object
256
                    humkyung 2018.05.10 set found object's owner
257
                    humkyung 2018.05.17 try to connect both symbol and line
258
                    humkyung 2018.06.22 order connected objects
259
    '''
260
    def find_connected_objects(self, start, to=None, primary=False):
261
        from EngineeringLineItem import QEngineeringLineItem
262
        from EngineeringEquipmentItem import QEngineeringEquipmentItem
263
        from SymbolSvgItem import SymbolSvgItem
264

    
265
        visited = [start]
266

    
267
        try:
268
            pool = []
269
            pool.append((0, start))
270
            
271
            while len(pool) > 0:
272
                sign, obj = pool.pop()
273
                
274
                #""" check obj is upstream or downstream of spec break """
275
                #matches = [spec_break for spec_break in self._spec_breaks if spec_break.is_connected(obj)]
276
                #if matches or issubclass(type(obj), QEngineeringEquipmentItem):
277
                #    visited.pop(visited.index(obj))
278
                #    continue
279
                #print('obj={} pool={}'.format(obj, pool))
280

    
281
                match = False
282
                if not primary:
283
                    for end_break in self._end_breaks: 
284
                        if obj is end_break.owner or obj is end_break.prop('Connected Item'):
285
                            match = True
286
                            break
287

    
288
                if issubclass(type(obj), QEngineeringEquipmentItem):
289
                    visited.pop(visited.index(obj))
290
                    continue    
291
                elif match:
292
                    continue
293

    
294
                """ end loop if obj is to """
295
                if to is not None and str(obj.uid) == str(to.uid): break
296

    
297
                # nextmatches list always has one item
298
                if type(obj) is QEngineeringLineItem:
299
                    symbolMatches = [x for x in self._symbols if (x.owner is None or x.owner == start.owner) and (x not in visited) and obj.is_connected(x)]
300
                    lineMatches = [x for x in self._lines if (x.owner is None or x.owner == start.owner) and (x is not obj) and (x not in visited) and obj.is_connected(x)]
301
                    nextMatches = symbolMatches + lineMatches
302

    
303
                elif issubclass(type(obj), SymbolSvgItem):
304
                    # symbol can be connected with line and another symbol at the same time
305
                    lineMatches = [x for x in self._lines if (x.owner is None or x.owner == start.owner) and (x not in visited) and obj.is_connected(x)]
306
                    symbolMatches = [x for x in self._symbols if (x.owner is None or x.owner == start.owner) and (x is not obj) and (x not in visited) and obj.is_connected(x, None)]
307
                    nextMatches = symbolMatches + lineMatches
308

    
309
                    if len(nextMatches) > 1: # choose one if connected items are more than 2
310
                        matches = [x for x in visited if obj.is_connected(x)]
311
                        if matches:
312
                            next_connected = [x for x in nextMatches if obj.next_connected(x, matches[0])]
313

    
314
                            if next_connected:
315
                                nextMatches = next_connected
316
                            else:
317
                                nextMatches = [lineMatches[0]]
318
                
319
                # order connected objects
320
                matches = []
321
                matches.extend(nextMatches)
322

    
323
                if sign == 0 and len(matches) > 1:
324
                    mid = int(len(matches)*0.5)
325
                    lhs = matches[0:mid]
326
                    rhs = matches[mid:]
327
                elif sign == -1:
328
                    lhs = matches
329
                    rhs = []
330
                else:
331
                    lhs = []
332
                    rhs = matches
333

    
334
                for match in lhs:
335
                    #print(match)
336
                    pool.append((-1, match))
337
                    visited.insert(0, match)
338

    
339
                for match in rhs:
340
                    #print(match)
341
                    pool.append((1, match))
342
                    visited.append(match)
343
                # up to here
344

    
345
        except Exception as ex:
346
            from App import App 
347

    
348
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
349
            App.mainWnd().addMessage.emit(MessageType.Error, message)
350

    
351
        #print(visited)
352
        return visited
353

    
354
'''
355
    @brief      connect attributes
356
    @author     humkyung
357
    @date       2018.06.17
358
    @history    humkyung 2018.06.21 paste connect attributes codes from recognizeLine function
359
                kyouho  2018.09.14  clear Item's owner 
360
'''
361
def connectAttrImpl(worker, update_line_type):
362
    import os, math
363
    from App import App
364
    from LineNoTracer import LineNoTracer
365
    from AppDocData import AppDocData
366
    from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
367
    from EngineeringInstrumentItem import QEngineeringInstrumentItem
368
    from EngineeringReducerItem import QEngineeringReducerItem
369
    from EngineeringEquipmentItem import QEngineeringEquipmentItem
370
    from QEngineeringOPCItem import QEngineeringOPCItem
371
    from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
372
    from EngineeringVendorItem import QEngineeringVendorItem
373
    from EngineeringEndBreakItem import QEngineeringEndBreakItem
374
    from EngineeringFlowMarkItem import QEngineeringFlowMarkItem
375
    from EngineeringReservedWordTextItem import QEngineeringReservedWordTextItem
376
    from QEngineeringSizeTextItem import QEngineeringSizeTextItem
377
    from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
378
    from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
379
    from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
380

    
381
    try:
382
        worker.displayMessage.emit('Initiating...')
383
        docdata = AppDocData.instance()
384
        symbols = []
385
        lines = []
386
        lineNos = []
387
        specBreak = []
388
        lineIndicator = []
389
        vendor_packages = [item for item in worker.graphicsView.scene.items() if type(item) is QEngineeringVendorItem]
390
        end_breaks = []
391
        #flow_marks = []
392

    
393
        for end_break in [item for item in worker.graphicsView.scene.items() if type(item) is QEngineeringEndBreakItem]:
394
            if not end_break.prop('Freeze'):
395
                end_break.transfer.onRemoved.emit(end_break)
396
                #worker.graphicsView.scene.removeItem(end_break)
397
            else:
398
                end_breaks.append(end_break)
399
        
400
        for flow_mark in [item for item in worker.graphicsView.scene.items() if type(item) is QEngineeringFlowMarkItem]:
401
            if not flow_mark.prop('Freeze'):
402
                flow_mark.transfer.onRemoved.emit(flow_mark)
403
                #worker.graphicsView.scene.removeItem(end_break)
404
            else:
405
                flow_marks.append(flow_mark)
406

    
407
        configs = docdata.getConfigs('Supplied by Tag Rule', 'by Vendor')
408
        vendorTag = configs[0].value if configs else 'By Vendor'
409
        for item in worker.graphicsView.scene.items():
410
            if type(item) is QEngineeringSpecBreakItem:
411
                specBreak.append(item)
412
            elif issubclass(type(item), SymbolSvgItem) and not type(item) is QEngineeringUnknownItem:
413
                matches = [vendor_package for vendor_package in vendor_packages if vendor_package.includes(item)]
414
                if matches:
415
                    item.set_property('Supplied By', vendorTag)
416
                else:
417
                    item.set_property('Supplied By', '')
418
                symbols.append(item)
419
            elif type(item) is QEngineeringLineNoTextItem:
420
                lineNos.append(item)
421
            elif type(item) is QEngineeringLineItem:
422
                #matches = [vendor_package for vendor_package in vendor_packages if vendor_package.includes(item)]
423
                #if not matches: lines.append(item)
424
                lines.append(item)
425
            elif type(item) is QEngineeringUnknownItem and item.lineIndicator != 'False':
426
                lineIndicator.append(item)
427
            elif issubclass(type(item), QEngineeringTextItem):
428
                item.owner = None
429

    
430
        # remove unknown line's
431
        pastTrim = docdata.tracerLineNos
432
        treeWidget = App.mainWnd().itemTreeWidget
433
        for pastTrimIndex in reversed(range(len(pastTrim))):
434
            if type(pastTrim[pastTrimIndex]) is QEngineeringTrimLineNoTextItem:
435
                try:
436
                    connected_items = pastTrim[pastTrimIndex].getConnectedItems()
437
                    for item in connected_items:
438
                        treeWidget.addTreeItem(treeWidget.SymbolsTreeItem, item)
439
                    pastTrim[pastTrimIndex].explode()
440
                finally:
441
                    pass
442

    
443
        # trace line no
444
        tracer = LineNoTracer(symbols, lines, lineNos, specBreak, lineIndicator, vendor_packages, end_breaks)
445
        tracer.execute(worker.displayMessage, worker.updateProgress)
446
        # up to here
447

    
448
        # connect attribute
449
        worker.displayMessage.emit('Connecting Attribute...')
450
        texts = [item for item in worker.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
451
        for text in texts:
452
            text.onwer = None
453
        for symbol in symbols:
454
            try:
455
                symbol.connectAttribute(texts)
456
            except Exception as ex:
457
                from App import App 
458
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
459
                App.mainWnd().addMessage.emit(MessageType.Error, message)
460

    
461
        """ try to connect label to valve """
462
        labels = [symbol for symbol in symbols if type(symbol) is QEngineeringInstrumentItem and not symbol.has_connection]
463
        #print(labels[0])
464
        valves = [symbol for symbol in symbols if (type(symbol) is QEngineeringInstrumentItem and symbol.has_connection) and type(symbol) is not QEngineeringReducerItem and type(symbol) is not QEngineeringEquipmentItem \
465
            and type(symbol) is not QEngineeringOPCItem and type(symbol) is not QEngineeringSpecBreakItem]
466
        #print(valves[0])
467
        for valve in valves:
468
            valve.connectAttribute(labels, clear=False)
469

    
470
        for symbol in symbols:
471
            for assoc in symbol.associations():
472
                if assoc.owner is None:
473
                    assoc.owner = symbol
474

    
475
        """ try to find text item's owner """
476
        texts = [item for item in worker.graphicsView.scene.items() if type(item) is QEngineeringReservedWordTextItem]
477
        for text in texts:
478
            text.findOwner(lines)
479
        texts = [item for item in worker.graphicsView.scene.items() if type(item) is QEngineeringSizeTextItem or type(item) is QEngineeringValveOperCodeTextItem or type(item) is QEngineeringTagNoTextItem]            
480
        for text in texts:
481
            text.findOwner(symbols)
482

    
483
        """ update line type """
484
        if update_line_type == True:
485
            worker.displayMessage.emit('Updating Line Type...')
486
            #lines = [line for line in worker.graphicsView.scene.items() if type(line) is QEngineeringLineItem]
487
            #for line in lines: line.lineType = 'Primary'
488
            for line in lines: line.update_line_type()
489

    
490
        """make end break"""
491
        end_break_names = docdata.getSymbolListByType('type', 'End Break')
492
        if len(end_break_names) is not 0:
493
                
494
            svgFileName = end_break_names[0].sName
495
            symbol = docdata.getSymbolByQuery('name', svgFileName)
496
            svgFilePath = os.path.join(docdata.getCurrentProject().getSvgFilePath(), symbol.getType(), svgFileName+'.svg')
497

    
498
            #end_breaks = []
499
            lineNo_froms = []
500
            lineNo_tos = []
501

    
502
            for lineNo in lineNos:
503
                lineNo_froms.append(lineNo.prop('From')) if lineNo.prop('From') is not None else None
504
                lineNo_tos.append(lineNo.prop('To')) if lineNo.prop('To') is not None else None
505
                #end_breaks.extend(lineNo.end_break())
506

    
507
            for line_end in lineNo_froms + lineNo_tos:
508
                #print(type(line_end))
509
                for connector in line_end.connectors:
510
                    if connector.connectedItem is not None and connector.connectedItem.owner is not line_end.owner:
511
                        end_break = SymbolSvgItem.createItem(symbol.getType(), svgFilePath)
512
                        pt = [connector.center()[0] - float(symbol.getOriginalPoint().split(',')[0]), connector.center()[1] - float(symbol.getOriginalPoint().split(',')[1])]
513
                        origin = [0,0]
514
                        if 2 == len(symbol.getOriginalPoint().split(',')):
515
                            tokens = symbol.getOriginalPoint().split(',')
516
                            origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
517
                        end_break.buildItem(svgFileName, symbol.getType(), 5.7, pt, [end_break.boundingRect().width(), end_break.boundingRect().height()], origin, [], symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getHasInstrumentLabel())
518
        
519
                        end_break.set_property('Connected Item', connector.connectedItem)
520
                        end_break.setToolTip('owner : ' + str(line_end))
521
                        end_break.area = 'Drawing'
522
                        end_break.owner = line_end
523
                        end_breaks.append(end_break)
524
            
525
            if end_breaks:
526
            # check dulplication
527
                dupl = set()
528
                for i in range(len(end_breaks)):
529
                    for j in range(len(end_breaks)):
530
                        if i == j: continue
531
                        else:
532
                            setI = set([end_breaks[i].owner, end_breaks[i].prop('Connected Item')])
533
                            setJ = set([end_breaks[j].owner, end_breaks[j].prop('Connected Item')])
534
                            if not (setI - setJ):
535
                                index = [i, j]
536
                                index.sort()
537
                                index = tuple(index)
538
                                dupl.add(index)
539
                #print(dupl)
540
                dupl = list(set([(indexSet[1] if not end_breaks[indexSet[1]].prop('Freeze') else indexSet[0]) for indexSet in list(dupl)]))
541
                dupl.sort(reverse=True)
542
                #print(dupl)
543
                for index in dupl:
544
                    end_breaks.pop(index)
545

    
546
                for end_break in end_breaks:
547
                    if not end_break.prop('Freeze'):
548
                        end_break.transfer.onRemoved.connect(App.mainWnd().itemRemoved)
549
                        end_break.addSvgItemToScene(worker.graphicsView.scene)
550
        
551
        """make flow mark"""
552
        for line in lines:
553
            line.flowMark = None
554
            line.update_arrow()
555

    
556
        configs = docdata.getConfigs('Flow Mark')
557
        position = int(configs[0].value) if 2 == len(configs) else 100
558
        length = int(configs[1].value) if 2 == len(configs) else 200
559
        for lineNo in lineNos + docdata.tracerLineNos:
560
            lineNo.update_flow_mark(position, length)
561

    
562
        '''
563
        line_names = docdata.getSymbolListByType('type', 'Flow Mark')
564
        if len(line_names) is not 0:
565
                
566
            svgFileName = line_names[0].sName
567
            symbol = docdata.getSymbolByQuery('name', svgFileName)
568
            svgFilePath = os.path.join(docdata.getCurrentProject().getSvgFilePath(), symbol.getType(), svgFileName+'.svg')
569

570
            allowed_error = 0.000001
571

572
            for lineNo in lineNos + docdata.tracerLineNos:
573
                for run in lineNo.runs:
574
                    pre = None
575
                    preRadian = None
576
                    for item in run.items:
577
                        if pre is None and type(item) is QEngineeringLineItem and (item._lineType == 'Primary' or item._lineType == 'Secondary'):
578
                            pre = item
579
                            start = item.line().p1()
580
                            end = item.line().p2()
581
                            _dir = [(end.x() - start.x())/item.length(), (end.y() - start.y())/item.length()]
582
                            radian = math.atan2(_dir[0], _dir[1]) - math.pi / 2
583
                            preRadian = radian if radian >= 0 else radian + 2 * math.pi
584
                            preDir = _dir
585
                            #print(_dir)
586
                            continue
587
                        elif type(item) is QEngineeringLineItem and (item._lineType == 'Primary' or item._lineType == 'Secondary'):
588
                            pre._flowMark = []
589
                            start = item.line().p1()
590
                            end = item.line().p2()
591
                            _dir = [(end.x() - start.x())/item.length(), (end.y() - start.y())/item.length()]
592
                            radian = math.atan2(_dir[0], _dir[1]) - math.pi / 2
593
                            currRadian = radian if radian >= 0 else radian + 2 * math.pi
594
                            if abs(currRadian - preRadian) > allowed_error:
595
                                # insert flow mark at pre line
596
                                #print(currRadian)
597
                                flow_mark = SymbolSvgItem.createItem(symbol.getType(), svgFilePath)
598
                                pt = [pre.connectors[1].center()[0] - float(symbol.getOriginalPoint().split(',')[0]) - preDir[0] * 20, pre.connectors[1].center()[1] - float(symbol.getOriginalPoint().split(',')[1]) - preDir[1] * 20]
599
                                origin = [0,0]
600
                                if 2 == len(symbol.getOriginalPoint().split(',')):
601
                                    tokens = symbol.getOriginalPoint().split(',')
602
                                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
603
                                flow_mark.buildItem(svgFileName, symbol.getType(), preRadian, pt, [flow_mark.boundingRect().width(), flow_mark.boundingRect().height()], origin, [], symbol.getBaseSymbol(), symbol.getAdditionalSymbol(), symbol.getHasInstrumentLabel())
604
                                flow_mark.setToolTip('owner : ' + str(pre))
605
                                flow_mark.area = 'Drawing'
606
                                flow_mark.owner = pre
607
                                flow_mark.setParentItem(pre)
608
                                pre._flowMark.append(flow_mark)
609
                                flow_marks.append(flow_mark)
610

611
                                pre = item
612
                                preDir = _dir
613
                                preRadian = currRadian
614
            
615
            for flow_mark in flow_marks:
616
                if not flow_mark.prop('Freeze'):
617
                    flow_mark.transfer.onRemoved.connect(App.mainWnd().itemRemoved)
618
                    flow_mark.addSvgItemToScene(worker.graphicsView.scene)
619
            '''
620

    
621
    except Exception as ex:
622
        from App import App 
623
        message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
624
        App.mainWnd().addMessage.emit(MessageType.Error, message)
625
    except:
626
        (type1, value, traceback) = sys.exc_info()
627
        sys.excepthook(type1, value, traceback)
628
    finally:
629
        worker.finished.emit()
630

    
클립보드 이미지 추가 (최대 크기: 500 MB)