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,601 @@
1
+ # this is the fully fixed version with the new rect
2
+ # THIS IS THE NEW VERSION OF THE CODE BUT IN ORDER NOT TO BREAK STUFF I WILL KEEP IT LIKE THAT
3
+
4
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
5
+ set_UI()
6
+ import os
7
+ import sys
8
+ import traceback
9
+ from qtpy.QtCore import QPointF, QRectF, Qt, QRect
10
+ from qtpy.QtGui import QBrush, QPen, QColor, QTransform
11
+ from batoolset.tools.logger import TA_logger
12
+
13
+ logger = TA_logger()
14
+
15
+ # TODO --> try to simplify that and finalize it once for good
16
+ # 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
17
+ '''
18
+ def __init__(self, *args, **kwargs):
19
+ # set default values for keyword arguments
20
+ color = kwargs.get('color', 0xFFFF00)
21
+ stroke = kwargs.get('stroke', 0.65)
22
+ '''
23
+
24
+ class Rectangle2D(QRectF):
25
+ """
26
+ A custom class for 2D rectangles with additional features such as color, fill color, opacity, stroke, line style,
27
+ rotation, scale, and translation.
28
+
29
+ Args:
30
+ *args: Variable-length arguments that can represent the rectangle coordinates.
31
+ color (int): Color of the rectangle in hexadecimal format (default: 0xFFFF00).
32
+ fill_color (int): Fill color of the rectangle in hexadecimal format (default: None).
33
+ opacity (float): Opacity value between 0.0 and 1.0 (default: 1.0).
34
+ stroke (float): Stroke width of the rectangle (default: 0.65).
35
+ line_style (Union[None, int, List[int]]): Line style of the rectangle. None for a solid line,
36
+ or any of the following values: Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine.
37
+ If a list of integers is provided, it represents a custom dash pattern (default: None).
38
+ theta (float): Rotation angle in degrees (default: 0.0).
39
+ **kwargs: Additional keyword arguments.
40
+
41
+ Attributes:
42
+ isSet (bool): Indicates whether the rectangle is set.
43
+ color (int): Color of the rectangle in hexadecimal format.
44
+ fill_color (int): Fill color of the rectangle in hexadecimal format.
45
+ stroke (float): Stroke width of the rectangle.
46
+ opacity (float): Opacity value between 0.0 and 1.0.
47
+ scale (float): Scaling factor of the rectangle (default: 1.0).
48
+ translation (QPointF): Translation of the rectangle.
49
+ line_style (Union[None, int, List[int]]): Line style of the rectangle.
50
+
51
+ """
52
+
53
+ def __init__(self, *args,x=0, y=0, width=0, height=0, color=0xFFFFFF, fill_color=None, opacity=1., stroke=0.65, line_style=None, theta=0, __version__=1.0,**kwargs):
54
+ if args:
55
+ super(Rectangle2D, self).__init__(*args)
56
+ else:
57
+ super(Rectangle2D, self).__init__(x,y,width,height)
58
+
59
+ # if not args:
60
+ # self.isSet = False
61
+ # else:
62
+ # self.isSet = True
63
+ self.color = color
64
+ self.fill_color = fill_color
65
+ self.stroke = stroke
66
+ self.opacity = opacity
67
+ self.isSet = False
68
+ self.scale = 1
69
+ # self.translation = QPointF()
70
+ self.line_style = line_style
71
+ self.theta = theta
72
+ self.incompressible_width=0
73
+ self.incompressible_height=0
74
+ self.immutable = False
75
+ self.__init_called__ = True # this is just to be used to prevent non initialized images to exist
76
+ # self.__sel = None
77
+ self.__version__ = __version__
78
+
79
+ def set_rotation(self, theta):
80
+ """
81
+ Set the rotation angle of the rectangle.
82
+
83
+ Args:
84
+ theta (float): Rotation angle in degrees.
85
+
86
+ """
87
+ self.theta = theta
88
+
89
+ def set_opacity(self, opacity):
90
+ """
91
+ Set the opacity value of the rectangle.
92
+
93
+ Args:
94
+ opacity (float): Opacity value between 0.0 and 1.0.
95
+
96
+ """
97
+ self.opacity = opacity
98
+
99
+ def set_line_style(self,style):
100
+ """
101
+ allows lines to be dashed or dotted or have custom pattern
102
+
103
+ :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
104
+ :return:
105
+ """
106
+ self.line_style = style
107
+ # if style is a list then assume custom pattern otherwise apply solidline
108
+
109
+
110
+ def draw(self, painter, parent=None, **kwargs):
111
+ # print(kwargs)
112
+ # if kwargs is not None and kwargs:
113
+ # pass
114
+ # else:
115
+ # return
116
+ # self.__sel = None
117
+ if self.color is None and self.fill_color is None:
118
+ return
119
+
120
+ painter.save()
121
+
122
+ painter.setPen(Qt.NoPen)
123
+ painter.setBrush(Qt.NoBrush)
124
+
125
+ painter.setOpacity(self.opacity)
126
+
127
+
128
+
129
+
130
+
131
+ if self.color is not None:
132
+ pen = QPen(QColor(self.color))
133
+ if self.stroke is not None:
134
+ pen.setWidthF(self.stroke)
135
+ if self.line_style is not None:
136
+ if self.line_style in [Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine]:
137
+ pen.setStyle(self.line_style)
138
+ elif isinstance(self.line_style, list):
139
+ pen.setStyle(Qt.CustomDashLine)
140
+ pen.setDashPattern(self.line_style)
141
+ pen.setJoinStyle(Qt.MiterJoin)# RoundJoin #BevelJoin # some day offer the handling of that but later
142
+ # if kwargs['draw']==True:
143
+
144
+ # pen.setStyle(Qt.DashLine)
145
+ # pen.setStyle(Qt.CustomDashLine)
146
+ # pen.setDashPattern([1, 4, 5, 4])
147
+
148
+ painter.setPen(pen)
149
+ # if kwargs['fill']==True:
150
+ else:
151
+ painter.setPen(Qt.NoPen) # required to draw something filled without a border
152
+
153
+ # needed to have a filling color in a shape without contour
154
+ if self.fill_color is not None:
155
+ painter.setBrush(QBrush(QColor(self.fill_color)))
156
+
157
+ # rect_to_plot = self.adjusted(0,0,0,0)
158
+ rect_to_plot = self.getRect(scale=True).adjusted(0,0,0,0)
159
+
160
+ if parent is not None and parent.scale is not None and parent.scale != 1:
161
+ rect_to_plot = self.__get_scaled_rect(rect_to_plot, 1. / parent.scale)
162
+
163
+ if parent is not None:
164
+ rect_to_plot = rect_to_plot.translated(parent.topLeft())
165
+
166
+ # print('rect_to_plot',rect_to_plot)
167
+
168
+ # print('begin rect_to_plot', rect_to_plot, self.scale)
169
+ # if kwargs['draw']==True or kwargs['fill']==True:
170
+ # if self.scale is None or self.scale==1:
171
+ # painter.drawRect(self)
172
+ # else:
173
+ # on clone le rect
174
+ # old crappy code --> forget and clean
175
+ # if self.scale is not None and self.scale != 1:
176
+ # # TODO KEEP THE ORDER THIS MUST BE DONE THIS WAY OR IT WILL GENERATE PLENTY OF BUGS...
177
+ # new_width = rect_to_plot.width() * self.scale
178
+ # new_height = rect_to_plot.height() * self.scale
179
+ # # print(rect_to_plot.width(), rect_to_plot.height()) # here ok
180
+ # # setX changes width --> why is that
181
+ #
182
+ # # 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!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
183
+ # # 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!!!
184
+ # rect_to_plot.setX(rect_to_plot.x()*self.scale)
185
+ # rect_to_plot.setY(rect_to_plot.y()*self.scale)
186
+ # # maybe to avoid bugs I should use translate instead rather that set x but ok anyways
187
+ # # print(rect_to_plot.width(), rect_to_plot.height())# bug here --> too big
188
+ #
189
+ # # print(new_height, new_height, self.width(), self.scale, self.scale* self.width())
190
+ # rect_to_plot.setWidth(new_width)
191
+ # rect_to_plot.setHeight(new_height)
192
+
193
+ # print('mid rect_to_plot', rect_to_plot)
194
+ # if self.translation is not None:
195
+ #
196
+ # # rect_to_plot.setX(rect_to_plot.x()+self.translation.x())
197
+ # # rect_to_plot.setY(rect_to_plot.y()+self.translation.y())
198
+ # rect_to_plot.translate(self.translation)
199
+
200
+ # print('rect to plot', rect_to_plot)
201
+
202
+ # if self.color is not None:
203
+
204
+ # rotation marche mais position est pas du tout bonne --> voir comment gérer ça ??
205
+ # center = rect_to_plot.center()
206
+ # painter.translate(center.x(), center.y())
207
+ # painter.rotate(45)
208
+ # rct = QRectF(-center.x(), -center.y(), rect_to_plot.width(), rect_to_plot.height())
209
+ # painter.drawRect(rct)
210
+ # rotatedRect = rect_to_plot
211
+
212
+ if self.theta is not None and self.theta != 0:
213
+ # this is only if a rotation should be applied
214
+ painter.translate(rect_to_plot.center())
215
+ # print('center', rect_to_plot.center())
216
+ # painter.setWorldTransform()
217
+ # print(painter.combinedTransform().)
218
+
219
+
220
+
221
+ # TODO use this maybe to get bounds of rotated shape properly...
222
+ # center = rect_to_plot.center()
223
+ # t = QTransform().translate( center.x(), center.y() ).rotate( self.theta ).translate( -center.x(), -center.y() )
224
+ # rotatedRect = t.mapToPolygon( rect_to_plot.toRect() ) #// mapRect() returns the bounding rect of the rotated rect
225
+
226
+ # on dirait que c'est ça faut faire deux translations en x
227
+
228
+ painter.rotate(self.theta)
229
+
230
+ # ça marche faut deux translations
231
+
232
+ # painter.translate(rect_to_plot.width() / 2, -rect_to_plot.height() )
233
+
234
+
235
+ #see https://www.qtcentre.org/threads/15540-Rotating-a-rectangle-about-its-origin --> maybe ok
236
+
237
+ # difference = old center -
238
+ # old_center = self.boundingRect().center()
239
+ # trans = painter.combinedTransform()
240
+ # transformed = trans.mapRect(rect_to_plot)
241
+
242
+ # peut etre une piste mais a pas l'air de marcher
243
+ # print(self.boundingRect(), transformed)
244
+ # trans = transformed.center()-self.boundingRect().center()
245
+
246
+
247
+ # width_dif = transformed.width()-self.boundingRect().width()
248
+ # width_dif/=2
249
+ # print('trans', trans, transformed.center(), self.boundingRect().center(), width_dif)
250
+
251
+ # painter.translate(-trans)
252
+ # only if rotation
253
+ painter.translate(-rect_to_plot.center())
254
+ painter.drawRect(rect_to_plot)
255
+ # else:
256
+ # painter.fillRect(rect_to_plot, QColor(self.fill_color))
257
+
258
+ painter.restore()
259
+
260
+ # self.__sel = rotatedRect
261
+ # if rotatedRect:
262
+ # if isinstance(rotatedRect, QRectF):
263
+ # return rotatedRect
264
+ # self.__sel =rotatedRect.boundingRect()
265
+ # return self.__sel
266
+ # else:
267
+ # return self.__sel
268
+
269
+
270
+ def __get_scaled_rect(self, rect_to_plot, scale):
271
+ rect = QRectF(rect_to_plot.x()*scale, rect_to_plot.y()*scale, rect_to_plot.width()*scale, rect_to_plot.height()*scale)
272
+ return rect
273
+
274
+ # TODO modify that to handle rotation etc...
275
+ def boundingRect(self, scaled=True):
276
+ # should I return the scaled version or the orig --> think about it...
277
+ if scaled:
278
+ # in fact scale only handles rotation and not scale --> the size is therefore wrong -->
279
+ try:
280
+ if self.theta is not None and self.theta!=0:
281
+ # print('entering')
282
+ center = self.center()
283
+ t = QTransform().translate( center.x(), center.y()).rotate(self.theta).translate(-center.x(), -center.y())
284
+ # print('entersd')
285
+ rotatedRect = t.mapRect( self ) #// mapRect() returns the bounding rect of the rotated rect
286
+ # print('rotated',rotatedRect )
287
+ return rotatedRect
288
+ except:
289
+ pass
290
+ return self
291
+
292
+ # def add(self, *args):
293
+ # point = args[1]
294
+ # 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
295
+ # self.setHeight(point.y()-self.y())
296
+ # # self.isSet = True
297
+
298
+ # def set_P1(self, *args):
299
+ # if not args:
300
+ # logger.error("no coordinate set...")
301
+ # return
302
+ # if len(args) == 1:
303
+ # self.moveTo(args[0].x(), args[0].y())
304
+ # else:
305
+ # self.moveTo(QPointF(args[0], args[1]))
306
+
307
+ # def get_P1(self):
308
+ # return QPointF(self.x(), self.y())
309
+
310
+ def set_to_scale(self, factor):
311
+ self.scale = factor
312
+
313
+ # def set_to_translation(self, translation):
314
+ # self.translation = translation
315
+
316
+ # 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
317
+ def __eq__(self, other):
318
+ try:
319
+ return hash(str(self)) == other.__hash__()
320
+ except:
321
+ return False
322
+
323
+ # 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
324
+ def __hash__(self):
325
+ return hash(str(self))
326
+
327
+ def getIncompressibleWidth(self):
328
+ return self.incompressible_width
329
+
330
+ def getIncompressibleHeight(self):
331
+ return self.incompressible_height
332
+
333
+ def get_incompressible_size(self, axis=None):
334
+ # DO I REALLY NEED THAT ANYMORE --> SHALL IT NOT SIMPLY ALWAYS RETURN 0 ???
335
+ if axis:
336
+ if axis == 'X':
337
+ return self.getIncompressibleWidth()
338
+ else:
339
+ return self.getIncompressibleHeight()
340
+ return 0
341
+
342
+ # can also be done like that
343
+ # def setTopLeft(self, x_or_rect, y=None):
344
+ # if y is None:
345
+ def setTopLeft(self, *args):
346
+ if args:
347
+ if len(args)==1:
348
+ # assume a QpointF
349
+ super().moveTopLeft(args[0])
350
+ elif len(args)==2:
351
+ super().moveTopLeft(QPointF(args[0], args[1]))
352
+ else:
353
+ logger.error('invalid args for top left')
354
+
355
+
356
+ # def getRect(self,*args, **kwargs):
357
+ # if args or kwargs:
358
+ # if 'all' in kwargs:
359
+ # # print('in there!')
360
+ # # rect_to_plot = QRectF(*super().getRect())#QRectF(self.x(), self.y(), self.width() / self.scale, self.height() / self.scale)
361
+ # rect_to_plot = QRectF(self.x(), self.y(), self.width() , self.height() )
362
+ # center = rect_to_plot.center()
363
+ # if self.theta:
364
+ # # t = QTransform().translate(center.x(), center.y()).rotate(self.theta).translate(-center.x(),-center.y())
365
+ # # rotatedRect = t.mapToPolygon(rect_to_plot.toRect()) # // mapRect() returns the bounding rect
366
+ # t = QTransform().translate(center.x(), center.y()).rotate(self.theta).translate(-center.x(),
367
+ # -center.y())
368
+ # rotatedPolygon = t.mapToPolygon(rect_to_plot.toRect()) # Map the rectangle to a rotated polygon
369
+ #
370
+ # # Create a QRectF from the bounding rectangle of the rotated polygon
371
+ # rotatedRect = QRectF(rotatedPolygon.boundingRect())
372
+ #
373
+ # if self.crop_left:
374
+ # rotatedRect.setWidth(rotatedRect.width()-self.crop_left)
375
+ # if self.crop_right:
376
+ # rotatedRect.setWidth(rotatedRect.width()-self.crop_right)
377
+ # if self.crop_top:
378
+ # rotatedRect.setHeight(rotatedRect.height()-self.crop_top)
379
+ # if self.crop_bottom:
380
+ # rotatedRect.setHeight(rotatedRect.height()-self.crop_bottom)
381
+ #
382
+ # rotatedRect.setWidth(rotatedRect.width()/self.scale)
383
+ # rotatedRect.setHeight(rotatedRect.height()/self.scale)
384
+ # else:
385
+ # if self.crop_left:
386
+ # rect_to_plot.setWidth(rect_to_plot.width() - self.crop_left)
387
+ # if self.crop_right:
388
+ # rect_to_plot.setWidth(rect_to_plot.width() - self.crop_right)
389
+ # if self.crop_top:
390
+ # rect_to_plot.setHeight(rect_to_plot.height() - self.crop_top)
391
+ # if self.crop_bottom:
392
+ # rect_to_plot.setHeight(rect_to_plot.height() - self.crop_bottom)
393
+ # rect_to_plot.setWidth(rect_to_plot.width() / self.scale)
394
+ # rect_to_plot.setHeight(rect_to_plot.height() / self.scale)
395
+ # return rect_to_plot
396
+ # try:
397
+ # return QRectF(rotatedRect.boundingRect())
398
+ # except:
399
+ # return rotatedRect
400
+ # # return QRectF(self.x(), self.y(), self.width() / self.scale, self.height() / self.scale)
401
+ # else:
402
+ # # default to scaled object
403
+ # return QRectF(self.x(), self.y(), self.width()/self.scale, self.height()/self.scale)
404
+ # else:
405
+ # # return super().getRect()
406
+ # return QRectF(*super().getRect())
407
+
408
+
409
+ def getRect(self,*args, **kwargs):
410
+ if args or kwargs:
411
+ if 'all' in kwargs:
412
+ # print('in there!')
413
+ # rect_to_plot = QRectF(*super().getRect())#QRectF(self.x(), self.y(), self.width() / self.scale, self.height() / self.scale)
414
+ rect_to_plot = QRectF(self.x(), self.y(), self.width() / self.scale, self.height() / self.scale)
415
+ center = rect_to_plot.center()
416
+ if self.theta:
417
+ # t = QTransform().translate(center.x(), center.y()).rotate(self.theta).translate(-center.x(),-center.y())
418
+ # rotatedRect = t.mapToPolygon(rect_to_plot.toRect()) # // mapRect() returns the bounding rect
419
+ t = QTransform().translate(center.x(), center.y()).rotate(self.theta).translate(-center.x(),
420
+ -center.y())
421
+ rotatedPolygon = t.mapToPolygon(rect_to_plot.toRect()) # Map the rectangle to a rotated polygon
422
+
423
+ # Create a QRectF from the bounding rectangle of the rotated polygon
424
+ rotatedRect = QRectF(rotatedPolygon.boundingRect())
425
+ else:
426
+ return rect_to_plot
427
+ try:
428
+ return QRectF(rotatedRect.boundingRect())
429
+ except:
430
+ return rotatedRect
431
+ # return QRectF(self.x(), self.y(), self.width() / self.scale, self.height() / self.scale)
432
+ else:
433
+ # default to scaled object
434
+ return QRectF(self.x(), self.y(), self.width()/self.scale, self.height()/self.scale)
435
+ else:
436
+ # return super().getRect()
437
+ return QRectF(*super().getRect())
438
+
439
+ def width(self,*args, **kwargs):
440
+ if args or kwargs:
441
+ return self.width()/self.scale # this is probably incorrect but ok for now
442
+ else:
443
+ return super().width()
444
+ # return self.getRect(*args, **kwargs).width()
445
+
446
+ def height(self,*args, **kwargs):
447
+ if args or kwargs:
448
+ return self.height()/self.scale
449
+ else:
450
+ return super().height()
451
+ # return self.getRect(*args, **kwargs).height()
452
+
453
+ def getAR(self, invert=False):
454
+ # try:
455
+ if invert:
456
+ return float(self.height()) / float(self.width())
457
+ return float(self.width()) / float(self.height())
458
+ # except:
459
+ # return 1.
460
+
461
+ def contains(self, *__args):
462
+ try:
463
+ # if self.__sel:
464
+ # return self.__sel.contains(*__args)
465
+ if __args is not None and __args:
466
+ return self.getRect(all=True).contains(*__args)
467
+ else:
468
+ return False
469
+ # return self.getRect(scale=True).contains(*__args)
470
+ except:
471
+ # traceback.print_exc() # somehow this generates an error but does it make sense
472
+ # I have too many handling of rotations --> that may cause trouble too
473
+ # simplest is to really make the rect as it should be and as selection should be !!!
474
+ pass
475
+ return False
476
+
477
+ # def __str__(self):
478
+ # return f'rectangle {super().__str__()}'
479
+ def set_to_center(self, centroid):
480
+ w = self.width()
481
+ h = self.height()
482
+ if isinstance(centroid, (tuple, list)):
483
+
484
+ self.setX(centroid[0]-self.width()/2.)
485
+ self.setY(centroid[1]-self.height()/2.)
486
+
487
+ else:
488
+ self.setX(centroid.x()-self.width()/2.)
489
+ self.setY(centroid.y()-self.height()/2.)
490
+ self.setWidth(w)
491
+ self.setHeight(h)
492
+ def add(self, *args):
493
+ point = args[1]
494
+ 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
495
+ self.setHeight(point.y()-self.y())
496
+ self.isSet = True
497
+
498
+ # def __repr__(self):
499
+ # default_repr = object.__repr__(self)
500
+ # class_name = type(self).__name__
501
+ # return f"{class_name}{default_repr}"
502
+ def __repr__(self):
503
+ class_name = type(self).__name__
504
+ memory_address = hex(id(self))
505
+ return f"{class_name}-{memory_address}"
506
+
507
+ def to_dict(self):
508
+ x = self.x()
509
+ y = self.y()
510
+ width = self.width()
511
+ height = self.height()
512
+
513
+ # Create a dictionary representation of the values of the super object
514
+ output_dict = {
515
+ 'x': x,
516
+ 'y': y,
517
+ 'width': width,
518
+ 'height': height,
519
+ }
520
+ # Update the dictionary with the __dict__ of Rectangle2D
521
+ output_dict.update(self.__dict__)
522
+ return output_dict
523
+
524
+ if __name__ == '__main__':
525
+ # ça marche --> voici deux examples de shapes
526
+ test = Rectangle2D(10, 0, 100, 100)
527
+ print(test)
528
+ # print(test.get_P1())
529
+
530
+ test2 = Rectangle2D(QRectF(10, 0, 100, 100))
531
+ print('pt2', test2)
532
+
533
+ # then use my set_P1
534
+ 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
535
+ print(test2)
536
+ sys.exit(0)
537
+
538
+ test.incompressible_width = 10
539
+ test.incompressible_height = 5
540
+ 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
541
+ # in the case of rows that should be the space between cols or rows and in the case of panels it is both
542
+
543
+ rect = QRectF(10, 0, 125, 256)
544
+ print(rect.x())
545
+ print(rect.y())
546
+ print(rect.width())
547
+ print(rect.height())
548
+
549
+ rect.setTopLeft(QPointF(10.,20.))
550
+
551
+ print('sum',rect.x()+rect.width(), type(rect.x()+rect.width())) # float
552
+
553
+ print(rect.topLeft()) # this is same as get_P1 --> maybe stick to that
554
+
555
+ rect.translate(10,20) # ça marche
556
+ print(rect)
557
+
558
+ print(test)
559
+ test.set_to_scale(0.5) #scale is not applied to the object so its size isn't the real size
560
+ # pb is that if I modify this class there will be tremendous repercusion on other classes --> be careful...
561
+ print('scaled test',test)
562
+ print('scaled test',test.boundingRect())
563
+ print('scaled test',test.boundingRect(scaled=True))
564
+
565
+ (test.x(), test.y(), test.width(), test.height())
566
+ print(test.contains(QPointF(50, 50)))
567
+ print(test.contains(QPointF(-1, -1)))
568
+ print(test.contains(QPointF(0, 0)))
569
+ print(test.contains(QPointF(100, 100)))
570
+ print(test.contains(QPointF(100, 100.1)))
571
+
572
+
573
+ # shall I do rotation
574
+
575
+
576
+ # ideally plot it so that I can test all
577
+
578
+
579
+ # p1 = test.p1()
580
+ # print(p1.x(), p1.y())
581
+ # p2 = test.p2()
582
+ # print(p2.x(), p2.y())
583
+ # print(test.arrow)
584
+ # print(test.length()) # sqrt 2 --> 141
585
+ # # if it's an arrow I can add easily all the stuff I need
586
+ #
587
+ # test = Rect2D(0, 0, 1, 1)
588
+ # p1 = test.p1()
589
+ # print(p1.x(), p1.y())
590
+ # p2 = test.p2()
591
+ # print(p2.x(), p2.y())
592
+ # print(test.arrow)
593
+ # import math
594
+ # print(test.length() == math.sqrt(2)) # sqrt 2
595
+ #
596
+ # test2 = Rect2D()
597
+ # p1 = test2.p1()
598
+ # print(p1.x(), p1.y())
599
+ # p2 = test2.p2()
600
+ # print(p2.x(), p2.y())
601
+ # print(test2.arrow)