304 |
304 |
|
305 |
305 |
def importClicked(self):
|
306 |
306 |
if self.ui.checkBoxLegend.isChecked():
|
307 |
|
pass
|
|
307 |
self.on_import_legend()
|
308 |
308 |
else:
|
309 |
309 |
self.on_import_autocad()
|
310 |
310 |
|
... | ... | |
794 |
794 |
QMessageBox.information(self, self.tr('Information'), self.tr('Successfully saved.'))
|
795 |
795 |
"""up to here"""
|
796 |
796 |
|
|
797 |
def on_import_legend(self):
|
|
798 |
import XmlGenerator as xg
|
|
799 |
import uuid
|
|
800 |
from Drawing import Drawing
|
|
801 |
from SymbolEditorDialog import QSymbolEditorDialog
|
|
802 |
from App import App
|
|
803 |
|
|
804 |
if not self._dwgs:
|
|
805 |
QMessageBox.information(self, self.tr('Information'), self.tr('There is no selected file'))
|
|
806 |
return
|
|
807 |
|
|
808 |
app_doc_data = AppDocData.instance()
|
|
809 |
project = app_doc_data.getCurrentProject()
|
|
810 |
|
|
811 |
temp_path, drawing_path = project.getTempPath(), project.getDrawingFilePath()
|
|
812 |
id2_xml_files = [f for f in os.listdir(temp_path) if os.path.isfile(os.path.join(temp_path, f)) and
|
|
813 |
(os.path.splitext(f)[1].upper() == '.XML')]
|
|
814 |
|
|
815 |
for _file in self._dwgs:
|
|
816 |
file_name = os.path.splitext(os.path.basename(_file))[0]
|
|
817 |
id2_image_file = os.path.join(drawing_path, file_name + '.png')
|
|
818 |
autocad_xml_path = os.path.join(os.path.dirname(_file), os.path.splitext(os.path.basename(_file))[0] + '.xml')
|
|
819 |
matches = [id2_xml_file for id2_xml_file in id2_xml_files if id2_xml_file.replace(file_name, '').upper() == '.XML']
|
|
820 |
if matches and os.path.exists(id2_image_file):
|
|
821 |
try:
|
|
822 |
symbols = {}
|
|
823 |
|
|
824 |
drawing = Drawing(str(uuid.uuid4()), file_name + ".PNG", None)
|
|
825 |
_image = drawing.image#QImage(id2_image_file, "PNG")
|
|
826 |
bytesPerLine = _image.shape[1]
|
|
827 |
image = QImage(_image.data, _image.shape[1], _image.shape[0], bytesPerLine, QImage.Format_Indexed8)
|
|
828 |
autocad_xml = parse(autocad_xml_path)
|
|
829 |
|
|
830 |
autocad_xml_root = autocad_xml.getroot()
|
|
831 |
|
|
832 |
id2_bbox = self.get_contents_size_from_image(id2_image_file)
|
|
833 |
|
|
834 |
for blk_tbl_record in autocad_xml_root.iter('AcDbBlockTableRecord'):
|
|
835 |
if blk_tbl_record.attrib['Name'].upper() != '*Model_Space'.upper():
|
|
836 |
continue
|
|
837 |
|
|
838 |
min_values = [float(token) for token in
|
|
839 |
blk_tbl_record.attrib['MinExtents'].strip('()').split(',')]
|
|
840 |
max_values = [float(token) for token in
|
|
841 |
blk_tbl_record.attrib['MaxExtents'].strip('()').split(',')]
|
|
842 |
autocad_bbox = [min_values[0], min_values[1],
|
|
843 |
max_values[0] - min_values[0], max_values[1] - min_values[1]]
|
|
844 |
|
|
845 |
if self.ui.checkBoxAuto.isChecked():
|
|
846 |
scale_x = id2_bbox[2] / autocad_bbox[2]
|
|
847 |
scale_y = id2_bbox[3] / autocad_bbox[3]
|
|
848 |
self.scales = [scale_x, scale_y]
|
|
849 |
offsets = [id2_bbox[0] - autocad_bbox[0] * scale_x, id2_bbox[3] + id2_bbox[1]]
|
|
850 |
self.offsets = offsets + [autocad_bbox[1]]
|
|
851 |
else:
|
|
852 |
self.scales = [self.ui.doubleSpinBox.value(), self.ui.doubleSpinBox_2.value()]
|
|
853 |
self.offsets = [self.ui.spinBoxTextX.value(), self.ui.spinBoxTextY.value(), id2_bbox[5]]
|
|
854 |
|
|
855 |
for blk_ref in blk_tbl_record.iter('AcDbBlockReference'):
|
|
856 |
node = self.symbol_info(blk_ref)
|
|
857 |
if node[0] not in symbols:
|
|
858 |
symbols[node[0]] = node
|
|
859 |
|
|
860 |
for key, value in symbols.items():
|
|
861 |
symbolEditorDialog = QSymbolEditorDialog(self, image.copy(math.floor(value[2][0]), math.floor(value[2][1]), \
|
|
862 |
math.ceil(value[3] + 1), math.ceil(value[4] + 1)), \
|
|
863 |
AppDocData.instance().getCurrentProject(), value[1], False)
|
|
864 |
(isAccepted, _, _, _, _) = symbolEditorDialog.showDialog()
|
|
865 |
|
|
866 |
if not isAccepted:
|
|
867 |
reply = QMessageBox.question(self, self.tr('Stop?'), self.tr('Do you want to stop registering symbols?'), QMessageBox.Yes, QMessageBox.Cancel)
|
|
868 |
if reply == QMessageBox.Yes:
|
|
869 |
break
|
|
870 |
|
|
871 |
App.mainWnd().symbolTreeWidget.initSymbolTreeView()
|
|
872 |
|
|
873 |
except Exception as ex:
|
|
874 |
from App import App
|
|
875 |
from AppDocData import MessageType
|
|
876 |
|
|
877 |
message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
|
|
878 |
f"{sys.exc_info()[-1].tb_lineno}"
|
|
879 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
|
880 |
else:
|
|
881 |
from App import App
|
|
882 |
from AppDocData import MessageType
|
|
883 |
|
|
884 |
message = 'There is no xml file'
|
|
885 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
|
886 |
|
|
887 |
def get_contents_size_from_image(self, img_file_path: str) -> list:
|
|
888 |
"""get actual size of image from image file"""
|
|
889 |
from AppDocData import AppDocData
|
|
890 |
import cv2
|
|
891 |
|
|
892 |
min_x, min_y, max_x, max_y, width, height = None, None, None, None, None, None
|
|
893 |
|
|
894 |
img = AppDocData.my_imread(file_path=img_file_path)
|
|
895 |
_width = img.shape[1]
|
|
896 |
_height = img.shape[0]
|
|
897 |
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
|
898 |
img = cv2.bitwise_not(img) # background should be 'BLACK'
|
|
899 |
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
900 |
for cnt in contours:
|
|
901 |
x, y, width, height = cv2.boundingRect(cnt)
|
|
902 |
min_x = x if not min_x else min(x, min_x)
|
|
903 |
min_y = y if not min_y else min(y, min_y)
|
|
904 |
max_x = x + width if not max_x else max(x + width, max_x)
|
|
905 |
max_y = y + height if not max_y else max(y + height, max_y)
|
|
906 |
|
|
907 |
del img
|
|
908 |
|
|
909 |
return min_x, min_y, max_x - min_x, max_y - min_y, _width, _height
|
|
910 |
|
797 |
911 |
def on_import_autocad(self):
|
798 |
912 |
"""
|
799 |
913 |
import line, text and symbol from autocad
|
800 |
914 |
@return: None
|
801 |
915 |
"""
|
802 |
916 |
|
803 |
|
from AppDocData import Config
|
804 |
917 |
import XmlGenerator as xg
|
805 |
918 |
|
806 |
|
def get_contents_size_from_image(img_file_path: str) -> list:
|
807 |
|
"""get actual size of image from image file"""
|
808 |
|
from AppDocData import AppDocData
|
809 |
|
import cv2
|
810 |
|
|
811 |
|
min_x, min_y, max_x, max_y, width, height = None, None, None, None, None, None
|
812 |
|
|
813 |
|
img = AppDocData.my_imread(file_path=img_file_path)
|
814 |
|
_width = img.shape[1]
|
815 |
|
_height = img.shape[0]
|
816 |
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
817 |
|
img = cv2.bitwise_not(img) # background should be 'BLACK'
|
818 |
|
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
819 |
|
for cnt in contours:
|
820 |
|
x, y, width, height = cv2.boundingRect(cnt)
|
821 |
|
min_x = x if not min_x else min(x, min_x)
|
822 |
|
min_y = y if not min_y else min(y, min_y)
|
823 |
|
max_x = x + width if not max_x else max(x + width, max_x)
|
824 |
|
max_y = y + height if not max_y else max(y + height, max_y)
|
825 |
|
|
826 |
|
del img
|
827 |
|
|
828 |
|
return min_x, min_y, max_x - min_x, max_y - min_y, _width, _height
|
829 |
|
|
830 |
919 |
if not self._dwgs:
|
831 |
920 |
QMessageBox.information(self, self.tr('Information'), self.tr('There is no selected file(s)'))
|
832 |
921 |
return
|
... | ... | |
881 |
970 |
line_type_name = line_type_tbl_record.attrib['Name']
|
882 |
971 |
line_types.append([line_type_oid, line_type_name])
|
883 |
972 |
|
|
973 |
'''
|
884 |
974 |
for blk_ref_record in autocad_xml_root.iter('AcDbBlockReference'):
|
885 |
975 |
blk_ref_handle = blk_ref_record.attrib['Handle']
|
886 |
976 |
blk_ref_name = blk_ref_record.attrib['Name']
|
887 |
977 |
symbols.append([blk_ref_handle, blk_ref_name])
|
|
978 |
'''
|
888 |
979 |
"""up to here"""
|
889 |
980 |
|
890 |
981 |
id2_xml_path = os.path.join(temp_path, matches[0])
|
... | ... | |
892 |
983 |
id2_xml_root = id2_xml.getroot()
|
893 |
984 |
|
894 |
985 |
#id2_bbox = [0, 0, 9600, 6781]
|
895 |
|
id2_bbox = get_contents_size_from_image(id2_image_file)
|
|
986 |
id2_bbox = self.get_contents_size_from_image(id2_image_file)
|
896 |
987 |
|
897 |
988 |
if 'Symbol' in will_be_converted_items:
|
898 |
989 |
symbols_node = id2_xml_root.find(xg.SYMBOL_LIST_NODE_NAME)
|
... | ... | |
963 |
1054 |
symbols_node.append(node)
|
964 |
1055 |
|
965 |
1056 |
if 'Text' in will_be_converted_items:
|
966 |
|
angle = round(float(blk_ref.attrib['Angle']), 2)
|
|
1057 |
#angle = round(float(blk_ref.attrib['Angle']), 2)
|
967 |
1058 |
for record in blk_ref.iter('AcDbAttribute'):
|
968 |
1059 |
node = self.text_to_xml(record)
|
969 |
1060 |
if node:
|
... | ... | |
1004 |
1095 |
QMessageBox.information(self, self.tr('Information'), self.tr('Importing finished!'),
|
1005 |
1096 |
QMessageBox.Close)
|
1006 |
1097 |
|
|
1098 |
def symbol_info(self, blk_ref_node) -> str:
|
|
1099 |
"""try to convert block reference element to id2 xml"""
|
|
1100 |
import symbol
|
|
1101 |
|
|
1102 |
try:
|
|
1103 |
_name = blk_ref_node.attrib['Name']
|
|
1104 |
if '+' in _name:
|
|
1105 |
name = _name.split('+')[1]
|
|
1106 |
type = _name.split('+')[2]
|
|
1107 |
else:
|
|
1108 |
name = _name
|
|
1109 |
type = 'Valves'
|
|
1110 |
_origin = self.convert_to_image_coords([float(blk_ref_node.attrib['X']), float(blk_ref_node.attrib['Y'])])
|
|
1111 |
|
|
1112 |
"""check if maxtents or minextents attribute exists"""
|
|
1113 |
if 'MaxExtents' not in blk_ref_node.attrib or 'MinExtents' not in blk_ref_node.attrib:
|
|
1114 |
return None
|
|
1115 |
|
|
1116 |
min_extents, max_extents = None, None
|
|
1117 |
tokens = blk_ref_node.attrib['MaxExtents'].strip('()').split(',')
|
|
1118 |
if 3 == len(tokens):
|
|
1119 |
max_extents = self.convert_to_image_coords([float(tokens[0]), float(tokens[1])])
|
|
1120 |
|
|
1121 |
tokens = blk_ref_node.attrib['MinExtents'].strip('()').split(',')
|
|
1122 |
if 3 == len(tokens):
|
|
1123 |
min_extents = self.convert_to_image_coords([float(tokens[0]), float(tokens[1])])
|
|
1124 |
|
|
1125 |
_height = abs(max_extents[1] - min_extents[1])
|
|
1126 |
_width = abs(max_extents[0] - min_extents[0])
|
|
1127 |
|
|
1128 |
loc = [min(min_extents[0], max_extents[0]), min(min_extents[1], max_extents[1])]
|
|
1129 |
|
|
1130 |
origin = [math.ceil(_origin[0] - loc[0]), math.ceil(_origin[1] - loc[1])]
|
|
1131 |
|
|
1132 |
ret = symbol.SymbolBase(name, type, 0.75, 0, 1, 0, 0, 0, \
|
|
1133 |
"{},{}".format(origin[0], origin[1]), \
|
|
1134 |
'', \
|
|
1135 |
'None', '', 0, 0, -1, \
|
|
1136 |
iType=-2, detectFlip=0, text_area='')
|
|
1137 |
|
|
1138 |
#symbolEditorDialog = QSymbolEditorDialog(self, image.copy(math.floor(loc[0]), math.floor(int(loc[1])), math.ceil(_width + 1), math.ceil(_height + 1)), \
|
|
1139 |
# AppDocData.instance().getCurrentProject(), ret, False)
|
|
1140 |
#(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
|
|
1141 |
|
|
1142 |
return [_name, ret, loc, _width, _height]
|
|
1143 |
except Exception as ex:
|
|
1144 |
from App import App
|
|
1145 |
from AppDocData import MessageType
|
|
1146 |
|
|
1147 |
message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
|
|
1148 |
f"{sys.exc_info()[-1].tb_lineno}"
|
|
1149 |
|
|
1150 |
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
|
1151 |
|
|
1152 |
return None
|
|
1153 |
|
1007 |
1154 |
def convert_to_image_coords(self, pt):
|
1008 |
1155 |
"""convert autocad coordinates to image coordinates"""
|
1009 |
1156 |
if self.ui.checkBoxAuto.isChecked():
|
... | ... | |
1013 |
1160 |
|
1014 |
1161 |
def symbol_to_xml(self, blk_ref_node, mapping_configs: list) -> str:
|
1015 |
1162 |
"""try to convert block reference element to id2 xml"""
|
1016 |
|
import uuid
|
1017 |
1163 |
from SymbolSvgItem import SymbolSvgItem
|
1018 |
1164 |
|
1019 |
1165 |
try:
|