add Gis feature class on send and receive (#195)

* send GisFeature

* remove display val from child geometries

* receive GisFeature

* fix

* ensure units are strings

* fix failing test
This commit is contained in:
KatKatKateryna 2024-06-05 17:48:19 +08:00 коммит произвёл GitHub
Родитель 8463c82260
Коммит ad34e3bbe6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
5 изменённых файлов: 54 добавлений и 13 удалений

Просмотреть файл

@ -0,0 +1,13 @@
from typing import List, Optional
from specklepy.objects.base import Base
class GisFeature(
Base, speckle_type="Objects.GIS.GisFeature", detachable={"displayValue"}
):
"""GIS Feature"""
geometry: Optional[List[Base]] = None
attributes: Base
displayValue: Optional[List[Base]] = None

Просмотреть файл

@ -9,6 +9,7 @@ import hashlib
import scipy as sp
from plugin_utils.helpers import findOrCreatePath, get_scale_factor_to_meter
from speckle.converter.features.GisFeature import GisFeature
from speckle.converter.geometry import transform
from speckle.converter.geometry.conversions import (
convertToNative,
@ -79,15 +80,18 @@ def featureToSpeckle(
iterations = 0
try:
geom = None
new_geom = None
if geomType == "None":
geom = GisNonGeometryElement()
geom = GisNonGeometryElement() # redundant, delete in refactor
new_geom = GisFeature()
new_report = {"obj_type": geom.speckle_type, "errors": ""}
else:
# Try to extract geometry
skipped_msg = f"'{geomType}' feature skipped due to invalid geometry"
try:
geom, iterations = convertToSpeckle(f, selectedLayer, dataStorage)
if geom is not None and geom != "None":
if not isinstance(geom.geometry, List):
logToUser(
@ -97,6 +101,16 @@ def featureToSpeckle(
)
return None
# geom is GisPointElement, GisLineElement, GisPolygonElement
new_geom = GisFeature()
new_geom.geometry = []
for g in geom.geometry:
obj = g
if isinstance(g, GisPolygonGeometry):
new_geom.displayValue = []
obj = GisPolygonGeometry(boundary=g.boundary, voids=g.voids)
new_geom.geometry.append(obj)
all_errors = ""
for g in geom.geometry:
if g is None or g == "None":
@ -114,6 +128,7 @@ def featureToSpeckle(
func=inspect.stack()[0][3],
)
elif iterations is not None and iterations > 0:
new_geom.displayValue.extend(g.displayValue)
all_errors += (
"Polygon display mesh is simplified" + ", "
)
@ -122,6 +137,8 @@ def featureToSpeckle(
level=1,
func=inspect.stack()[0][3],
)
else:
new_geom.displayValue.extend(g.displayValue)
if len(geom.geometry) == 0:
all_errors = "No geometry converted"
@ -129,7 +146,7 @@ def featureToSpeckle(
{"obj_type": geom.speckle_type, "errors": all_errors}
)
else: # geom is None
else: # geom is None, should not happen, but we should pass the object with attributes anyway
new_report = {"obj_type": "", "errors": skipped_msg}
logToUser(skipped_msg, level=2, func=inspect.stack()[0][3])
geom = GisNonGeometryElement()
@ -162,11 +179,12 @@ def featureToSpeckle(
# if geom is not None and geom!="None":
geom.attributes = attributes
new_geom.attributes = attributes
dataStorage.latestActionFeaturesReport[
len(dataStorage.latestActionFeaturesReport) - 1
].update(new_report)
return geom
return new_geom
except Exception as e:
new_report.update({"errors": e})
@ -174,7 +192,7 @@ def featureToSpeckle(
len(dataStorage.latestActionFeaturesReport) - 1
].update(new_report)
logToUser(e, level=2, func=inspect.stack()[0][3])
return geom
return new_geom
def rasterFeatureToSpeckle(
@ -987,7 +1005,9 @@ def featureToNative(feature: Base, fields: "QgsFields", dataStorage):
try:
qgsGeom = None
if isinstance(feature, GisNonGeometryElement):
if isinstance(feature, GisNonGeometryElement) or (
isinstance(feature, GisFeature) and feature.geometry is None
):
pass
else:
try:
@ -1006,7 +1026,10 @@ def featureToNative(feature: Base, fields: "QgsFields", dataStorage):
qgsGeom = convertToNative(speckle_geom, dataStorage)
elif isinstance(speckle_geom, list):
if len(speckle_geom) == 1:
# add condition for new GisFeature class
if isinstance(feature, GisFeature) and isinstance(speckle_geom[0], GisPolygonGeometry) and speckle_geom[0].boundary is None:
qgsGeom = convertToNativeMulti(feature.displayValue, dataStorage)
elif len(speckle_geom) == 1:
qgsGeom = convertToNative(speckle_geom[0], dataStorage)
elif len(speckle_geom) > 1:
qgsGeom = convertToNativeMulti(speckle_geom, dataStorage)

Просмотреть файл

@ -237,9 +237,7 @@ def convertToSpeckle(
v[1] for v in enumerate(poly.exteriorRing().vertices())
]
except:
boundaryPts = [
v[1] for v in enumerate(poly.vertices())
]
boundaryPts = [v[1] for v in enumerate(poly.vertices())]
if height is not None:
if isFlat(boundaryPts) is False:
logToUser(
@ -445,6 +443,9 @@ def convertToNativeMulti(
return multiPolylineToNative(items, dataStorage)
# elif isinstance(first, Arc) or isinstance(first, Polycurve) or isinstance(first, Ellipse) or isinstance(first, Circle) or isinstance(first, Curve):
# return [convertToNative(it, dataStorage) for it in items]
elif isinstance(first, Mesh):
converted: QgsMultiPolygon = meshToNative(items, dataStorage)
return converted
elif isinstance(first, Base):
try:
displayVals = []
@ -453,7 +454,7 @@ def convertToNativeMulti(
displayVals.extend(it.displayValue)
except:
displayVals.extend(it["@displayValue"])
if isinstance(first, GisPolygonGeometry):
if isinstance(first, GisPolygonGeometry) or isinstance(first, Mesh):
if first.boundary is None:
converted: QgsMultiPolygon = meshToNative(
displayVals, dataStorage

Просмотреть файл

@ -496,7 +496,8 @@ class SpeckleQGIS:
units = str(QgsUnitTypes.encodeUnit(projectCRS.mapUnits()))
self.dataStorage.latestActionUnits = units
try:
units = get_units_from_string(units)
units_class = get_units_from_string(units)
units = units_class.value
except SpeckleInvalidUnitException:
units = "none"
self.dataStorage.currentUnits = units

Просмотреть файл

@ -116,8 +116,11 @@ def test_validateBranch(stream):
assert isinstance(result, Branch)
def test_validateBranch_no_commits(stream_fe1):
branch_name = "main"
def test_validateBranch_no_commits():
sample_wrapper = StreamWrapper("https://latest.speckle.dev/streams/7117052f4e")
sample_wrapper.get_client()
stream_fe1 = sample_wrapper._client.stream.get(id=sample_wrapper.stream_id)
branch_name = "empty_branch"
result = validateBranch(stream_fe1, branch_name, checkCommits=True, dockwidget=None)
assert result is None