프로젝트

일반

사용자정보

개정판 844f6269

ID844f6269a683271eb340d20fbe04e305281af623
상위 6d5ea555

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

issue #1445: Bezier 곡선을 다각선으로 처리

Change-Id: Id52b9c1f7fe43feed040a4e313a7d0c76cc7008d

차이점 보기:

DTI_PID/DTI_PID/DEXPI/Shape.py
66 66
        """write line to element"""
67 67

  
68 68
        node = Element(name)
69
        Presentation.to_xml(node, layer='125', color='0', line_type='1', line_weight=0.35, r=0, g=0, b=0)
69
        Presentation.to_xml(node, layer='125', color='0', line_type='1', line_weight=1, r=0, g=0, b=0)
70 70
        extent_node = SubElement(node, 'Extent')
71 71
        min_node = SubElement(extent_node, 'Min')
72 72

  
......
100 100
        node = SubElement(parent, 'CenterLine')
101 101
        node.attrib['NumPoints'] = '2'
102 102

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

  
105 105
        Extent.to_xml(node, line)
106 106
        rect = line.scene().sceneRect()
......
117 117
        pass
118 118

  
119 119
    @staticmethod
120
    def binomial(i, n):
121
        """Binomial coefficient"""
122
        import math
123

  
124
        return math.factorial(n) / float(math.factorial(i) * math.factorial(n - i))
125

  
126
    @staticmethod
127
    def bernstein(t, i, n):
128
        """Bernstein polynom"""
129

  
130
        return BsplineCurve.binomial(i, n) * (t ** i) * ((1 - t) ** (n - i))
131

  
132
    @staticmethod
133
    def bezier(t, points):
134
        """Calculate coordinate of a point in the bezier curve"""
135

  
136
        n = len(points) - 1
137
        x = y = 0
138
        for i, pos in enumerate(points):
139
            bern = BsplineCurve.bernstein(t, i, n)
140
            x += pos.real * bern
141
            y += pos.imag * bern
142

  
143
        return x, y
144

  
145
    @staticmethod
146
    def bezier_curve_range(n, points) -> list:
147
        """Range of points in a curve bezier"""
148

  
149
        pts = []
150
        for i in range(n):
151
            t = i / float(n - 1)
152
            pts.append(BsplineCurve.bezier(t, points))
153

  
154
        return pts
155

  
156
    @staticmethod
120 157
    def to_xml(controls: list, _type: str, knots: list) -> Element:
121 158
        """return element for bspline curve"""
122 159

  
160
        steps = 16
161
        points = BsplineCurve.bezier_curve_range(steps, controls)
162

  
163
        node = Element('PolyLine')
164
        node.attrib['NumPoints'] = f"{len(points)}"
165

  
166
        Presentation.to_xml(node, layer="125", color="-32363", line_type="1", r=0, g=0, b=0)
167

  
168
        min_x = min([control.real for control in controls])
169
        max_x = max([control.real for control in controls])
170
        min_y = min([control.imag for control in controls])
171
        max_y = max([control.imag for control in controls])
172
        _extent_node = SubElement(node, 'Extent')
173
        _min_node = SubElement(_extent_node, 'Min')
174
        _min_node.attrib['X'] = str(min_x)
175
        _min_node.attrib['Y'] = str(min_y)
176
        _min_node.attrib['Z'] = '0'
177
        _max_node = SubElement(_extent_node, 'Max')
178
        _max_node.attrib['X'] = str(max_x)
179
        _max_node.attrib['Y'] = str(max_y)
180
        _max_node.attrib['Z'] = '0'
181

  
182
        for point in points:
183
            node.append(Point.to_xml('Coordinate', x=point[0], y=point[1], z=0))
184

  
185
        """
123 186
        node = Element('BsplineCurve')
124 187
        node.attrib['Degree'] = f"{len(controls) - 1}"
125 188
        node.attrib['CurveType'] = _type
......
127 190
        if _type == 'BsplineCurveWithKnots':
128 191
            node.attrib['NumKnots'] = f"{len(knots)}"
129 192

  
130
        Presentation.to_xml(node, layer="", color="-32363", r=0.67, g=0.38, b=0)
193
        Presentation.to_xml(node, layer="125", color="-32363", line_type="1", r=0.67, g=0.38, b=0)
131 194

  
132 195
        min_x = min([control.real for control in controls])
133 196
        max_x = max([control.real for control in controls])
......
153 216
                knot_node = SubElement(knots_node, 'Knot')
154 217
                knot_node.text = f"{knot}"
155 218

  
219
            knots_multi_node = SubElement(node, 'KnotMultiplicities')
220
            for knot in knots:
221
                knot_multi_node = SubElement(knots_multi_node, 'Multiplicity')
222
                knot_multi_node.text = '1'
223

  
156 224
        weights_node = SubElement(node, 'WeightsData')
157 225
        for idx, control in enumerate(controls):
158 226
            weight_node = SubElement(weights_node, 'ControlPointWeight')
159
            weight_node.text = '1' if idx == 0 or idx == len(controls) - 1 else '0.5'
227
            weight_node.text = '1'
228
        """
160 229

  
161 230
        return node
162 231

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

  
4
import sys
4 5
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse, tostring
5 6
from PyQt5.QtWidgets import *
6 7
from PyQt5.QtGui import *
......
27 28

  
28 29
        node = Element('ShapeCatalogue')
29 30
        node.attrib['Name'] = 'ShapeCatalogue'
30

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

  
43
                position_node = SubElement(shape_node, 'Position')
44
                position_node.append(Point.to_xml('Location', x=item.symbolOrigin[0], y=item.symbolOrigin[1], z=0))
45
                position_node.append(Point.to_xml('Axis', x=0, y=0, z=1))
46
                position_node.append(Point.to_xml('Reference', x=1, y=0, z=0))
47

  
48
                generic_attributes = GenericAttributes(item)
49
                _attr_node = generic_attributes.to_xml()
50
                if _attr_node:
51
                    shape_node.append(_attr_node)
52

  
53
                extent = None
54

  
55
                scale_trans = QTransform()
56
                scale_trans.scale(1, -1)
57

  
58
                svg = item.to_svg(parent=None)
59
                paths = svg[0].findall('path')
60
                for path in paths:
61
                    trans = Transform.to_transform(path.attrib['transform']) * scale_trans
62
                    path_ele = parse_path(path.attrib['d'])
63
                    for idx, ele in enumerate(path_ele):
64
                        if type(ele) is Move:
65
                            continue
66
                        elif type(ele) is Line:
67
                            line = DEXPI_Line(Transform.apply_transform(trans, ele.start),
68
                                              Transform.apply_transform(trans, ele.end))
69
                            extent = ShapeCatalogue.merge_extent(extent, line.extent())
70
                            shape_node.append(line.to_xml('Line', None))
71
                        elif type(ele) is Arc:
72
                            continue
73
                        elif type(ele) is CubicBezier:
74
                            line = DEXPI_Line(Transform.apply_transform(trans, ele.start),
75
                                              Transform.apply_transform(trans, ele.control1))
76
                            extent = ShapeCatalogue.merge_extent(extent, line.extent())
77
                            shape_node.append(line.to_xml('Line', None))
78

  
79
                            line = DEXPI_Line(Transform.apply_transform(trans, ele.control1),
80
                                              Transform.apply_transform(trans, ele.control2))
81
                            extent = ShapeCatalogue.merge_extent(extent, line.extent())
82
                            shape_node.append(line.to_xml('Line', None))
83

  
84
                            line = DEXPI_Line(Transform.apply_transform(trans, ele.control2),
85
                                              Transform.apply_transform(trans, ele.end))
86
                            extent = ShapeCatalogue.merge_extent(extent, line.extent())
87
                            shape_node.append(line.to_xml('Line', None))
88
                            """
89
                            bspline_curve_node = BsplineCurve.to_xml(controls=[ele.start, ele.control1,
90
                                                                               ele.control2, ele.end],
91
                                                                     _type='BsplineCurve', knots=[])
92
                            shape_node.append(bspline_curve_node)
93
                            """
94
                        elif type(ele) is QuadraticBezier:
95
                            continue
96
                        else:
97
                            continue
98

  
99
                extent_node = SubElement(shape_node, 'Extent')
100
                extent_node.append(Point.to_xml('Min', x=extent[0], y=extent[1], z=0))
101
                extent_node.append(Point.to_xml('Max', x=extent[2], y=extent[2], z=0))
102

  
103
                ShapeCatalogue.ITEMS += 1
104

  
105
                _conn_node = ConnectionPoints.to_xml(item.symbolOrigin, item.connectors)
106
                if _conn_node:
107
                    shape_node.append(_conn_node)
108

  
109
                catalogue.add(type_str)
31
        try:
32

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

  
45
                    position_node = SubElement(shape_node, 'Position')
46
                    position_node.append(Point.to_xml('Location', x=item.symbolOrigin[0], y=item.symbolOrigin[1], z=0))
47
                    position_node.append(Point.to_xml('Axis', x=0, y=0, z=1))
48
                    position_node.append(Point.to_xml('Reference', x=1, y=0, z=0))
49

  
50
                    generic_attributes = GenericAttributes(item)
51
                    _attr_node = generic_attributes.to_xml()
52
                    if _attr_node:
53
                        shape_node.append(_attr_node)
54

  
55
                    extent = None
56

  
57
                    scale_trans = QTransform()
58
                    scale_trans.scale(1, -1)
59

  
60
                    svg = item.to_svg(parent=None)
61
                    paths = svg[0].findall('path')
62
                    for path in paths:
63
                        trans = Transform.to_transform(path.attrib['transform']) * scale_trans
64
                        path_ele = parse_path(path.attrib['d'])
65
                        for idx, ele in enumerate(path_ele):
66
                            if type(ele) is Move:
67
                                continue
68
                            elif type(ele) is Line:
69
                                line = DEXPI_Line(Transform.apply_transform(trans, ele.start),
70
                                                  Transform.apply_transform(trans, ele.end))
71
                                extent = ShapeCatalogue.merge_extent(extent, line.extent())
72
                                shape_node.append(line.to_xml('Line', None))
73
                            elif type(ele) is Arc:
74
                                continue
75
                            elif type(ele) is CubicBezier:
76
                                """
77
                                line = DEXPI_Line(Transform.apply_transform(trans, ele.start),
78
                                                  Transform.apply_transform(trans, ele.control1))
79
                                extent = ShapeCatalogue.merge_extent(extent, line.extent())
80
                                shape_node.append(line.to_xml('Line', None))
81

  
82
                                line = DEXPI_Line(Transform.apply_transform(trans, ele.control1),
83
                                                  Transform.apply_transform(trans, ele.control2))
84
                                extent = ShapeCatalogue.merge_extent(extent, line.extent())
85
                                shape_node.append(line.to_xml('Line', None))
86

  
87
                                line = DEXPI_Line(Transform.apply_transform(trans, ele.control2),
88
                                                  Transform.apply_transform(trans, ele.end))
89
                                extent = ShapeCatalogue.merge_extent(extent, line.extent())
90
                                shape_node.append(line.to_xml('Line', None))
91
                                """
92
                                controls = [Transform.apply_transform(trans, ele.start),
93
                                            Transform.apply_transform(trans, ele.control1),
94
                                            Transform.apply_transform(trans, ele.control2),
95
                                            Transform.apply_transform(trans, ele.end)]
96
                                min_x = min([control.real for control in controls])
97
                                max_x = max([control.real for control in controls])
98
                                min_y = min([control.imag for control in controls])
99
                                max_y = max([control.imag for control in controls])
100
                                extent = ShapeCatalogue.merge_extent(extent, (min_x, min_y, max_x, max_y))
101

  
102
                                bspline_curve_node = BsplineCurve.to_xml(controls=controls,
103
                                                                         _type='BsplineCurve',
104
                                                                         knots=[0, 0, 0, 0, 1, 1, 1, 1])
105
                                shape_node.append(bspline_curve_node)
106
                            elif type(ele) is QuadraticBezier:
107
                                continue
108
                            else:
109
                                continue
110

  
111
                    extent_node = SubElement(shape_node, 'Extent')
112
                    extent_node.append(Point.to_xml('Min', x=extent[0], y=extent[1], z=0))
113
                    extent_node.append(Point.to_xml('Max', x=extent[2], y=extent[2], z=0))
114

  
115
                    ShapeCatalogue.ITEMS += 1
116

  
117
                    _conn_node = ConnectionPoints.to_xml(item.symbolOrigin, item.connectors)
118
                    if _conn_node:
119
                        shape_node.append(_conn_node)
120

  
121
                    catalogue.add(type_str)
122
        except Exception as ex:
123
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
124
                      f"{sys.exc_info()[-1].tb_lineno}"
125
            print(message)
110 126

  
111 127
        return node
112 128

  

내보내기 Unified diff

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