Skip to content

Commit

Permalink
Merge pull request #52 from GispoCoding/45-add-processing-script-to-c…
Browse files Browse the repository at this point in the history
…ount-trajectories-crossing-gates

45 add processing script to count trajectories crossing gates
  • Loading branch information
JuhoErvasti authored Oct 31, 2024
2 parents fc69949 + 61272fe commit 530fb9b
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 214 deletions.
2 changes: 1 addition & 1 deletion fvh3t/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

py_files = [fil for fil in glob.glob("**/*.py", recursive=True) if "test/" not in fil and "test\\" not in fil]
locales = ["fi"]
profile = "default"
profile = "FVH-3T"
ui_files = list(glob.glob("**/*.ui", recursive=True))
resources = list(glob.glob("**/*.qrc", recursive=True))
extra_dirs = ["resources"]
Expand Down
47 changes: 41 additions & 6 deletions fvh3t/core/gate_layer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

from qgis.core import QgsFeatureSource, QgsField, QgsVectorLayer, QgsWkbTypes
from qgis.core import QgsFeature, QgsFeatureSource, QgsField, QgsVectorLayer, QgsWkbTypes
from qgis.PyQt.QtCore import QMetaType, QVariant

from fvh3t.core.exceptions import InvalidLayerException
from fvh3t.core.exceptions import InvalidFeatureException, InvalidLayerException
from fvh3t.core.gate import Gate


Expand Down Expand Up @@ -51,7 +52,41 @@ def create_gates(self) -> None:
def gates(self) -> tuple[Gate, ...]:
return self.__gates

def is_field_valid(self, field_name: str, *, accepted_types: list[str]) -> bool:
def as_line_layer(self) -> QgsVectorLayer | None:
line_layer = QgsVectorLayer("LineString?crs=3067", "Line Layer", "memory")

line_layer.startEditing()

line_layer.addAttribute(QgsField("fid", QVariant.Int))
line_layer.addAttribute(QgsField("counts_left", QVariant.Bool))
line_layer.addAttribute(QgsField("counts_right", QVariant.Bool))
line_layer.addAttribute(QgsField("trajectory_count", QVariant.Int))

fields = line_layer.fields()

for i, gate in enumerate(self.__gates):
feature = QgsFeature(fields)

feature.setAttributes(
[
i,
gate.counts_left(),
gate.counts_right(),
gate.trajectory_count(),
]
)
feature.setGeometry(gate.geometry())

if not feature.isValid():
raise InvalidFeatureException

line_layer.addFeature(feature)

line_layer.commitChanges()

return line_layer

def is_field_valid(self, field_name: str, *, accepted_types: list[QMetaType.Type]) -> bool:
"""
Check that a field 1) exists and 2) has an
acceptable type. Leave type list empty to
Expand All @@ -66,7 +101,7 @@ def is_field_valid(self, field_name: str, *, accepted_types: list[str]) -> bool:
return True

field: QgsField = self.__layer.fields().field(field_id)
field_type: str = field.displayType()
field_type: QMetaType.Type = field.type()

return field_type in accepted_types

Expand All @@ -86,11 +121,11 @@ def is_valid(self) -> bool:
msg = "Layer has no features."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__counts_left_field, accepted_types=["boolean"]):
if not self.is_field_valid(self.__counts_left_field, accepted_types=[QMetaType.Type.Bool]):
msg = "Counts left field either not found or of incorrect type."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__counts_right_field, accepted_types=["boolean"]):
if not self.is_field_valid(self.__counts_right_field, accepted_types=[QMetaType.Type.Bool]):
msg = "Counts right field either not found or of incorrect type."
raise InvalidLayerException(msg)

Expand Down
28 changes: 21 additions & 7 deletions fvh3t/core/trajectory_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,27 @@
QgsVectorLayer,
QgsWkbTypes,
)
from qgis.PyQt.QtCore import QVariant
from qgis.PyQt.QtCore import QMetaType, QVariant

from fvh3t.core.exceptions import InvalidFeatureException, InvalidLayerException, InvalidTrajectoryException
from fvh3t.core.trajectory import Trajectory, TrajectoryNode

UNIX_TIMESTAMP_UNIT_THRESHOLD = 13
N_NODES_MIN = 2
QT_NUMERIC_TYPES = [
QMetaType.Type.Int,
QMetaType.Type.UInt,
QMetaType.Type.Double,
QMetaType.Type.Long,
QMetaType.Type.LongLong,
QMetaType.Type.ULong,
QMetaType.Type.ULongLong,
QMetaType.Type.Short,
QMetaType.Type.UShort,
QMetaType.Type.SChar,
QMetaType.Type.UChar,
QMetaType.Type.Float,
]


def digits_in_timestamp_int(num: int):
Expand Down Expand Up @@ -220,7 +234,7 @@ def as_line_layer(self) -> QgsVectorLayer | None:

return line_layer

def is_field_valid(self, field_name: str, *, accepted_types: list[str]) -> bool:
def is_field_valid(self, field_name: str, *, accepted_types: list[QMetaType.Type]) -> bool:
"""
Check that a field 1) exists and 2) has an
acceptable type. Leave type list empty to
Expand All @@ -235,7 +249,7 @@ def is_field_valid(self, field_name: str, *, accepted_types: list[str]) -> bool:
return True

field: QgsField = self.__layer.fields().field(field_id)
field_type: str = field.displayType()
field_type: QMetaType.Type = field.type()

return field_type in accepted_types

Expand All @@ -259,19 +273,19 @@ def is_valid(self) -> bool:
msg = "Id field either not found or of incorrect type."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__timestamp_field, accepted_types=["integer", "double"]):
if not self.is_field_valid(self.__timestamp_field, accepted_types=QT_NUMERIC_TYPES):
msg = "Timestamp field either not found or of incorrect type."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__width_field, accepted_types=["integer", "double"]):
if not self.is_field_valid(self.__width_field, accepted_types=QT_NUMERIC_TYPES):
msg = "Width field either not found or of incorrect type."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__length_field, accepted_types=["integer", "double"]):
if not self.is_field_valid(self.__length_field, accepted_types=QT_NUMERIC_TYPES):
msg = "Length field either not found or of incorrect type."
raise InvalidLayerException(msg)

if not self.is_field_valid(self.__height_field, accepted_types=["integer", "double"]):
if not self.is_field_valid(self.__height_field, accepted_types=QT_NUMERIC_TYPES):
msg = "Height field either not found or of incorrect type."
raise InvalidLayerException(msg)

Expand Down
Loading

0 comments on commit 530fb9b

Please sign in to comment.