batoolset 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. batoolset/GUI/__init__.py +0 -0
  2. batoolset/GUI/list_gui.py +513 -0
  3. batoolset/GUI/multi_image_display.py +989 -0
  4. batoolset/GUI/open.py +325 -0
  5. batoolset/GUI/overlay_hints.py +45 -0
  6. batoolset/GUI/paint2.py +1345 -0
  7. batoolset/GUI/scrollablepaint.py +1152 -0
  8. batoolset/IJ_ROIs/__init__.py +0 -0
  9. batoolset/IJ_ROIs/tools.py +40 -0
  10. batoolset/PATH/__init__.py +0 -0
  11. batoolset/PATH/tools.py +79 -0
  12. batoolset/SQLite_tools/__init__.py +0 -0
  13. batoolset/SQLite_tools/tools.py +840 -0
  14. batoolset/__init__.py +0 -0
  15. batoolset/binary/__init__.py +0 -0
  16. batoolset/binary/tools.py +123 -0
  17. batoolset/binarytools/__init__.py +0 -0
  18. batoolset/binarytools/cell_center_detector.py +290 -0
  19. batoolset/clipboard_tools/__init__.py +0 -0
  20. batoolset/clipboard_tools/tools.py +7 -0
  21. batoolset/colors/__init__.py +0 -0
  22. batoolset/colors/colorgen.py +193 -0
  23. batoolset/colors/tools.py +22 -0
  24. batoolset/command_line/__init__.py +0 -0
  25. batoolset/command_line/tools.py +18 -0
  26. batoolset/dialogs/__init__.py +0 -0
  27. batoolset/dialogs/opensave.py +228 -0
  28. batoolset/dicts/__init__.py +0 -0
  29. batoolset/dicts/tools.py +299 -0
  30. batoolset/dims/__init__.py +0 -0
  31. batoolset/dims/tools.py +83 -0
  32. batoolset/draw/__init__.py +0 -0
  33. batoolset/draw/shapes/Position.py +183 -0
  34. batoolset/draw/shapes/__init__.py +0 -0
  35. batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
  36. batoolset/draw/shapes/circle2d.py +99 -0
  37. batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
  38. batoolset/draw/shapes/ellipse2d.py +336 -0
  39. batoolset/draw/shapes/freehand2d.py +235 -0
  40. batoolset/draw/shapes/group.py +1830 -0
  41. batoolset/draw/shapes/image2d.py +2469 -0
  42. batoolset/draw/shapes/line2d.py +575 -0
  43. batoolset/draw/shapes/point2d.py +257 -0
  44. batoolset/draw/shapes/polygon2d.py +357 -0
  45. batoolset/draw/shapes/polyline2d.py +235 -0
  46. batoolset/draw/shapes/rect2d.py +388 -0
  47. batoolset/draw/shapes/rectangle2d.py +601 -0
  48. batoolset/draw/shapes/scalebar.py +304 -0
  49. batoolset/draw/shapes/serializablefont.py +126 -0
  50. batoolset/draw/shapes/serializableguiparams.py +10 -0
  51. batoolset/draw/shapes/square2d.py +103 -0
  52. batoolset/draw/shapes/textorientation.py +45 -0
  53. batoolset/draw/shapes/tools.py +467 -0
  54. batoolset/draw/shapes/transform2D.py +350 -0
  55. batoolset/draw/shapes/txt2d.py +550 -0
  56. batoolset/draw/widgets/__init__.py +0 -0
  57. batoolset/draw/widgets/col.py +343 -0
  58. batoolset/draw/widgets/image_group.py +248 -0
  59. batoolset/draw/widgets/image_organizer.py +96 -0
  60. batoolset/draw/widgets/paint.py +184 -0
  61. batoolset/draw/widgets/vectorial.py +257 -0
  62. batoolset/figure/__init__.py +0 -0
  63. batoolset/figure/alignment.py +814 -0
  64. batoolset/figure/column.py +1117 -0
  65. batoolset/figure/fig_tools.py +285 -0
  66. batoolset/figure/minimal_debugger_scale_etc.py +139 -0
  67. batoolset/figure/panel.py +697 -0
  68. batoolset/figure/row.py +852 -0
  69. batoolset/figure/user_selection.py +287 -0
  70. batoolset/files/__init__.py +0 -0
  71. batoolset/files/tools.py +1321 -0
  72. batoolset/images/__init__.py +0 -0
  73. batoolset/images/tools.py +81 -0
  74. batoolset/img.py +5216 -0
  75. batoolset/linux/__init__.py +0 -0
  76. batoolset/linux/tools.py +72 -0
  77. batoolset/lists/__init__.py +0 -0
  78. batoolset/lists/tools.py +436 -0
  79. batoolset/luts/__init__.py +0 -0
  80. batoolset/luts/lut_minimal_test.py +1207 -0
  81. batoolset/matplolib/__init__.py +0 -0
  82. batoolset/matplolib/tools.py +44 -0
  83. batoolset/np_tools/__init__.py +0 -0
  84. batoolset/np_tools/tools.py +252 -0
  85. batoolset/np_tools/trash.py +15 -0
  86. batoolset/pandas_tools/__init__.py +0 -0
  87. batoolset/pandas_tools/tools.py +880 -0
  88. batoolset/partials/__init__.py +0 -0
  89. batoolset/partials/tools.py +83 -0
  90. batoolset/plot_tools/__init__.py +0 -0
  91. batoolset/plot_tools/tools.py +70 -0
  92. batoolset/pyqt/__init__.py +0 -0
  93. batoolset/pyqt/tools.py +691 -0
  94. batoolset/re_tools/__init__.py +0 -0
  95. batoolset/re_tools/tools.py +35 -0
  96. batoolset/serialization/__init__.py +0 -0
  97. batoolset/serialization/tools.py +1192 -0
  98. batoolset/sets/__init__.py +0 -0
  99. batoolset/sets/tools.py +109 -0
  100. batoolset/settings/__init__.py +0 -0
  101. batoolset/settings/global_settings.py +134 -0
  102. batoolset/strings/__init__.py +0 -0
  103. batoolset/strings/tools.py +225 -0
  104. batoolset/ta/__init__.py +0 -0
  105. batoolset/ta/database/__init__.py +0 -0
  106. batoolset/ta/database/advanced_sql_plotter.py +1170 -0
  107. batoolset/ta/database/my_qt_table.py +79 -0
  108. batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
  109. batoolset/ta/database/sql.py +2141 -0
  110. batoolset/ta/database/sql_column_name_dialog.py +122 -0
  111. batoolset/ta/measurements/TAmeasures.py +2226 -0
  112. batoolset/ta/measurements/__init__.py +0 -0
  113. batoolset/ta/measurements/measurements3D/__init__.py +0 -0
  114. batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
  115. batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
  116. batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
  117. batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
  118. batoolset/ta/measurements/nematic.py +562 -0
  119. batoolset/ta/measurements/nematic_measurements.py +107 -0
  120. batoolset/ta/segmentation/__init__.py +0 -0
  121. batoolset/ta/segmentation/neo_wshed.py +314 -0
  122. batoolset/ta/selections/__init__.py +0 -0
  123. batoolset/ta/selections/selection.py +329 -0
  124. batoolset/ta/tracking/__init__.py +0 -0
  125. batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
  126. batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
  127. batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
  128. batoolset/ta/tracking/registration.py +108 -0
  129. batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
  130. batoolset/ta/tracking/track_correction.py +238 -0
  131. batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
  132. batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
  133. batoolset/ta/utils/TA_tools.py +43 -0
  134. batoolset/ta/utils/__init__.py +0 -0
  135. batoolset/ta/utils/rps_tools.py +1783 -0
  136. batoolset/tests/__init__.py +0 -0
  137. batoolset/tests/rps_tools.py +51 -0
  138. batoolset/tests/tools.py +10 -0
  139. batoolset/tools/__init__.py +0 -0
  140. batoolset/tools/early_stopper_class.py +9 -0
  141. batoolset/tools/guided_data_recoverer.py +110 -0
  142. batoolset/tools/logger.py +100 -0
  143. batoolset/tools/mytimer.py +31 -0
  144. batoolset/tools/prompt_color.py +160 -0
  145. batoolset/tools/qthandler.py +118 -0
  146. batoolset/uitools/__init__.py +0 -0
  147. batoolset/uitools/blinker.py +56 -0
  148. batoolset/unsafe/__init__.py +0 -0
  149. batoolset/unsafe/tools.py +115 -0
  150. batoolset/utils/__init__.py +0 -0
  151. batoolset/utils/commontools.py +158 -0
  152. batoolset/utils/loadlist.py +728 -0
  153. batoolset/version.py +10 -0
  154. batoolset/xml/__init__.py +0 -0
  155. batoolset/xml/tools.py +65 -0
  156. batoolset/zip_tools/__init__.py +0 -0
  157. batoolset/zip_tools/tools.py +76 -0
  158. batoolset-0.1.0.dist-info/LICENSE +24 -0
  159. batoolset-0.1.0.dist-info/METADATA +45 -0
  160. batoolset-0.1.0.dist-info/RECORD +162 -0
  161. batoolset-0.1.0.dist-info/WHEEL +5 -0
  162. batoolset-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,235 @@
1
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
2
+ set_UI()
3
+ import os
4
+ from qtpy import QtCore
5
+ from qtpy.QtCore import QPointF, Qt
6
+ from qtpy.QtGui import QPainter, QBrush, QPen, QImage, QColor, QPolygonF
7
+ # from qtpy.Qt
8
+ # from qtpy.Qt import (QPaintEngine, QPaintDevice, QTransform, QBrush)
9
+ from batoolset.draw.shapes.polygon2d import Polygon2D
10
+
11
+ from batoolset.tools.logger import TA_logger
12
+
13
+ logger = TA_logger()
14
+
15
+ class PolyLine2D(Polygon2D):
16
+
17
+ def __init__(self, *args, coords_as_list=None,color=0xFFFFFF, opacity=1., stroke=0.65, line_style=None, theta=0, fill_color=None, __version__=1.0, **kwargs):
18
+ super(PolyLine2D, self).__init__()
19
+ points = []
20
+ if len(args) > 0:
21
+ if isinstance(args[0],tuple):
22
+ for i in range(0, len(args)):
23
+ self.append(QPointF(args[i][0], args[i][1]))
24
+ else:
25
+ for i in range(0, len(args), 2):
26
+ self.append(QPointF(args[i], args[i+1]))
27
+
28
+ if coords_as_list:
29
+ # print(coords_as_list)
30
+ for i in range(0, len(coords_as_list), 2):
31
+ self.append(QPointF(coords_as_list[i], coords_as_list[i + 1]))
32
+
33
+ self.color = color
34
+ self.fill_color = fill_color
35
+ self.stroke = stroke
36
+ self.opacity = opacity
37
+ self.isSet = False
38
+ self.line_style = line_style
39
+ # rotation
40
+ self.theta = theta
41
+ self.__version__ = __version__
42
+
43
+ def set_rotation(self, theta):
44
+ self.theta = theta
45
+
46
+ def set_opacity(self, opacity):
47
+ self.opacity = opacity
48
+
49
+ def set_line_style(self, style):
50
+ """
51
+ allows lines to be dashed or dotted or have custom pattern
52
+
53
+ :param style: a list of numbers or any of the following Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine but not Qt.CustomDashLine, Qt.CustomDashLine is assumed by default if a list is passed in. None is also a valid value that resets the line --> assume plain line
54
+ :return:
55
+ """
56
+ self.line_style = style
57
+ # if style is a list then assume custom pattern otherwise apply solidline
58
+
59
+ def draw(self, painter, draw=True, parent=None):
60
+ if self.color is None: # and self.fill_color is None
61
+ return
62
+
63
+ if draw:
64
+ painter.save()
65
+ pen = QPen(QColor(self.color))
66
+ if self.stroke is not None:
67
+ pen.setWidthF(self.stroke)
68
+ if self.line_style is not None:
69
+ if self.line_style in [Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine]:
70
+ pen.setStyle(self.line_style)
71
+ elif isinstance(self.line_style, list):
72
+ pen.setStyle(Qt.CustomDashLine)
73
+ pen.setDashPattern(self.line_style)
74
+ if self.color is not None:
75
+ painter.setPen(pen)
76
+ else:
77
+ painter.setPen(Qt.NoPen)
78
+ if self.fill_color is not None:
79
+ # print('coloring')
80
+ brush = QBrush(QColor(self.fill_color))
81
+ painter.setBrush(brush)
82
+ else:
83
+ painter.setBrush(Qt.NoBrush)
84
+
85
+ painter.setOpacity(self.opacity)
86
+ polyline_to_draw = self.translated(0, 0)
87
+
88
+ if parent is not None and parent.scale is not None and parent.scale != 1:
89
+ polyline_to_draw = self.__get_scaled_polyline(polyline_to_draw,1. / parent.scale)
90
+
91
+ if parent is not None:
92
+ polyline_to_draw = polyline_to_draw.translated(parent.topLeft())
93
+
94
+
95
+ # print(polyline_to_draw)
96
+
97
+ # if self.scale is not None and self.scale != 1:
98
+ # polyline_to_draw = self.__scaled()
99
+ # print('mid rect_to_plot', rect_to_plot)
100
+ # if self.translation is not None:
101
+ # # rect_to_plot.setX(rect_to_plot.x()+self.translation.x())
102
+ # # rect_to_plot.setY(rect_to_plot.y()+self.translation.y())
103
+ # polyline_to_draw.translate(self.translation.x(), self.translation.y())
104
+ # painter.drawPolygon(polygon_to_draw)
105
+ if self.theta is not None and self.theta != 0:
106
+ painter.translate(polyline_to_draw.boundingRect().center())
107
+ painter.rotate(self.theta)
108
+ painter.translate(-polyline_to_draw.boundingRect().center())
109
+
110
+ # painter.drawPolygon(polyline_to_draw)
111
+ painter.drawPolyline(polyline_to_draw)
112
+ painter.restore()
113
+ #
114
+ # def fill(self, painter, draw=True):
115
+ # if self.fill_color is None:
116
+ # return
117
+ # if draw:
118
+ # painter.save()
119
+ # painter.setBrush(QBrush(QColor(self.fill_color)))
120
+ # painter.setOpacity(self.opacity)
121
+ # if draw:
122
+ # painter.drawPolyline(self)
123
+ # painter.restore()
124
+ #
125
+ # # TODO pb will draw the shape twice.... ---> because painter drawpolygon is called twice
126
+ # def drawAndFill(self, painter):
127
+ # painter.save()
128
+ # self.draw(painter, draw=False)
129
+ # self.fill(painter, draw=False)
130
+ # painter.drawPolyline(self)
131
+ # painter.restore()
132
+ #
133
+ # def setP1(self, point):
134
+ # self.append(point)
135
+
136
+ def add(self, *args, force=True):
137
+ if self.count() > 1:
138
+ self.remove(self.count()-1)
139
+ self.append(args[1])
140
+ # self.isSet = True
141
+
142
+ # def listVertices(self):
143
+ # return [point for point in self]
144
+ def listVertices(self, polygon=None):
145
+ if polygon is None:
146
+ polygon = self
147
+ return [point for point in polygon]
148
+
149
+ def __get_scaled_polyline(self, polygon, scale):
150
+ vertices = self.listVertices(polygon)
151
+ scaled_poly = QPolygonF()
152
+ for vx in vertices:
153
+ vx.setX(vx.x()*scale)
154
+ vx.setY(vx.y()*scale)
155
+ scaled_poly.append(vx)
156
+ # print(vertices)
157
+ return scaled_poly
158
+
159
+ # def __get_scaled_polyline(self, scale):
160
+ # vertices = self.listVertices()
161
+ # scaled_poly = QPolygonF()
162
+ # for vx in vertices:
163
+ # vx.setX(vx.x()*scale)
164
+ # vx.setY(vx.y()*scale)
165
+ # scaled_poly.append(vx)
166
+ # print(vertices)
167
+ # return scaled_poly
168
+
169
+ def __scaled(self):
170
+ vertices = self.listVertices()
171
+ scaled_poly = QPolygonF()
172
+ for vx in vertices:
173
+ vx.setX(vx.x()*self.scale)
174
+ vx.setY(vx.y()*self.scale)
175
+ scaled_poly.append(vx)
176
+ return scaled_poly
177
+
178
+ def __repr__(self):
179
+ class_name = type(self).__name__
180
+ memory_address = hex(id(self))
181
+ return f"{class_name}-{memory_address}"
182
+
183
+ if __name__ == '__main__':
184
+ test = PolyLine2D(0, 0, 10, 0,10, 20, 0, 20, 0, 0)
185
+ print(test.count()) # marche pas --> pas ajouté
186
+ print(test)
187
+
188
+ hexagon = PolyLine2D()
189
+ print(hexagon)
190
+ hexagon.append(QPointF(10, 20))
191
+ hexagon.append(QPointF(10, 30))
192
+ hexagon.append(QPointF(20, 30))
193
+
194
+ print(hexagon)
195
+ print(hexagon.isEmpty())
196
+ print(hexagon.count())
197
+ print(hexagon.stroke)
198
+ print(hexagon.get_stroke_size())
199
+ # ça marche maintenant
200
+ # print(hexagon.)
201
+ # trop cool l'acces aux points
202
+ for point in hexagon:
203
+ print(point)
204
+
205
+ print(hexagon.get_points())
206
+ print(hexagon.contains(QPointF(10, 20)))
207
+ print(hexagon.contains(QPointF(10, 21)))
208
+
209
+ print(hexagon.isClosed()) #
210
+ hexagon.append(QPointF(10, 20)) # closing the hexagon --> the last and first point should be the same
211
+ print(hexagon.isClosed()) #
212
+ #
213
+ # image = QImage('./../data/handCorrection.png')
214
+ # painter = QPainter()
215
+ # painter.begin(image)
216
+ # # painter.setOpacity(0.3);
217
+ # painter.drawImage(0, 0, image)
218
+ # painter.setPen(QtCore.Qt.blue)
219
+ # painter.drawPolygon(hexagon)
220
+ # hexagon.opacity = 0.7
221
+ # painter.translate(10, 20)
222
+ # hexagon.draw(painter) # ça marche pourrait overloader ça avec du svg
223
+ # painter.end()
224
+ #
225
+ # # painter.save()
226
+ # # painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
227
+ # # painter.eraseRect(r)
228
+ # # painter.restore()
229
+ #
230
+ # image.save('./../trash/test_pyQT_draw.png', "PNG");
231
+ #
232
+ # #pas mal TODO faire une classe drawsmthg qui dessine n'importe quelle forme que l'on lui passe avec des parametres de couleur, transparence, ...
233
+
234
+ # tt marche aps mal ça va très vite
235
+
@@ -0,0 +1,388 @@
1
+ # code cleaning not finished... --> KEEP FOR COMPAT WITH OLD EPYSEG CODE (UNTIL CLEANING) --> BUT DO NOT USE ANYMORE
2
+
3
+ import os
4
+ import sys
5
+
6
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
7
+ set_UI()
8
+ from qtpy.QtCore import QPointF, QRectF, Qt
9
+ from qtpy.QtGui import QBrush, QPen, QColor, QTransform
10
+
11
+ from batoolset.tools.logger import TA_logger
12
+
13
+ logger = TA_logger()
14
+
15
+
16
+ # TODO --> try to simplify that and finalize it once for good
17
+
18
+
19
+
20
+ # rather use a dict as **kwargs to set opacity and alike --> that would allow me to handle much more flexibly my tools -−> this is not possible in fact possible but not very beautiful
21
+ '''
22
+ def __init__(self, *args, **kwargs):
23
+ # set default values for keyword arguments
24
+ color = kwargs.get('color', 0xFFFF00)
25
+ stroke = kwargs.get('stroke', 0.65)
26
+
27
+ '''
28
+ #
29
+
30
+
31
+ class Rect2D(QRectF):
32
+ """
33
+ A custom class for 2D rectangles with additional features such as color, fill color, opacity, stroke, line style,
34
+ rotation, scale, and translation.
35
+
36
+ Args:
37
+ *args: Variable-length arguments that can represent the rectangle coordinates.
38
+ color (int): Color of the rectangle in hexadecimal format (default: 0xFFFF00).
39
+ fill_color (int): Fill color of the rectangle in hexadecimal format (default: None).
40
+ opacity (float): Opacity value between 0.0 and 1.0 (default: 1.0).
41
+ stroke (float): Stroke width of the rectangle (default: 0.65).
42
+ line_style (Union[None, int, List[int]]): Line style of the rectangle. None for a solid line,
43
+ or any of the following values: Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine.
44
+ If a list of integers is provided, it represents a custom dash pattern (default: None).
45
+ theta (float): Rotation angle in degrees (default: 0.0).
46
+ **kwargs: Additional keyword arguments.
47
+
48
+ Attributes:
49
+ isSet (bool): Indicates whether the rectangle is set.
50
+ color (int): Color of the rectangle in hexadecimal format.
51
+ fill_color (int): Fill color of the rectangle in hexadecimal format.
52
+ stroke (float): Stroke width of the rectangle.
53
+ opacity (float): Opacity value between 0.0 and 1.0.
54
+ scale (float): Scaling factor of the rectangle (default: 1.0).
55
+ translation (QPointF): Translation of the rectangle.
56
+ line_style (Union[None, int, List[int]]): Line style of the rectangle.
57
+
58
+ """
59
+
60
+ def __init__(self, *args, color=0xFFFF00, fill_color=None, opacity=1., stroke=0.65, line_style=None, theta=0, **kwargs):
61
+ super(Rect2D, self).__init__(*args)
62
+ if not args:
63
+ self.isSet = False
64
+ else:
65
+ self.isSet = True
66
+ self.color = color
67
+ self.fill_color = fill_color
68
+ self.stroke = stroke
69
+ self.opacity = opacity
70
+ self.isSet = False
71
+ self.scale = 1
72
+ self.translation = QPointF()
73
+ self.line_style = line_style
74
+ self.theta = theta
75
+ self.incompressible_width=0
76
+ self.incompressible_height=0
77
+
78
+ def set_rotation(self, theta):
79
+ """
80
+ Set the rotation angle of the rectangle.
81
+
82
+ Args:
83
+ theta (float): Rotation angle in degrees.
84
+
85
+ """
86
+ self.theta = theta
87
+
88
+ def set_opacity(self, opacity):
89
+ """
90
+ Set the opacity value of the rectangle.
91
+
92
+ Args:
93
+ opacity (float): Opacity value between 0.0 and 1.0.
94
+
95
+ """
96
+ self.opacity = opacity
97
+
98
+ def set_line_style(self,style):
99
+ """
100
+ allows lines to be dashed or dotted or have custom pattern
101
+
102
+ :param style: a list of numbers or any of the following Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine but not Qt.CustomDashLine, Qt.CustomDashLine is assumed by default if a list is passed in. None is also a valid value that resets the line --> assume plain line
103
+ :return:
104
+ """
105
+ self.line_style = style
106
+ # if style is a list then assume custom pattern otherwise apply solidline
107
+
108
+
109
+ def draw(self, painter, **kwargs):
110
+ # print(kwargs)
111
+ # if kwargs is not None and kwargs:
112
+ # pass
113
+ # else:
114
+ # return
115
+
116
+ if self.color is None and self.fill_color is None:
117
+ return
118
+
119
+ painter.save()
120
+ painter.setOpacity(self.opacity)
121
+
122
+ if self.color is not None:
123
+ pen = QPen(QColor(self.color))
124
+ if self.stroke is not None:
125
+ pen.setWidthF(self.stroke)
126
+ if self.line_style is not None:
127
+ if self.line_style in [Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine]:
128
+ pen.setStyle(self.line_style)
129
+ elif isinstance(self.line_style, list):
130
+ pen.setStyle(Qt.CustomDashLine)
131
+ pen.setDashPattern(self.line_style)
132
+ pen.setJoinStyle(Qt.MiterJoin)# RoundJoin #BevelJoin # some day offer the handling of that but later
133
+ # if kwargs['draw']==True:
134
+
135
+ # pen.setStyle(Qt.DashLine)
136
+ # pen.setStyle(Qt.CustomDashLine)
137
+ # pen.setDashPattern([1, 4, 5, 4])
138
+
139
+ painter.setPen(pen)
140
+ # if kwargs['fill']==True:
141
+ else:
142
+ painter.setPen(Qt.NoPen) # required to draw something filled without a border
143
+
144
+ # needed to have a filling color in a shape without contour
145
+ if self.fill_color is not None:
146
+ painter.setBrush(QBrush(QColor(self.fill_color)))
147
+
148
+ rect_to_plot = self.adjusted(0,0,0,0)
149
+ # print('begin rect_to_plot', rect_to_plot, self.scale)
150
+ # if kwargs['draw']==True or kwargs['fill']==True:
151
+ # if self.scale is None or self.scale==1:
152
+ # painter.drawRect(self)
153
+ # else:
154
+ # on clone le rect
155
+ if self.scale is not None and self.scale != 1:
156
+ # TODO KEEP THE ORDER THIS MUST BE DONE THIS WAY OR IT WILL GENERATE PLENTY OF BUGS...
157
+ new_width = rect_to_plot.width() * self.scale
158
+ new_height = rect_to_plot.height() * self.scale
159
+ # print(rect_to_plot.width(), rect_to_plot.height()) # here ok
160
+ # setX changes width --> why is that
161
+
162
+ # TODO BE EXTREMELY CAREFUL AS SETX AND SETY CAN CHANGE WIDTH AND HEIGHT --> ALWAYS TAKE SIZE BEFORE OTHERWISE THERE WILL BE A PB AND ALWAYS RESET THE SIZE WHEN SETX IS CALLED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
163
+ # Sets the left edge of the rectangle to the given x coordinate. May change the width, but will never change the right edge of the rectangle. --> NO CLUE WHY SHOULD CHANGE WIDTH THOUGH BUT BE CAREFUL!!!
164
+ rect_to_plot.setX(rect_to_plot.x()*self.scale)
165
+ rect_to_plot.setY(rect_to_plot.y()*self.scale)
166
+ # maybe to avoid bugs I should use translate instead rather that set x but ok anyways
167
+ # print(rect_to_plot.width(), rect_to_plot.height())# bug here --> too big
168
+
169
+ # print(new_height, new_height, self.width(), self.scale, self.scale* self.width())
170
+ rect_to_plot.setWidth(new_width)
171
+ rect_to_plot.setHeight(new_height)
172
+
173
+ # print('mid rect_to_plot', rect_to_plot)
174
+ if self.translation is not None:
175
+
176
+ # rect_to_plot.setX(rect_to_plot.x()+self.translation.x())
177
+ # rect_to_plot.setY(rect_to_plot.y()+self.translation.y())
178
+ rect_to_plot.translate(self.translation)
179
+
180
+ # print('rect to plot', rect_to_plot)
181
+
182
+ # if self.color is not None:
183
+
184
+ # rotation marche mais position est pas du tout bonne --> voir comment gérer ça ??
185
+ # center = rect_to_plot.center()
186
+ # painter.translate(center.x(), center.y())
187
+ # painter.rotate(45)
188
+ # rct = QRectF(-center.x(), -center.y(), rect_to_plot.width(), rect_to_plot.height())
189
+ # painter.drawRect(rct)
190
+
191
+
192
+ if self.theta is not None and self.theta != 0:
193
+ # this is only if a rotation should be applied
194
+ painter.translate(rect_to_plot.center())
195
+ # print('center', rect_to_plot.center())
196
+ # painter.setWorldTransform()
197
+ # print(painter.combinedTransform().)
198
+
199
+
200
+
201
+ # TODO use this maybe to get bounds of rotated shape properly...
202
+ # center = rect_to_plot.center()
203
+ # t = QTransform().translate( center.x(), center-y() ).rotate( angle ).translate( -center.x(), -center.y() )
204
+ # rotatedRect = t.mapToPolygon( rect_to_plot ) #// mapRect() returns the bounding rect of the rotated rect
205
+
206
+ # on dirait que c'est ça faut faire deux translations en x
207
+
208
+ painter.rotate(self.theta)
209
+
210
+ # ça marche faut deux translations
211
+
212
+ # painter.translate(rect_to_plot.width() / 2, -rect_to_plot.height() )
213
+
214
+
215
+ #see https://www.qtcentre.org/threads/15540-Rotating-a-rectangle-about-its-origin --> maybe ok
216
+
217
+ # difference = old center -
218
+ # old_center = self.boundingRect().center()
219
+ # trans = painter.combinedTransform()
220
+ # transformed = trans.mapRect(rect_to_plot)
221
+
222
+ # peut etre une piste mais a pas l'air de marcher
223
+ # print(self.boundingRect(), transformed)
224
+ # trans = transformed.center()-self.boundingRect().center()
225
+
226
+
227
+ # width_dif = transformed.width()-self.boundingRect().width()
228
+ # width_dif/=2
229
+ # print('trans', trans, transformed.center(), self.boundingRect().center(), width_dif)
230
+
231
+ # painter.translate(-trans)
232
+ # only if rotation
233
+ painter.translate(-rect_to_plot.center())
234
+ painter.drawRect(rect_to_plot)
235
+ # else:
236
+ # painter.fillRect(rect_to_plot, QColor(self.fill_color))
237
+
238
+ painter.restore()
239
+
240
+ # TODO modify that to handle rotation etc...
241
+ def boundingRect(self, scaled=True):
242
+ # should I return the scaled version or the orig --> think about it...
243
+ if scaled:
244
+ # in fact scale only handles rotation and not scale --> the size is therefore wrong -->
245
+ try:
246
+ if self.theta is not None and self.theta!=0:
247
+ # print('entering')
248
+ center = self.center()
249
+ t = QTransform().translate( center.x(), center.y()).rotate(self.theta).translate(-center.x(), -center.y())
250
+ # print('entersd')
251
+ rotatedRect = t.mapRect( self ) #// mapRect() returns the bounding rect of the rotated rect
252
+ # print('rotated',rotatedRect )
253
+ return rotatedRect
254
+ except:
255
+ pass
256
+ return self
257
+
258
+ def add(self, *args):
259
+ point = args[1]
260
+ self.setWidth(point.x()-self.x()) # WHY IS THAT A - AND NOT A + ??? DID I DO A MISTAKE ??? −−> COULD BE # BUT KEEP LIKE THAT JUST IN CASE
261
+ self.setHeight(point.y()-self.y())
262
+ self.isSet = True
263
+
264
+ # def set_P1(self, *args):
265
+ # if not args:
266
+ # logger.error("no coordinate set...")
267
+ # return
268
+ # if len(args) == 1:
269
+ # self.moveTo(args[0].x(), args[0].y())
270
+ # else:
271
+ # self.moveTo(QPointF(args[0], args[1]))
272
+
273
+ # def get_P1(self):
274
+ # return QPointF(self.x(), self.y())
275
+
276
+ def set_to_scale(self, factor):
277
+ self.scale = factor
278
+
279
+ def set_to_translation(self, translation):
280
+ self.translation = translation
281
+
282
+ # hack to make column hashable to be able to add it to a dict, see https://stackoverflow.com/questions/10994229/how-to-make-an-object-properly-hashable
283
+ def __eq__(self, other):
284
+ try:
285
+ return hash(str(self)) == other.__hash__()
286
+ except:
287
+ return False
288
+
289
+ # hack to make column hashable to be able to add it to a dict, see https://stackoverflow.com/questions/10994229/how-to-make-an-object-properly-hashable
290
+ def __hash__(self):
291
+ return hash(str(self))
292
+
293
+ def getIncompressibleWidth(self):
294
+ return self.incompressible_width
295
+
296
+ def getIncompressibleHeight(self):
297
+ return self.incompressible_height
298
+
299
+ # can also be done like that
300
+ # def setTopLeft(self, x_or_rect, y=None):
301
+ # if y is None:
302
+ def setTopLeft(self, *args):
303
+ if args:
304
+ if len(args)==1:
305
+ # assume a QpointF
306
+ super().moveTopLeft(args[0])
307
+ elif len(args)==2:
308
+ super().moveTopLeft(QPointF(args[0], args[1]))
309
+ else:
310
+ logger.error('invalid args for top left')
311
+
312
+
313
+ if __name__ == '__main__':
314
+ # ça marche --> voici deux examples de shapes
315
+ test = Rect2D(10, 0, 100, 100)
316
+ print(test)
317
+ # print(test.get_P1())
318
+
319
+ test2 = Rect2D(QRectF(10, 0, 100, 100))
320
+ print('pt2', test2)
321
+
322
+ # then use my set_P1
323
+ print(test2.setTopLeft(10,20)) # setTopLeft really sucks because set top left crops the rect for unknown reason --> use moveTopLeft instead --> ça marche maintenant comme je pensais
324
+ print(test2)
325
+ sys.exit(0)
326
+
327
+ test.incompressible_width = 10
328
+ test.incompressible_height = 5
329
+ print(test.getIncompressibleWidth(),test.getIncompressibleHeight()) # --> that works --> this is a very easy way to get it then -−> this could also be borders around the image to fake it has the same size as another bigger image even if not --> can also be used by the tool that generates the stuff
330
+ # in the case of rows that should be the space between cols or rows and in the case of panels it is both
331
+
332
+ rect = QRectF(10, 0, 125, 256)
333
+ print(rect.x())
334
+ print(rect.y())
335
+ print(rect.width())
336
+ print(rect.height())
337
+
338
+ rect.setTopLeft(QPointF(10.,20.))
339
+
340
+ print('sum',rect.x()+rect.width(), type(rect.x()+rect.width())) # float
341
+
342
+ print(rect.topLeft()) # this is same as get_P1 --> maybe stick to that
343
+
344
+ rect.translate(10,20) # ça marche
345
+ print(rect)
346
+
347
+ print(test)
348
+ test.set_to_scale(0.5) #scale is not applied to the object so its size isn't the real size
349
+ # pb is that if I modify this class there will be tremendous repercusion on other classes --> be careful...
350
+ print('scaled test',test)
351
+ print('scaled test',test.boundingRect())
352
+ print('scaled test',test.boundingRect(scaled=True))
353
+
354
+ (test.x(), test.y(), test.width(), test.height())
355
+ print(test.contains(QPointF(50, 50)))
356
+ print(test.contains(QPointF(-1, -1)))
357
+ print(test.contains(QPointF(0, 0)))
358
+ print(test.contains(QPointF(100, 100)))
359
+ print(test.contains(QPointF(100, 100.1)))
360
+
361
+
362
+ # shall I do rotation
363
+
364
+
365
+
366
+ # p1 = test.p1()
367
+ # print(p1.x(), p1.y())
368
+ # p2 = test.p2()
369
+ # print(p2.x(), p2.y())
370
+ # print(test.arrow)
371
+ # print(test.length()) # sqrt 2 --> 141
372
+ # # if it's an arrow I can add easily all the stuff I need
373
+ #
374
+ # test = Rect2D(0, 0, 1, 1)
375
+ # p1 = test.p1()
376
+ # print(p1.x(), p1.y())
377
+ # p2 = test.p2()
378
+ # print(p2.x(), p2.y())
379
+ # print(test.arrow)
380
+ # import math
381
+ # print(test.length() == math.sqrt(2)) # sqrt 2
382
+ #
383
+ # test2 = Rect2D()
384
+ # p1 = test2.p1()
385
+ # print(p1.x(), p1.y())
386
+ # p2 = test2.p2()
387
+ # print(p2.x(), p2.y())
388
+ # print(test2.arrow)