diff --git a/pygeoapi/provider/speckle.py b/pygeoapi/provider/speckle.py index 9846369..5a8d18f 100644 --- a/pygeoapi/provider/speckle.py +++ b/pygeoapi/provider/speckle.py @@ -144,6 +144,7 @@ class SpeckleProvider(BaseProvider): self.limit_message = "" self.extent = [-180,-90,180,90] + self.extent3d = [-180,-90,0,180,90,1000] self.material_color_proxies = {} @@ -420,6 +421,7 @@ class SpeckleProvider(BaseProvider): speckle_data["model_last_version_date"] = datetime.strptime(commit['createdAt'].replace("T", " ").replace("Z","").split(".")[0], '%Y-%m-%d %H:%M:%S') speckle_data["model_id"] = wrapper.model_id speckle_data["extent"] = self.extent + speckle_data["extent3d"] = self.extent3d speckle_data["limit_message"] = self.limit_message return speckle_data @@ -437,7 +439,7 @@ class SpeckleProvider(BaseProvider): ) from pygeoapi.provider.speckle_utils.crs_utils import get_set_crs_settings from pygeoapi.provider.speckle_utils.feature_utils import create_features - from pygeoapi.provider.speckle_utils.display_utils import set_default_color, get_material_color_proxies + from pygeoapi.provider.speckle_utils.display_utils import isDisplayable, set_default_color, get_material_color_proxies supported_classes = [GisFeature, GisPolygonElement, Mesh, Brep, Point, Line, Polyline, Curve, Arc, Circle, Ellipse, Polycurve] supported_types = [y().speckle_type for y in supported_classes] @@ -472,7 +474,7 @@ class SpeckleProvider(BaseProvider): and (isinstance(getattr(x, item, None), list) or ("grasshopper" in self.sourceApp.lower() and x.speckle_type == "Base") ) ], ) - context_list = [x for x in GraphTraversal([rule]).traverse(commit_obj)] + context_list = [x for x in GraphTraversal([rule]).traverse(commit_obj) if isDisplayable(x.current)] get_set_crs_settings(self, commit_obj, context_list, data) diff --git a/pygeoapi/provider/speckle_utils/coords_utils.py b/pygeoapi/provider/speckle_utils/coords_utils.py index 5e02d02..c1aa6f1 100644 --- a/pygeoapi/provider/speckle_utils/coords_utils.py +++ b/pygeoapi/provider/speckle_utils/coords_utils.py @@ -55,7 +55,15 @@ def reproject_bulk(self, all_coords: List[List[List[float]]], all_coord_counts: if geometry["type"] == "MultiPoint": poly_part.extend([local_flat_coords[ind] for ind in range_coords_indices]) else: - poly_part.append([local_flat_coords[ind] for ind in range_coords_indices]) + new_list = [] + for ind in range_coords_indices: + try: + new_list.append(local_flat_coords[ind]) + except Exception as e: # corrupted geometry, ignore altogether + new_list = [] + break + if len(new_list)>0: + poly_part.append(new_list) start_index += part_count @@ -89,7 +97,9 @@ def reproject_2d_coords_list(self, coords_in: List[List[float]]) -> List[List[fl all_x = [x[0] for x in transformed] all_y = [x[1] for x in transformed] + all_z = [x[2] for x in transformed] self.extent = [min(all_x), min(all_y), max(all_x), max(all_y)] + self.extent3d = [min(all_x), min(all_y), min(all_z), max(all_x), max(all_y), max(all_z)] return transformed def offset_rotate(self, coords_in: List[list]) -> List[List[float]]: diff --git a/pygeoapi/provider/speckle_utils/display_utils.py b/pygeoapi/provider/speckle_utils/display_utils.py index db9da0b..9ae1a21 100644 --- a/pygeoapi/provider/speckle_utils/display_utils.py +++ b/pygeoapi/provider/speckle_utils/display_utils.py @@ -54,6 +54,7 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]: count = 0 all_count = len(item.faces) + sub_meshes = [] for _ in item.faces: if count < all_count: faces = [] @@ -61,33 +62,64 @@ def separate_display_vals(displayValue: List) -> List[Tuple["Base"]]: colors = [] vert_num = item.faces[count] + if vert_num == 0: + vert_num = 3 + elif vert_num == 1: + vert_num = 4 faces.append(vert_num) faces.extend([ x for x in list(range(vert_num))]) - for ind in range(vert_num): - face_vert_index = count+1+ind - vert_index = item.faces[face_vert_index] + try: + for ind in range(vert_num): + face_vert_index = count+1+ind + #print(face_vert_index) + vert_index = item.faces[face_vert_index] - new_vert = item.vertices[3*vert_index : 3*vert_index + 3] - verts.extend(new_vert) + new_vert = item.vertices[3*vert_index : 3*vert_index + 3] + verts.extend(new_vert) - if isinstance(item.colors, List) and len(item.colors) > vert_index: - color = item.colors[vert_index] - colors.append(color) + if isinstance(item.colors, List) and len(item.colors) > vert_index: + color = item.colors[vert_index] + colors.append(color) + + count += vert_num+1 + if len(colors)>0: + mesh = Mesh.create(faces= faces, vertices=verts, colors=colors) + else: + mesh = Mesh.create(faces= faces, vertices=verts) + + sub_meshes.append((mesh, item)) - count += vert_num+1 - if len(colors)>0: - mesh = Mesh.create(faces= faces, vertices=verts, colors=colors) - else: - mesh = Mesh.create(faces= faces, vertices=verts) - display_objs.append((mesh, item)) + except IndexError: # corrupted mesh, drop altogether + sub_meshes = [] + break + + display_objs.extend(sub_meshes) elif item is not None: display_objs.append((item, item)) return display_objs +def isDisplayable(obj: "Base") -> bool: + + if is_primitive(obj): + return True + + displayValue = None + if hasattr(obj, 'displayValue'): + displayValue = getattr(obj, 'displayValue') + elif hasattr(obj, '@displayValue'): + displayValue = getattr(obj, '@displayValue') + + # merge to sigle object, if List + if isinstance(displayValue, List): + return True + + return False + + def find_display_obj(obj) -> Tuple["Base", "Base"]: """Get displayable object.""" @@ -121,11 +153,12 @@ def find_display_obj(obj) -> Tuple["Base", "Base"]: def is_convertible(obj) -> bool: """Check if the object can be converted directly.""" - from specklepy.objects.geometry import Base, Point, Line, Arc, Circle, Curve, Polycurve, Mesh, Brep + from specklepy.objects.geometry import Base, Point, Line, Polyline, Arc, Circle, Curve, Polycurve, Mesh, Brep if ( (isinstance(obj, Base) and obj.speckle_type.endswith("Feature")) or isinstance(obj, Point) or isinstance(obj, Line) or + isinstance(obj, Polyline) or isinstance(obj, Arc) or isinstance(obj, Circle) or isinstance(obj, Curve) or @@ -135,6 +168,23 @@ def is_convertible(obj) -> bool: return True return False +def is_primitive(obj) -> bool: + """Check if the object can be converted directly.""" + + from specklepy.objects.geometry import Polyline, Point, Line, Arc, Circle, Curve, Polycurve, Mesh, Brep + + if ( + isinstance(obj, Point) or + isinstance(obj, Line) or + isinstance(obj, Polyline) or + isinstance(obj, Arc) or + isinstance(obj, Circle) or + isinstance(obj, Curve) or + isinstance(obj, Mesh) + ): + return True + return False + def get_single_display_object(displayValForColor: List) -> "Base": """Get a merged Mesh or a first item from displayValue list."""