프로젝트

일반

사용자정보

개정판 4d44771b

ID4d44771bc7ef693b58f6a166094b72fd0bcb2788
상위 9fdc723f
하위 f155c8ad, 74df5d6f

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

issue #1445: add PipingNetworkSystem and PipingNetworkSegment classes

Change-Id: I0ed14e5ffc6ddcb22ff66de27d729e511057f1b4

차이점 보기:

DTI_PID/DTI_PID/DEXPI/Equipment.py
5 5
from PyQt5.QtWidgets import *
6 6
from .Extent import Extent
7 7
from .Presentation import Presentation
8
from .Shape import Point, Line as DEXPI_Line, ConnectionPoints, GenericAttributes, BsplineCurve
8 9

  
9 10

  
10 11
class Equipment:
12
    ITEMS = 0
13

  
11 14
    def __init__(self):
12 15
        pass
13 16

  
14 17
    @staticmethod
15 18
    def to_xml(item) -> Element:
16 19
        """return element for equipment"""
20
        import sys
21
        from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
22
        from svg.path.path import Move
17 23

  
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'
24
        try:
25
            node = Element('Equipment')
26
            node.attrib['ID'] = f"XME_{Equipment.ITEMS}"
27
            Equipment.ITEMS += 1
28
            node.attrib['TagName'] = item.tag_no if item.tag_no else ''
29
            node.attrib['ComponentClass'] = ''
30
            node.attrib['ComponentName'] = ''
31
            node.attrib['ComponentType'] = 'Explicit'
32
            node.attrib['Status'] = 'Current'
25 33

  
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)
34
            Presentation.to_xml(node, layer='0', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
35
            Extent.to_xml(node, item=item)
28 36

  
29
        return node
37
            _node = SubElement(node, 'Position')
38
            pt = item.pos()
39
            _node.append(Point.to_xml('Location', pt.x(), pt.y()))
40
            _node.append(Point.to_xml('Axis', 0, 0, 1))
41
            _node.append(Point.to_xml('Reference', 1, 0, 0))
42

  
43
            node.append(Point.to_xml('Scale', 1, 1, 1))
44

  
45
            _node = SubElement(node, 'PersistentID')
46
            _node.attrib['Identifier'] = str(item.uid)
47
            _node.attrib['Context'] = 'ID2'
48

  
49
            svg = item.to_svg(parent=None)
50
            paths = svg[0].findall('path')
51
            for path in paths:
52
                path_ele = parse_path(path.attrib['d'])
53
                for idx, ele in enumerate(path_ele):
54
                    if type(ele) is Move:
55
                        continue
56
                    elif type(ele) is Line:
57
                        line = DEXPI_Line(ele.start, ele.end)
58
                        node.append(line.to_xml())
59
                    elif type(ele) is Arc:
60
                        continue
61
                    elif type(ele) is CubicBezier:
62
                        bspline_curve_node = BsplineCurve.to_xml(controls=[ele.start, ele.control1,
63
                                                                           ele.control2, ele.end],
64
                                                                 _type='BsplineCurve', knots=[])
65
                        node.append(bspline_curve_node)
66
                    elif type(ele) is QuadraticBezier:
67
                        continue
68
                    else:
69
                        continue
70

  
71
            generic_attributes = GenericAttributes(item)
72
            _attr_node = generic_attributes.to_xml()
73
            if _attr_node:
74
                node.append(_attr_node)
75

  
76
            connection_points_node = ConnectionPoints(item.connectors)
77
            _conn_node = connection_points_node.to_xml()
78
            if _conn_node:
79
                node.append(_conn_node)
80

  
81
            return node
82
        except Exception as ex:
83
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
84
                      f"{sys.exc_info()[-1].tb_lineno}"
85
            print(message)
30 86

  
31 87

  
32 88
class Nozzle:
......
42 98
        node.attrib['TagName'] = ''
43 99
        node.attrib['ComponentClass'] = 'Nozzle'
44 100
        node.attrib['ComponentName'] = ''
45
        node.attrib['ComponentType'] = ''
101
        node.attrib['ComponentType'] = 'Explicit'
46 102
        node.attrib['Status'] = 'Current'
47 103

  
48 104
        Presentation.to_xml(node, layer='30', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
DTI_PID/DTI_PID/DEXPI/PipingNetworkSegment.py
1
# coding: utf-8
2
""" This is PipingNetworkSystem 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 .Shape import Point
8
from .Presentation import Presentation
9

  
10

  
11
class PipingNetworkSegment:
12
    ITEMS = 0
13

  
14
    def __init__(self):
15
        pass
16

  
17
    @staticmethod
18
    def to_xml(parent: Element, run) -> Element:
19
        """return element for PipingNetworkSegment"""
20

  
21
        from EngineeringLineItem import QEngineeringLineItem
22

  
23
        node = SubElement(parent, 'PipingNetworkSegment')
24
        node.attrib['ID'] = f"XNG_{PipingNetworkSegment.ITEMS}"
25
        PipingNetworkSegment.ITEMS += 1
26
        node.attrib['TagName'] = 'Z001'  #TODO:
27
        node.attrib['ComponentClass'] = 'PipeSection'
28
        node.attrib['Status'] = 'Current'
29

  
30
        for item in run.items:
31
            if type(item) is QEngineeringLineItem:
32
                PipingNetworkSegment.line_to_xml(node, item)
33

  
34
        return node
35

  
36
    @staticmethod
37
    def line_to_xml(parent: Element, line) -> Element:
38
        """return element for CenterLine"""
39

  
40
        node = SubElement(parent, 'CenterLine')
41
        node.attrib['NumPoints'] = '2'
42

  
43
        Presentation.to_xml(node, layer='20', color='0', line_type='1', line_weight=0.5, r=0, g=0, b=0)
44

  
45
        Extent.to_xml(node, line)
46
        x, y = line.start_point()[0], line.start_point()[1]
47
        node.append(Point.to_xml('Coordinate', x=x, y=y))
48
        x, y = line.end_point()[0], line.end_point()[1]
49
        node.append(Point.to_xml('Coordinate', x=x, y=y))
50

  
51
        return node
DTI_PID/DTI_PID/DEXPI/PipingNetworkSystem.py
1
# coding: utf-8
2
""" This is PipingNetworkSystem 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 .PipingNetworkSegment import PipingNetworkSegment
8

  
9

  
10
class PipingNetworkSystem:
11
    ITEMS = 0
12

  
13
    def __init__(self):
14
        pass
15

  
16
    @staticmethod
17
    def to_xml(parent: Element, line_no) -> Element:
18
        """return element for PipingNetworkSystem"""
19

  
20
        node = SubElement(parent, 'PipingNetworkSystem')
21
        node.attrib['ID'] = f"XNS_{PipingNetworkSystem.ITEMS}"
22
        PipingNetworkSystem.ITEMS += 1
23
        node.attrib['TagName'] = line_no.text()
24
        node.attrib['ComponentClass'] = 'Pipe'
25
        node.attrib['Status'] = 'Current'
26

  
27
        for run in line_no.runs:
28
            PipingNetworkSegment.to_xml(node, run)
29

  
30
        return node
DTI_PID/DTI_PID/DEXPI/Shape.py
62 62
        node.attrib['Degree'] = f"{len(controls) - 1}"
63 63
        node.attrib['CurveType'] = _type
64 64
        node.attrib['NumControlPoints'] = f"{len(controls)}"
65
        node.attrib['NumKnots'] = f"{len(knots)}"
65
        if _type == 'BsplineCurveWithKnots':
66
            node.attrib['NumKnots'] = f"{len(knots)}"
67

  
68
        Presentation.to_xml(node, layer="", color="-32363", r=0.67, g=0.38, b=0)
69

  
70
        min_x = min([control.real for control in controls])
71
        max_x = max([control.real for control in controls])
72
        min_y = min([control.imag for control in controls])
73
        max_y = max([control.imag for control in controls])
74
        _extent_node = SubElement(node, 'Extent')
75
        _min_node = SubElement(_extent_node, 'Min')
76
        _min_node.attrib['X'] = str(min_x)
77
        _min_node.attrib['Y'] = str(min_y)
78
        _min_node.attrib['Z'] = '0'
79
        _max_node = SubElement(_extent_node, 'Max')
80
        _max_node.attrib['X'] = str(max_x)
81
        _max_node.attrib['Y'] = str(max_y)
82
        _max_node.attrib['Z'] = '0'
66 83

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

  
71
        knots_node = SubElement(node, 'Knots')
72
        for knot in knots:
73
            knot_node = SubElement(knots_node, 'Knot')
74
            knot_node.text = f"{knot}"
88
        if _type == 'BsplineCurveWithKnots':
89
            knots_node = SubElement(node, 'Knots')
90
            for knot in knots:
91
                knot_node = SubElement(knots_node, 'Knot')
92
                knot_node.text = f"{knot}"
75 93

  
76 94
        weights_node = SubElement(node, 'WeightsData')
77 95
        for control in controls:
......
87 105
        pass
88 106

  
89 107
    def to_xml(self):
90
        xml = Element('GenericAttributes')
91
        xml.attrib['Set'] = 'ID2Properties'
92

  
93 108
        attrs = self.item.getAttributes()
94
        xml.attrib['Number'] = str(len(attrs))
95
        for key, value in attrs.items():
96
            generic_attribute_node = SubElement(xml, 'GenericAttribute')
97
            generic_attribute_node.attrib['Name'] = key.Attribute
98
            generic_attribute_node.attrib['Value'] = value if value else ''
99
            generic_attribute_node.attrib['Format'] = key.AttributeType
109
        if attrs:
110
            xml = Element('GenericAttributes')
111
            xml.attrib['Set'] = 'ID2Properties'
112

  
113
            xml.attrib['Number'] = str(len(attrs))
114
            for key, value in attrs.items():
115
                generic_attribute_node = SubElement(xml, 'GenericAttribute')
116
                generic_attribute_node.attrib['Name'] = key.Attribute
117
                generic_attribute_node.attrib['Value'] = value if value else ''
118
                generic_attribute_node.attrib['Format'] = 'string'  # key.AttributeType
119

  
120
            return xml
100 121

  
101
        return xml
122
        return None
102 123

  
103 124

  
104 125
class ConnectionPoints:
126
    NODES = 0
127

  
105 128
    def __init__(self, connectors):
106 129
        self.connectors = connectors
107 130

  
108 131
    def to_xml(self):
109
        xml = Element('ConnectionPoints')
110
        xml.attrib['NumPoints'] = str(len(self.connectors))
111

  
112
        min_x, min_y = None, None
113
        max_x, max_y = None, None
114
        for conn in self.connectors:
115
            center = conn.center()
116
            min_x = center[0] if min_x is None or min_x > center[0] else min_x
117
            max_x = center[0] if max_x is None or max_x < center[0] else max_x
118
            min_y = center[1] if min_y is None or min_y > center[1] else min_y
119
            max_y = center[1] if max_y is None or max_y < center[1] else max_y
120

  
121
        extent_node = SubElement(xml, 'Extent')
122
        min_node = SubElement(extent_node, 'Min')
123
        min_node.attrib['X'] = str(min_x)
124
        min_node.attrib['Y'] = str(min_y)
125
        min_node.attrib['Z'] = '0'
126
        max_node = SubElement(extent_node, 'Max')
127
        max_node.attrib['X'] = str(max_x)
128
        max_node.attrib['Y'] = str(max_y)
129
        max_node.attrib['Z'] = '0'
130

  
131
        for idx, conn in enumerate(self.connectors):
132
            node = SubElement(xml, 'Node')
133
            node.attrib['ID'] = str(conn.uid)
134
            node.attrib['Name'] = f"conn{idx}"
135
            position_node = SubElement(node, 'Position')
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)
142

  
143
        generic_attributes_node = SubElement(xml, 'GenericAttributes')
144
        generic_attributes_node.attrib['Number'] = str(len(self.connectors))
145
        for idx in range(len(self.connectors)):
146
            generic_attribute_node = SubElement(generic_attributes_node, 'GenericAttribute')
147
            generic_attribute_node.attrib['Name'] = f"NodeName{idx}"
148
            generic_attribute_node.attrib['Value'] = f"conn{idx}"
149
            generic_attribute_node.attrib['Format'] = 'string'
150

  
151
        return xml
132
        if self.connectors:
133
            xml = Element('ConnectionPoints')
134
            xml.attrib['NumPoints'] = str(len(self.connectors))
135

  
136
            min_x, min_y = None, None
137
            max_x, max_y = None, None
138
            for conn in self.connectors:
139
                center = conn.center()
140
                min_x = center[0] if min_x is None or min_x > center[0] else min_x
141
                max_x = center[0] if max_x is None or max_x < center[0] else max_x
142
                min_y = center[1] if min_y is None or min_y > center[1] else min_y
143
                max_y = center[1] if max_y is None or max_y < center[1] else max_y
144

  
145
            extent_node = SubElement(xml, 'Extent')
146
            min_node = SubElement(extent_node, 'Min')
147
            min_node.attrib['X'] = str(min_x)
148
            min_node.attrib['Y'] = str(min_y)
149
            min_node.attrib['Z'] = '0'
150
            max_node = SubElement(extent_node, 'Max')
151
            max_node.attrib['X'] = str(max_x)
152
            max_node.attrib['Y'] = str(max_y)
153
            max_node.attrib['Z'] = '0'
154

  
155
            for idx, conn in enumerate(self.connectors):
156
                node = SubElement(xml, 'Node')
157
                node.attrib['ID'] = f"XMP_{ConnectionPoints.NODES}"
158
                node.attrib['Name'] = f"conn{idx}"
159
                position_node = SubElement(node, 'Position')
160
                location_node = Point.to_xml('Location', x=conn.center()[0], y=conn.center()[1], z=0)
161
                position_node.append(location_node)
162
                axis_node = Point.to_xml('Axis', x=0, y=0, z=1)
163
                position_node.append(axis_node)
164
                reference_node = Point.to_xml('Reference', x=1, y=0, z=0)
165
                position_node.append(reference_node)
166

  
167
                ConnectionPoints.NODES += 1
168

  
169
            generic_attributes_node = SubElement(xml, 'GenericAttributes')
170
            generic_attributes_node.attrib['Number'] = str(len(self.connectors))
171
            for idx in range(len(self.connectors)):
172
                generic_attribute_node = SubElement(generic_attributes_node, 'GenericAttribute')
173
                generic_attribute_node.attrib['Name'] = f"NodeName{idx}"
174
                generic_attribute_node.attrib['Value'] = f"conn{idx}"
175
                generic_attribute_node.attrib['Format'] = 'string'
176

  
177
            return xml
178

  
179
        return None
DTI_PID/DTI_PID/DEXPI/ShapeCatalogue.py
8 8

  
9 9

  
10 10
class ShapeCatalogue:
11
    ITEMS = 0
12

  
11 13
    def __init__(self):
12 14
        pass
13 15

  
......
29 31
            type_str = f"{item.type}/{item.name}"
30 32
            if type_str not in catalogue:
31 33
                shape_node = SubElement(node, 'Nozzle' if item.type == 'Nozzles' else 'Equipment')
34
                shape_node.attrib['ID'] = f"XMC_{ShapeCatalogue.ITEMS}"
32 35
                shape_node.attrib['ComponentClass'] = item.type
33 36
                shape_node.attrib['ComponentName'] = item.name
34 37
                shape_node.attrib['Status'] = 'Current'
35 38
                Presentation.to_xml(shape_node, layer='0', color='0', line_type='0', line_weight=0.1, r=0, g=0, b=0)
36 39
                generic_attributes = GenericAttributes(item)
37
                shape_node.append(generic_attributes.to_xml())
40
                _attr_node = generic_attributes.to_xml()
41
                if _attr_node:
42
                    shape_node.append(_attr_node)
38 43

  
44
                """
39 45
                svg = item.to_svg(parent=None)
40 46
                paths = svg[0].findall('path')
41 47
                for path in paths:
......
51 57
                        elif type(ele) is CubicBezier:
52 58
                            bspline_curve_node = BsplineCurve.to_xml(controls=[ele.start, ele.control1,
53 59
                                                                               ele.control2, ele.end],
54
                                                                     _type='BsplineCurveWithKnots', knots=[])
60
                                                                     _type='BsplineCurve', knots=[])
55 61
                            shape_node.append(bspline_curve_node)
56 62
                        elif type(ele) is QuadraticBezier:
57 63
                            continue
58 64
                        else:
59 65
                            continue
66
                """
67

  
68
                ShapeCatalogue.ITEMS += 1
60 69

  
61 70
                connection_points_node = ConnectionPoints(item.connectors)
62
                shape_node.append(connection_points_node.to_xml())
71
                _conn_node = connection_points_node.to_xml()
72
                if _conn_node:
73
                    shape_node.append(_conn_node)
63 74

  
64 75
                catalogue.add(type_str)
65 76

  
DTI_PID/DTI_PID/DEXPI/__init__.py
3 3

  
4 4

  
5 5
def scene_to_dexpi(path, name, scene: QGraphicsScene) -> None:
6
    import sys
6 7
    from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
7 8
    from .formatter import Formatter
8 9

  
9
    formatter = Formatter()
10
    data = formatter.to_dexpi(name, scene)
11
    ElementTree(data).write(path, encoding='utf-8', xml_declaration=True)
10
    try:
11
        formatter = Formatter()
12
        data = formatter.to_dexpi(name, scene)
13
        ElementTree(data).write(path, encoding='utf-8', xml_declaration=True)
14
    except Exception as ex:
15
        message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
16
                  f"{sys.exc_info()[-1].tb_lineno}"
17
        print(message)
DTI_PID/DTI_PID/DEXPI/formatter.py
6 6
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
7 7
from PyQt5.QtWidgets import *
8 8
from EngineeringEquipmentItem import QEngineeringEquipmentItem
9
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
9 10

  
10 11
from .Drawing import Drawing
11 12
from .Extent import Extent
12 13
from .ShapeCatalogue import ShapeCatalogue
13 14
from .Equipment import Equipment
15
from .PipingNetworkSystem import PipingNetworkSystem
14 16

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

  
......
32 34
        def piping_network_system(parent):
33 35
            pass
34 36

  
35
        today = date.today()
36

  
37
        xml = Element(Formatter.PlantModel)  # Root Node
38
        xml.attrib['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
39
        xml.attrib['xsi:noNamespaceSchemaLocation'] = 'XMpLantPIDProfileSchema_4.0.1.xsd'
40
        node = Element(Formatter.PlantInformation)
41
        node.attrib['SchemaVersion'] = '4.0.1'
42
        node.attrib['OriginatingSystem'] = 'ID2'
43
        node.attrib['Date'] = today.strftime("%Y-%m-%d")
44
        node.attrib['Time'] = datetime.now().strftime('%H:%M:%S')
45
        node.attrib['Is3D'] = 'no'
46
        node.attrib['Units'] = 'mm'
47
        node.attrib['Discipline'] = 'PID'
48
        SubElement(node, 'UnitsOfMeasure').attrib['Distance'] = 'Millimetre'
49
        xml.append(node)
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)
37
        try:
38
            today = date.today()
39

  
40
            xml = Element(Formatter.PlantModel)  # Root Node
41
            xml.attrib['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
42
            xml.attrib['xsi:noNamespaceSchemaLocation'] = 'XMpLantPIDProfileSchema_4.0.1.xsd'
43
            node = Element(Formatter.PlantInformation)
44
            node.attrib['SchemaVersion'] = '4.0.1'
45
            node.attrib['OriginatingSystem'] = 'ID2'
46
            node.attrib['Date'] = today.strftime("%Y-%m-%d")
47
            node.attrib['Time'] = datetime.now().strftime('%H:%M:%S')
48
            node.attrib['Is3D'] = 'no'
49
            node.attrib['Units'] = 'mm'
50
            node.attrib['Discipline'] = 'PID'
51
            SubElement(node, 'UnitsOfMeasure').attrib['Distance'] = 'Millimetre'
64 52
            xml.append(node)
65

  
66
        """piping network system"""
67
        piping_network_system_node = piping_network_system(xml)
68

  
69
        for item in scene.items():
70
            formatter(item)
71

  
72
        return xml
53
            extent = Extent.to_xml(xml, scene=scene)
54

  
55
            """drawing node"""
56
            drawing_node = Drawing.to_xml(name, scene)
57
            xml.append(drawing_node)
58

  
59
            """shape catalogue node"""
60
            shape_catalogue_node = ShapeCatalogue.to_xml(scene)
61
            xml.append(shape_catalogue_node)
62

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

  
69
            """piping network system"""
70
            line_nos = [item for item in scene.items() if type(item) is QEngineeringLineNoTextItem]
71
            for line_no in line_nos:
72
                PipingNetworkSystem.to_xml(xml, line_no)
73

  
74
            for item in scene.items():
75
                formatter(item)
76

  
77
            return xml
78
        except Exception as ex:
79
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
80
                      f"{sys.exc_info()[-1].tb_lineno}"
81
            print(message)

내보내기 Unified diff

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