Commit b99097d9 authored by Josef Brandt's avatar Josef Brandt

Basic spiral function (not fully controllable)

parent 1ea15db5
import numpy as np
from methods import SubsamplingMethod
class CrossBoxSelector(SubsamplingMethod):
def __init__(self, particleContainer, desiredFraction:float = 0.1) -> None:
super(CrossBoxSelector, self).__init__(particleContainer, desiredFraction)
self.fraction = desiredFraction
self.filterWidth: float = 1000
self.filterHeight: float = 1000
self.numBoxesAcross: int = 3 #either 3 or 5
......@@ -66,4 +67,55 @@ class CrossBoxSelector(SubsamplingMethod):
start: float = i * filterSize / self.numBoxesAcross + (maxBoxSize - boxSize) / 2
tileStarts.append(start)
return tileStarts
\ No newline at end of file
return tileStarts
class SpiralSelector(SubsamplingMethod):
def __init__(self, particleContainer, desiredFraction: float = 0.1) -> None:
super(SpiralSelector, self).__init__(particleContainer, desiredFraction)
self.filterWidth: float
self.filterHeight: float
self.boxSize: float = 50
self.numBoxes = 20
# self.numTurns: float = 4
@property
def spiralSlope(self) -> float:
assert self.filterHeight == self.filterWidth
return self.armDistance / (2*np.pi)
@property
def armDistance(self) -> float:
return np.sqrt(2) * self.boxSize
@property
def numTurns(self) -> float:
assert self.filterHeight == self.filterWidth
return (self.filterHeight / 2) / self.armDistance
@property
def finalAngle(self) -> float:
return self.numTurns * 2*np.pi
def get_topLeft_of_boxes(self) -> list:
totalLength: float = self._get_spiralLength_after_angle(self.finalAngle)
boxDistance: float = totalLength / self.numBoxes * 0.5
filterCenter: tuple = self.filterWidth / 2, self.filterHeight / 2
slope = self.spiralSlope
theta: float = 0
topLefts: list = []
for _ in range(self.numBoxes):
newPoint: tuple = self._get_xy_at_angle(theta, filterCenter)
topLefts.append(newPoint)
theta += boxDistance / (slope * np.sqrt(1 + theta**2))
return topLefts
def _get_spiralLength_after_angle(self, theta: float):
return 0.5*self.spiralSlope*(theta*(1+theta**2)**0.5 + np.sinh(theta)**(-1))
def _get_xy_at_angle(self, theta: float, centerXY: tuple = (0, 0)) -> tuple:
distance: float = self.spiralSlope * theta
return distance * np.cos(theta) + centerXY[0], distance * np.sin(theta) + centerXY[1]
\ No newline at end of file
......@@ -35,7 +35,7 @@ class FilterGraphItem(QtWidgets.QGraphicsItem):
"""
The Graphical Representation of the actual filter
"""
def __init__(self, filterWidth:float=500, filterHeight:float=500):
def __init__(self, filterWidth: float = 500, filterHeight: float = 500):
super(FilterGraphItem, self).__init__()
self.width = filterWidth
self.height = filterHeight
......
from PyQt5 import QtWidgets
from filterView import FilterView
from measureModes import CrossBoxMode, CrossBoxesControls
from gui.filterView import FilterView
from gui.measureModes import MeasureMode, CrossBoxMode, CrossBoxesControls, SpiralBoxMode
class MainView(QtWidgets.QWidget):
......@@ -12,8 +12,9 @@ class MainView(QtWidgets.QWidget):
self.setLayout(self.layout)
self.modeSelector: QtWidgets.QComboBox = QtWidgets.QComboBox()
self.modeSelector.currentTextChanged.connect(self._switch_to_mode)
self.measureModes: dict = {}
self.activeMode = None
self.activeMode: MeasureMode = None
self.activeModeControl: QtWidgets.QGroupBox = QtWidgets.QGroupBox()
self.controlGroup = QtWidgets.QGroupBox()
......@@ -31,20 +32,30 @@ class MainView(QtWidgets.QWidget):
self._switch_to_default_mode()
def _add_measure_modes(self) -> None:
self.modeSelector.addItem('crossSelection')
self.measureModes['spiralSelection'] = SpiralBoxMode(self.filterView)
self.measureModes['crossSelection'] = CrossBoxMode(self.filterView)
self.modeSelector.addItem('spiralSelection')
self.modeSelector.addItem('crossSelection')
def _switch_to_default_mode(self) -> None:
modes: list = list(self.measureModes.keys())
self._activate_mode(modes[0])
def _switch_to_mode(self) -> None:
newMode: str = self.modeSelector.currentText()
self._activate_mode(newMode)
def _activate_mode(self, modeName: str) -> None:
self.activeModeControl.setParent(None)
self.controlGroupLayout.removeWidget(self.activeModeControl)
requestedMode: MeasureMode = self.measureModes[modeName]
if requestedMode is not self._activate_mode:
self.activeModeControl.setParent(None)
self.controlGroupLayout.removeWidget(self.activeModeControl)
self.activeMode = requestedMode
self.activeModeControl = self.activeMode.get_control_groupBox()
self.controlGroupLayout.insertWidget(2, self.activeModeControl)
self.activeMode = self.measureModes[modeName]
self.activeModeControl = self.activeMode.get_control_groupBox()
self.controlGroupLayout.insertWidget(2, self.activeModeControl)
self.activeMode.update_measure_viewItems()
if __name__ == '__main__':
......
......@@ -4,8 +4,8 @@ from PyQt5 import QtCore, QtWidgets
# parentdir = os.path.dirname(currentdir)
# sys.path.insert(0, parentdir)
# del currentdir, parentdir
from filterView import FilterView, MeasureBoxGraphItem
from geometricOperations import CrossBoxSelector
from gui.filterView import FilterView, MeasureBoxGraphItem
from geometricOperations import CrossBoxSelector, SpiralSelector
class MeasureMode(QtCore.QObject):
......@@ -88,4 +88,33 @@ class CrossBoxesControls(QtWidgets.QGroupBox):
if maxCoverage < self.coverageSpinbox.value():
self.coverageSpinbox.valueChanged.disconnect()
self.coverageSpinbox.setValue(maxCoverage)
self.coverageSpinbox.valueChanged.connect(self._config_changed)
\ No newline at end of file
self.coverageSpinbox.valueChanged.connect(self._config_changed)
class SpiralBoxMode(MeasureMode):
def __init__(self, *args):
super(SpiralBoxMode, self).__init__(*args)
self.uiControls = QtWidgets.QGroupBox('Spiral Box Controls')
self.spiralBoxGenerator: SpiralSelector = SpiralSelector(None)
self.update_measure_viewItems()
def update_measure_viewItems(self) -> None:
self.spiralBoxGenerator.filterHeight = self.filterView.filter.height
self.spiralBoxGenerator.filterWidth = self.filterView.filter.width
# desiredCoverage: int = self.uiControls.coverageSpinbox.value()
# maxCoverage: int = int(self.crossBoxGenerator.get_maximum_achievable_fraction() * 100)
# self.uiControls.set_to_max_possible_coverage(maxCoverage)
# if desiredCoverage > maxCoverage:
# desiredCoverage = maxCoverage
# self.crossBoxGenerator.fraction = desiredCoverage / 100
viewItems = []
topLefts: list = self.spiralBoxGenerator.get_topLeft_of_boxes()
boxSize = self.spiralBoxGenerator.boxSize
for (x, y) in topLefts:
newBox: MeasureBoxGraphItem = MeasureBoxGraphItem(x, y, boxSize, boxSize)
viewItems.append(newBox)
self.filterView.update_measure_boxes(viewItems)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment