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,184 @@
|
|
|
1
|
+
from batoolset.settings.global_settings import set_UI # set the UI to qtpy
|
|
2
|
+
set_UI()
|
|
3
|
+
import sys
|
|
4
|
+
from qtpy.QtCore import QRect, QTimer
|
|
5
|
+
from qtpy.QtGui import QPixmap
|
|
6
|
+
from qtpy.QtWidgets import QWidget
|
|
7
|
+
|
|
8
|
+
from batoolset.draw.widgets.vectorial import VectorialDrawPane
|
|
9
|
+
from qtpy.QtWidgets import QMenu, QApplication
|
|
10
|
+
from qtpy import QtCore, QtGui
|
|
11
|
+
|
|
12
|
+
from batoolset.img import toQimage
|
|
13
|
+
from batoolset.tools.logger import TA_logger # logging
|
|
14
|
+
|
|
15
|
+
logger = TA_logger()
|
|
16
|
+
|
|
17
|
+
class Createpaintwidget(QWidget):
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.vdp = VectorialDrawPane(active=False) #, demo=True
|
|
22
|
+
self.image = None
|
|
23
|
+
self.imageDraw = None
|
|
24
|
+
self.cursor = None
|
|
25
|
+
self.maskVisible = True
|
|
26
|
+
self.scale = 1.0
|
|
27
|
+
self.drawing = False
|
|
28
|
+
self.brushSize = 3
|
|
29
|
+
self._clear_size = 30
|
|
30
|
+
self.drawColor = QtGui.QColor(QtCore.Qt.red) # blue green cyan
|
|
31
|
+
self.eraseColor = QtGui.QColor(QtCore.Qt.black)
|
|
32
|
+
self.cursorColor = QtGui.QColor(QtCore.Qt.green)
|
|
33
|
+
self.lastPoint = QtCore.QPointF()
|
|
34
|
+
self.change = False
|
|
35
|
+
# KEEP IMPORTANT required to track mouse even when not clicked
|
|
36
|
+
self.setMouseTracking(True) # KEEP IMPORTANT
|
|
37
|
+
self.scrollArea = None
|
|
38
|
+
self.statusBar = None
|
|
39
|
+
|
|
40
|
+
def setImage(self, img):
|
|
41
|
+
if img is None:
|
|
42
|
+
self.image = None
|
|
43
|
+
self.imageDraw = None
|
|
44
|
+
self.update()
|
|
45
|
+
return
|
|
46
|
+
else:
|
|
47
|
+
self.image = toQimage(img) #.getQimage() # bug is here
|
|
48
|
+
|
|
49
|
+
# self.image = QPixmap(100,200).toImage()
|
|
50
|
+
width = self.image.size().width()
|
|
51
|
+
height = self.image.size().height()
|
|
52
|
+
top = self.geometry().x()
|
|
53
|
+
left = self.geometry().y()
|
|
54
|
+
self.setGeometry(top, left, int(width*self.scale), int(height*self.scale))
|
|
55
|
+
self.imageDraw = QtGui.QImage(self.image.size(), QtGui.QImage.Format_ARGB32)
|
|
56
|
+
self.imageDraw.fill(QtCore.Qt.transparent)
|
|
57
|
+
self.cursor = QtGui.QImage(self.image.size(), QtGui.QImage.Format_ARGB32)
|
|
58
|
+
self.cursor.fill(QtCore.Qt.transparent)
|
|
59
|
+
self.update()
|
|
60
|
+
|
|
61
|
+
def mousePressEvent(self, event):
|
|
62
|
+
if not self.hasMouseTracking():
|
|
63
|
+
return
|
|
64
|
+
self.clickCount = 1
|
|
65
|
+
if self.vdp.active:
|
|
66
|
+
self.vdp.mousePressEvent(event)
|
|
67
|
+
self.update()
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
if event.buttons() == QtCore.Qt.LeftButton or event.buttons() == QtCore.Qt.RightButton:
|
|
71
|
+
self.drawing = True
|
|
72
|
+
zoom_corrected_pos = event.position() / self.scale
|
|
73
|
+
self.lastPoint = zoom_corrected_pos
|
|
74
|
+
self.drawOnImage(event)
|
|
75
|
+
|
|
76
|
+
def mouseMoveEvent(self, event):
|
|
77
|
+
if not self.hasMouseTracking():
|
|
78
|
+
return
|
|
79
|
+
# print('in mouse move', self.hasMouseTracking(), self.drawing, self.vdp.active)
|
|
80
|
+
if self.statusBar:
|
|
81
|
+
zoom_corrected_pos = event.position() / self.scale
|
|
82
|
+
self.statusBar.showMessage('x=' + str(zoom_corrected_pos.x()) + ' y=' + str(
|
|
83
|
+
zoom_corrected_pos.y()))
|
|
84
|
+
if self.vdp.active:
|
|
85
|
+
self.vdp.mouseMoveEvent(event)
|
|
86
|
+
region = self.scrollArea.widget().visibleRegion()
|
|
87
|
+
self.update(region)
|
|
88
|
+
return
|
|
89
|
+
self.drawOnImage(event)
|
|
90
|
+
|
|
91
|
+
def drawOnImage(self, event):
|
|
92
|
+
zoom_corrected_pos = event.position() / self.scale
|
|
93
|
+
if self.drawing and (event.buttons() == QtCore.Qt.LeftButton or event.buttons() == QtCore.Qt.RightButton):
|
|
94
|
+
# now drawing or erasing over the image
|
|
95
|
+
painter = QtGui.QPainter(self.imageDraw)
|
|
96
|
+
if event.buttons() == QtCore.Qt.LeftButton:
|
|
97
|
+
painter.setPen(QtGui.QPen(self.drawColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
|
|
98
|
+
QtCore.Qt.RoundJoin))
|
|
99
|
+
else:
|
|
100
|
+
painter.setPen(QtGui.QPen(self.eraseColor, self.brushSize, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
|
|
101
|
+
QtCore.Qt.RoundJoin))
|
|
102
|
+
if self.lastPoint != zoom_corrected_pos:
|
|
103
|
+
painter.drawLine(self.lastPoint, zoom_corrected_pos)
|
|
104
|
+
else:
|
|
105
|
+
# if zero length line then draw point instead
|
|
106
|
+
painter.drawPoint(zoom_corrected_pos)
|
|
107
|
+
painter.end()
|
|
108
|
+
|
|
109
|
+
# Drawing the cursor TODO add boolean to ask if drawing cursor should be shown
|
|
110
|
+
painter = QtGui.QPainter(self.cursor)
|
|
111
|
+
# We erase previous pointer
|
|
112
|
+
r = QtCore.QRect(QtCore.QPoint(), self._clear_size * QtCore.QSize() * self.brushSize)
|
|
113
|
+
painter.save()
|
|
114
|
+
r.moveCenter(self.lastPoint.toPoint())
|
|
115
|
+
painter.setCompositionMode(QtGui.QPainter.CompositionMode_Clear)
|
|
116
|
+
painter.eraseRect(r)
|
|
117
|
+
painter.restore()
|
|
118
|
+
# draw the new one
|
|
119
|
+
painter.setPen(QtGui.QPen(self.cursorColor, 2, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
|
|
120
|
+
QtCore.Qt.RoundJoin))
|
|
121
|
+
painter.drawEllipse(zoom_corrected_pos, int(self.brushSize / 2.),
|
|
122
|
+
int(self.brushSize / 2.))
|
|
123
|
+
painter.end()
|
|
124
|
+
region = self.scrollArea.widget().visibleRegion()
|
|
125
|
+
self.update(region)
|
|
126
|
+
|
|
127
|
+
# required to erase mouse pointer
|
|
128
|
+
self.lastPoint = zoom_corrected_pos
|
|
129
|
+
|
|
130
|
+
def mouseReleaseEvent(self, event):
|
|
131
|
+
if not self.hasMouseTracking():
|
|
132
|
+
return
|
|
133
|
+
if self.vdp.active:
|
|
134
|
+
self.vdp.mouseReleaseEvent(event)
|
|
135
|
+
self.update() # required to update drawing
|
|
136
|
+
return
|
|
137
|
+
if event.button == QtCore.Qt.LeftButton:
|
|
138
|
+
self.drawing = False
|
|
139
|
+
if self.clickCount == 1:
|
|
140
|
+
QTimer.singleShot(QApplication.instance().doubleClickInterval(),
|
|
141
|
+
self.updateButtonCount)
|
|
142
|
+
|
|
143
|
+
# adds context/right click menu but only in vectorial mode
|
|
144
|
+
def contextMenuEvent(self, event):
|
|
145
|
+
if not self.vdp.active:
|
|
146
|
+
return
|
|
147
|
+
cmenu = QMenu(self)
|
|
148
|
+
newAct = cmenu.addAction("New")
|
|
149
|
+
opnAct = cmenu.addAction("Open")
|
|
150
|
+
quitAct = cmenu.addAction("Quit")
|
|
151
|
+
action = cmenu.exec_(self.mapToGlobal(event.position()))
|
|
152
|
+
if action == quitAct:
|
|
153
|
+
sys.exit(0)
|
|
154
|
+
|
|
155
|
+
def updateButtonCount(self):
|
|
156
|
+
self.clickCount = 1
|
|
157
|
+
|
|
158
|
+
def mouseDoubleClickEvent(self, event):
|
|
159
|
+
self.clickCount = 2
|
|
160
|
+
self.vdp.mouseDoubleClickEvent(event)
|
|
161
|
+
|
|
162
|
+
def paintEvent(self, event):
|
|
163
|
+
canvasPainter = QtGui.QPainter(self)
|
|
164
|
+
# the scrollpane visible region
|
|
165
|
+
visibleRegion = self.scrollArea.widget().visibleRegion()
|
|
166
|
+
# the corresponding rect
|
|
167
|
+
visibleRect = visibleRegion.boundingRect()
|
|
168
|
+
# the visibleRect taking zoom into account
|
|
169
|
+
scaledVisibleRect = QRect(int(visibleRect.x() / self.scale), int(visibleRect.y() / self.scale),
|
|
170
|
+
int(visibleRect.width() / self.scale), int(visibleRect.height() / self.scale))
|
|
171
|
+
if self.image is None:
|
|
172
|
+
canvasPainter.eraseRect(visibleRect)
|
|
173
|
+
canvasPainter.end()
|
|
174
|
+
return
|
|
175
|
+
|
|
176
|
+
canvasPainter.drawImage(visibleRect, self.image, scaledVisibleRect)
|
|
177
|
+
if not self.vdp.active and self.maskVisible:
|
|
178
|
+
canvasPainter.drawImage(visibleRect, self.imageDraw, scaledVisibleRect)
|
|
179
|
+
# should draw the cursor
|
|
180
|
+
canvasPainter.drawImage(visibleRect, self.cursor, scaledVisibleRect)
|
|
181
|
+
|
|
182
|
+
if self.vdp.active:
|
|
183
|
+
self.vdp.paintEvent(canvasPainter, scaledVisibleRect)
|
|
184
|
+
canvasPainter.end()
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# TODO -−> add the small displacement filtering there!!! --> jut copy it from the other code -−> should be easy and maybe it would be useful to have a list of shapes so that one can delete them -−> see if I add that as separate stuff!!!
|
|
2
|
+
# I could also save the polygonF maybe
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from batoolset.draw.shapes.txt2d import TAText2D
|
|
8
|
+
from batoolset.pyqt.tools import getCtrlModifier
|
|
9
|
+
from batoolset.settings.global_settings import set_UI # set the UI to qtpy
|
|
10
|
+
set_UI()
|
|
11
|
+
from qtpy import QtCore
|
|
12
|
+
from batoolset.draw.shapes.polygon2d import Polygon2D
|
|
13
|
+
from batoolset.draw.shapes.line2d import Line2D
|
|
14
|
+
from batoolset.draw.shapes.rect2d import Rect2D
|
|
15
|
+
from batoolset.draw.shapes.square2d import Square2D
|
|
16
|
+
from batoolset.draw.shapes.ellipse2d import Ellipse2D
|
|
17
|
+
from batoolset.draw.shapes.circle2d import Circle2D
|
|
18
|
+
from batoolset.draw.shapes.freehand2d import Freehand2D
|
|
19
|
+
from batoolset.draw.shapes.point2d import Point2D
|
|
20
|
+
from batoolset.draw.shapes.polyline2d import PolyLine2D
|
|
21
|
+
from batoolset.draw.shapes.image2d import Image2D
|
|
22
|
+
from qtpy.QtCore import QPointF, QRectF
|
|
23
|
+
from batoolset.tools.logger import TA_logger # logging
|
|
24
|
+
logger = TA_logger()
|
|
25
|
+
|
|
26
|
+
class VectorialDrawPane:
|
|
27
|
+
|
|
28
|
+
def __init__(self, active=False, demo=False, scale=1.0, drawing_mode=False, extra_size_for_sel=0, filter_out_unwanted_shapes_based_on_distance=True):
|
|
29
|
+
self.shapes = []
|
|
30
|
+
self.currently_drawn_shape = None
|
|
31
|
+
self.shape_to_draw = None
|
|
32
|
+
self.selected_shape = []
|
|
33
|
+
self.active = active
|
|
34
|
+
self.scale = scale
|
|
35
|
+
self.drawing_mode = drawing_mode
|
|
36
|
+
self.extra_size_for_sel = extra_size_for_sel # can be used to add an extra size around very small shapes --> TODO
|
|
37
|
+
self.filter_out_unwanted_shapes_based_on_distance = filter_out_unwanted_shapes_based_on_distance # if set to True the tool will attempt to filter accidental drawings by the user (based on distance between draw points)
|
|
38
|
+
if demo:
|
|
39
|
+
self.shapes.append(Polygon2D(0, 0, 10, 0, 10, 20, 0, 20, 0, 0, color=0x00FF00))
|
|
40
|
+
self.shapes.append(
|
|
41
|
+
Polygon2D(100, 100, 110, 100, 110, 120, 10, 120, 100, 100, color=0x0000FF, fill_color=0x00FFFF,
|
|
42
|
+
stroke=2))
|
|
43
|
+
self.shapes.append(Line2D(0, 0, 110, 100, color=0xFF0000, stroke=3))
|
|
44
|
+
self.shapes.append(Rect2D(200, 150, 250, 100, stroke=10))
|
|
45
|
+
self.shapes.append(Square2D(300, 260, 250, stroke=3))
|
|
46
|
+
self.shapes.append(Ellipse2D(0, 50, 600, 200, stroke=3))
|
|
47
|
+
self.shapes.append(Circle2D(150, 300, 30, color=0xFF0000))
|
|
48
|
+
self.shapes.append(PolyLine2D(10, 10, 20, 10, 20, 30, 40, 30, color=0xFF0000, stroke=2))
|
|
49
|
+
self.shapes.append(PolyLine2D(10, 10, 20, 10, 20, 30, 40, 30, color=0xFF0000, stroke=2))
|
|
50
|
+
self.shapes.append(Point2D(128, 128, color=0xFF0000, stroke=6))
|
|
51
|
+
self.shapes.append(Point2D(128, 128, color=0x00FF00, stroke=1))
|
|
52
|
+
self.shapes.append(Point2D(10, 10, color=0x000000, stroke=6))
|
|
53
|
+
img0 = Image2D('/E/Sample_images/counter/00.png')
|
|
54
|
+
img1 = Image2D('/E/Sample_images/counter/01.png')
|
|
55
|
+
img2 = Image2D('/E/Sample_images/counter/02.png')
|
|
56
|
+
img3 = Image2D('/E/Sample_images/counter/03.png')
|
|
57
|
+
img4 = Image2D('/E/Sample_images/counter/04.png')
|
|
58
|
+
img5 = Image2D('/E/Sample_images/counter/05.png')
|
|
59
|
+
img6 = Image2D('/E/Sample_images/counter/06.png')
|
|
60
|
+
img7 = Image2D('/E/Sample_images/counter/07.png')
|
|
61
|
+
img8 = Image2D('/E/Sample_images/counter/08.png')
|
|
62
|
+
img9 = Image2D('/E/Sample_images/counter/09.png')
|
|
63
|
+
img10 = Image2D('/E/Sample_images/counter/10.png')
|
|
64
|
+
|
|
65
|
+
row = img1 + img2 + img10
|
|
66
|
+
|
|
67
|
+
self.shapes.append(row)
|
|
68
|
+
|
|
69
|
+
row2 = img4 + img5
|
|
70
|
+
fig = row / row2
|
|
71
|
+
# fig = Column(row, row2)
|
|
72
|
+
#self.shapes.append(fig)
|
|
73
|
+
self.drawing_mode = True
|
|
74
|
+
# self.shape_to_draw = Line2D
|
|
75
|
+
# self.shape_to_draw = Rect2D
|
|
76
|
+
# self.shape_to_draw = Square2D
|
|
77
|
+
# self.shape_to_draw = Ellipse2D
|
|
78
|
+
# self.shape_to_draw = Circle2D
|
|
79
|
+
# self.shape_to_draw = Point2D # ok maybe small centering issue
|
|
80
|
+
# self.shape_to_draw = Freehand2D
|
|
81
|
+
# self.shape_to_draw = PolyLine2D
|
|
82
|
+
# self.shape_to_draw = Polygon2D
|
|
83
|
+
import random
|
|
84
|
+
drawing_methods = [Line2D, Rect2D, Square2D, Ellipse2D, Circle2D, Point2D, Freehand2D, PolyLine2D, Polygon2D]
|
|
85
|
+
self.shape_to_draw = random.choice(drawing_methods)
|
|
86
|
+
|
|
87
|
+
# TODO freehand drawing
|
|
88
|
+
# TODO broken line --> need double click for end
|
|
89
|
+
|
|
90
|
+
def paintEvent(self, *args):
|
|
91
|
+
painter = args[0]
|
|
92
|
+
visibleRect = None
|
|
93
|
+
if len(args) >= 2:
|
|
94
|
+
visibleRect = args[1]
|
|
95
|
+
|
|
96
|
+
painter.save()
|
|
97
|
+
if self.scale != 1.0:
|
|
98
|
+
painter.scale(self.scale, self.scale)
|
|
99
|
+
|
|
100
|
+
for shape in self.shapes:
|
|
101
|
+
# only draw shapes if they are visible --> requires a visiblerect to be passed
|
|
102
|
+
if visibleRect is not None:
|
|
103
|
+
# only draws if in visible rect
|
|
104
|
+
if shape.boundingRect().intersects(QRectF(visibleRect)):
|
|
105
|
+
shape.draw(painter)
|
|
106
|
+
else:
|
|
107
|
+
shape.draw(painter)
|
|
108
|
+
|
|
109
|
+
if self.currently_drawn_shape is not None:
|
|
110
|
+
if self.currently_drawn_shape.isSet:
|
|
111
|
+
self.currently_drawn_shape.draw(painter)
|
|
112
|
+
|
|
113
|
+
sel = self.create_master_rect()
|
|
114
|
+
if sel is not None:
|
|
115
|
+
painter.drawRect(sel)
|
|
116
|
+
painter.restore()
|
|
117
|
+
# painter.end() # probably a good idea ????
|
|
118
|
+
|
|
119
|
+
def group_contains(self, x, y):
|
|
120
|
+
# checks if master rect for group contains click
|
|
121
|
+
# get bounds and create union and compare
|
|
122
|
+
master_rect = self.create_master_rect()
|
|
123
|
+
if master_rect is None:
|
|
124
|
+
return False
|
|
125
|
+
return master_rect.contains(QPointF(x, y))
|
|
126
|
+
|
|
127
|
+
def create_master_rect(self):
|
|
128
|
+
master_rect = None
|
|
129
|
+
if self.selected_shape:
|
|
130
|
+
for shape in self.selected_shape:
|
|
131
|
+
if master_rect is None:
|
|
132
|
+
master_rect = shape.boundingRect()
|
|
133
|
+
else:
|
|
134
|
+
master_rect = master_rect.united(shape.boundingRect())
|
|
135
|
+
return master_rect
|
|
136
|
+
|
|
137
|
+
def removeCurShape(self):
|
|
138
|
+
if self.selected_shape:
|
|
139
|
+
self.shapes = [e for e in self.shapes if e not in self.selected_shape]
|
|
140
|
+
self.selected_shape = []
|
|
141
|
+
|
|
142
|
+
def mousePressEvent(self, event):
|
|
143
|
+
if event.button() == QtCore.Qt.LeftButton:
|
|
144
|
+
self.drawing = True
|
|
145
|
+
self.lastPoint = event.position() / self.scale
|
|
146
|
+
self.firstPoint = event.position() / self.scale
|
|
147
|
+
|
|
148
|
+
shapeFound = False
|
|
149
|
+
if self.currently_drawn_shape is None:
|
|
150
|
+
for shape in reversed(self.shapes):
|
|
151
|
+
if shape.contains(self.lastPoint, extra=self.extra_size_for_sel) and not shape in self.selected_shape:
|
|
152
|
+
logger.debug('you clicked shape:' + str(shape))
|
|
153
|
+
if event.modifiers() == getCtrlModifier():
|
|
154
|
+
if shape not in self.selected_shape: # avoid doublons
|
|
155
|
+
self.selected_shape.append(shape) # add shape to group
|
|
156
|
+
logger.debug('adding shape to group')
|
|
157
|
+
# shapeFound = True
|
|
158
|
+
else:
|
|
159
|
+
if not self.group_contains(self.lastPoint.x(), self.lastPoint.y()):
|
|
160
|
+
self.selected_shape = [shape]
|
|
161
|
+
logger.debug('only one element is selected')
|
|
162
|
+
# shapeFound = True
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
if not shapeFound and event.modifiers() == getCtrlModifier():
|
|
166
|
+
for shape in reversed(self.shapes):
|
|
167
|
+
if shape.contains(self.lastPoint, extra=self.extra_size_for_sel):
|
|
168
|
+
if shape in self.selected_shape: # avoid doublons
|
|
169
|
+
logger.debug('you clicked again shape:' + str(shape))
|
|
170
|
+
self.selected_shape.remove(shape) # add shape to group
|
|
171
|
+
logger.debug('removing a shape from group')
|
|
172
|
+
shapeFound = True
|
|
173
|
+
# no shape found --> reset sel
|
|
174
|
+
if not shapeFound and not self.group_contains(self.lastPoint.x(), self.lastPoint.y()):
|
|
175
|
+
logger.debug('resetting sel')
|
|
176
|
+
self.selected_shape = []
|
|
177
|
+
|
|
178
|
+
# check if a shape is selected and only move that
|
|
179
|
+
if self.drawing_mode and not self.selected_shape and self.currently_drawn_shape is None:
|
|
180
|
+
# do not reset shape if not done drawing...
|
|
181
|
+
if self.shape_to_draw is not None:
|
|
182
|
+
self.currently_drawn_shape = self.shape_to_draw()
|
|
183
|
+
else:
|
|
184
|
+
self.currently_drawn_shape = None
|
|
185
|
+
if self.drawing_mode and not self.selected_shape:
|
|
186
|
+
if self.currently_drawn_shape is not None:
|
|
187
|
+
self.currently_drawn_shape.setTopLeft(QPointF(self.lastPoint.x(), self.lastPoint.y()))
|
|
188
|
+
|
|
189
|
+
def mouseMoveEvent(self, event):
|
|
190
|
+
if event.buttons() and QtCore.Qt.LeftButton:
|
|
191
|
+
if self.selected_shape and self.currently_drawn_shape is None:
|
|
192
|
+
logger.debug('moving' + str(self.selected_shape))
|
|
193
|
+
for shape in self.selected_shape:
|
|
194
|
+
shape.translate(event.position() / self.scale - self.lastPoint)
|
|
195
|
+
|
|
196
|
+
if self.currently_drawn_shape is not None:
|
|
197
|
+
self.currently_drawn_shape.add(self.firstPoint, self.lastPoint)
|
|
198
|
+
|
|
199
|
+
self.lastPoint = event.position() / self.scale
|
|
200
|
+
|
|
201
|
+
def mouseReleaseEvent(self, event):
|
|
202
|
+
if event.button() == QtCore.Qt.LeftButton:
|
|
203
|
+
self.lastPoint = event.position() / self.scale
|
|
204
|
+
self.drawing = False
|
|
205
|
+
if self.drawing_mode and self.currently_drawn_shape is not None:
|
|
206
|
+
self.currently_drawn_shape.add(self.firstPoint, self.lastPoint)
|
|
207
|
+
if isinstance(self.currently_drawn_shape, Freehand2D):
|
|
208
|
+
# this closes the freehand shape
|
|
209
|
+
self.currently_drawn_shape.add(self.lastPoint, self.firstPoint)
|
|
210
|
+
# should not erase the shape if it's a polyline or a polygon by the way
|
|
211
|
+
if isinstance(self.currently_drawn_shape, Freehand2D) or (not isinstance(self.currently_drawn_shape, PolyLine2D) and not isinstance(self.currently_drawn_shape, Polygon2D)):
|
|
212
|
+
if self.check_shape_size_before_adding_it():
|
|
213
|
+
self.shapes.append(self.currently_drawn_shape)
|
|
214
|
+
self.selected_shape = [self.currently_drawn_shape]
|
|
215
|
+
self.currently_drawn_shape = None
|
|
216
|
+
else:
|
|
217
|
+
self.currently_drawn_shape = None
|
|
218
|
+
self.selected_shape = []
|
|
219
|
+
|
|
220
|
+
else:
|
|
221
|
+
self.currently_drawn_shape=None
|
|
222
|
+
self.selected_shape = []
|
|
223
|
+
|
|
224
|
+
def mouseDoubleClickEvent(self, event):
|
|
225
|
+
if isinstance(self.currently_drawn_shape, PolyLine2D) or isinstance(self.currently_drawn_shape, Polygon2D):
|
|
226
|
+
self.shapes.append(self.currently_drawn_shape)
|
|
227
|
+
self.currently_drawn_shape = None
|
|
228
|
+
|
|
229
|
+
def check_shape_size_before_adding_it(self):
|
|
230
|
+
if self.filter_out_unwanted_shapes_based_on_distance: # TODO maybe allow arrowheads to be drawn and stay small, allow lines only if they are in arrwohed only mode (if so do not allow the body of the li,ne to be drawn)
|
|
231
|
+
# if the movement is too small and the object is not a point then the shape drawing is probably undesised!!!
|
|
232
|
+
# print(self.firstPoint , self.lastPoint)
|
|
233
|
+
# print('distance', self.distance(self.firstPoint, self.lastPoint))
|
|
234
|
+
# print('scaled distance', self.distance(self.firstPoint, self.lastPoint)*self.scale)
|
|
235
|
+
# if self.distance(self.firstPoint, self.lastPoint) < 20:
|
|
236
|
+
# best is to look
|
|
237
|
+
# print(self.currently_drawn_shape.getRect())
|
|
238
|
+
rect = self.currently_drawn_shape.getRect()
|
|
239
|
+
|
|
240
|
+
print(rect, self.scale)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
print('area to check',rect.width()* rect.height()*self.scale)
|
|
244
|
+
if not isinstance(self.currently_drawn_shape,(Point2D, TAText2D, Line2D)) and rect.width()* rect.height()*self.scale<200:
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# if not isinstance(self.currently_drawn_shape,(Point2D)) and self.distance(self.firstPoint,self.lastPoint) * self.scale < 40: # , Polygon2D, PolyLine2D, Freehand2D)
|
|
248
|
+
logger.warning(str(self.currently_drawn_shape) + '-->' +
|
|
249
|
+
'area of object is too small, drawing is ignored, the software assumes unintended drawing, zoom more (Ctrl/Cmd +) and redraw the shape if wanted')
|
|
250
|
+
self.currently_drawn_shape = None
|
|
251
|
+
# self.update()
|
|
252
|
+
# print(distance )
|
|
253
|
+
return False
|
|
254
|
+
return True
|
|
255
|
+
|
|
256
|
+
if __name__ == '__main__':
|
|
257
|
+
VectorialDrawPane()
|
|
File without changes
|