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