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.
- batoolset/GUI/__init__.py +0 -0
- batoolset/GUI/list_gui.py +513 -0
- batoolset/GUI/multi_image_display.py +989 -0
- batoolset/GUI/open.py +325 -0
- batoolset/GUI/overlay_hints.py +45 -0
- batoolset/GUI/paint2.py +1345 -0
- batoolset/GUI/scrollablepaint.py +1152 -0
- batoolset/IJ_ROIs/__init__.py +0 -0
- batoolset/IJ_ROIs/tools.py +40 -0
- batoolset/PATH/__init__.py +0 -0
- batoolset/PATH/tools.py +79 -0
- batoolset/SQLite_tools/__init__.py +0 -0
- batoolset/SQLite_tools/tools.py +840 -0
- batoolset/__init__.py +0 -0
- batoolset/binary/__init__.py +0 -0
- batoolset/binary/tools.py +123 -0
- batoolset/binarytools/__init__.py +0 -0
- batoolset/binarytools/cell_center_detector.py +290 -0
- batoolset/clipboard_tools/__init__.py +0 -0
- batoolset/clipboard_tools/tools.py +7 -0
- batoolset/colors/__init__.py +0 -0
- batoolset/colors/colorgen.py +193 -0
- batoolset/colors/tools.py +22 -0
- batoolset/command_line/__init__.py +0 -0
- batoolset/command_line/tools.py +18 -0
- batoolset/dialogs/__init__.py +0 -0
- batoolset/dialogs/opensave.py +228 -0
- batoolset/dicts/__init__.py +0 -0
- batoolset/dicts/tools.py +299 -0
- batoolset/dims/__init__.py +0 -0
- batoolset/dims/tools.py +83 -0
- batoolset/draw/__init__.py +0 -0
- batoolset/draw/shapes/Position.py +183 -0
- batoolset/draw/shapes/__init__.py +0 -0
- batoolset/draw/shapes/automated_alignment_drawing_refactored.py +346 -0
- batoolset/draw/shapes/circle2d.py +99 -0
- batoolset/draw/shapes/compute_optimal_size_all_merged.py +317 -0
- batoolset/draw/shapes/ellipse2d.py +336 -0
- batoolset/draw/shapes/freehand2d.py +235 -0
- batoolset/draw/shapes/group.py +1830 -0
- batoolset/draw/shapes/image2d.py +2469 -0
- batoolset/draw/shapes/line2d.py +575 -0
- batoolset/draw/shapes/point2d.py +257 -0
- batoolset/draw/shapes/polygon2d.py +357 -0
- batoolset/draw/shapes/polyline2d.py +235 -0
- batoolset/draw/shapes/rect2d.py +388 -0
- batoolset/draw/shapes/rectangle2d.py +601 -0
- batoolset/draw/shapes/scalebar.py +304 -0
- batoolset/draw/shapes/serializablefont.py +126 -0
- batoolset/draw/shapes/serializableguiparams.py +10 -0
- batoolset/draw/shapes/square2d.py +103 -0
- batoolset/draw/shapes/textorientation.py +45 -0
- batoolset/draw/shapes/tools.py +467 -0
- batoolset/draw/shapes/transform2D.py +350 -0
- batoolset/draw/shapes/txt2d.py +550 -0
- batoolset/draw/widgets/__init__.py +0 -0
- batoolset/draw/widgets/col.py +343 -0
- batoolset/draw/widgets/image_group.py +248 -0
- batoolset/draw/widgets/image_organizer.py +96 -0
- batoolset/draw/widgets/paint.py +184 -0
- batoolset/draw/widgets/vectorial.py +257 -0
- batoolset/figure/__init__.py +0 -0
- batoolset/figure/alignment.py +814 -0
- batoolset/figure/column.py +1117 -0
- batoolset/figure/fig_tools.py +285 -0
- batoolset/figure/minimal_debugger_scale_etc.py +139 -0
- batoolset/figure/panel.py +697 -0
- batoolset/figure/row.py +852 -0
- batoolset/figure/user_selection.py +287 -0
- batoolset/files/__init__.py +0 -0
- batoolset/files/tools.py +1321 -0
- batoolset/images/__init__.py +0 -0
- batoolset/images/tools.py +81 -0
- batoolset/img.py +5216 -0
- batoolset/linux/__init__.py +0 -0
- batoolset/linux/tools.py +72 -0
- batoolset/lists/__init__.py +0 -0
- batoolset/lists/tools.py +436 -0
- batoolset/luts/__init__.py +0 -0
- batoolset/luts/lut_minimal_test.py +1207 -0
- batoolset/matplolib/__init__.py +0 -0
- batoolset/matplolib/tools.py +44 -0
- batoolset/np_tools/__init__.py +0 -0
- batoolset/np_tools/tools.py +252 -0
- batoolset/np_tools/trash.py +15 -0
- batoolset/pandas_tools/__init__.py +0 -0
- batoolset/pandas_tools/tools.py +880 -0
- batoolset/partials/__init__.py +0 -0
- batoolset/partials/tools.py +83 -0
- batoolset/plot_tools/__init__.py +0 -0
- batoolset/plot_tools/tools.py +70 -0
- batoolset/pyqt/__init__.py +0 -0
- batoolset/pyqt/tools.py +691 -0
- batoolset/re_tools/__init__.py +0 -0
- batoolset/re_tools/tools.py +35 -0
- batoolset/serialization/__init__.py +0 -0
- batoolset/serialization/tools.py +1192 -0
- batoolset/sets/__init__.py +0 -0
- batoolset/sets/tools.py +109 -0
- batoolset/settings/__init__.py +0 -0
- batoolset/settings/global_settings.py +134 -0
- batoolset/strings/__init__.py +0 -0
- batoolset/strings/tools.py +225 -0
- batoolset/ta/__init__.py +0 -0
- batoolset/ta/database/__init__.py +0 -0
- batoolset/ta/database/advanced_sql_plotter.py +1170 -0
- batoolset/ta/database/my_qt_table.py +79 -0
- batoolset/ta/database/preview_and_edit_sqlite_db.py +405 -0
- batoolset/ta/database/sql.py +2141 -0
- batoolset/ta/database/sql_column_name_dialog.py +122 -0
- batoolset/ta/measurements/TAmeasures.py +2226 -0
- batoolset/ta/measurements/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/__init__.py +0 -0
- batoolset/ta/measurements/measurements3D/get_point_on_surface_if_centroid_is_bad.py +175 -0
- batoolset/ta/measurements/measurements3D/height_map_to_projection.py +82 -0
- batoolset/ta/measurements/measurements3D/measures3D.py +208 -0
- batoolset/ta/measurements/measurements3D/triangulate.py +331 -0
- batoolset/ta/measurements/nematic.py +562 -0
- batoolset/ta/measurements/nematic_measurements.py +107 -0
- batoolset/ta/segmentation/__init__.py +0 -0
- batoolset/ta/segmentation/neo_wshed.py +314 -0
- batoolset/ta/selections/__init__.py +0 -0
- batoolset/ta/selections/selection.py +329 -0
- batoolset/ta/tracking/__init__.py +0 -0
- batoolset/ta/tracking/last_tracking_based_on_matching_or_on_translation_from_mermaid_warp.py +653 -0
- batoolset/ta/tracking/local_to_track_correspondance.py +138 -0
- batoolset/ta/tracking/rapid_detection_of_vertices.py +517 -0
- batoolset/ta/tracking/registration.py +108 -0
- batoolset/ta/tracking/swap_detector_and_fixer.py +296 -0
- batoolset/ta/tracking/track_correction.py +238 -0
- batoolset/ta/tracking/tracking_error_detector_and_fixer.py +3099 -0
- batoolset/ta/tracking/tracking_yet_another_approach_pyramidal_registration_n_neo_swapping_correction.py +725 -0
- batoolset/ta/utils/TA_tools.py +43 -0
- batoolset/ta/utils/__init__.py +0 -0
- batoolset/ta/utils/rps_tools.py +1783 -0
- batoolset/tests/__init__.py +0 -0
- batoolset/tests/rps_tools.py +51 -0
- batoolset/tests/tools.py +10 -0
- batoolset/tools/__init__.py +0 -0
- batoolset/tools/early_stopper_class.py +9 -0
- batoolset/tools/guided_data_recoverer.py +110 -0
- batoolset/tools/logger.py +100 -0
- batoolset/tools/mytimer.py +31 -0
- batoolset/tools/prompt_color.py +160 -0
- batoolset/tools/qthandler.py +118 -0
- batoolset/uitools/__init__.py +0 -0
- batoolset/uitools/blinker.py +56 -0
- batoolset/unsafe/__init__.py +0 -0
- batoolset/unsafe/tools.py +115 -0
- batoolset/utils/__init__.py +0 -0
- batoolset/utils/commontools.py +158 -0
- batoolset/utils/loadlist.py +728 -0
- batoolset/version.py +10 -0
- batoolset/xml/__init__.py +0 -0
- batoolset/xml/tools.py +65 -0
- batoolset/zip_tools/__init__.py +0 -0
- batoolset/zip_tools/tools.py +76 -0
- batoolset-0.1.0.dist-info/LICENSE +24 -0
- batoolset-0.1.0.dist-info/METADATA +45 -0
- batoolset-0.1.0.dist-info/RECORD +162 -0
- batoolset-0.1.0.dist-info/WHEEL +5 -0
- batoolset-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
from batoolset.settings.global_settings import set_UI # set the UI to qtpy
|
|
2
|
+
set_UI()
|
|
3
|
+
from batoolset.lists.tools import flatten_list
|
|
4
|
+
from qtpy.QtCore import QPointF, QRectF, QRect, Qt, QLineF
|
|
5
|
+
from qtpy.QtGui import QPolygonF, QPainterPath, QBrush
|
|
6
|
+
from qtpy.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
|
|
7
|
+
import math
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def subtract_polygons(polygon1, polygon2, return_path_instead_of_polygon=False):
|
|
12
|
+
path1 = QPainterPath()
|
|
13
|
+
path1.addPolygon(polygon1)
|
|
14
|
+
|
|
15
|
+
path2 = QPainterPath()
|
|
16
|
+
path2.addPolygon(polygon2)
|
|
17
|
+
|
|
18
|
+
result_path = path1 - path2
|
|
19
|
+
# result_path = path1.subtracted(path2)
|
|
20
|
+
if return_path_instead_of_polygon: # useful for an area of an intersection !!!
|
|
21
|
+
return result_path
|
|
22
|
+
|
|
23
|
+
result_polygon = result_path.toFillPolygon()
|
|
24
|
+
|
|
25
|
+
return result_polygon
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def union_of_polygons(polygon1: QPolygonF, polygon2: QPolygonF) -> QPolygonF:
|
|
29
|
+
path1 = QPainterPath()
|
|
30
|
+
path1.addPolygon(polygon1)
|
|
31
|
+
|
|
32
|
+
path2 = QPainterPath()
|
|
33
|
+
path2.addPolygon(polygon2)
|
|
34
|
+
|
|
35
|
+
result_path = path1 + path2
|
|
36
|
+
result_polygon = result_path.toFillPolygon()
|
|
37
|
+
|
|
38
|
+
return result_polygon
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def qpolygonf_to_list(qpolygonf, unpack=False):
|
|
42
|
+
lst = [(point.x(), point.y()) for point in qpolygonf]
|
|
43
|
+
if not unpack:
|
|
44
|
+
return lst
|
|
45
|
+
else:
|
|
46
|
+
return flatten_list(lst)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_area_after_subtraction(qpolygonf1, qpolygonf2):
|
|
50
|
+
from shapely.geometry import Polygon
|
|
51
|
+
# Function to convert QPolygonF to a list of tuples
|
|
52
|
+
|
|
53
|
+
# Convert QPolygonF to a list of tuples
|
|
54
|
+
polygon1_list = qpolygonf_to_list(qpolygonf1)
|
|
55
|
+
polygon2_list = qpolygonf_to_list(qpolygonf2)
|
|
56
|
+
|
|
57
|
+
# Convert the list of tuples to shapely Polygon objects
|
|
58
|
+
shapely_polygon1 = Polygon(polygon1_list)
|
|
59
|
+
shapely_polygon2 = Polygon(polygon2_list)
|
|
60
|
+
|
|
61
|
+
# Get the area of the resulting polygon after subtracting polygon2 from polygon1
|
|
62
|
+
result_polygon = shapely_polygon1.difference(shapely_polygon2)
|
|
63
|
+
result_area = result_polygon.area
|
|
64
|
+
|
|
65
|
+
return result_area
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Function to convert QPolygonF to a list of tuples
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def polygon_area(polygon: QPolygonF) -> float:
|
|
72
|
+
area = 0.
|
|
73
|
+
num_points = len(polygon)
|
|
74
|
+
j = num_points - 1
|
|
75
|
+
|
|
76
|
+
for i in range(num_points):
|
|
77
|
+
point1 = polygon[i]
|
|
78
|
+
point2 = polygon[j]
|
|
79
|
+
area += (point2.x() + point1.x()) * (point2.y() - point1.y())
|
|
80
|
+
j = i
|
|
81
|
+
|
|
82
|
+
return abs(area) / 2.
|
|
83
|
+
|
|
84
|
+
# area = 0.0
|
|
85
|
+
# n = len(polygon)
|
|
86
|
+
#
|
|
87
|
+
# # Iterate through the vertices of the polygon
|
|
88
|
+
# for i in range(n - 1):
|
|
89
|
+
# x1, y1 = polygon[i].x(), polygon[i].y()
|
|
90
|
+
# x2, y2 = polygon[i + 1].x(), polygon[i + 1].y()
|
|
91
|
+
# area += x1 * y2 - x2 * y1
|
|
92
|
+
#
|
|
93
|
+
# # Close the polygon by connecting the last vertex to the first one
|
|
94
|
+
# x1, y1 = polygon[n - 1].x(), polygon[n - 1].y()
|
|
95
|
+
# x2, y2 = polygon[0].x(), polygon[0].y()
|
|
96
|
+
# area += x1 * y2 - x2 * y1
|
|
97
|
+
#
|
|
98
|
+
# # Take the absolute value to ensure the area is positive
|
|
99
|
+
# area = abs(area / 2.0)
|
|
100
|
+
|
|
101
|
+
# return polygon.area()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# def calculate_area(*polygons):
|
|
105
|
+
# if not polygons:
|
|
106
|
+
# return 0
|
|
107
|
+
#
|
|
108
|
+
# path1 = QPainterPath()
|
|
109
|
+
# path1.addPolygon(polygons[0])
|
|
110
|
+
# path1 = path1.simplified()
|
|
111
|
+
#
|
|
112
|
+
# for polygon in polygons[1:]:
|
|
113
|
+
# path2 = QPainterPath()
|
|
114
|
+
# path2.addPolygon(polygon)
|
|
115
|
+
# path2 = path2.simplified()
|
|
116
|
+
# path1 = path1.subtracted(path2)
|
|
117
|
+
# path1 = path1.simplified()
|
|
118
|
+
#
|
|
119
|
+
# total_area = 0
|
|
120
|
+
# for subpath_polygon in path1.toSubpathPolygons():
|
|
121
|
+
# area = polygon_area(subpath_polygon)
|
|
122
|
+
# total_area += area
|
|
123
|
+
#
|
|
124
|
+
# return total_area
|
|
125
|
+
|
|
126
|
+
# from shapely.geometry import Polygon
|
|
127
|
+
#
|
|
128
|
+
# def calculate_area(*polygons):
|
|
129
|
+
# if not polygons:
|
|
130
|
+
# return 0
|
|
131
|
+
#
|
|
132
|
+
# polygon1 = Polygon(polygons[0])
|
|
133
|
+
#
|
|
134
|
+
# for points in polygons[1:]:
|
|
135
|
+
# polygon2 = Polygon(points)
|
|
136
|
+
# polygon1 = polygon1.difference(polygon2)
|
|
137
|
+
#
|
|
138
|
+
# if polygon1.is_empty:
|
|
139
|
+
# return 0
|
|
140
|
+
# else:
|
|
141
|
+
# return polygon1.area
|
|
142
|
+
#
|
|
143
|
+
# # Example usage
|
|
144
|
+
# polygon1 = np.array([[10, 10], [100, 10], [100, 100], [10, 100]])
|
|
145
|
+
# polygon2 = np.array([[30, 30], [80, 30], [80, 80], [30, 80]])
|
|
146
|
+
|
|
147
|
+
def calculate_area(qpolygon):
|
|
148
|
+
area = 0
|
|
149
|
+
for i in range(qpolygon.size()):
|
|
150
|
+
p1 = qpolygon[i]
|
|
151
|
+
p2 = qpolygon[(i + 1) % qpolygon.size()]
|
|
152
|
+
d = p1.x() * p2.y() - p2.x() * p1.y()
|
|
153
|
+
area += d
|
|
154
|
+
return abs(area) / 2
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def intersect(polygon1, polygon2):
|
|
158
|
+
return polygon1.intersected(polygon2)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def union(polygon1, polygon2):
|
|
162
|
+
return polygon1.united(polygon2)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# all the area calculations are wrong
|
|
166
|
+
|
|
167
|
+
# result_area = calculate_area(polygon1, polygon2)
|
|
168
|
+
# print(f"Area of the resulting polygon: {result_area}")
|
|
169
|
+
|
|
170
|
+
# def polygon_to_closest_circle(polygon: QPolygonF) -> QPolygonF:
|
|
171
|
+
# # Calculate the area of the polygon
|
|
172
|
+
# area = calculate_area(polygon)
|
|
173
|
+
#
|
|
174
|
+
# # Calculate the equivalent circle radius
|
|
175
|
+
# radius = math.sqrt(area / math.pi)
|
|
176
|
+
#
|
|
177
|
+
# # Create a QRectF object that represents the bounding rectangle of the circle
|
|
178
|
+
# bounding_rect = QRectF(-radius, -radius, 2 * radius, 2 * radius)
|
|
179
|
+
#
|
|
180
|
+
# # Create a QPainterPath object and add an ellipse (circle) to it
|
|
181
|
+
# path = QPainterPath()
|
|
182
|
+
# path.addEllipse(bounding_rect)
|
|
183
|
+
#
|
|
184
|
+
# # Convert the QPainterPath object to a QPolygonF object
|
|
185
|
+
# circle_polygon = path.toFillPolygon()
|
|
186
|
+
#
|
|
187
|
+
# return circle_polygon
|
|
188
|
+
def get_radius_of_circle_corresponding_to_polygon(poly):
|
|
189
|
+
area = calculate_area(poly)
|
|
190
|
+
# Calculate the equivalent circle radius
|
|
191
|
+
radius = math.sqrt(area / math.pi)
|
|
192
|
+
# Calculate the diameter
|
|
193
|
+
# diameter = 2. * radius
|
|
194
|
+
|
|
195
|
+
return radius
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def create_rect_centered_at(point, radius):
|
|
199
|
+
rect = QRectF()
|
|
200
|
+
rect.setLeft(point.x() - radius)
|
|
201
|
+
rect.setTop(point.y() - radius)
|
|
202
|
+
rect.setWidth(2 * radius)
|
|
203
|
+
rect.setHeight(2 * radius)
|
|
204
|
+
return rect
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def rect_intersects_polygon(rect: QRectF, polygon: QPolygonF) -> bool:
|
|
208
|
+
# Create a QPainterPath object for the QRectF
|
|
209
|
+
rect_path = QPainterPath()
|
|
210
|
+
rect_path.addRect(rect)
|
|
211
|
+
|
|
212
|
+
# Create a QPainterPath object for the QPolygonF
|
|
213
|
+
polygon_path = QPainterPath()
|
|
214
|
+
polygon_path.addPolygon(polygon)
|
|
215
|
+
|
|
216
|
+
# Check if the two paths intersect
|
|
217
|
+
intersects = rect_path.intersects(polygon_path)
|
|
218
|
+
|
|
219
|
+
return intersects
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def perpendicular_distance(point: QPointF, line_start: QPointF, line_end: QPointF) -> float:
|
|
223
|
+
dx = line_end.x() - line_start.x()
|
|
224
|
+
dy = line_end.y() - line_start.y()
|
|
225
|
+
|
|
226
|
+
# Normalize the vector
|
|
227
|
+
magnitude = math.hypot(dx, dy)
|
|
228
|
+
if magnitude > sys.float_info.epsilon:
|
|
229
|
+
dx /= magnitude
|
|
230
|
+
dy /= magnitude
|
|
231
|
+
|
|
232
|
+
# Calculate the vector dot product
|
|
233
|
+
pvx = point.x() - line_start.x()
|
|
234
|
+
pvy = point.y() - line_start.y()
|
|
235
|
+
dot_product = dx * pvx + dy * pvy
|
|
236
|
+
|
|
237
|
+
# Calculate the perpendicular distance
|
|
238
|
+
ax = line_start.x() + dot_product * dx
|
|
239
|
+
ay = line_start.y() + dot_product * dy
|
|
240
|
+
distance = math.hypot(point.x() - ax, point.y() - ay)
|
|
241
|
+
|
|
242
|
+
return distance
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
# def simplify_polygon(polygon, tolerance):
|
|
246
|
+
# if len(polygon) <= 2:
|
|
247
|
+
# return polygon
|
|
248
|
+
#
|
|
249
|
+
# markers = [False] * len(polygon)
|
|
250
|
+
# markers[0] = markers[-1] = True
|
|
251
|
+
#
|
|
252
|
+
# dists = [0.0] * len(polygon)
|
|
253
|
+
# furthest_point_index = 0
|
|
254
|
+
# furthest_distance = 0.0
|
|
255
|
+
#
|
|
256
|
+
# line = QLineF(polygon[0], polygon[-1])
|
|
257
|
+
# line_length = line.length()
|
|
258
|
+
# for i in range(1, len(polygon) - 1):
|
|
259
|
+
# point = polygon[i]
|
|
260
|
+
# closest_point = line.closestPointWithinLine(point)
|
|
261
|
+
# dist = closest_point.distanceToPoint(point)
|
|
262
|
+
# dists[i] = dist
|
|
263
|
+
# if dist > furthest_distance:
|
|
264
|
+
# furthest_distance = dist
|
|
265
|
+
# furthest_point_index = i
|
|
266
|
+
#
|
|
267
|
+
# if furthest_distance > tolerance:
|
|
268
|
+
# markers[furthest_point_index] = True
|
|
269
|
+
# simplified_left = simplify_polygon([polygon[i] for i in range(furthest_point_index + 1)], tolerance)
|
|
270
|
+
# simplified_right = simplify_polygon([polygon[i] for i in range(furthest_point_index, len(polygon))], tolerance)
|
|
271
|
+
# simplified_polygon = simplified_left[:-1] + simplified_right
|
|
272
|
+
# else:
|
|
273
|
+
# simplified_polygon = [polygon[0], polygon[-1]]
|
|
274
|
+
#
|
|
275
|
+
# return QPolygonF(simplified_polygon)
|
|
276
|
+
|
|
277
|
+
def simplify_polygon2(polygon: QPolygonF) -> QPolygonF:
|
|
278
|
+
# # not tested --> TODO
|
|
279
|
+
# if len(polygon) <= 2:
|
|
280
|
+
# return polygon
|
|
281
|
+
#
|
|
282
|
+
# # Find the point with the maximum distance from the line between the start and end points
|
|
283
|
+
# max_distance = 0.0
|
|
284
|
+
# index = 0
|
|
285
|
+
# for i in range(1, len(polygon) - 1):
|
|
286
|
+
# distance = perpendicular_distance(polygon[i], polygon[0], polygon[-1])
|
|
287
|
+
# if distance > max_distance:
|
|
288
|
+
# max_distance = distance
|
|
289
|
+
# index = i
|
|
290
|
+
#
|
|
291
|
+
# # Check if the maximum distance is greater than the epsilon threshold
|
|
292
|
+
# if max_distance > epsilon:
|
|
293
|
+
# # Recursively simplify the two sub-polygons
|
|
294
|
+
# first_half = simplify_polygon(polygon[:index + 1], epsilon)
|
|
295
|
+
# second_half = simplify_polygon(polygon[index:], epsilon)
|
|
296
|
+
#
|
|
297
|
+
# # Combine the results and remove the duplicate point
|
|
298
|
+
# simplified_polygon = first_half[:-1] + second_half[1:]
|
|
299
|
+
# else:
|
|
300
|
+
# # The polygon can be represented by a line between the start and end points
|
|
301
|
+
# simplified_polygon = QPolygonF([polygon[0], polygon[-1]])
|
|
302
|
+
#
|
|
303
|
+
# return simplified_polygon
|
|
304
|
+
return polygon.simplified()
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
# def qrectf_qpolygonf_intersection(qrectf, qpolygonf):
|
|
308
|
+
# rect_points = [(qrectf.left(), qrectf.top()),
|
|
309
|
+
# (qrectf.right(), qrectf.top()),
|
|
310
|
+
# (qrectf.right(), qrectf.bottom()),
|
|
311
|
+
# (qrectf.left(), qrectf.bottom())]
|
|
312
|
+
#
|
|
313
|
+
# poly_points = [(point.x(), point.y()) for point in qpolygonf]
|
|
314
|
+
#
|
|
315
|
+
# for point in rect_points:
|
|
316
|
+
# if qpolygonf.containsPoint(QPointF(*point), 0):
|
|
317
|
+
# return True
|
|
318
|
+
#
|
|
319
|
+
# for point in poly_points:
|
|
320
|
+
# if qrectf.contains(QPointF(*point)):
|
|
321
|
+
# return True
|
|
322
|
+
#
|
|
323
|
+
# return False
|
|
324
|
+
def get_polygon_union(*polygons):
|
|
325
|
+
if not polygons:
|
|
326
|
+
return QPolygonF()
|
|
327
|
+
|
|
328
|
+
union_path = QPainterPath()
|
|
329
|
+
union_path.addPolygon(polygons[0])
|
|
330
|
+
|
|
331
|
+
for polygon in polygons[1:]:
|
|
332
|
+
polygon_path = QPainterPath()
|
|
333
|
+
polygon_path.addPolygon(polygon)
|
|
334
|
+
union_path = union_path.united(polygon_path)
|
|
335
|
+
|
|
336
|
+
return union_path.toFillPolygon()
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def get_polygon_difference(polygons): # this is the intersection
|
|
340
|
+
if not polygons:
|
|
341
|
+
# return QPolygonF()
|
|
342
|
+
return None
|
|
343
|
+
|
|
344
|
+
# Find the largest polygon
|
|
345
|
+
largest_polygon = max(polygons, key=lambda p: p.boundingRect().width() * p.boundingRect().height())
|
|
346
|
+
|
|
347
|
+
diff_path = QPainterPath()
|
|
348
|
+
diff_path.addPolygon(largest_polygon)
|
|
349
|
+
|
|
350
|
+
for polygon in polygons:
|
|
351
|
+
if polygon != largest_polygon:
|
|
352
|
+
polygon_path = QPainterPath()
|
|
353
|
+
polygon_path.addPolygon(polygon)
|
|
354
|
+
diff_path = diff_path.subtracted(polygon_path)
|
|
355
|
+
|
|
356
|
+
return diff_path.toFillPolygon()
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
if __name__ == '__main__':
|
|
360
|
+
if True:
|
|
361
|
+
# try the fusion of
|
|
362
|
+
|
|
363
|
+
sys.exit(0)
|
|
364
|
+
|
|
365
|
+
app = QApplication([])
|
|
366
|
+
|
|
367
|
+
polygon1 = QPolygonF([
|
|
368
|
+
QPointF(10, 10),
|
|
369
|
+
QPointF(100, 10),
|
|
370
|
+
QPointF(100, 100),
|
|
371
|
+
QPointF(10, 100)
|
|
372
|
+
])
|
|
373
|
+
|
|
374
|
+
polygon2 = QPolygonF([
|
|
375
|
+
QPointF(30, 30),
|
|
376
|
+
QPointF(80, 30),
|
|
377
|
+
QPointF(80, 80),
|
|
378
|
+
QPointF(30, 80)
|
|
379
|
+
])
|
|
380
|
+
|
|
381
|
+
# Create a complex polygon that roughly simplifies to polygon2
|
|
382
|
+
complex_polygon = QPolygonF([
|
|
383
|
+
QPointF(30, 30),
|
|
384
|
+
QPointF(35, 33),
|
|
385
|
+
QPointF(40, 32),
|
|
386
|
+
QPointF(45, 35),
|
|
387
|
+
QPointF(50, 30),
|
|
388
|
+
QPointF(55, 32),
|
|
389
|
+
QPointF(60, 35),
|
|
390
|
+
QPointF(65, 28),
|
|
391
|
+
QPointF(70, 33),
|
|
392
|
+
QPointF(75, 29),
|
|
393
|
+
QPointF(80, 30),
|
|
394
|
+
|
|
395
|
+
QPointF(80, 80),
|
|
396
|
+
QPointF(75, 78),
|
|
397
|
+
QPointF(70, 82),
|
|
398
|
+
QPointF(65, 80),
|
|
399
|
+
QPointF(60, 85),
|
|
400
|
+
QPointF(55, 82),
|
|
401
|
+
QPointF(50, 80),
|
|
402
|
+
QPointF(45, 83),
|
|
403
|
+
QPointF(40, 79),
|
|
404
|
+
QPointF(35, 81),
|
|
405
|
+
QPointF(30, 80),
|
|
406
|
+
|
|
407
|
+
QPointF(30, 30) # Close the polygon by connecting the last point to the first point
|
|
408
|
+
])
|
|
409
|
+
|
|
410
|
+
intersection = polygon1.united(polygon2)
|
|
411
|
+
|
|
412
|
+
result_polygon = subtract_polygons(polygon1, polygon2)
|
|
413
|
+
|
|
414
|
+
print(result_polygon)
|
|
415
|
+
# print(result_polygon.points)
|
|
416
|
+
|
|
417
|
+
# Calculate the area of the result_polygon
|
|
418
|
+
# area = polygon_area(result_polygon)
|
|
419
|
+
area = calculate_area(result_polygon) # incorrect
|
|
420
|
+
print(f"Area of the resulting polygon (incorrect): {area}") # incorrect -−> USE THE ONE BELOW
|
|
421
|
+
print(
|
|
422
|
+
f"Area of the resulting polygon: {get_area_after_subtraction(polygon1, polygon2)}") # now that works too bad i can't get it directly from the resulting polygon of the subtraction
|
|
423
|
+
|
|
424
|
+
# epsilon = 1.0 # The epsilon value controls the level of simplification (higher values result in more simplification)
|
|
425
|
+
# simplified_polygon = simplify_polygon(complex_polygon, epsilon)
|
|
426
|
+
# simplified_polygon = simplify_polygon(complex_polygon)
|
|
427
|
+
# simplified_polygon = simplify_polygon(complex_polygon, 5) --> TODO reimplement my own java code because it was much better than that
|
|
428
|
+
|
|
429
|
+
# Convert the polygon to the closest circle
|
|
430
|
+
# circle_polygon = polygon_to_closest_circle(polygon1)
|
|
431
|
+
# Calculate the area of the polygon
|
|
432
|
+
# area = calculate_area(polygon1)
|
|
433
|
+
# Calculate the equivalent circle radius
|
|
434
|
+
radius = get_radius_of_circle_corresponding_to_polygon(polygon1)
|
|
435
|
+
# Calculate the diameter
|
|
436
|
+
diameter = 2. * radius
|
|
437
|
+
print(f"Radius of the closest circle: {radius}")
|
|
438
|
+
print(f"Diameter of the closest circle: {diameter}")
|
|
439
|
+
|
|
440
|
+
# no way
|
|
441
|
+
# area_result = calculate_area(polygon1, polygon2)
|
|
442
|
+
# area_result = calculate_area(result_polygon)
|
|
443
|
+
# print(f"Area of the resulting polygon: {area_result}")
|
|
444
|
+
|
|
445
|
+
print(f"Area of the parent polygons: {polygon_area(polygon1)}, {polygon_area(polygon2)}")
|
|
446
|
+
|
|
447
|
+
scene = QGraphicsScene()
|
|
448
|
+
# polygon_item =scene.addPolygon(result_polygon)
|
|
449
|
+
|
|
450
|
+
polygon_item = scene.addPolygon(intersection)
|
|
451
|
+
|
|
452
|
+
scene.addPolygon(simplified_polygon)
|
|
453
|
+
|
|
454
|
+
print(calculate_area(simplified_polygon)) # it does not work it is 0
|
|
455
|
+
|
|
456
|
+
# scene.addPolygon(circle_polygon)
|
|
457
|
+
|
|
458
|
+
if False:
|
|
459
|
+
# Set a brush for the polygon_item to fill it with a specific color
|
|
460
|
+
brush = QBrush(Qt.darkBlue)
|
|
461
|
+
polygon_item.setBrush(brush)
|
|
462
|
+
|
|
463
|
+
view = QGraphicsView(scene)
|
|
464
|
+
view.setGeometry(QRect(0, 0, 400, 400))
|
|
465
|
+
view.show()
|
|
466
|
+
|
|
467
|
+
app.exec_()
|