@@ -46,13 +46,16 @@ def __add__(self, other):
4646
4747 for i in other .elements :
4848 new_id = i .mesh_id + max_mesh_id + 1
49- new_elements .append (Element (mesh_id = new_id ,
50- color = copy .deepcopy (i .color ),
51- rotation = copy .deepcopy (i .rotation ),
52- vector = copy .deepcopy (i .vector ),
53- info = i .info .copy (),
54- type = i .type ,
55- guid = i .guid ))
49+ new_element = Element (mesh_id = new_id ,
50+ color = copy .deepcopy (i .color ),
51+ rotation = copy .deepcopy (i .rotation ),
52+ vector = copy .deepcopy (i .vector ),
53+ info = i .info .copy (),
54+ type = i .type ,
55+ guid = i .guid )
56+ if i .check_if_has_face_colors ():
57+ new_element .face_colors = copy .deepcopy (i .face_colors )
58+ new_elements .append (new_element )
5659
5760 return File (schema_version = new_schema_version ,
5861 info = new_file_info ,
@@ -74,7 +77,7 @@ def create_plotly_figure(self):
7477 geometries = []
7578 for i in self .elements :
7679 mesh = next ((x for x in self .meshes if x .mesh_id == i .mesh_id ), None )
77- geometries .append ( self . __convert_dotbim_mesh_to_plotly ( mesh_to_convert = mesh , element = i ))
80+ geometries .extend ( mesh . convert_to_plotly_meshes_with_face_colors ( element = i ))
7881
7982 layout = go .Layout (scene = dict (aspectmode = 'data' ))
8083 figure = go .Figure (data = [], layout = layout )
@@ -94,47 +97,6 @@ def read(path):
9497
9598 return file
9699
97- @staticmethod
98- def __convert_dotbim_mesh_to_plotly (mesh_to_convert , element ):
99- color_hex = '#%02x%02x%02x' % (element .color .r , element .color .g , element .color .b )
100- opacity = element .color .a / 255
101-
102- x = []
103- y = []
104- z = []
105- counter = 0
106- while counter < len (mesh_to_convert .coordinates ):
107- point = np .array ([
108- mesh_to_convert .coordinates [counter ],
109- mesh_to_convert .coordinates [counter + 1 ],
110- mesh_to_convert .coordinates [counter + 2 ]])
111-
112- rotation = pyquaternion .Quaternion (
113- a = element .rotation .qw ,
114- b = element .rotation .qx ,
115- c = element .rotation .qy ,
116- d = element .rotation .qz )
117-
118- point_rotated = rotation .rotate (point )
119-
120- x .append (point_rotated [0 ] + element .vector .x )
121- y .append (point_rotated [1 ] + element .vector .y )
122- z .append (point_rotated [2 ] + element .vector .z )
123- counter += 3
124-
125- i = []
126- j = []
127- k = []
128- counter = 0
129- while counter < len (mesh_to_convert .indices ):
130- i .append (mesh_to_convert .indices [counter ])
131- j .append (mesh_to_convert .indices [counter + 1 ])
132- k .append (mesh_to_convert .indices [counter + 2 ])
133- counter += 3
134-
135- return go .Mesh3d (x = x , y = y , z = z , i = i , j = j , k = k , color = color_hex , opacity = opacity , name = element .type ,
136- showscale = True )
137-
138100 @staticmethod
139101 def __convert_JSON_to_file (json_dictionary ):
140102
@@ -153,7 +115,7 @@ def __convert_JSON_to_file(json_dictionary):
153115
154116 created_elements = []
155117 for i in elements :
156- created_elements . append ( Element (
118+ new_element = Element (
157119 mesh_id = i ["mesh_id" ],
158120 vector = Vector (x = i ["vector" ]["x" ],
159121 y = i ["vector" ]["y" ],
@@ -169,22 +131,32 @@ def __convert_JSON_to_file(json_dictionary):
169131 a = i ["color" ]["a" ]),
170132 type = i ["type" ],
171133 guid = i ["guid" ]
172- ))
134+ )
135+ try :
136+ new_element .face_colors = i ["face_colors" ]
137+ except KeyError as e :
138+ if str (e ) == "'face_colors'" :
139+ pass
140+ else :
141+ raise
142+ created_elements .append (new_element )
173143
174144 file = File (schema_version = schema_version , meshes = created_meshes , elements = created_elements , info = created_info )
175145
176146 return file
177147
178148
179149class Element :
180- def __init__ (self , mesh_id , vector , rotation , guid , type , color , info ):
150+ def __init__ (self , mesh_id , vector , rotation , guid , type , color , info , face_colors = None ):
181151 self .info = info
182152 self .color = color
183153 self .guid = guid
184154 self .rotation = rotation
185155 self .vector = vector
186156 self .type = type
187157 self .mesh_id = mesh_id
158+ if face_colors is not None :
159+ self .face_colors = face_colors
188160
189161 def __eq__ (self , other ):
190162 if not isinstance (other , Element ):
@@ -196,7 +168,8 @@ def __eq__(self, other):
196168 and self .rotation == other .rotation \
197169 and self .vector == other .vector \
198170 and self .type == other .type \
199- and self .mesh_id == other .mesh_id
171+ and self .mesh_id == other .mesh_id \
172+ and Element .__check_if_both_elements_have_the_same_face_colors (self , other )
200173
201174 def equals_without_mesh_id (self , other ):
202175 if not isinstance (other , Element ):
@@ -207,7 +180,27 @@ def equals_without_mesh_id(self, other):
207180 and self .guid == other .guid \
208181 and self .rotation == other .rotation \
209182 and self .vector == other .vector \
210- and self .type == other .type
183+ and self .type == other .type \
184+ and Element .__check_if_both_elements_have_the_same_face_colors (self , other )
185+
186+ def check_if_has_face_colors (self ):
187+ try :
188+ self .face_colors
189+ except AttributeError as e :
190+ if str (e ) == "'Element' object has no attribute 'face_colors'" :
191+ return False
192+ else :
193+ raise
194+ return True
195+
196+ @staticmethod
197+ def __check_if_both_elements_have_the_same_face_colors (first_element , second_element ):
198+ if first_element .check_if_has_face_colors () and second_element .check_if_has_face_colors ():
199+ return first_element .face_colors == second_element .face_colors
200+ if not first_element .check_if_has_face_colors () and not second_element .check_if_has_face_colors ():
201+ return True
202+ else :
203+ return False
211204
212205
213206class Color :
@@ -242,6 +235,82 @@ def equals_without_mesh_id(self, other):
242235
243236 return self .coordinates == other .coordinates and self .indices == other .indices
244237
238+ def __convert_to_plotly (self , element ):
239+ color_hex = '#%02x%02x%02x' % (element .color .r , element .color .g , element .color .b )
240+ opacity = element .color .a / 255
241+
242+ x , y , z = self .__repack_mesh_vertices_to_xyz_lists (element )
243+ i , j , k = self .__repack_mesh_indices_to_ijk_lists ()
244+
245+ return go .Mesh3d (x = x , y = y , z = z , i = i , j = j , k = k , color = color_hex , opacity = opacity , name = element .type ,
246+ showscale = True )
247+
248+ def convert_to_plotly_meshes_with_face_colors (self , element ):
249+ if not Element .check_if_has_face_colors (element ):
250+ return [self .__convert_to_plotly (element )]
251+ else :
252+ plotly_meshes = []
253+ face_colors_counter = 0
254+ indices_counter = 0
255+ while face_colors_counter < len (element .face_colors ):
256+ color_hex = '#%02x%02x%02x' % (element .face_colors [face_colors_counter ],
257+ element .face_colors [face_colors_counter + 1 ],
258+ element .face_colors [face_colors_counter + 2 ])
259+ opacity = element .face_colors [face_colors_counter + 3 ] / 255
260+
261+ i = [self .indices [indices_counter ]]
262+ j = [self .indices [indices_counter + 1 ]]
263+ k = [self .indices [indices_counter + 2 ]]
264+ x , y , z = self .__repack_mesh_vertices_to_xyz_lists (element )
265+
266+ plotly_meshes .append (go .Mesh3d (x = x , y = y , z = z , i = i , j = j , k = k , color = color_hex , opacity = opacity ,
267+ name = element .type , showscale = True ))
268+
269+ face_colors_counter += 4
270+ indices_counter += 3
271+
272+ return plotly_meshes
273+
274+ def __repack_mesh_indices_to_ijk_lists (self ):
275+ i = []
276+ j = []
277+ k = []
278+ counter = 0
279+ while counter < len (self .indices ):
280+ i .append (self .indices [counter ])
281+ j .append (self .indices [counter + 1 ])
282+ k .append (self .indices [counter + 2 ])
283+ counter += 3
284+
285+ return i , j , k
286+
287+ def __repack_mesh_vertices_to_xyz_lists (self , element ):
288+
289+ x = []
290+ y = []
291+ z = []
292+ counter = 0
293+ while counter < len (self .coordinates ):
294+ point = np .array ([
295+ self .coordinates [counter ],
296+ self .coordinates [counter + 1 ],
297+ self .coordinates [counter + 2 ]])
298+
299+ rotation = pyquaternion .Quaternion (
300+ a = element .rotation .qw ,
301+ b = element .rotation .qx ,
302+ c = element .rotation .qy ,
303+ d = element .rotation .qz )
304+
305+ point_rotated = rotation .rotate (point )
306+
307+ x .append (point_rotated [0 ] + element .vector .x )
308+ y .append (point_rotated [1 ] + element .vector .y )
309+ z .append (point_rotated [2 ] + element .vector .z )
310+ counter += 3
311+
312+ return x , y , z
313+
245314
246315class Rotation :
247316 def __init__ (self , qx , qy , qz , qw ):
0 commit comments