개정판 81940728
issue #480: GAP testing
Change-Id: I96ec8deb577c3f3a778d6526b4f646900103463c
DTI_PID/DTI_PID/LineDetector.py | ||
---|---|---|
4 | 4 |
import math |
5 | 5 |
import shapely |
6 | 6 |
|
7 |
from PyQt5.QtCore import * |
|
8 |
from PyQt5.QtGui import * |
|
9 |
from PyQt5.QtWidgets import * |
|
10 |
|
|
7 | 11 |
__author__ = "humkyung <humkyung.doftech.co.kr>" |
8 | 12 |
__version__ = '1.0.0' |
9 | 13 |
|
... | ... | |
77 | 81 |
qy = origin[1] + math.sin(angle) * dx + math.cos(angle) * dy |
78 | 82 |
return [qx, qy] |
79 | 83 |
|
80 |
def is_connected(self, lhs, rhs, toler=20): |
|
84 |
def is_connected(self, lhs, rhs, toler=20, gap=None):
|
|
81 | 85 |
"""check if given two lines are connected""" |
82 | 86 |
|
83 | 87 |
try: |
84 |
''' |
|
85 |
len_x = [] |
|
86 |
len_y = [] |
|
87 |
|
|
88 |
dx = abs(lhs[0][0] - rhs[0][0]) |
|
89 |
dy = abs(lhs[0][1] - rhs[0][1]) |
|
90 |
len_x.append(dx) |
|
91 |
len_y.append(dy) |
|
92 |
dx = abs(lhs[1][0] - rhs[0][0]) |
|
93 |
dy = abs(lhs[1][1] - rhs[0][1]) |
|
94 |
len_x.append(dx) |
|
95 |
len_y.append(dy) |
|
96 |
dx = abs(lhs[0][0] - rhs[1][0]) |
|
97 |
dy = abs(lhs[0][1] - rhs[1][1]) |
|
98 |
len_x.append(dx) |
|
99 |
len_y.append(dy) |
|
100 |
dx = abs(lhs[1][0] - rhs[1][0]) |
|
101 |
dy = abs(lhs[1][1] - rhs[1][1]) |
|
102 |
len_x.append(dx) |
|
103 |
len_y.append(dy) |
|
104 |
|
|
105 |
for index in range(4): |
|
106 |
if (len_x[index] < toler and len_y[index] < toler * 5) or (len_x[index] < toler * 5 and len_y[index] < toler): |
|
107 |
return True |
|
108 |
|
|
109 |
return False |
|
110 |
''' |
|
111 |
|
|
88 |
if gap: |
|
89 |
l_v = self.is_vertical([lhs[0][0], lhs[0][1], lhs[1][0], lhs[1][1]]) |
|
90 |
r_v = self.is_vertical([rhs[0][0], rhs[0][1], rhs[1][0], rhs[1][1]]) |
|
91 |
# return False if not same angle |
|
92 |
if l_v ^ r_v: |
|
93 |
return False |
|
94 |
len_x = [] |
|
95 |
len_y = [] |
|
96 |
x_y_1 = [] |
|
97 |
x_y_2 = [] |
|
98 |
|
|
99 |
dx = abs(lhs[0][0] - rhs[0][0]) |
|
100 |
dy = abs(lhs[0][1] - rhs[0][1]) |
|
101 |
len_x.append(dx) |
|
102 |
len_y.append(dy) |
|
103 |
x_y_1.append((lhs[0][0], lhs[0][1])) |
|
104 |
x_y_2.append((rhs[0][0], rhs[0][1])) |
|
105 |
|
|
106 |
dx = abs(lhs[1][0] - rhs[0][0]) |
|
107 |
dy = abs(lhs[1][1] - rhs[0][1]) |
|
108 |
len_x.append(dx) |
|
109 |
len_y.append(dy) |
|
110 |
x_y_1.append((lhs[1][0], lhs[1][1])) |
|
111 |
x_y_2.append((rhs[0][0], rhs[0][1])) |
|
112 |
|
|
113 |
dx = abs(lhs[0][0] - rhs[1][0]) |
|
114 |
dy = abs(lhs[0][1] - rhs[1][1]) |
|
115 |
len_x.append(dx) |
|
116 |
len_y.append(dy) |
|
117 |
x_y_1.append((lhs[0][0], lhs[0][1])) |
|
118 |
x_y_2.append((rhs[1][0], rhs[1][1])) |
|
119 |
|
|
120 |
dx = abs(lhs[1][0] - rhs[1][0]) |
|
121 |
dy = abs(lhs[1][1] - rhs[1][1]) |
|
122 |
len_x.append(dx) |
|
123 |
len_y.append(dy) |
|
124 |
x_y_1.append((lhs[1][0], lhs[1][1])) |
|
125 |
x_y_2.append((rhs[1][0], rhs[1][1])) |
|
126 |
|
|
127 |
count = 0 |
|
128 |
for index in range(4): |
|
129 |
if (l_v and (len_x[index] < toler / 2 and len_y[index] < toler * 5)) or \ |
|
130 |
(not l_v and (len_x[index] < toler * 5 and len_y[index] < toler / 2)): |
|
131 |
x1, y1 = x_y_1[index][0], x_y_1[index][1] |
|
132 |
x2, y2 = x_y_2[index][0], x_y_2[index][1] |
|
133 |
x = (x1 + x2) / 2 |
|
134 |
y = (y1 + y2) / 2 |
|
135 |
for sym_rect in gap: |
|
136 |
if sym_rect.contains(QPoint(x, y)): |
|
137 |
return False |
|
138 |
|
|
139 |
count += 1 |
|
112 | 140 |
|
113 |
length = [] |
|
114 |
# check if share one point |
|
115 |
dx = (lhs[0][0] - rhs[0][0]) |
|
116 |
dy = (lhs[0][1] - rhs[0][1]) |
|
117 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
118 |
dx = (lhs[1][0] - rhs[0][0]) |
|
119 |
dy = (lhs[1][1] - rhs[0][1]) |
|
120 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
121 |
dx = (lhs[0][0] - rhs[1][0]) |
|
122 |
dy = (lhs[0][1] - rhs[1][1]) |
|
123 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
124 |
dx = (lhs[1][0] - rhs[1][0]) |
|
125 |
dy = (lhs[1][1] - rhs[1][1]) |
|
126 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
127 |
matches = [len for len in length if len < toler] |
|
128 |
# up to here |
|
129 |
|
|
130 |
return len(matches) == 1 |
|
141 |
return False if count is not 1 else True |
|
142 |
else: |
|
143 |
length = [] |
|
144 |
# check if share one point |
|
145 |
dx = (lhs[0][0] - rhs[0][0]) |
|
146 |
dy = (lhs[0][1] - rhs[0][1]) |
|
147 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
148 |
dx = (lhs[1][0] - rhs[0][0]) |
|
149 |
dy = (lhs[1][1] - rhs[0][1]) |
|
150 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
151 |
dx = (lhs[0][0] - rhs[1][0]) |
|
152 |
dy = (lhs[0][1] - rhs[1][1]) |
|
153 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
154 |
dx = (lhs[1][0] - rhs[1][0]) |
|
155 |
dy = (lhs[1][1] - rhs[1][1]) |
|
156 |
length.append(math.sqrt(dx * dx + dy * dy)) |
|
157 |
matches = [len for len in length if len < toler] |
|
158 |
# up to here |
|
159 |
|
|
160 |
return len(matches) == 1 |
|
131 | 161 |
|
132 | 162 |
except Exception as ex: |
133 | 163 |
from App import App |
... | ... | |
139 | 169 |
|
140 | 170 |
return False |
141 | 171 |
|
142 |
def is_collinear(self, lhs, rhs, toler): |
|
172 |
def is_vertical(self, line): |
|
173 |
from HoughBundler import HoughBundler |
|
174 |
|
|
175 |
diagonal = HoughBundler() |
|
176 |
angle = diagonal.get_orientation(line) |
|
177 |
|
|
178 |
if 45 < angle < 135: |
|
179 |
return False |
|
180 |
else: |
|
181 |
return True |
|
182 |
|
|
183 |
def is_collinear(self, lhs, rhs, toler, gap=None): |
|
143 | 184 |
"""check if given two lines are connected and collinear""" |
144 | 185 |
try: |
145 |
if self.is_connected(lhs, rhs, toler): |
|
186 |
if self.is_connected(lhs, rhs, toler, gap=gap):
|
|
146 | 187 |
dx = lhs[1][0] - lhs[0][0] |
147 | 188 |
dy = lhs[1][1] - lhs[0][1] |
148 | 189 |
length = math.sqrt(dx * dx + dy * dy) |
... | ... | |
341 | 382 |
sys.exc_info()[-1].tb_lineno) |
342 | 383 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
343 | 384 |
|
344 |
def mergeLines(self, connectedLines, toler): |
|
385 |
def mergeLines(self, connectedLines, toler=20, symbol_areas=None):
|
|
345 | 386 |
"""merge lines(1.connect collinear lines 2.connect lines)""" |
346 | 387 |
try: |
388 |
# merge near line |
|
347 | 389 |
for line in connectedLines: |
348 | 390 |
matches = [param for param in connectedLines |
349 | 391 |
if (line != param) and self.is_collinear(line, param, toler)] |
... | ... | |
354 | 396 |
connectedLines.append(mergedLine) |
355 | 397 |
for match in matches: |
356 | 398 |
connectedLines.remove(match) |
399 |
# up to here |
|
400 |
|
|
401 |
# merge gap |
|
402 |
for line in connectedLines: |
|
403 |
matches = [param for param in connectedLines |
|
404 |
if (line != param) and self.is_collinear(line, param, toler, gap=symbol_areas)] |
|
405 |
if len(matches) > 0: |
|
406 |
matches.append(line) |
|
407 |
mergedLine = self.connect_lines(matches, toler) |
|
408 |
if mergedLine is not None and len(mergedLine) > 0: |
|
409 |
connectedLines.append(mergedLine) |
|
410 |
for match in matches: |
|
411 |
connectedLines.remove(match) |
|
412 |
# up to here |
|
357 | 413 |
except Exception as ex: |
358 | 414 |
from App import App |
359 | 415 |
from AppDocData import MessageType |
DTI_PID/DTI_PID/RecognitionDialog.py | ||
---|---|---|
656 | 656 |
|
657 | 657 |
# remove line has not connected item |
658 | 658 |
try: |
659 |
for line in reversed(app_doc_data.lines): |
|
660 |
if not line.has_connection: |
|
661 |
app_doc_data.lines.remove(line) |
|
659 |
count = 1 |
|
660 |
while count > 0: |
|
661 |
count = 0 |
|
662 |
for line in reversed(app_doc_data.lines): |
|
663 |
if not line.has_connection: |
|
664 |
app_doc_data.lines.remove(line) |
|
665 |
app_doc_data.allItems.remove(line) |
|
666 |
count += 1 |
|
667 |
for item in app_doc_data.lines + symbols: |
|
668 |
for conn in item.connectors: |
|
669 |
if conn.connectedItem is line: |
|
670 |
conn.connectedItem = None |
|
671 |
|
|
662 | 672 |
except Exception as ex: |
663 | 673 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[ |
664 | 674 |
-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
... | ... | |
738 | 748 |
connectedLines.extend(res) |
739 | 749 |
|
740 | 750 |
# line detection without symbol connection point info |
741 |
configs = app_doc_data.getConfigs('Line', 'Diagonal') |
|
742 |
if configs and int(configs[0].value) is 1: |
|
743 |
remainLines = detector.detectLineWithoutSymbol() |
|
744 |
windowSize = app_doc_data.getSlidingWindowSize() |
|
745 |
thickness = int(windowSize[1]) |
|
751 |
remainLines = detector.detectLineWithoutSymbol() |
|
752 |
windowSize = app_doc_data.getSlidingWindowSize() |
|
753 |
thickness = int(windowSize[1]) |
|
746 | 754 |
|
755 |
configs = app_doc_data.getConfigs('Line', 'Diagonal') |
|
756 |
if configs and int(configs[0].value) is not 1: |
|
747 | 757 |
diagonal = HoughBundler() |
748 | 758 |
for index in reversed(range(len(remainLines))): |
749 | 759 |
angle = diagonal.get_orientation([remainLines[index][0][0], remainLines[index][0][1], remainLines[index][1][0], remainLines[index][1][1]]) |
750 | 760 |
if not (angle < 3 or angle > 87): |
751 | 761 |
remainLines.pop(index) |
752 | 762 |
|
753 |
for line in remainLines:
|
|
754 |
line.append(thickness)
|
|
755 |
connectedLines.extend(remainLines)
|
|
763 |
for line in remainLines: |
|
764 |
line.append(thickness) |
|
765 |
connectedLines.extend(remainLines) |
|
756 | 766 |
|
757 | 767 |
configs = app_doc_data.getConfigs('Line Detector', 'Length to connect line') |
758 | 768 |
toler = int(configs[0].value) if configs else 20 |
759 |
detector.mergeLines(connectedLines, toler=toler) |
|
769 |
|
|
770 |
symbol_areas = [] |
|
771 |
for symbol in symbols: |
|
772 |
symbol_areas.append(QRect(symbol.loc[0] - area.x, symbol.loc[1] - area.y, symbol.size[0], symbol.size[1])) |
|
773 |
|
|
774 |
detector.mergeLines(connectedLines, toler=toler, symbol_areas=symbol_areas) |
|
760 | 775 |
|
761 | 776 |
for pts in connectedLines: |
762 | 777 |
line = QEngineeringLineItem( |
DTI_PID/DTI_PID/SpecBreakDialog.py | ||
---|---|---|
106 | 106 |
|
107 | 107 |
if tableDatas: |
108 | 108 |
valueComboBox = QComboBox(self) |
109 |
valueComboBox.addItem('') |
|
109 | 110 |
for value in tableDatas: |
110 | 111 |
valueComboBox.addItem(value[1]) |
111 | 112 |
return valueComboBox |
내보내기 Unified diff