프로젝트

일반

사용자정보

개정판 610a02c5

ID610a02c56d844e43430f61a96694f4fa271fadd8
상위 6e5ea1b0
하위 9a554a33

백흠경이(가) 4년 이상 전에 추가함

issue #1445: DEXPI용 클래스 추가

Change-Id: I875dec6125c091d37154c48a5ca3457b39995c95

차이점 보기:

DTI_PID/DTI_PID/DEXPI/Drawing.py
1
# coding: utf-8
2
""" This is Drawing module """
3

  
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from PyQt5.QtWidgets import *
6
from .Extent import Extent
7
from .Presentation import Presentation
8

  
9

  
10
class Drawing:
11
    def __init__(self):
12
        pass
13

  
14
    @staticmethod
15
    def to_xml(name: str, scene: QGraphicsScene) -> Element:
16
        """return element for drawing"""
17

  
18
        node = Element('Drawing')
19
        node.attrib['Name'] = name
20
        node.attrib['Type'] = 'PID'
21
        node.attrib['Title'] = ''
22
        Presentation.to_xml(node)
23
        Extent.to_xml(node, scene=scene)
24

  
25
        return node
DTI_PID/DTI_PID/DEXPI/Equipment.py
1
# coding: utf-8
2
""" This is Equipment module """
3

  
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from PyQt5.QtWidgets import *
6
from .Extent import Extent
7
from .Presentation import Presentation
8

  
9

  
10
class Equipment:
11
    def __init__(self):
12
        pass
13

  
14
    @staticmethod
15
    def to_xml(item) -> Element:
16
        """return element for equipment"""
17

  
18
        node = Element('Equipment')
19
        node.attrib['ID'] = str(item.uid)
20
        node.attrib['TagName'] = item.tag_no if item.tag_no else ''
21
        node.attrib['ComponentClass'] = ''
22
        node.attrib['ComponentName'] = ''
23
        node.attrib['ComponentType'] = ''
24
        node.attrib['Status'] = 'Current'
25

  
26
        Presentation.to_xml(node, layer='0', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
27
        Extent.to_xml(node, item=item)
28

  
29
        return node
30

  
31

  
32
class Nozzle:
33
    def __init__(self):
34
        pass
35

  
36
    @staticmethod
37
    def to_xml(item) -> Element:
38
        """return element for nozzle"""
39

  
40
        node = Element('Nozzle')
41
        node.attrib['ID'] = ''
42
        node.attrib['TagName'] = ''
43
        node.attrib['ComponentClass'] = 'Nozzle'
44
        node.attrib['ComponentName'] = ''
45
        node.attrib['ComponentType'] = ''
46
        node.attrib['Status'] = 'Current'
47

  
48
        Presentation.to_xml(node, layer='30', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
49

  
50
        return node
DTI_PID/DTI_PID/DEXPI/Extent.py
1
# coding: utf-8
2
""" This is Extent module """
3

  
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from PyQt5.QtWidgets import *
6
from SymbolSvgItem import SymbolSvgItem
7

  
8

  
9
class Extent:
10
    def __init__(self):
11
        pass
12

  
13
    @staticmethod
14
    def to_xml(parent: Element, item: SymbolSvgItem = None, scene: QGraphicsScene = None) -> Element:
15
        """return element for extent"""
16
        _node = SubElement(parent, 'Extent')
17

  
18
        rect = None
19
        if item:
20
            rect = item.boundingRect()
21
        elif scene:
22
            rect = scene.itemsBoundingRect()
23

  
24
        _min = SubElement(_node, 'Min')
25
        _min.attrib['X'] = str(int(rect.left()))
26
        _min.attrib['Y'] = str(int(rect.top()))
27
        _min.attrib['Z'] = '0'
28
        _max = SubElement(_node, 'Max')
29
        _max.attrib['X'] = str(int(rect.right()))
30
        _max.attrib['Y'] = str(int(rect.bottom()))
31
        _max.attrib['Z'] = '0'
32

  
33
        return _node
34

  
DTI_PID/DTI_PID/DEXPI/Presentation.py
1
# coding: utf-8
2
""" This is Presentation module """
3

  
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from PyQt5.QtWidgets import *
6
from .Extent import Extent
7

  
8

  
9
class Presentation:
10
    def __init__(self):
11
        pass
12

  
13
    @staticmethod
14
    def to_xml(parent: Element, layer: str = '', color: str = '16777215', line_type: str = '', line_weight: float = 1,
15
               r: float = 1, g: float = 1, b: float = 1) -> Element:
16
        """return element for Presentation"""
17

  
18
        node = SubElement(parent, 'Presentation')
19
        node.attrib['Layer'] = f"{layer}"
20
        node.attrib['Color'] = f"{color}"
21
        node.attrib['LineType'] = f"{line_type}"
22
        node.attrib['LineWeight'] = f"{line_weight}"
23
        node.attrib['R'] = f"{r}"
24
        node.attrib['G'] = f"{g}"
25
        node.attrib['B'] = f"{b}"
26

  
27
        return node
DTI_PID/DTI_PID/DEXPI/Shape.py
2 2
""" This is Shape module """
3 3

  
4 4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from .Presentation import Presentation
6

  
7

  
8
class Point:
9
    def __init__(self):
10
        pass
11

  
12
    @staticmethod
13
    def to_xml(name: str, x: float, y: float, z: float = 0) -> Element:
14
        """return element for control point"""
15

  
16
        node = Element(name)
17
        node.attrib['X'] = f"{x}"
18
        node.attrib['Y'] = f"{y}"
19
        node.attrib['Z'] = f"{z}"
20

  
21
        return node
5 22

  
6 23

  
7 24
class Line:
......
10 27
        self.end = end
11 28

  
12 29
    def to_xml(self):
13
        xml = Element('Line')
14
        presentation_node = SubElement(xml, 'Presentation')
15
        presentation_node.attrib['Layer'] = '125'
16
        presentation_node.attrib['Color'] = '0'
17
        presentation_node.attrib['LineType'] = '1'
18
        presentation_node.attrib['LineWeight'] = '0.35'
19
        presentation_node.attrib['R'] = '0'
20
        presentation_node.attrib['G'] = '0'
21
        presentation_node.attrib['B'] = '0'
22
        extent_node = SubElement(xml, 'Extent')
30
        node = Element('Line')
31
        Presentation.to_xml(node, layer='125', color='0', line_type='1', line_weight=0.35, r=0, g=0, b=0)
32
        extent_node = SubElement(node, 'Extent')
23 33
        min_node = SubElement(extent_node, 'Min')
24 34
        min_node.attrib['X'] = str(min(self.start.real, self.end.real))
25 35
        min_node.attrib['Y'] = str(min(self.start.imag, self.end.imag))
......
28 38
        max_node.attrib['X'] = str(max(self.start.real, self.end.real))
29 39
        max_node.attrib['Y'] = str(max(self.start.imag, self.end.imag))
30 40
        max_node.attrib['Z'] = '0'
31
        coordinate_node = SubElement(xml, 'Coordinate')
41
        coordinate_node = SubElement(node, 'Coordinate')
32 42
        coordinate_node.attrib['X'] = str(self.start.real)
33 43
        coordinate_node.attrib['Y'] = str(self.start.imag)
34 44
        coordinate_node.attrib['Z'] = '0'
35
        coordinate_node = SubElement(xml, 'Coordinate')
45
        coordinate_node = SubElement(node, 'Coordinate')
36 46
        coordinate_node.attrib['X'] = str(self.end.real)
37 47
        coordinate_node.attrib['Y'] = str(self.end.imag)
38 48
        coordinate_node.attrib['Z'] = '0'
39 49

  
40
        return xml
50
        return node
51

  
52

  
53
class BsplineCurve:
54
    def __init__(self):
55
        pass
56

  
57
    @staticmethod
58
    def to_xml(controls: list, _type: str, knots: list) -> Element:
59
        """return element for bspline curve"""
60

  
61
        node = Element('BsplineCurve')
62
        node.attrib['Degree'] = f"{len(controls) - 1}"
63
        node.attrib['CurveType'] = _type
64
        node.attrib['NumControlPoints'] = f"{len(controls)}"
65
        node.attrib['NumKnots'] = f"{len(knots)}"
66

  
67
        controls_node = SubElement(node, 'ControlPoints')
68
        for control in controls:
69
            controls_node.append(Point.to_xml('Coordinate', control.real, control.imag))
70

  
71
        knots_node = SubElement(node, 'Knots')
72
        for knot in knots:
73
            knot_node = SubElement(knots_node, 'Knot')
74
            knot_node.text = f"{knot}"
75

  
76
        weights_node = SubElement(node, 'WeightsData')
77
        for control in controls:
78
            weight_node = SubElement(weights_node, 'ControlPointWeight')
79
            weight_node.text = '1'
80

  
81
        return node
41 82

  
42 83

  
43 84
class GenericAttributes:
......
92 133
            node.attrib['ID'] = str(conn.uid)
93 134
            node.attrib['Name'] = f"conn{idx}"
94 135
            position_node = SubElement(node, 'Position')
95
            location_node = SubElement(position_node, 'Location')
96
            location_node.attrib['X'] = str(conn.center()[0])
97
            location_node.attrib['Y'] = str(conn.center()[1])
98
            location_node.attrib['Z'] = '0'
99
            axis_node = SubElement(position_node, 'Axis')
100
            axis_node.attrib['X'] = '0'
101
            axis_node.attrib['Y'] = '0'
102
            axis_node.attrib['Z'] = '1'
103
            reference_node = SubElement(position_node, 'Reference')
104
            reference_node.attrib['X'] = '1'
105
            reference_node.attrib['Y'] = '0'
106
            reference_node.attrib['Z'] = '0'
136
            location_node = Point.to_xml('Location', x=conn.center()[0], y=conn.center()[1], z=0)
137
            position_node.append(location_node)
138
            axis_node = Point.to_xml('Axis', x=0, y=0, z=1)
139
            position_node.append(axis_node)
140
            reference_node = Point.to_xml('Reference', x=1, y=0, z=0)
141
            position_node.append(reference_node)
107 142

  
108 143
        generic_attributes_node = SubElement(xml, 'GenericAttributes')
109 144
        generic_attributes_node.attrib['Number'] = str(len(self.connectors))
......
113 148
            generic_attribute_node.attrib['Value'] = f"conn{idx}"
114 149
            generic_attribute_node.attrib['Format'] = 'string'
115 150

  
116
        return xml
151
        return xml
DTI_PID/DTI_PID/DEXPI/ShapeCatalogue.py
1
# coding: utf-8
2
""" This is ShapeCatalogue module """
3

  
4
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5
from PyQt5.QtWidgets import *
6
from .Extent import Extent
7
from .Presentation import Presentation
8

  
9

  
10
class ShapeCatalogue:
11
    def __init__(self):
12
        pass
13

  
14
    @staticmethod
15
    def to_xml(scene: QGraphicsScene) -> Element:
16
        """return element for shape catalogue"""
17

  
18
        from SymbolSvgItem import SymbolSvgItem
19
        from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
20
        from svg.path.path import Move
21
        from .Shape import Line as DEXPI_Line, ConnectionPoints, GenericAttributes, BsplineCurve
22

  
23
        node = Element('ShapeCatalogue')
24
        node.attrib['Name'] = 'ShapeCatalogue'
25

  
26
        catalogue = set()
27
        items = [item for item in scene.items() if issubclass(type(item), SymbolSvgItem)]
28
        for item in items:
29
            type_str = f"{item.type}/{item.name}"
30
            if type_str not in catalogue:
31
                shape_node = SubElement(node, 'Nozzle' if item.type == 'Nozzles' else 'Equipment')
32
                shape_node.attrib['ComponentClass'] = item.type
33
                shape_node.attrib['ComponentName'] = item.name
34
                shape_node.attrib['Status'] = 'Current'
35
                Presentation.to_xml(shape_node, layer='0', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
36
                generic_attributes = GenericAttributes(item)
37
                shape_node.append(generic_attributes.to_xml())
38

  
39
                svg = item.to_svg(parent=None)
40
                paths = svg[0].findall('path')
41
                for path in paths:
42
                    path_ele = parse_path(path.attrib['d'])
43
                    for idx, ele in enumerate(path_ele):
44
                        if type(ele) is Move:
45
                            continue
46
                        elif type(ele) is Line:
47
                            line = DEXPI_Line(ele.start, ele.end)
48
                            shape_node.append(line.to_xml())
49
                        elif type(ele) is Arc:
50
                            continue
51
                        elif type(ele) is CubicBezier:
52
                            bspline_curve_node = BsplineCurve.to_xml(controls=[ele.start, ele.control1,
53
                                                                               ele.control2, ele.end],
54
                                                                     _type='BsplineCurveWithKnots', knots=[])
55
                            shape_node.append(bspline_curve_node)
56
                        elif type(ele) is QuadraticBezier:
57
                            continue
58
                        else:
59
                            continue
60

  
61
                connection_points_node = ConnectionPoints(item.connectors)
62
                shape_node.append(connection_points_node.to_xml())
63

  
64
                catalogue.add(type_str)
65

  
66
        return node
DTI_PID/DTI_PID/DEXPI/formatter.py
5 5
import os
6 6
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
7 7
from PyQt5.QtWidgets import *
8
from EngineeringEquipmentItem import QEngineeringEquipmentItem
9

  
10
from .Drawing import Drawing
11
from .Extent import Extent
12
from .ShapeCatalogue import ShapeCatalogue
13
from .Equipment import Equipment
8 14

  
9 15
sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '..\\Shapes'))
10 16

  
......
23 29
        def formatter(item):
24 30
            pass
25 31

  
26
        def extent_node(parent, scene):
27
            extent = SubElement(parent, 'Extent')
28
            rect = scene.itemsBoundingRect()
29
            _min = SubElement(extent, 'Min')
30
            _min.attrib['X'] = str(int(rect.left()))
31
            _min.attrib['Y'] = str(int(rect.top()))
32
            _min.attrib['Z'] = '0'
33
            _max = SubElement(extent, 'Max')
34
            _max.attrib['X'] = str(int(rect.right()))
35
            _max.attrib['Y'] = str(int(rect.bottom()))
36
            _max.attrib['Z'] = '0'
37

  
38
            return extent
39

  
40
        def drawing(name, parent, scene: QGraphicsScene):
41
            _drawing = SubElement(parent, 'Drawing')
42
            _drawing.attrib['Name'] = name
43
            _drawing.attrib['Type'] = 'PID'
44
            _drawing.attrib['Title'] = ''
45
            presentation = SubElement(_drawing, 'Presentation')
46
            presentation.attrib['Layer'] = ''
47
            presentation.attrib['Color'] = '16777215'
48
            presentation.attrib['LineType'] = ''
49
            presentation.attrib['LineWeight'] = ''
50
            presentation.attrib['R'] = '1.000'
51
            presentation.attrib['G'] = '1.000'
52
            presentation.attrib['B'] = '1.000'
53

  
54
            extent = extent_node(_drawing, scene)
55

  
56
            return _drawing
57

  
58
        def shape_catalogue_node(parent, scene):
59
            from SymbolSvgItem import SymbolSvgItem
60
            from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
61
            from svg.path.path import Move
62
            from .Shape import Line as DEXPI_Line, ConnectionPoints, GenericAttributes
63

  
64
            node = SubElement(parent, 'ShapeCatalogue')
65
            node.attrib['Name'] = 'ShapeCatalogue'
66

  
67
            catalogue = set()
68
            items = [item for item in scene.items() if issubclass(type(item), SymbolSvgItem)]
69
            for item in items:
70
                type_str = f"{item.type}/{item.name}"
71
                if type_str not in catalogue:
72
                    shape_node = SubElement(node, 'Nozzle' if item.type == 'Nozzles' else 'Equipment')
73
                    shape_node.attrib['ComponentClass'] = item.type
74
                    shape_node.attrib['ComponentName'] = item.name
75
                    shape_node.attrib['Status'] = 'Current'
76
                    presentation_node = SubElement(shape_node, 'Presentation')
77
                    presentation_node.attrib['Layer'] = '0'
78
                    presentation_node.attrib['Color'] = '0'
79
                    presentation_node.attrib['LineType'] = '0'
80
                    presentation_node.attrib['LineWeight'] = '0.1'
81
                    presentation_node.attrib['R'] = '0'
82
                    presentation_node.attrib['G'] = '0'
83
                    presentation_node.attrib['B'] = '0'
84

  
85
                    generic_attributes = GenericAttributes(item)
86
                    shape_node.append(generic_attributes.to_xml())
87

  
88
                    svg = item.to_svg(parent=None)
89
                    paths = svg[0].findall('path')
90
                    for path in paths:
91
                        path_ele = parse_path(path.attrib['d'])
92
                        for idx, ele in enumerate(path_ele):
93
                            if type(ele) is Move:
94
                                pass
95
                            elif type(ele) is Line:
96
                                line = DEXPI_Line(ele.start, ele.end)
97
                                shape_node.append(line.to_xml())
98
                            elif type(ele) is Arc:
99
                                pass
100
                            elif type(ele) is CubicBezier:
101
                                pass
102
                            elif type(ele) is QuadraticBezier:
103
                                pass
104

  
105
                    connection_points_node = ConnectionPoints(item.connectors)
106
                    shape_node.append(connection_points_node.to_xml())
107

  
108
                    catalogue.add(type_str)
109

  
110
            return node
111

  
112
        def equipment(parent):
113
            pass
114

  
115 32
        def piping_network_system(parent):
116 33
            pass
117 34

  
......
122 39
        xml.attrib['xsi:noNamespaceSchemaLocation'] = 'XMpLantPIDProfileSchema_4.0.1.xsd'
123 40
        node = Element(Formatter.PlantInformation)
124 41
        node.attrib['SchemaVersion'] = '4.0.1'
125
        node.attrib['OriginatingSystem'] = 'Comos'
42
        node.attrib['OriginatingSystem'] = 'ID2'
126 43
        node.attrib['Date'] = today.strftime("%Y-%m-%d")
127 44
        node.attrib['Time'] = datetime.now().strftime('%H:%M:%S')
128 45
        node.attrib['Is3D'] = 'no'
......
130 47
        node.attrib['Discipline'] = 'PID'
131 48
        SubElement(node, 'UnitsOfMeasure').attrib['Distance'] = 'px'
132 49
        xml.append(node)
133
        extent = extent_node(xml, scene)
50
        extent = Extent.to_xml(xml, scene=scene)
51

  
52
        """drawing node"""
53
        drawing_node = Drawing.to_xml(name, scene)
54
        xml.append(drawing_node)
55

  
56
        """shape catalogue node"""
57
        shape_catalogue_node = ShapeCatalogue.to_xml(scene)
58
        xml.append(shape_catalogue_node)
59

  
60
        """equipment nodes"""
61
        equipments = [item for item in scene.items() if type(item) is QEngineeringEquipmentItem]
62
        for equipment in equipments:
63
            node = Equipment.to_xml(equipment)
64
            xml.append(node)
134 65

  
135
        """drawing"""
136
        drawing_node = drawing(name, xml, scene)
137
        shape_catalogue_node = shape_catalogue_node(xml, scene)
138
        equipment_node = equipment(xml)
66
        """piping network system"""
139 67
        piping_network_system_node = piping_network_system(xml)
140 68

  
141 69
        for item in scene.items():
DTI_PID/DTI_PID/MainWindow.py
2337 2337

  
2338 2338
            QMainWindow.keyPressEvent(self, event)
2339 2339
        except Exception as ex:
2340
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2341
                                                           sys.exc_info()[-1].tb_lineno)
2340
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2341
                      f"{sys.exc_info()[-1].tb_lineno}"
2342 2342
            self.addMessage.emit(MessageType.Error, message)
2343 2343

  
2344 2344
    def recognize(self):

내보내기 Unified diff

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