support ICurves and new GisFeatures, and (possible) hatches
This commit is contained in:
@@ -370,7 +370,7 @@ class SpeckleProvider(BaseProvider):
|
||||
def traverse_data(self, commit_obj) -> Dict:
|
||||
"""Traverse Speckle commit and return geojson with features."""
|
||||
|
||||
from specklepy.objects.geometry import Point, Line, Polyline, Curve, Mesh, Brep
|
||||
from specklepy.objects.geometry import Point, Line, Curve, Arc, Circle, Ellipse, Polyline, Polycurve, Mesh, Brep
|
||||
from specklepy.objects.GIS.layers import VectorLayer
|
||||
from specklepy.objects.GIS.geometry import GisPolygonElement
|
||||
from specklepy.objects.GIS.GisFeature import GisFeature
|
||||
@@ -382,7 +382,7 @@ class SpeckleProvider(BaseProvider):
|
||||
from pygeoapi.provider.speckle_utils.feature_utils import create_features
|
||||
from pygeoapi.provider.speckle_utils.display_utils import set_default_color
|
||||
|
||||
supported_classes = [GisFeature, GisPolygonElement, Mesh, Brep, Point, Line, Polyline, Curve]
|
||||
supported_classes = [GisFeature, GisPolygonElement, Mesh, Brep, Point, Line, Polyline, Curve, Arc, Circle, Ellipse, Polycurve]
|
||||
supported_types = [y().speckle_type for y in supported_classes]
|
||||
supported_types.extend([
|
||||
"Objects.Other.Revit.RevitInstance",
|
||||
|
||||
@@ -1,13 +1,248 @@
|
||||
|
||||
from typing import Dict, List
|
||||
import math
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
|
||||
def assign_geometry(feature: Dict, f_base) -> ( List[List[List[float]]], List[List[None| List[int]]] ):
|
||||
def convert_point(f_base: "Point", coords, coord_counts):
|
||||
"""Convert Point."""
|
||||
|
||||
coords.append([f_base.x, f_base.y, f_base.z])
|
||||
coord_counts.append([1])
|
||||
|
||||
def convert_line(f_base: "Line", coords, coord_counts):
|
||||
"""Convert Line."""
|
||||
|
||||
start = [f_base.start.x, f_base.start.y, f_base.start.z]
|
||||
end = [f_base.end.x, f_base.end.y, f_base.end.z]
|
||||
|
||||
coords.extend([start, end])
|
||||
coord_counts.append([2])
|
||||
|
||||
def convert_polyline(f_base: "Polyline", coords, coord_counts):
|
||||
"""Convert Polyline."""
|
||||
|
||||
coord_counts.append([])
|
||||
local_poly_count = 0
|
||||
|
||||
for pt in f_base.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
local_poly_count += 1
|
||||
|
||||
# closing point
|
||||
if local_poly_count>2 and f_base.closed is True and coords[0] != coords[-1]:
|
||||
coords.append(coords[0])
|
||||
local_poly_count += 1
|
||||
coord_counts[-1].append(local_poly_count)
|
||||
|
||||
def convert_arc(f_base: "Arc", coords, coord_counts):
|
||||
"""Convert Arc."""
|
||||
|
||||
if f_base.plane is None or f_base.plane.normal.z == 0:
|
||||
normal = 1
|
||||
else:
|
||||
normal = f_base.plane.normal.z
|
||||
|
||||
# calculate angles and interval
|
||||
interval, angle1, angle2 = getArcRadianAngle(f_base)
|
||||
|
||||
if (angle1 > angle2 and normal == -1) or (angle2 > angle1 and normal == 1):
|
||||
pass
|
||||
if angle1 > angle2 and normal == 1:
|
||||
interval = abs((2 * math.pi - angle1) + angle2)
|
||||
if angle2 > angle1 and normal == -1:
|
||||
interval = abs((2 * math.pi - angle2) + angle1)
|
||||
|
||||
# set a (random) point density: 24 per 1 rad
|
||||
pointsNum = math.floor(abs(interval)) * 24
|
||||
if pointsNum < 4:
|
||||
pointsNum = 4
|
||||
|
||||
# assign coordinates
|
||||
coord_counts.append([])
|
||||
local_poly_count = 0
|
||||
|
||||
for i in range(0, pointsNum + 1):
|
||||
k = i / pointsNum # reset values to fraction
|
||||
angle = angle1 + k * interval * normal
|
||||
|
||||
x=f_base.plane.origin.x + f_base.radius * math.cos(angle)
|
||||
y=f_base.plane.origin.y + f_base.radius * math.sin(angle)
|
||||
z=f_base.plane.origin.z
|
||||
|
||||
coords.append([x, y, z])
|
||||
local_poly_count += 1
|
||||
coord_counts[-1].append(local_poly_count)
|
||||
|
||||
def convert_circle(f_base: "Circle", coords, coord_counts):
|
||||
"""Convert Circle."""
|
||||
|
||||
if f_base.plane is None or f_base.plane.normal.z == 0:
|
||||
normal = 1
|
||||
else:
|
||||
normal = f_base.plane.normal.z
|
||||
|
||||
# set a (random) point density: 24 per 1 rad
|
||||
interval = 2 * math.pi
|
||||
pointsNum = math.floor(abs(interval)) * 24
|
||||
if pointsNum < 4:
|
||||
pointsNum = 4
|
||||
|
||||
# assign coordinates
|
||||
coord_counts.append([])
|
||||
local_poly_count = 0
|
||||
|
||||
for i in range(0, pointsNum + 1):
|
||||
k = i / pointsNum # reset values to fraction
|
||||
angle = k * interval * normal
|
||||
|
||||
x=f_base.plane.origin.x + f_base.radius * math.cos(angle)
|
||||
y=f_base.plane.origin.y + f_base.radius * math.sin(angle)
|
||||
z=f_base.plane.origin.z
|
||||
|
||||
coords.append([x, y, z])
|
||||
local_poly_count += 1
|
||||
coord_counts[-1].append(local_poly_count)
|
||||
|
||||
def convert_polycurve(f_base: "Polycurve", coords, coord_counts):
|
||||
"""Convert Polycurve."""
|
||||
|
||||
flat_coords = []
|
||||
flat_coord_count = [0]
|
||||
|
||||
# put together results from all segment conversions
|
||||
for segm in f_base.segments:
|
||||
convert_icurve(segm, coords, coord_counts)
|
||||
if len(coord_counts)==0:
|
||||
continue
|
||||
flat_coords.extend(coords)
|
||||
flat_coord_count[-1] += coord_counts[-1][-1]
|
||||
|
||||
coords = flat_coords
|
||||
coord_counts = flat_coord_count
|
||||
|
||||
def convert_curve(f_base: "Curve", coords, coord_counts):
|
||||
"""Convert Curve using its Polyline displayValue."""
|
||||
|
||||
return convert_polyline(f_base.displayValue, coords, coord_counts)
|
||||
|
||||
def convert_icurve(f_base: "Base", coords, coord_counts):
|
||||
"""Convert any ICurve."""
|
||||
|
||||
from specklepy.objects.geometry import Line, Polyline, Arc, Curve, Circle, Polycurve, Mesh, Brep
|
||||
|
||||
if isinstance(f_base, Line):
|
||||
convert_line(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Polyline):
|
||||
convert_polyline(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Curve):
|
||||
convert_curve(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Arc):
|
||||
convert_arc(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Circle):
|
||||
convert_circle(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Polycurve):
|
||||
convert_polycurve(f_base, coords, coord_counts)
|
||||
|
||||
def convert_mesh_or_brep(f_base: "Base", coords, coord_counts):
|
||||
"""Convert Mesh object or Mesh derived from Brep display value."""
|
||||
from specklepy.objects.geometry import Mesh, Brep
|
||||
|
||||
faces = []
|
||||
vertices = []
|
||||
|
||||
# get faces and vertices
|
||||
if isinstance(f_base, Mesh):
|
||||
faces = f_base.faces
|
||||
vertices = f_base.vertices
|
||||
elif isinstance(f_base, Brep):
|
||||
if f_base.displayValue is None or (
|
||||
isinstance(f_base.displayValue, list)
|
||||
and len(f_base.displayValue) == 0
|
||||
):
|
||||
geometry = {}
|
||||
return
|
||||
elif isinstance(f_base.displayValue, list):
|
||||
faces = f_base.displayValue[0].faces
|
||||
vertices = f_base.displayValue[0].vertices
|
||||
else:
|
||||
faces = f_base.displayValue.faces
|
||||
vertices = f_base.displayValue.vertices
|
||||
|
||||
# add coordinates
|
||||
count: int = 0
|
||||
for i, pt_count in enumerate(faces):
|
||||
if i != count:
|
||||
continue
|
||||
|
||||
# old encoding
|
||||
if pt_count == 0:
|
||||
pt_count = 3
|
||||
elif pt_count == 1:
|
||||
pt_count = 4
|
||||
coord_counts.append([pt_count])
|
||||
|
||||
for vertex_index in faces[count + 1 : count + 1 + pt_count]:
|
||||
x = vertices[vertex_index * 3]
|
||||
y = vertices[vertex_index * 3 + 1]
|
||||
z = vertices[vertex_index * 3 + 2]
|
||||
coords.append([x, y, z])
|
||||
|
||||
count += pt_count + 1
|
||||
|
||||
def convert_polygon(polygon: "Base", coords, coord_counts):
|
||||
"""Convert GisPolygonGeometry."""
|
||||
|
||||
coord_counts.append([])
|
||||
boundary_count = 0
|
||||
|
||||
for pt in polygon.boundary.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
boundary_count += 1
|
||||
coord_counts[-1].append(boundary_count)
|
||||
|
||||
for void in polygon.voids:
|
||||
void_count = 0
|
||||
for pt_void in void.as_points():
|
||||
coords.append([pt_void.x, pt_void.y, pt_void.z])
|
||||
void_count += 1
|
||||
coord_counts[-1].append(void_count)
|
||||
|
||||
def convert_hatch(hatch: "Base", coords, coord_counts):
|
||||
"""Convert Hatch."""
|
||||
|
||||
coord_counts.append([])
|
||||
boundary_count = 0
|
||||
|
||||
loops: list = hatch["loops"]
|
||||
boundary = None
|
||||
voids = []
|
||||
for loop in loops:
|
||||
print(loop)
|
||||
print(loop.get_member_names())
|
||||
|
||||
if len(loops)==1 or loop["type"] == "Outer":
|
||||
boundary = loop["curve"]
|
||||
else:
|
||||
voids.append(loop["curve"])
|
||||
if boundary is None:
|
||||
return
|
||||
|
||||
# record coordinates
|
||||
convert_icurve(boundary, coords, coord_counts)
|
||||
for void in voids:
|
||||
convert_icurve(void, coords, coord_counts)
|
||||
|
||||
|
||||
def assign_geometry(feature: Dict, f_base) -> Tuple[ List[List[List[float]]], List[List[None| List[int]]] ]:
|
||||
"""Assign geom type and convert object coords into flat lists of coordinates and schema."""
|
||||
|
||||
from specklepy.objects.geometry import Point, Line, Polyline, Curve, Mesh, Brep
|
||||
from specklepy.objects.geometry import Point, Line, Polyline, Arc, Curve, Circle, Polycurve, Mesh, Brep
|
||||
from specklepy.objects.GIS.geometry import GisPolygonGeometry
|
||||
from specklepy.objects.GIS.GisFeature import GisFeature
|
||||
|
||||
geometry = feature["geometry"]
|
||||
coords = []
|
||||
@@ -15,131 +250,132 @@ def assign_geometry(feature: Dict, f_base) -> ( List[List[List[float]]], List[Li
|
||||
|
||||
if isinstance(f_base, Point):
|
||||
geometry["type"] = "MultiPoint"
|
||||
coord_counts.append(None)
|
||||
coord_counts.append(None) # as an indicator of a Multi..type
|
||||
convert_point(f_base, coords, coord_counts)
|
||||
|
||||
coords.append([f_base.x, f_base.y, f_base.z])
|
||||
coord_counts.append([1])
|
||||
elif (isinstance(f_base, Line) or
|
||||
isinstance(f_base, Polyline) or
|
||||
isinstance(f_base, Curve) or
|
||||
isinstance(f_base, Arc) or
|
||||
isinstance(f_base, Circle) or
|
||||
isinstance(f_base, Polycurve)):
|
||||
|
||||
geometry["type"] = "LineString"
|
||||
convert_icurve(f_base, coords, coord_counts)
|
||||
|
||||
elif f_base.speckle_type.endswith(".Hatch"):
|
||||
geometry["type"] = "MultiPolygon"
|
||||
coord_counts.append(None)
|
||||
convert_hatch(f_base, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base, Mesh) or isinstance(f_base, Brep):
|
||||
geometry["type"] = "MultiPolygon"
|
||||
coord_counts.append(None) # as an indicator of a MultiPolygon
|
||||
geometry["type"] = "MultiPolygon"
|
||||
coord_counts.append(None) # as an indicator of a Multi..type
|
||||
convert_mesh_or_brep(f_base, coords, coord_counts)
|
||||
|
||||
faces = []
|
||||
vertices = []
|
||||
if isinstance(f_base, Mesh):
|
||||
faces = f_base.faces
|
||||
vertices = f_base.vertices
|
||||
elif isinstance(f_base, Brep):
|
||||
if f_base.displayValue is None or (
|
||||
isinstance(f_base.displayValue, list)
|
||||
and len(f_base.displayValue) == 0
|
||||
):
|
||||
geometry = {}
|
||||
return
|
||||
elif isinstance(f_base.displayValue, list):
|
||||
faces = f_base.displayValue[0].faces
|
||||
vertices = f_base.displayValue[0].vertices
|
||||
else:
|
||||
faces = f_base.displayValue.faces
|
||||
vertices = f_base.displayValue.vertices
|
||||
|
||||
count: int = 0
|
||||
for i, pt_count in enumerate(faces):
|
||||
if i != count:
|
||||
continue
|
||||
|
||||
# old encoding
|
||||
if pt_count == 0:
|
||||
pt_count = 3
|
||||
elif pt_count == 1:
|
||||
pt_count = 4
|
||||
coord_counts.append([pt_count])
|
||||
|
||||
for vertex_index in faces[count + 1 : count + 1 + pt_count]:
|
||||
x = vertices[vertex_index * 3]
|
||||
y = vertices[vertex_index * 3 + 1]
|
||||
z = vertices[vertex_index * 3 + 2]
|
||||
coords.append([x, y, z])
|
||||
|
||||
count += pt_count + 1
|
||||
|
||||
elif f_base.speckle_type.endswith(".GisFeature") and len(f_base["geometry"]) > 0: # isinstance(f_base, GisFeature) and len(f_base.geometry) > 0:
|
||||
elif f_base.speckle_type.endswith("Feature") and len(f_base["geometry"]) > 0: # isinstance(f_base, GisFeature) and len(f_base.geometry) > 0:
|
||||
# GisFeature doesn't deserialize properly, need to check for speckle_type
|
||||
|
||||
if isinstance(f_base.geometry[0], Point):
|
||||
if isinstance(f_base["geometry"][0], Point):
|
||||
geometry["type"] = "MultiPoint"
|
||||
coord_counts.append(None)
|
||||
coord_counts.append(None) # as an indicator of a Multi..type
|
||||
|
||||
for geom in f_base.geometry:
|
||||
coords.append([geom.x, geom.y, geom.z])
|
||||
coord_counts.append([1])
|
||||
for geom in f_base["geometry"]:
|
||||
convert_point(geom, coords, coord_counts)
|
||||
|
||||
elif isinstance(f_base.geometry[0], Polyline):
|
||||
elif isinstance(f_base["geometry"][0], Polyline):
|
||||
geometry["type"] = "MultiLineString"
|
||||
coord_counts.append(None)
|
||||
|
||||
for geom in f_base.geometry:
|
||||
coord_counts.append([])
|
||||
local_poly_count = 0
|
||||
for geom in f_base["geometry"]:
|
||||
convert_polyline(geom, coords, coord_counts)
|
||||
|
||||
for pt in geom.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
local_poly_count += 1
|
||||
if len(coords)>2 and geom.closed is True and coords[0] != coords[-1]:
|
||||
coords.append(coords[0])
|
||||
local_poly_count += 1
|
||||
|
||||
coord_counts[-1].append(local_poly_count)
|
||||
|
||||
elif isinstance(f_base.geometry[0], GisPolygonGeometry):
|
||||
elif isinstance(f_base["geometry"][0], GisPolygonGeometry):
|
||||
geometry["type"] = "MultiPolygon"
|
||||
coord_counts.append(None)
|
||||
|
||||
for polygon in f_base.geometry:
|
||||
coord_counts.append([])
|
||||
boundary_count = 0
|
||||
for pt in polygon.boundary.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
boundary_count += 1
|
||||
|
||||
coord_counts[-1].append(boundary_count)
|
||||
|
||||
for void in polygon.voids:
|
||||
void_count = 0
|
||||
for pt_void in void.as_points():
|
||||
coords.append([pt_void.x, pt_void.y, pt_void.z])
|
||||
void_count += 1
|
||||
|
||||
coord_counts[-1].append(void_count)
|
||||
|
||||
elif isinstance(f_base, Line):
|
||||
geometry["type"] = "LineString"
|
||||
start = [f_base.start.x, f_base.start.y, f_base.start.z]
|
||||
end = [f_base.end.x, f_base.end.y, f_base.end.z]
|
||||
|
||||
coords.extend([start, end])
|
||||
coord_counts.append([2])
|
||||
|
||||
elif isinstance(f_base, Polyline):
|
||||
geometry["type"] = "LineString"
|
||||
for pt in f_base.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
if len(coords)>2 and f_base.closed is True and coords[0] != coords[-1]:
|
||||
coords.append(coords[0])
|
||||
|
||||
coord_counts.append([len(coords)])
|
||||
|
||||
elif isinstance(f_base, Curve):
|
||||
geometry["type"] = "LineString"
|
||||
for pt in f_base.displayValue.as_points():
|
||||
coords.append([pt.x, pt.y, pt.z])
|
||||
if len(coords)>2 and f_base.displayValue.closed is True and coords[0] != coords[-1]:
|
||||
coords.append(coords[0])
|
||||
|
||||
coord_counts.append([len(coords)])
|
||||
for geom in f_base["geometry"]:
|
||||
convert_polygon(geom, coords, coord_counts)
|
||||
|
||||
else:
|
||||
geometry = {}
|
||||
# print(f"Unsupported geometry type: {f_base.speckle_type}")
|
||||
|
||||
return coords, coord_counts
|
||||
|
||||
|
||||
def getArcRadianAngle(arc: "Arc") -> List[float]:
|
||||
"""Calculate start & end angle, and interval of an Arc."""
|
||||
|
||||
interval = None
|
||||
normal = arc.plane.normal.z
|
||||
angle1, angle2 = getArcAngles(arc)
|
||||
if angle1 is None or angle2 is None:
|
||||
return None
|
||||
interval = abs(angle2 - angle1)
|
||||
|
||||
if (angle1 > angle2 and normal == -1) or (angle2 > angle1 and normal == 1):
|
||||
pass
|
||||
if angle1 > angle2 and normal == 1:
|
||||
interval = abs((2 * math.pi - angle1) + angle2)
|
||||
if angle2 > angle1 and normal == -1:
|
||||
interval = abs((2 * math.pi - angle2) + angle1)
|
||||
return interval, angle1, angle2
|
||||
|
||||
|
||||
def getArcAngles(poly: "Arc") -> Tuple[float | None]:
|
||||
|
||||
if poly.startPoint.x == poly.plane.origin.x:
|
||||
angle1 = math.pi / 2
|
||||
else:
|
||||
angle1 = math.atan(
|
||||
abs(
|
||||
(poly.startPoint.y - poly.plane.origin.y)
|
||||
/ (poly.startPoint.x - poly.plane.origin.x)
|
||||
)
|
||||
) # between 0 and pi/2
|
||||
|
||||
if (
|
||||
poly.plane.origin.x < poly.startPoint.x
|
||||
and poly.plane.origin.y > poly.startPoint.y
|
||||
):
|
||||
angle1 = 2 * math.pi - angle1
|
||||
if (
|
||||
poly.plane.origin.x > poly.startPoint.x
|
||||
and poly.plane.origin.y > poly.startPoint.y
|
||||
):
|
||||
angle1 = math.pi + angle1
|
||||
if (
|
||||
poly.plane.origin.x > poly.startPoint.x
|
||||
and poly.plane.origin.y < poly.startPoint.y
|
||||
):
|
||||
angle1 = math.pi - angle1
|
||||
|
||||
if poly.endPoint.x == poly.plane.origin.x:
|
||||
angle2 = math.pi / 2
|
||||
else:
|
||||
angle2 = math.atan(
|
||||
abs(
|
||||
(poly.endPoint.y - poly.plane.origin.y)
|
||||
/ (poly.endPoint.x - poly.plane.origin.x)
|
||||
)
|
||||
) # between 0 and pi/2
|
||||
|
||||
if (
|
||||
poly.plane.origin.x < poly.endPoint.x
|
||||
and poly.plane.origin.y > poly.endPoint.y
|
||||
):
|
||||
angle2 = 2 * math.pi - angle2
|
||||
if (
|
||||
poly.plane.origin.x > poly.endPoint.x
|
||||
and poly.plane.origin.y > poly.endPoint.y
|
||||
):
|
||||
angle2 = math.pi + angle2
|
||||
if (
|
||||
poly.plane.origin.x > poly.endPoint.x
|
||||
and poly.plane.origin.y < poly.endPoint.y
|
||||
):
|
||||
angle2 = math.pi - angle2
|
||||
|
||||
return angle1, angle2
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ DEFAULT_COLOR = (255 << 24) + (150 << 16) + (150 << 8) + 150
|
||||
def find_display_obj(obj) -> Tuple["Base", "Base"]:
|
||||
"""Get displayable object."""
|
||||
|
||||
from specklepy.objects.geometry import Base, Mesh
|
||||
from specklepy.objects.geometry import Point, Line, Arc, Circle, Curve, Polycurve, Mesh, Brep
|
||||
|
||||
displayVal = obj
|
||||
displayValForColor = obj
|
||||
@@ -52,8 +52,20 @@ def find_display_obj(obj) -> Tuple["Base", "Base"]:
|
||||
|
||||
displayVal = displayValForColor
|
||||
|
||||
# if not searching for colored object, return GisFeatures as is
|
||||
if obj.speckle_type.endswith(".GisFeature"):
|
||||
# keep reading color from GisFeature Meshes
|
||||
if not obj.speckle_type.endswith("Feature"):
|
||||
displayValForColor = obj
|
||||
|
||||
# return known types as is
|
||||
if (obj.speckle_type.endswith("Feature") or
|
||||
isinstance(obj, Point) or
|
||||
isinstance(obj, Line) or
|
||||
isinstance(obj, Arc) or
|
||||
isinstance(obj, Circle) or
|
||||
isinstance(obj, Curve) or
|
||||
isinstance(obj, Polycurve) or
|
||||
isinstance(obj, Mesh) or
|
||||
isinstance(obj, Brep)):
|
||||
displayVal = obj
|
||||
|
||||
return displayVal, displayValForColor
|
||||
@@ -107,14 +119,14 @@ def assign_color(obj_display, props) -> None:
|
||||
color = DEFAULT_COLOR
|
||||
|
||||
try:
|
||||
if hasattr(obj_display, 'renderMaterial'):
|
||||
color = obj_display['renderMaterial']['diffuse']
|
||||
elif hasattr(obj_display, '@renderMaterial'):
|
||||
color = obj_display['@renderMaterial']['diffuse']
|
||||
elif hasattr(obj_display, 'displayStyle'):
|
||||
if hasattr(obj_display, 'displayStyle'):
|
||||
color = obj_display['displayStyle']['color']
|
||||
elif hasattr(obj_display, '@displayStyle'):
|
||||
color = obj_display['@displayStyle']['color']
|
||||
elif hasattr(obj_display, 'renderMaterial'):
|
||||
color = obj_display['renderMaterial']['diffuse']
|
||||
elif hasattr(obj_display, '@renderMaterial'):
|
||||
color = obj_display['@renderMaterial']['diffuse']
|
||||
elif isinstance(obj_display, Mesh) and isinstance(obj_display.colors, List):
|
||||
sameColors = True
|
||||
color1 = obj_display.colors[0]
|
||||
|
||||
Reference in New Issue
Block a user