#!/usr/bin/env python # coding: utf-8 # In[115]: import os from OCC.Core.IFSelect import IFSelect_RetDone from OCC.Core.STEPCAFControl import STEPCAFControl_Reader from OCC.Core.TCollection import TCollection_ExtendedString from OCC.Core.TDocStd import TDocStd_Document from OCC.Core.VrmlAPI import VrmlAPI_Writer from OCC.Core.VrmlData import VrmlData_WorldInfo from OCC.Core.XCAFDoc import XCAFDoc_ShapeTool, XCAFDoc_DocumentTool, XCAFDoc_DocumentTool_ShapeTool from OCC.Core.XCAFApp import XCAFApp_Application_GetApplication from OCC.Core.XCAFDoc import XCAFDoc_DocumentTool_ShapeTool, xcafdoc from OCC.Core.BRep import BRep_Tool from OCC.Core.TDF import TDF_LabelSequence, TDF_Label, TDF_ChildIterator, TDF_AttributeIterator, TDF_Tool, TDF_AttributeMap, TDF_Attribute, TDF_ChildIDIterator from OCC.Core.TCollection import TCollection_AsciiString from OCC.Core.TDataStd import TDataStd_TreeNode from OCC.Core.Standard import Standard_GUID #, Standard_Handle #from OCC.Core.Standard import Standard_Real from OCC.Core.TNaming import TNaming_UsedShapes from OCC.Extend.TopologyUtils import TopologyExplorer from OCC.Extend.TopologyUtils import is_edge, is_wire, discretize_edge, discretize_wire from OCC.Extend.DataExchange import read_step_file_with_names_colors, read_step_file from OCC.Display.WebGl.x3dom_renderer import X3DExporter, X3DomRenderer from OCC.Core.Tesselator import ShapeTesselator from OCC.Core.TopAbs import topabs from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh from OCC.Core.gp import gp_XYZ, gp_Vec import xml.etree.ElementTree as ET from IPython.display import HTML import x3d.x3d as XX3D import re # In[162]: #stp_filename = 'VentilatorAP203' #'as1_pe_203' stp_filename = 'as1-oc-214' #stp_filename = 'as1_pe_203' #stp_filename = 'screw' stp_path = os.path.join('assets', stp_filename + '.stp') # load the STEP file doc = TDocStd_Document(TCollection_ExtendedString("pythonocc-doc")) step_reader = STEPCAFControl_Reader() step_reader.SetColorMode(True) step_reader.SetLayerMode(True) step_reader.SetNameMode(True) step_reader.SetMatMode(True) step_reader.SetGDTMode(True) status = step_reader.ReadFile(stp_path) if status == IFSelect_RetDone: step_reader.Transfer(doc) else: raise IOError("STEP file could not be read.") # In[163]: doc # In[176]: ##Copyright 2018 Thomas Paviot (tpaviot@gmail.com) ##(C) 2020 Andreas Plesch ## ##This file is part of pythonOCC. ## ##pythonOCC is free software: you can redistribute it and/or modify ##it under the terms of the GNU Lesser General Public License as published by ##the Free Software Foundation, either version 3 of the License, or ##(at your option) any later version. ## ##pythonOCC is distributed in the hope that it will be useful, ##but WITHOUT ANY WARRANTY; without even the implied warranty of ##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ##GNU Lesser General Public License for more details. ## ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see . import os from OCC.Core.TopoDS import TopoDS_Shape from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh from OCC.Core.StlAPI import stlapi_Read, StlAPI_Writer from OCC.Core.BRep import BRep_Builder from OCC.Core.gp import gp_Pnt, gp_Dir, gp_Pnt2d from OCC.Core.Bnd import Bnd_Box2d from OCC.Core.TopoDS import TopoDS_Compound from OCC.Core.IGESControl import IGESControl_Reader, IGESControl_Writer from OCC.Core.STEPControl import STEPControl_Reader, STEPControl_Writer, STEPControl_AsIs from OCC.Core.Interface import Interface_Static_SetCVal from OCC.Core.IFSelect import IFSelect_RetDone, IFSelect_ItemsByEntity from OCC.Core.TDocStd import TDocStd_Document from OCC.Core.XCAFDoc import (XCAFDoc_DocumentTool_ShapeTool, XCAFDoc_DocumentTool_ColorTool) from OCC.Core.STEPCAFControl import STEPCAFControl_Reader from OCC.Core.TDF import TDF_LabelSequence, TDF_Label from OCC.Core.TCollection import TCollection_ExtendedString from OCC.Core.Quantity import Quantity_Color, Quantity_TOC_RGB from OCC.Core.TopLoc import TopLoc_Location from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform from OCC.Extend.TopologyUtils import (discretize_edge, get_sorted_hlr_edges, list_of_shapes_to_compound) try: import svgwrite HAVE_SVGWRITE = True except ImportError: HAVE_SVGWRITE = False def read_document_with_names_colors(doc): """ Returns list of tuples (topods_shape, label, color) Use OCAF. """ output_shapes = {} scene = [] visited = {} DEFset = set() x3dscene = XX3D.Scene(children=[]) x3d_doc = XX3D.X3D(Scene = x3dscene) # Get root assembly shape_tool = XCAFDoc_DocumentTool_ShapeTool(doc.Main()) color_tool = XCAFDoc_DocumentTool_ColorTool(doc.Main()) locs = [] def _get_sub_shapes(lab, loc, parent, x3dgroup): name = lab.GetLabelName() labelString = lab.EntryDumpToString() if labelString in visited: return visited[labelString] = lab if shape_tool.IsAssembly(lab): node = { 'node' : 'Group', 'DEF' : labelString, 'name' : name, 'children' : [] } x3dnode = XX3D.Group(DEF = node['DEF'], class_ = node['name'], children = []) #print('assembly group:', x3dnode.XML()) l_c = TDF_LabelSequence() shape_tool.GetComponents(lab, l_c) for i in range(l_c.Length()): label = l_c.Value(i + 1) print("Group Name DEF :", name, labelString) if shape_tool.IsReference(label): print("######## component label :", label.GetLabelName() ) loc = shape_tool.GetLocation(label) print(" Transform loc DEF :", loc.HashCode(100)) trafo = { 'node' : 'Transform', 'DEF' : label.EntryDumpToString(), 'name' : 'reference location', 'transform' : loc, 'children': [] } x3dtransform = XX3D.Transform(DEF = trafo['DEF'], class_ = trafo['name'], children = []) _x3dapplyLocation(x3dtransform, loc) #print('locator transform:', x3dtransform.XML()) locs.append(loc) print("loc chain depth :", len(locs)) label_reference = TDF_Label() shape_tool.GetReferredShape(label, label_reference) print("######## Transform USE to DEF ==> referenced label :", label_reference.GetLabelName() ) reference_entry = label_reference.EntryDumpToString() if reference_entry not in DEFset: DEFset.add(reference_entry) _get_sub_shapes(label_reference, loc, trafo['children'], x3dtransform.children) else: reference = { 'node' : 'Transform', 'USE' : reference_entry, 'refname' : label_reference.GetLabelName() } trafo['children'].append(reference) x3dtransform.children.append(XX3D.Transform(USE = reference['USE'], class_ = reference['refname'])) locs.pop() node['children'].append(trafo) x3dnode.children.append(x3dtransform) #print("added child: ", x3dnode.XML()) elif shape_tool.IsSimpleShape(lab): print("Transform DEF Shape Name :", name, labelString ) shape = shape_tool.GetShape(lab) #print(" all ass locs :", locs) # loc = TopLoc_Location() # for l in locs: # loc = loc.Multiplied(l) c = _set_color(lab, shape) n = c.Name(c.Red(), c.Green(), c.Blue()) print(' instance color Name & RGB: ', n, c.Red(), c.Green(), c.Blue()) labloc = shape_tool.GetLocation(lab) print(" Shape Transform: ", labloc.HashCode(100)) #shape_disp = BRepBuilderAPI_Transform(shape, loc.Transformation()).Shape() #shape_disp = shape #if not shape_disp in output_shapes: # output_shapes[shape_disp] = [lab.GetLabelName(), c] ##subshapes l_subss = TDF_LabelSequence() shape_tool.GetSubShapes(lab, l_subss) #node = {} if (l_subss.Length() == 0 and labloc.IsIdentity()): # does not need transform node = { 'node' : 'Shape', 'DEF' : labelString, 'shape' : lab, 'name' : name + '-shape', 'color' : f"{c.Red()} {c.Green()} {c.Blue()}" } x3dnode = XX3D.Shape( DEF = node['DEF'], geometry = _x3dgeofromTShape(node['shape']), appearance = _x3dappfromColor(c), class_ = node['name'] ) else: # needs grouping or has transform node = { 'node' : 'Transform', 'DEF' : labelString, 'transform' : labloc, 'transformhash' : labloc.HashCode(100), 'name' : name, 'children' : [] } shapenode = { 'node' : 'Shape', 'shape' : lab, 'name' : name + '-shape', 'color' : f"{c.Red()} {c.Green()} {c.Blue()}" } node['children'].append(shapenode) x3dnode = XX3D.Transform(DEF = node['DEF'], class_ = node['name'], children = []) _x3dapplyLocation(x3dnode, labloc) x3dshape = XX3D.Shape ( geometry = _x3dgeofromTShape(shapenode['shape']), appearance = _x3dappfromColor(c), class_ = shapenode['name'] ) x3dnode.children.append(x3dshape) for i in range(l_subss.Length()): lab_subs = l_subss.Value(i+1) print("######## Transform DEF simpleshape subshape label :", lab.GetLabelName()) shape_sub = shape_tool.GetShape(lab_subs) c = _set_color(lab_subs, shape_sub) n = c.Name(c.Red(), c.Green(), c.Blue()) print(' shape color Name & RGB: ', n, c.Red(), c.Green(), c.Blue()) subloc = shape_tool.GetLocation(lab_subs) print(" subshape Transform: ", subloc.HashCode(100)) shapenode = { 'node' : 'SubShape', 'shape' : lab_subs, 'DEF' : lab_subs.EntryDumpToString(), 'name' : lab_subs.GetLabelName()+'-subshape', 'color' : f"{c.Red()} {c.Green()} {c.Blue()}", 'trafo' : subloc } node['children'].append(shapenode) x3dshape = XX3D.Shape ( DEF = shapenode['DEF'], class_ = shapenode['name'], geometry = _x3dgeofromTShape(shapenode['shape']), appearance = _x3dappfromColor(c) ) x3dnode.children.append(x3dshape) #shape_to_disp = BRepBuilderAPI_Transform(shape_sub, loc.Transformation()).Shape() #shape_to_disp = shape_sub # position the subshape to display #if not shape_to_disp in output_shapes: # output_shapes[shape_to_disp] = [lab_subs.GetLabelName(), c] parent.append(node) #print(x3dgroup.XML()) x3dgroup.append(x3dnode) #print(x3dscene.XML()) #print(x3dgroup.XML()) def _x3dapplyLocation(x3dtransformnode, location): # get translation and rotation from location transformation = location.Transformation() rot_axis = gp_XYZ() #rot_angle = 0.0 success, rot_angle = transformation.GetRotation(rot_axis)#.GetVectorAndAngle(rot_axis, rot_angle) translation = transformation.TranslationPart() scale_factor = transformation.ScaleFactor() x3dtransformnode.rotation = (rot_axis.X(), rot_axis.Y(), rot_axis.Z(), rot_angle) x3dtransformnode.translation = (translation.X(), translation.Y(), translation.Z()) x3dtransformnode.scale = (scale_factor, scale_factor, scale_factor) return def _x3dgeofromTShape(label): shape = shape_tool.GetShape(label) tesselator = ShapeTesselator(shape) tesselator.Compute( compute_edges=False, mesh_quality=1, parallel=True) x3dstring = tesselator.ExportShapeToX3DIndexedFaceSet()#x3dexp._triangle_sets[0] # there should be just one element = ET.XML(x3dstring) geo = XX3D.Box() if (element.tag == 'TriangleSet'): coordele = list(element.iter('Coordinate'))[0] normalele = list(element.iter('Normal'))[0] coord = XX3D.Coordinate(point = _MFVec3ffromString(coordele.attrib['point'])) normal = XX3D.Normal(vector = _MFVec3ffromString(normalele.attrib['vector'])) geo = XX3D.TriangleSet(coord = coord, normal=normal, solid=False) # get tesselated triangleset or lineset return geo def _MFVec3ffromString(sepString): mflist = sepString.split() mf = [] for i in range(len(mflist)): if (i % 3 == 2): mf.append((float(mflist[i-2]), float(mflist[i-1]), float(mflist[i]))) return mf def _x3dappfromColor(c): x3dmat = XX3D.Material(diffuseColor = (c.Red(),c.Green(),c.Blue())) return XX3D.Appearance(material = x3dmat) def _set_color(lab, shape): c = Quantity_Color(0.5, 0.5, 0.5, Quantity_TOC_RGB) # default color colorSet = False if (color_tool.GetInstanceColor(shape, 0, c) or color_tool.GetInstanceColor(shape, 1, c) or color_tool.GetInstanceColor(shape, 2, c)): colorSet = True if not colorSet: if (color_tool.GetColor(lab, 0, c) or color_tool.GetColor(lab, 1, c) or color_tool.GetColor(lab, 2, c)): colorSet = True if colorSet: color_tool.SetInstanceColor(shape, 0, c) color_tool.SetInstanceColor(shape, 1, c) color_tool.SetInstanceColor(shape, 2, c) return c def _get_shapes(): labels = TDF_LabelSequence() shape_tool.GetFreeShapes(labels) #global cnt #cnt += 1 print() print("Number of shapes at root :", labels.Length()) print() for i in range(labels.Length()): root_item = labels.Value(i+1) _get_sub_shapes(root_item, None, scene, x3dscene.children) _get_shapes() print('DONE') return { 'scene' : scene, 'x3d_doc' : x3d_doc } # In[ ]: ascene=read_document_with_names_colors(doc) ascene['scene'] # In[178]: print(ascene['x3d_doc'].Scene.XML()) # In[179]: x3domHEAD = ''' ''' # In[180]: x3dele = list(ET.XML(ascene['x3d_doc'].XML()).iter('X3D'))[0] x3dHTML = ET.tostring(x3dele, encoding="unicode", short_empty_elements=False) # In[181]: HTML(x3domHEAD + x3dHTML) # In[ ]: