diff --git a/pygeoapi/provider/speckle.py b/pygeoapi/provider/speckle.py index fd9b922..3442646 100644 --- a/pygeoapi/provider/speckle.py +++ b/pygeoapi/provider/speckle.py @@ -134,6 +134,8 @@ class SpeckleProvider(BaseProvider): self.limit = 10000 self.limit_message = "" + self.material_color_proxies = {} + def get_fields(self): """ @@ -377,6 +379,8 @@ class SpeckleProvider(BaseProvider): print(f"Rendering model '{branch['name']}' of the project '{stream['name']}'") speckle_data = self.traverse_data(commit_obj, comments) + + speckle_data["features"].extend(speckle_data["comments"]) speckle_data["comments"] = [] @@ -402,7 +406,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 + from pygeoapi.provider.speckle_utils.display_utils import 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] @@ -436,7 +440,9 @@ class SpeckleProvider(BaseProvider): context_list = [x for x in GraphTraversal([rule]).traverse(commit_obj)] get_set_crs_settings(self, commit_obj, context_list, data) + set_default_color(context_list) + self.material_color_proxies: dict = get_material_color_proxies(commit_obj) create_features(self, context_list, comments, data) diff --git a/pygeoapi/provider/speckle_utils/display_utils.py b/pygeoapi/provider/speckle_utils/display_utils.py index d0a37e6..96e0b04 100644 --- a/pygeoapi/provider/speckle_utils/display_utils.py +++ b/pygeoapi/provider/speckle_utils/display_utils.py @@ -201,6 +201,49 @@ def get_display_units(context_list: List["TraversalContext"]) -> None | str: return displayUnits +def get_material_color_proxies(root_obj) -> Dict: + """Get colors and object IDs using ColorProxies and renderMaterialProxies.""" + obj_colors = {} + + # first, get colors + try: + colorProxies = root_obj["colorProxies"] + if isinstance(colorProxies, List): + for proxy in colorProxies: + color = proxy.value + a, r, g, b = get_r_g_b(color) + color = f'rgba({r},{g},{b},{a})' + + for obj in proxy.objects: + obj_colors[obj] = color + except: + pass + + # overwrite with materials if available + try: + materialProxies = root_obj["renderMaterialProxies"] + if isinstance(materialProxies, List): + for proxy in materialProxies: + material = proxy.value + color = material['diffuse'] + opacity = material['opacity'] + + a, r, g, b = get_r_g_b(color) + if opacity is not None and isinstance(opacity, float): + a_test = int(255* opacity) + if 0 <= a_test <= 255: + a = a_test + color = f'rgba({r},{g},{b},{a})' + + for obj in proxy.objects: + obj_colors[obj] = color + + except: + pass + + + return obj_colors + def set_default_color(context_list: List["TraversalContext"]) -> None: """Get and set the default color.""" @@ -215,11 +258,18 @@ def set_default_color(context_list: List["TraversalContext"]) -> None: DEFAULT_COLOR = (255 << 24) + (10 << 16) + (132 << 8) + 255 break -def assign_color(obj_display, props) -> None: +def assign_color(self: "SpeckleProvider", obj_display, props) -> None: """Get and assign color to feature displayProperties.""" from specklepy.objects.geometry import Base, Mesh, Brep + try: + color = self.material_color_proxies[obj_display.applicationId] + props['color'] = color + return + except: + pass + # initialize Speckle Blue color color = DEFAULT_COLOR opacity = None @@ -286,12 +336,12 @@ def get_r_g_b(rgb: int) -> Tuple[int, int, int]: a = 255 return a, r, g, b -def assign_display_properties(feature: Dict, f_base: "Base", obj_display: "Base") -> None: +def assign_display_properties(self: "SpeckleProvider", feature: Dict, f_base: "Base", obj_display: "Base") -> None: """Assign displayProperties to the feature.""" from specklepy.objects.geometry import Mesh, Brep - assign_color(obj_display, feature["displayProperties"]) + assign_color(self, obj_display, feature["displayProperties"]) feature["properties"]["color"] = feature["displayProperties"]["color"] # other properties for rendering diff --git a/pygeoapi/provider/speckle_utils/feature_utils.py b/pygeoapi/provider/speckle_utils/feature_utils.py index 0b95bcd..992afb5 100644 --- a/pygeoapi/provider/speckle_utils/feature_utils.py +++ b/pygeoapi/provider/speckle_utils/feature_utils.py @@ -67,7 +67,7 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d if prop not in all_props: all_props.append(prop) - assign_display_properties(feature, f_base, obj_get_color) + assign_display_properties(self, feature, f_base, obj_get_color) feature["max_height"] = max([c[2] for c in coords]) data["features"].append(feature) feature_count += 1 @@ -107,7 +107,7 @@ def initialize_features(self: "SpeckleProvider", all_coords, all_coord_counts, d all_coords.extend(coords) all_coord_counts.append(coord_counts) - assign_display_properties(feature_new, f_base, obj_get_color) + assign_display_properties(self, feature_new, f_base, obj_get_color) feature_new["max_height"] = max([c[2] for c in coords]) data["features"].append(feature_new) feature_count +=1