From 712e0a06e6d1fd9510f444723c49052b8b51c177 Mon Sep 17 00:00:00 2001 From: Chaser Huang Date: Mon, 7 Oct 2024 21:21:51 -0400 Subject: [PATCH] support bd cad objects with color tagged --- yacv_server/cad.py | 13 ++++++++++++- yacv_server/tessellate.py | 15 ++++++++++----- yacv_server/yacv.py | 10 +++++++--- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/yacv_server/cad.py b/yacv_server/cad.py index 3a6a23b..d5bb972 100644 --- a/yacv_server/cad.py +++ b/yacv_server/cad.py @@ -10,12 +10,23 @@ from OCP.TopExp import TopExp from OCP.TopLoc import TopLoc_Location from OCP.TopTools import TopTools_IndexedMapOfShape from OCP.TopoDS import TopoDS_Shape -from build123d import Compound, Shape +from build123d import Compound, Shape, Color from yacv_server.gltf import GLTFMgr CADCoreLike = Union[TopoDS_Shape, TopLoc_Location] # Faces, Edges, Vertices and Locations for now CADLike = Union[CADCoreLike, any] # build123d and cadquery types +ColorTuple = Tuple[float, float, float, float] + +def get_color(obj: CADLike) -> Optional[ColorTuple]: + """Get color from a CAD Object""" + + if 'color' in dir(obj): + if isinstance(obj.color, tuple): + return obj.color + if isinstance(obj.color, Color): + return obj.color.to_tuple() + return None def get_shape(obj: CADLike, error: bool = True) -> Optional[CADCoreLike]: diff --git a/yacv_server/tessellate.py b/yacv_server/tessellate.py index 03ffe23..b4d1b47 100644 --- a/yacv_server/tessellate.py +++ b/yacv_server/tessellate.py @@ -1,4 +1,4 @@ -from typing import List, Dict, Tuple +from typing import List, Dict, Tuple, Optional from OCP.BRep import BRep_Tool from OCP.BRepAdaptor import BRepAdaptor_Curve @@ -8,7 +8,7 @@ from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex from build123d import Shape, Vertex, Face, Location from pygltflib import GLTF2 -from yacv_server.cad import CADCoreLike +from yacv_server.cad import CADCoreLike, ColorTuple from yacv_server.gltf import GLTFMgr from yacv_server.mylogger import logger @@ -20,6 +20,7 @@ def tessellate( faces: bool = True, edges: bool = True, vertices: bool = True, + obj_color: Optional[ColorTuple] = None, ) -> GLTF2: """Tessellate a whole shape into a list of triangle vertices and a list of triangle indices.""" mgr = GLTFMgr() @@ -35,7 +36,7 @@ def tessellate( vertex_to_faces: Dict[str, List[TopoDS_Face]] = {} if faces: for face in shape.faces(): - _tessellate_face(mgr, face.wrapped, tolerance, angular_tolerance) + _tessellate_face(mgr, face.wrapped, tolerance, angular_tolerance, color) if edges: for edge in face.edges(): edge_to_faces[edge.wrapped] = edge_to_faces.get(edge.wrapped, []) + [face.wrapped] @@ -57,7 +58,8 @@ def _tessellate_face( mgr: GLTFMgr, ocp_face: TopoDS_Face, tolerance: float = 1e-3, - angular_tolerance: float = 0.1 + angular_tolerance: float = 0.1, + color: Optional[ColorTuple] = None, ): face = Shape(ocp_face) # face.mesh(tolerance, angular_tolerance) @@ -75,7 +77,10 @@ def _tessellate_face( vertices = tri_mesh[0] indices = tri_mesh[1] - mgr.add_face(vertices, indices, uv) + if color is None: + mgr.add_face(vertices, indices, uv) + else: + mgr.add_face(vertices, indices, uv, color) def _push_point(v: Tuple[float, float, float], faces: List[TopoDS_Face]) -> Tuple[float, float, float]: diff --git a/yacv_server/yacv.py b/yacv_server/yacv.py index deba145..022ab49 100644 --- a/yacv_server/yacv.py +++ b/yacv_server/yacv.py @@ -24,7 +24,7 @@ from yacv_server.mylogger import logger from yacv_server.pubsub import BufferedPubSub from yacv_server.rwlock import RWLock from yacv_server.tessellate import tessellate -from yacv_server.cad import _hashcode +from yacv_server.cad import _hashcode, ColorTuple, get_color @dataclass_json @@ -49,11 +49,13 @@ class UpdatesApiFullData(UpdatesApiData): """The show_object options, if any (not serialized)""" def __init__(self, obj: YACVSupported, name: str, _hash: str, is_remove: Optional[bool] = False, + color: Optional[ColorTuple] = None, kwargs: Optional[Dict[str, any]] = None): self.name = name self.hash = _hash self.is_remove = is_remove self.obj = obj + self.color = color self.kwargs = kwargs def to_json(self) -> str: @@ -185,10 +187,11 @@ class YACV: # Publish the show event for obj, name in zip(objs, names): + color = get_color(obj) if not isinstance(obj, bytes): obj = _preprocess_cad(obj, **kwargs) _hash = _hashcode(obj, **kwargs) - event = UpdatesApiFullData(name=name, _hash=_hash, obj=obj, kwargs=kwargs or {}) + event = UpdatesApiFullData(name=name, _hash=_hash, obj=obj, color=color, kwargs=kwargs or {}) self.show_events.publish(event) logger.info('show %s took %.3f seconds', names, time.time() - start) @@ -277,7 +280,8 @@ class YACV: angular_tolerance=event.kwargs.get('angular_tolerance', 0.1), faces=event.kwargs.get('faces', True), edges=event.kwargs.get('edges', True), - vertices=event.kwargs.get('vertices', True)) + vertices=event.kwargs.get('vertices', True), + obj_color=event.color) glb_list_of_bytes = gltf.save_to_bytes() glb_bytes = b''.join(glb_list_of_bytes) publish_to.publish(glb_bytes)