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,257 @@
1
+ import os
2
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
3
+ set_UI()
4
+ from math import sqrt
5
+
6
+ from qtpy.QtCore import QRectF
7
+
8
+ from batoolset.draw.shapes.circle2d import *
9
+ from batoolset.tools.logger import TA_logger
10
+ logger = TA_logger()
11
+
12
+ class Point2D(QPointF):
13
+
14
+ def __init__(self, *args, x=0,y=0, color=0xFFFFFF, fill_color=None, opacity=1., stroke=0.65, line_style=None,__version__=1.0, **kwargs):
15
+ # self.isSet = True
16
+ self.size = 5
17
+ if len(args)==2:
18
+ #TODO need fix size
19
+ super(Point2D, self).__init__(*args)
20
+ else:
21
+ # self.size = 5
22
+ if args:
23
+ super(Point2D, self).__init__(*args) # create an empty point for drawing
24
+ else:
25
+ super(Point2D, self).__init__(x,y)
26
+
27
+ if stroke is not None and stroke > 2:
28
+ self.size = stroke
29
+ self.color = color
30
+ self.fill_color = fill_color
31
+ self.stroke = stroke
32
+ self.opacity = opacity
33
+ self.theta = 0 # useless for a point but useful for compat
34
+ self.scale = 1
35
+ self.translation = QPointF()
36
+ self.line_style = line_style
37
+ self.__version__ = __version__
38
+
39
+ def set_opacity(self, opacity):
40
+ self.opacity = opacity
41
+
42
+ def set_line_style(self,style):
43
+ """
44
+ allows lines to be dashed or dotted or have custom pattern
45
+
46
+ :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
47
+ :return:
48
+ """
49
+ self.line_style = style
50
+ # if style is a list then assume custom pattern otherwise apply solidline
51
+
52
+ def contains(self, *args):
53
+ x=0
54
+ y=0
55
+ if isinstance(args[0], QPoint) or isinstance(args[0], QPointF):
56
+ x = args[0].x()
57
+ y = args[0].y()
58
+ if sqrt((x-self.x())**2+(y-self.y())**2)<10:
59
+ return True
60
+ return False
61
+
62
+ def translate(self, *translation):
63
+ # if isinstance(translation, (QPoint, QPointF)):
64
+ if isinstance(translation[0], (int, float)):
65
+ translation = QPointF(translation[0], translation[1])
66
+
67
+ if isinstance(translation, tuple):
68
+ # not sure this is normal that I have to do that but if I don't do it dragging the ellipse in the demo image crashes the soft
69
+ translation = QPointF(translation[0])
70
+
71
+ self.setX(self.x() + translation.x())
72
+ self.setY(self.y() + translation.y())
73
+
74
+ def draw(self, painter, draw=True, parent=None):
75
+ if self.color is None and self.fill_color is None:
76
+ return
77
+
78
+ if draw:
79
+ painter.save()
80
+ painter.setOpacity(self.opacity)
81
+ if self.color is not None:
82
+ pen = QPen(QColor(self.color))
83
+ if self.stroke is not None:
84
+ pen.setWidthF(self.stroke)
85
+ if self.line_style is not None:
86
+ if self.line_style in [Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine]:
87
+ pen.setStyle(self.line_style)
88
+ elif isinstance(self.line_style, list):
89
+ pen.setStyle(Qt.CustomDashLine)
90
+ pen.setDashPattern(self.line_style)
91
+ painter.setPen(pen)
92
+ else:
93
+ painter.setPen(Qt.NoPen) # required to draw something filled without a border
94
+ if self.fill_color is not None:
95
+ painter.setBrush(QBrush(QColor(self.fill_color)))
96
+ point_to_draw = QPointF(self.x(), self.y())
97
+
98
+ # print('point_to_draw', point_to_draw)
99
+
100
+ if parent is not None and parent.scale is not None and parent.scale != 1:
101
+ point_to_draw = QPointF(point_to_draw.x()/parent.scale, self.y()/parent.scale)
102
+
103
+ if parent is not None:
104
+ point_to_draw = QPointF(point_to_draw.x()+parent.x(), point_to_draw.y()+parent.y())
105
+
106
+ # print('point_to_draw2', point_to_draw)
107
+
108
+ # if self.scale is not None and self.scale != 1:
109
+ # point_to_draw.setX(point_to_draw.x()*self.scale)
110
+ # point_to_draw.setY(point_to_draw.y()*self.scale)
111
+ # if self.translation is not None:
112
+ # point_to_draw.setX(point_to_draw.x()+self.translation.x())
113
+ # point_to_draw.setY(point_to_draw.y()+self.translation.y())
114
+
115
+ # painter.drawEllipse(point_to_draw.x()-self.stroke/2., point_to_draw.y()-self.stroke/2, self.stroke, self.stroke)
116
+ painter.drawEllipse(int(point_to_draw.x()-self.stroke/2.), int(point_to_draw.y()-self.stroke/2), int(self.stroke), int(self.stroke)) # why tale int here --> draw in float precision --> because there is no simple ellipse object in pyqt -−> see my ellipse implementation --> and fix that some day!!
117
+ # painter.drawEllipse(point_to_draw.x()-self.stroke/2., point_to_draw.y()-self.stroke/2, self.stroke, self.stroke) # why tale int here --> draw in float precision
118
+ painter.restore()
119
+
120
+ # def fill(self, painter, draw=True):
121
+ # if self.fill_color is None:
122
+ # return
123
+ # if draw:
124
+ # painter.save()
125
+ # painter.setBrush(QBrush(QColor(self.fill_color)))
126
+ # painter.setOpacity(self.opacity)
127
+ # if draw:
128
+ # painter.drawEllipse(self.x()-self.stroke/2., self.y()-self.stroke/2, self.stroke, self.stroke)
129
+ # painter.restore()
130
+ #
131
+ # def drawAndFill(self, painter):
132
+ # painter.save()
133
+ # self.draw(painter, draw=False)
134
+ # self.fill(painter, draw=False)
135
+ # size = max(self.size, self.stroke)
136
+ # painter.drawEllipse(self.x()-size/2., self.y()-size/2, size, size) # drawEllipse (x, y, w, h)
137
+ # painter.restore()
138
+
139
+ def boundingRect(self):
140
+ return QRectF(self.x()-self.stroke/2., self.y()-self.stroke/2, self.stroke, self.stroke)
141
+
142
+ def add(self, *args):
143
+ point = args[1]
144
+ self.setX(point.x())
145
+ self.setY(point.y())
146
+
147
+ # def set_P1(self, *args):
148
+ # if not args:
149
+ # logger.error("no coordinate set...")
150
+ # return
151
+ # if len(args) == 1:
152
+ # # self.moveTo(args[0].x(), args[0].y())
153
+ # self.setX(args[0].x())
154
+ # self.setY(args[0].y())
155
+ # else:
156
+ # # self.moveTo(QPointF(args[0], args[1]))
157
+ # self.setX(args[0])
158
+ # self.setY(args[1])
159
+ # # self.setX(point.x())
160
+ # # self.setY(point.y())
161
+
162
+ # def get_P1(self):
163
+ # return self
164
+ def setTopLeft(self, *args):
165
+ if args:
166
+ if len(args)==1:
167
+ # assume a QpointF
168
+ super().setP1(args[0])
169
+ elif len(args)==2:
170
+ super().setP1(QPointF(args[0], args[1]))
171
+ else:
172
+ logger.error('invalid args for top left')
173
+
174
+
175
+ def topLeft(self):
176
+ return self
177
+
178
+ def getRect(self, *args, **kwargs):
179
+ return self.boundingRect()
180
+
181
+ def width(self):
182
+ return 0
183
+
184
+ def height(self):
185
+ return 0
186
+
187
+ def set_to_scale(self, factor):
188
+ self.scale = factor
189
+
190
+ def set_to_translation(self, translation):
191
+ self.translation = translation
192
+
193
+ def set_to_center(self, centroid):
194
+ if isinstance(centroid, (tuple, list)):
195
+ self.setX(centroid[0])
196
+ self.setY(centroid[1])
197
+ else:
198
+ self.setX(centroid.x())
199
+ self.setY(centroid.y())
200
+
201
+ def __repr__(self):
202
+ class_name = type(self).__name__
203
+ memory_address = hex(id(self))
204
+ return f"{class_name}-{memory_address}"
205
+
206
+ def to_dict(self):
207
+ x = self.x()
208
+ y = self.y()
209
+
210
+ # Create a dictionary representation of the values of the super object
211
+ output_dict = {
212
+ 'x': x,
213
+ 'y': y,
214
+ }
215
+ # Update the dictionary with the __dict__ of Rectangle2D
216
+ output_dict.update(self.__dict__)
217
+ return output_dict
218
+
219
+ if __name__ == '__main__':
220
+ # ça marche --> voici deux examples de shapes
221
+ test = Point2D(128, 128)
222
+ # print(test.x(), test.y(), test.width(), test.height())
223
+ print(test.contains(QPointF(128, 128)))
224
+ print(test.contains(QPointF(129, 129))) # why True ??? --> maybe ok but think
225
+ print(test.contains(QPointF(-1, -1)))
226
+ print(test.contains(QPointF(0, 0)))
227
+ print(test.contains(QPointF(100, 100)))
228
+ print(test.contains(QPointF(100, 100.1)))
229
+ print(test.x())
230
+ print(test.y())
231
+ print(test.translate(QPoint(10, 10)))
232
+ print(test.x())
233
+ print(test.y())
234
+
235
+ # p1 = test.p1()
236
+ # print(p1.x(), p1.y())
237
+ # p2 = test.p2()
238
+ # print(p2.x(), p2.y())
239
+ # print(test.arrow)
240
+ # print(test.length()) # sqrt 2 --> 141
241
+ # # if it's an arrow I can add easily all the stuff I need
242
+ #
243
+ # test = Rect2D(0, 0, 1, 1)
244
+ # p1 = test.p1()
245
+ # print(p1.x(), p1.y())
246
+ # p2 = test.p2()
247
+ # print(p2.x(), p2.y())
248
+ # print(test.arrow)
249
+ # import math
250
+ # print(test.length() == math.sqrt(2)) # sqrt 2
251
+ #
252
+ # test2 = Rect2D()
253
+ # p1 = test2.p1()
254
+ # print(p1.x(), p1.y())
255
+ # p2 = test2.p2()
256
+ # print(p2.x(), p2.y())
257
+ # print(test2.arrow)
@@ -0,0 +1,357 @@
1
+ from batoolset.settings.global_settings import set_UI # set the UI to qtpy
2
+ set_UI()
3
+ import os
4
+ from batoolset.draw.shapes.tools import rect_intersects_polygon, create_rect_centered_at, qpolygonf_to_list
5
+ from qtpy import QtCore
6
+ from qtpy.QtCore import QPointF, Qt
7
+ from qtpy.QtGui import QPolygonF, QTransform
8
+ from qtpy.QtGui import QPainter, QBrush, QPen, QImage, QColor
9
+ # from qtpy.Qt
10
+ # from qtpy.Qt import (QPaintEngine, QPaintDevice, QTransform, QBrush)
11
+
12
+ from batoolset.tools.logger import TA_logger
13
+ logger = TA_logger()
14
+
15
+ class Polygon2D(QPolygonF):
16
+
17
+ def __init__(self, *args, coords_as_list=None, color=0xFFFFFF, fill_color=None, opacity=1., stroke=0.65, line_style=None, theta=0,__version__=1.0, **kwargs):
18
+ super(Polygon2D, self).__init__()
19
+ self.isSet = False
20
+ if len(args) > 0:
21
+ if isinstance(args[0], (float,int)):
22
+ for i in range(0, len(args), 2):
23
+ self.append(QPointF(args[i], args[i+1]))
24
+ else:
25
+ # to handle list of vertices!!!
26
+ for pt in args:
27
+ self.append(QPointF(pt[0],pt[1]))
28
+
29
+ if 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.scale = 1
38
+ self.translation = QPointF()
39
+ self.line_style = line_style
40
+ # self.isSet = False
41
+ # rotation
42
+ self.theta = theta
43
+ self.__version__ = __version__
44
+
45
+ def set_rotation(self, theta):
46
+ self.theta = theta
47
+
48
+ def set_opacity(self, opacity):
49
+ self.opacity = opacity
50
+
51
+ def set_line_style(self,style):
52
+ """
53
+ allows lines to be dashed or dotted or have custom pattern
54
+
55
+ :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
56
+ :return:
57
+ """
58
+ self.line_style = style
59
+ # if style is a list then assume custom pattern otherwise apply solidline
60
+
61
+ def get_color(self):
62
+ return self.color
63
+
64
+ def get_fill_color(self):
65
+ return self.fill_color
66
+
67
+ def get_stroke_size(self):
68
+ return self.stroke
69
+
70
+ def get_points(self): #nb if closed it returns also the closing point (e.g. first==last) which may not always be desired! -−> maybe offer an option
71
+ points = []
72
+ for point in self:
73
+ points.append((point.x(), point.y()))
74
+ return points
75
+
76
+ def contains(self, *args,**kwargs):
77
+ # print("kwargs", kwargs)
78
+ extra=0
79
+ if kwargs:
80
+ if 'extra' in kwargs:
81
+ extra=kwargs['extra']
82
+ if len(args)!=1:
83
+ point = QPointF(float(args[0]),float(args[1]))
84
+ if extra:
85
+ return rect_intersects_polygon(create_rect_centered_at(point, extra), self)
86
+ else:
87
+ return self.containsPoint(point, Qt.OddEvenFill)
88
+ else:
89
+ if extra:
90
+ return rect_intersects_polygon(create_rect_centered_at(args[0], extra), self)
91
+ else:
92
+ return self.containsPoint(args[0], Qt.OddEvenFill)
93
+
94
+ def draw(self, painter, draw=True, parent=None):
95
+ if self.color is None and self.fill_color is None:
96
+ return
97
+
98
+ if draw:
99
+ painter.save()
100
+ painter.setPen(Qt.NoPen)
101
+ painter.setBrush(Qt.NoBrush)
102
+ painter.setOpacity(self.opacity)
103
+ if self.color is not None:
104
+ pen = QPen(QColor(self.color))
105
+ if self.stroke is not None:
106
+ pen.setWidthF(self.stroke)
107
+ if self.line_style is not None:
108
+ if self.line_style in [Qt.SolidLine, Qt.DashLine, Qt.DashDotLine, Qt.DotLine, Qt.DashDotDotLine]:
109
+ pen.setStyle(self.line_style)
110
+ elif isinstance(self.line_style, list):
111
+ pen.setStyle(Qt.CustomDashLine)
112
+ pen.setDashPattern(self.line_style)
113
+ painter.setPen(pen)
114
+ else:
115
+ painter.setPen(Qt.NoPen) # required to draw something filled without a border
116
+ if self.fill_color is not None:
117
+ painter.setBrush(QBrush(QColor(self.fill_color)))
118
+ else:
119
+ painter.setBrush(Qt.NoBrush)
120
+ polygon_to_draw = self.translated(0, 0)
121
+
122
+ # print(type(polygon_to_draw))
123
+ # print('polygon_to_draw.listVertices()', self.listVertices(polygon_to_draw))
124
+
125
+ if parent is not None and parent.scale is not None and parent.scale != 1:
126
+ polygon_to_draw = self.__get_scaled_polygon(polygon_to_draw,1. / parent.scale)
127
+
128
+ if parent is not None:
129
+ polygon_to_draw = polygon_to_draw.translated(parent.topLeft())
130
+
131
+ # print('polygon_to_draw.listVertices()2', self.listVertices(polygon_to_draw))
132
+
133
+ # if self.scale is not None and self.scale != 1:
134
+ # polygon_to_draw = self.__scaled()
135
+
136
+ # print('mid rect_to_plot', rect_to_plot)
137
+ # if self.translation is not None:
138
+ # # rect_to_plot.setX(rect_to_plot.x()+self.translation.x())
139
+ # # rect_to_plot.setY(rect_to_plot.y()+self.translation.y())
140
+ # polygon_to_draw.translate(self.translation.x(), self.translation.y())
141
+
142
+ if self.theta is not None and self.theta != 0:
143
+ painter.translate(polygon_to_draw.boundingRect().center())
144
+ painter.rotate(self.theta)
145
+ painter.translate(-polygon_to_draw.boundingRect().center())
146
+
147
+ # pen = QPen(QColor(self.color))
148
+ # painter.setPen(pen)
149
+ # pen.setWidthF(self.stroke)
150
+ painter.drawPolygon(polygon_to_draw)
151
+ # painter.setBrush(QBrush(QColor(0xFF0000)))
152
+ # painter.drawPolygon(polygon_to_draw)
153
+
154
+
155
+ painter.restore()
156
+
157
+ # def fill(self, painter, draw=True):
158
+ # if self.fill_color is None:
159
+ # return
160
+ # if draw:
161
+ # painter.save()
162
+ # painter.setBrush(QBrush(QColor(self.fill_color)))
163
+ # painter.setOpacity(self.opacity)
164
+ # if draw:
165
+ # painter.drawPolygon(self)
166
+ # painter.restore()
167
+ #
168
+ # def drawAndFill(self, painter):
169
+ # painter.save()
170
+ # self.draw(painter, draw=False)
171
+ # self.fill(painter, draw=False)
172
+ # painter.drawPolygon(self)
173
+ # painter.restore()
174
+
175
+ # def setP1(self, point):
176
+ # self.append(point)
177
+
178
+
179
+ def add(self, *args, force=False):
180
+ if self.count() > 1 and not force:
181
+ self.remove(self.count()-1)
182
+ self.append(args[1])
183
+ # self.isSet = True
184
+
185
+ def listVertices(self, polygon=None): # redundant with get_points !
186
+ if polygon is None:
187
+ polygon = self
188
+ return [point for point in polygon]
189
+
190
+ def set_to_scale(self, factor):
191
+ self.scale = factor
192
+
193
+ def set_to_translation(self, translation):
194
+ self.translation = translation
195
+
196
+ def topLeft(self):
197
+ return self.boundingRect().topLeft()
198
+
199
+ # def get_P1(self):
200
+ # return self.boundingRect().topLeft()
201
+
202
+ # def set_P1(self, point):# see how to do that
203
+ def setTopLeft(self, point):# see how to do that
204
+ #self.append(point)
205
+ # get bounding box and set top left to P1
206
+ current_pos = self.boundingRect().topLeft()
207
+ self.translate(point.x()-current_pos.x(), point.y()-current_pos.y())
208
+
209
+ def __get_scaled_polygon(self, polygon, scale):
210
+ vertices = self.listVertices(polygon)
211
+ scaled_poly = QPolygonF()
212
+ for vx in vertices:
213
+ vx.setX(vx.x()*scale)
214
+ vx.setY(vx.y()*scale)
215
+ scaled_poly.append(vx)
216
+ # print(vertices)
217
+ return scaled_poly
218
+
219
+ def __scaled(self):
220
+ vertices = self.listVertices()
221
+ scaled_poly = QPolygonF()
222
+ for vx in vertices:
223
+ vx.setX(vx.x()*self.scale)
224
+ vx.setY(vx.y()*self.scale)
225
+ scaled_poly.append(vx)
226
+ return scaled_poly
227
+
228
+ def boundingRect(self):
229
+ polygon_to_draw = self.translated(0, 0)
230
+ try:
231
+ # print('tada')
232
+ if self.theta is not None and self.theta != 0:
233
+ # print('entering')
234
+ center = polygon_to_draw.boundingRect().center()
235
+ # print('entering2')
236
+ t = QTransform().translate(center.x(), center.y()).rotate(self.theta).translate(-center.x(),
237
+ -center.y())
238
+ # print('entering3')
239
+ # transformed = self.setTransform(t)
240
+ # print('entering4')
241
+ # print(transformed)
242
+ # print(QRectF(min(transformed.p1().x(), transformed.p2().x()), min(transformed.p1().y(), transformed.p2().y()),
243
+ # abs(transformed.p2().x() - transformed.p1().x()), abs(transformed.p2().y() - transformed.p1().y())))
244
+ # return QRectF(min(transformed.p1().x(), transformed.p2().x()), min(transformed.p1().y(), transformed.p2().y()),
245
+ # abs(transformed.p2().x() - transformed.p1().x()), abs(transformed.p2().y() - transformed.p1().y()))
246
+
247
+ # copy.setT
248
+ # print('entering')
249
+
250
+ # t = QTransform().translate( center.x(), center.y()).rotate(self.theta).translate(-center.x(), -center.y())
251
+ # # print('entersd')
252
+ transformed = t.map(polygon_to_draw) # // mapRect() returns the bounding rect of the rotated rect
253
+
254
+ # print('rotated',rotatedRect )
255
+ # return rotatedRect
256
+ return transformed.boundingRect()
257
+ except:
258
+ pass
259
+ return polygon_to_draw.boundingRect()
260
+
261
+ def getRect(self, *args, **kwargs):
262
+ return self.boundingRect()
263
+
264
+ def width(self, *args, **kwargs):
265
+ return self.boundingRect().width()
266
+
267
+ def height(self, *args, **kwargs):
268
+ return self.boundingRect().height()
269
+
270
+ def set_to_center(self, centroid):
271
+ current_centroid = self.boundingRect().center()
272
+ if isinstance(centroid, (tuple, list)):
273
+ self.translate(centroid[0]-current_centroid.x(), centroid[1]-current_centroid.y())
274
+ else:
275
+ self.translate(centroid.x() - current_centroid.x(), centroid.y() - current_centroid.y())
276
+
277
+ def __repr__(self):
278
+ class_name = type(self).__name__
279
+ memory_address = hex(id(self))
280
+ return f"{class_name}-{memory_address}"
281
+
282
+ def to_dict(self):
283
+ # x = self.x()
284
+ # y = self.y()
285
+
286
+ # Create a dictionary representation of the values of the super object
287
+ output_dict = {
288
+ # 'x': x,
289
+ # 'y': y,
290
+ 'coords_as_list': str(qpolygonf_to_list(self, unpack=True))
291
+ }
292
+ # Update the dictionary with the __dict__ of Rectangle2D
293
+ output_dict.update(self.__dict__)
294
+ return output_dict
295
+
296
+
297
+ if __name__ == '__main__':
298
+
299
+ test = Polygon2D(0, 0, 10, 0, 10, 20, 0, 20, 0, 0)
300
+ print(test.count()) # marche pas --> pas ajouté
301
+ print(test)
302
+
303
+ hexagon = Polygon2D()
304
+ print(hexagon)
305
+ hexagon.append(QPointF(10, 20))
306
+ hexagon.append(QPointF(10, 30))
307
+ hexagon.append(QPointF(20, 30))
308
+
309
+
310
+
311
+ # hexagon.append(QPointF(10, 20))
312
+ print(hexagon)
313
+ print(hexagon.isEmpty())
314
+ print(hexagon.count())
315
+ print(hexagon.stroke)
316
+ print(hexagon.get_stroke_size())
317
+ # ça marche maintenant
318
+ # print(hexagon.)
319
+ # trop cool l'acces aux points
320
+ for point in hexagon:
321
+ print(point)
322
+
323
+ print(hexagon.get_points())
324
+ # print(hexagon.contains(10, 20))
325
+ print(hexagon.contains(QPointF(10, 20)))
326
+ print(hexagon.contains(QPointF(10, 21)))
327
+
328
+ print(hexagon.isClosed()) #
329
+ hexagon.append(QPointF(10, 20)) # closing the hexagon --> the last and first point should be the same
330
+ print(hexagon.isClosed()) #
331
+
332
+ # print(hexagon.translate(10, 20)) # why none ???
333
+ # translate and so on can all be saved...
334
+
335
+ image = QImage('/E/Sample_images/sample_images_PA/mini/focused_Series012/handCorrection.png')
336
+ painter = QPainter()
337
+ painter.begin(image)
338
+ # painter.setOpacity(0.3);
339
+ painter.drawImage(0, 0, image)
340
+ painter.setPen(QtCore.Qt.blue)
341
+ painter.drawPolygon(hexagon)
342
+ hexagon.opacity = 0.7
343
+ painter.translate(10, 20)
344
+ hexagon.draw(painter) # ça marche pourrait overloader ça avec du svg
345
+ painter.end()
346
+
347
+ # painter.save()
348
+ # painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
349
+ # painter.eraseRect(r)
350
+ # painter.restore()
351
+
352
+ image.save('/E/trash/test_pyQT_draw.png', "PNG");
353
+
354
+ #pas mal TODO faire une classe drawsmthg qui dessine n'importe quelle forme que l'on lui passe avec des parametres de couleur, transparence, ...
355
+
356
+ # tt marche aps mal ça va très vite
357
+