1 Star 0 Fork 1

kaohui/occ_example

forked from loujiand/occ_example 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
assemble.py 23.32 KB
一键复制 编辑 原始数据 按行查看 历史
loujosh 提交于 2021-07-09 01:11 . Add files via upload
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
##Copyright 2018 Thomas Paviot ([email protected])
##
##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 <http://www.gnu.org/licenses/>.
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)
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox
from OCC.Display.OCCViewer import rgb_color
from OCC.Display.SimpleGui import init_display
try:
import svgwrite
HAVE_SVGWRITE = True
except ImportError:
HAVE_SVGWRITE = False
##########################
# Step import and export #
##########################
def read_step_file(filename, as_compound=True, verbosity=True):
""" read the STEP file and returns a compound
filename: the file path
verbosity: optional, False by default.
as_compound: True by default. If there are more than one shape at root,
gather all shapes into one compound. Otherwise returns a list of shapes.
"""
if not os.path.isfile(filename):
raise FileNotFoundError("%s not found." % filename)
step_reader = STEPControl_Reader()
status = step_reader.ReadFile(filename)
if status == IFSelect_RetDone: # check status
if verbosity:
failsonly = False
step_reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity)
step_reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity)
transfer_result = step_reader.TransferRoots()
if not transfer_result:
raise AssertionError("Transfer failed.")
_nbs = step_reader.NbShapes()
if _nbs == 0:
raise AssertionError("No shape to transfer.")
elif _nbs == 1: # most cases
return step_reader.Shape(1)
elif _nbs > 1:
print("Number of shapes:", _nbs)
shps = []
# loop over root shapes
for k in range(1, _nbs + 1):
new_shp = step_reader.Shape(k)
if not new_shp.IsNull():
shps.append(new_shp)
if as_compound:
compound, result = list_of_shapes_to_compound(shps)
if not result:
print("Warning: all shapes were not added to the compound")
return compound
else:
print("Warning, returns a list of shapes.")
return shps
else:
raise AssertionError("Error: can't read file.")
return None
def write_step_file(a_shape, filename, application_protocol="AP203"):
""" exports a shape to a STEP file
a_shape: the topods_shape to export (a compound, a solid etc.)
filename: the filename
application protocol: "AP203" or "AP214IS" or "AP242DIS"
"""
# a few checks
if a_shape.IsNull():
raise AssertionError("Shape %s is null." % a_shape)
if application_protocol not in ["AP203", "AP214IS", "AP242DIS"]:
raise AssertionError("application_protocol must be either AP203 or AP214IS. You passed %s." % application_protocol)
if os.path.isfile(filename):
print("Warning: %s file already exists and will be replaced" % filename)
# creates and initialise the step exporter
step_writer = STEPControl_Writer()
Interface_Static_SetCVal("write.step.schema", application_protocol)
# transfer shapes and write file
step_writer.Transfer(a_shape, STEPControl_AsIs)
status = step_writer.Write(filename)
if not status == IFSelect_RetDone:
raise IOError("Error while writing shape to STEP file.")
if not os.path.isfile(filename):
raise IOError("File %s was not saved to filesystem." % filename)
def read_step_file_with_names_colors(filename):
""" Returns list of tuples (topods_shape, label, color)
Use OCAF.
"""
assemble_relation_list=[]
if not os.path.isfile(filename):
raise FileNotFoundError("%s not found." % filename)
# the list:
output_shapes = {}
# create an handle to a document
doc = TDocStd_Document(TCollection_ExtendedString("pythonocc-doc"))
# Get root assembly
shape_tool = XCAFDoc_DocumentTool_ShapeTool(doc.Main())
color_tool = XCAFDoc_DocumentTool_ColorTool(doc.Main())
#layer_tool = XCAFDoc_DocumentTool_LayerTool(doc.Main())
#mat_tool = XCAFDoc_DocumentTool_MaterialTool(doc.Main())
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(filename)
if status == IFSelect_RetDone:
step_reader.Transfer(doc)
locs = []
def _get_sub_shapes(lab, loc):
#global cnt, lvl
#cnt += 1
#print("\n[%d] level %d, handling LABEL %s\n" % (cnt, lvl, _get_label_name(lab)))
#print()
#print(lab.DumpToString())
#print()
#print("Is Assembly :", shape_tool.IsAssembly(lab))
#print("Is Free :", shape_tool.IsFree(lab))
#print("Is Shape :", shape_tool.IsShape(lab))
#print("Is Compound :", shape_tool.IsCompound(lab))
#print("Is Component :", shape_tool.IsComponent(lab))
#print("Is SimpleShape :", shape_tool.IsSimpleShape(lab))
#print("Is Reference :", shape_tool.IsReference(lab))
#users = TDF_LabelSequence()
#users_cnt = shape_tool.GetUsers(lab, users)
#print("Nr Users :", users_cnt)
#shape_tool.
l_subss = TDF_LabelSequence()
shape_tool.GetSubShapes(lab, l_subss)
#print("Nb subshapes :", l_subss.Length())
l_comps = TDF_LabelSequence()
shape_tool.GetComponents(lab, l_comps)
#print("Nb components :", l_comps.Length())
#print()
name = lab.GetLabelName()
dict_1={"name":name,"isassemble":shape_tool.IsAssembly(lab),"components number":l_comps.Length()}
assemble_relation_list.append(dict_1)
#print("Name :", name)
if shape_tool.IsAssembly(lab):
l_c = TDF_LabelSequence()
shape_tool.GetComponents(lab, l_c)
for i in range(l_c.Length()):
print("loc",i)
label = l_c.Value(i+1)
if shape_tool.IsReference(label):
#print("\n######## reference label :", label)
label_reference = TDF_Label()
shape_tool.GetReferredShape(label, label_reference)
loc = shape_tool.GetLocation(label)
#print(" loc :", loc)
#trans = loc.Transformation()
#print(" tran form :", trans.Form())
#rot = trans.GetRotation()
#print(" rotation :", rot)
#print(" X :", rot.X())
#print(" Y :", rot.Y())
#print(" Z :", rot.Z())
#print(" W :", rot.W())
#tran = trans.TranslationPart()
#print(" translation :", tran)
#print(" X :", tran.X())
#print(" Y :", tran.Y())
#print(" Z :", tran.Z())
locs.append(loc)
#print(">>>>")
#lvl += 1
_get_sub_shapes(label_reference, loc)
#lvl -= 1
#print("<<<<")
locs.pop()
elif shape_tool.IsSimpleShape(lab):
#print("\n######## simpleshape label :", lab)
shape = shape_tool.GetShape(lab)
#print(" all ass locs :", locs)
loc = TopLoc_Location()
for l in locs:
#print(" take loc :", l)
loc = loc.Multiplied(l)
#trans = loc.Transformation()
#print(" FINAL loc :")
#print(" tran form :", trans.Form())
#rot = trans.GetRotation()
#print(" rotation :", rot)
#print(" X :", rot.X())
#print(" Y :", rot.Y())
#print(" Z :", rot.Z())
#print(" W :", rot.W())
#tran = trans.TranslationPart()
#print(" translation :", tran)
#print(" X :", tran.X())
#print(" Y :", tran.Y())
#print(" Z :", tran.Z())
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)):
color_tool.SetInstanceColor(shape, 0, c)
color_tool.SetInstanceColor(shape, 1, c)
color_tool.SetInstanceColor(shape, 2, c)
colorSet = True
n = c.Name(c.Red(), c.Green(), c.Blue())
#print(' instance color Name & RGB: ', c, n, c.Red(), c.Green(), c.Blue())
if not colorSet:
if (color_tool.GetColor(lab, 0, c) or
color_tool.GetColor(lab, 1, c) or
color_tool.GetColor(lab, 2, c)):
color_tool.SetInstanceColor(shape, 0, c)
color_tool.SetInstanceColor(shape, 1, c)
color_tool.SetInstanceColor(shape, 2, c)
n = c.Name(c.Red(), c.Green(), c.Blue())
#print(' shape color Name & RGB: ', c, n, c.Red(), c.Green(), c.Blue())
shape_disp = BRepBuilderAPI_Transform(shape, loc.Transformation()).Shape()
if not shape_disp in output_shapes:
output_shapes[shape_disp] = [lab.GetLabelName(), c]
for i in range(l_subss.Length()):
lab_subs = l_subss.Value(i+1)
#print("\n######## simpleshape subshape label :", lab)
shape_sub = shape_tool.GetShape(lab_subs)
c = Quantity_Color(0.5, 0.5, 0.5, Quantity_TOC_RGB) # default color
colorSet = False
if (color_tool.GetInstanceColor(shape_sub, 0, c) or
color_tool.GetInstanceColor(shape_sub, 1, c) or
color_tool.GetInstanceColor(shape_sub, 2, c)):
color_tool.SetInstanceColor(shape_sub, 0, c)
color_tool.SetInstanceColor(shape_sub, 1, c)
color_tool.SetInstanceColor(shape_sub, 2, c)
colorSet = True
n = c.Name(c.Red(), c.Green(), c.Blue())
#print(' instance color Name & RGB: ', c, n, c.Red(), c.Green(), c.Blue())
if not colorSet:
if (color_tool.GetColor(lab_subs, 0, c) or
color_tool.GetColor(lab_subs, 1, c) or
color_tool.GetColor(lab_subs, 2, c)):
color_tool.SetInstanceColor(shape, 0, c)
color_tool.SetInstanceColor(shape, 1, c)
color_tool.SetInstanceColor(shape, 2, c)
n = c.Name(c.Red(), c.Green(), c.Blue())
#print(' shape color Name & RGB: ', c, n, c.Red(), c.Green(), c.Blue())
shape_to_disp = BRepBuilderAPI_Transform(shape_sub, loc.Transformation()).Shape()
# position the subshape to display
if not shape_to_disp in output_shapes:
output_shapes[shape_to_disp] = [lab_subs.GetLabelName(), 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)
_get_shapes()
return output_shapes,assemble_relation_list
#########################
# STL import and export #
#########################
def write_stl_file(a_shape, filename, mode="ascii", linear_deflection=0.9, angular_deflection=0.5):
""" export the shape to a STL file
Be careful, the shape first need to be explicitely meshed using BRepMesh_IncrementalMesh
a_shape: the topods_shape to export
filename: the filename
mode: optional, "ascii" by default. Can either be "binary"
linear_deflection: optional, default to 0.001. Lower, more occurate mesh
angular_deflection: optional, default to 0.5. Lower, more accurate_mesh
"""
if a_shape.IsNull():
raise AssertionError("Shape is null.")
if mode not in ["ascii", "binary"]:
raise AssertionError("mode should be either ascii or binary")
if os.path.isfile(filename):
print("Warning: %s file already exists and will be replaced" % filename)
# first mesh the shape
mesh = BRepMesh_IncrementalMesh(a_shape, linear_deflection, False, angular_deflection, True)
#mesh.SetDeflection(0.05)
mesh.Perform()
if not mesh.IsDone():
raise AssertionError("Mesh is not done.")
stl_exporter = StlAPI_Writer()
if mode == "ascii":
stl_exporter.SetASCIIMode(True)
else: # binary, just set the ASCII flag to False
stl_exporter.SetASCIIMode(False)
stl_exporter.Write(a_shape, filename)
if not os.path.isfile(filename):
raise IOError("File not written to disk.")
def read_stl_file(filename):
""" opens a stl file, reads the content, and returns a BRep topods_shape object
"""
if not os.path.isfile(filename):
raise FileNotFoundError("%s not found." % filename)
the_shape = TopoDS_Shape()
stlapi_Read(the_shape, filename)
if the_shape.IsNull():
raise AssertionError("Shape is null.")
return the_shape
######################
# IGES import/export #
######################
def read_iges_file(filename, return_as_shapes=False, verbosity=False, visible_only=False):
""" read the IGES file and returns a compound
filename: the file path
return_as_shapes: optional, False by default. If True returns a list of shapes,
else returns a single compound
verbosity: optionl, False by default.
"""
if not os.path.isfile(filename):
raise FileNotFoundError("%s not found." % filename)
iges_reader = IGESControl_Reader()
iges_reader.SetReadVisible(visible_only)
status = iges_reader.ReadFile(filename)
_shapes = []
if status == IFSelect_RetDone: # check status
if verbosity:
failsonly = False
iges_reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity)
iges_reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity)
iges_reader.TransferRoots()
nbr = iges_reader.NbRootsForTransfer()
for _ in range(1, nbr+1):
nbs = iges_reader.NbShapes()
if nbs == 0:
print("At least one shape in IGES cannot be transfered")
elif nbr == 1 and nbs == 1:
a_res_shape = iges_reader.Shape(1)
if a_res_shape.IsNull():
print("At least one shape in IGES cannot be transferred")
else:
_shapes.append(a_res_shape)
else:
for i in range(1, nbs+1):
a_shape = iges_reader.Shape(i)
if a_shape.IsNull():
print("At least one shape in STEP cannot be transferred")
else:
_shapes.append(a_shape)
# if not return as shapes
# create a compound and store all shapes
if not return_as_shapes:
builder = BRep_Builder()
compound = TopoDS_Compound()
builder.MakeCompound(compound)
for s in _shapes:
builder.Add(compound, s)
_shapes = compound
return _shapes
def write_iges_file(a_shape, filename):
""" exports a shape to a STEP file
a_shape: the topods_shape to export (a compound, a solid etc.)
filename: the filename
application protocol: "AP203" or "AP214"
"""
# a few checks
if a_shape.IsNull():
raise AssertionError("Shape is null.")
if os.path.isfile(filename):
print("Warning: %s file already exists and will be replaced" % filename)
# creates and initialise the step exporter
iges_writer = IGESControl_Writer()
iges_writer.AddShape(a_shape)
status = iges_writer.Write(filename)
if status != IFSelect_RetDone:
raise AssertionError("Not done.")
if not os.path.isfile(filename):
raise IOError("File not written to disk.")
##############
# SVG export #
##############
def edge_to_svg_polyline(topods_edge, tol=0.1, unit="mm"):
""" Returns a svgwrite.Path for the edge, and the 2d bounding box
"""
unit_factor = 1 # by default
if unit == "mm":
unit_factor = 1
elif unit == "m":
unit_factor = 1e3
points_3d = discretize_edge(topods_edge, tol)
points_2d = []
box2d = Bnd_Box2d()
for point in points_3d:
# we tak only the first 2 coordinates (x and y, leave z)
x_p = - point[0] * unit_factor
y_p = point[1] * unit_factor
box2d.Add(gp_Pnt2d(x_p, y_p))
points_2d.append((x_p, y_p))
return svgwrite.shapes.Polyline(points_2d, fill="none"), box2d
def export_shape_to_svg(shape, filename=None,
width=800, height=600, margin_left=10,
margin_top=30, export_hidden_edges=True,
location=gp_Pnt(0, 0, 0), direction=gp_Dir(1, 1, 1),
color="black",
line_width="1px",
unit="mm"):
""" export a single shape to an svg file and/or string.
shape: the TopoDS_Shape to export
filename (optional): if provided, save to an svg file
width, height (optional): integers, specify the canva size in pixels
margin_left, margin_top (optional): integers, in pixel
export_hidden_edges (optional): whether or not draw hidden edges using a dashed line
location (optional): a gp_Pnt, the lookat
direction (optional): to set up the projector direction
color (optional), "default to "black".
line_width (optional, default to 1): an integer
"""
if shape.IsNull():
raise AssertionError("shape is Null")
if not HAVE_SVGWRITE:
print("svg exporter not available because the svgwrite package is not installed.")
print("please use '$ conda install -c conda-forge svgwrite'")
return False
# find all edges
visible_edges, hidden_edges = get_sorted_hlr_edges(shape, position=location, direction=direction, export_hidden_edges=export_hidden_edges)
# compute polylines for all edges
# we compute a global 2d bounding box as well, to be able to compute
# the scale factor and translation vector to apply to all 2d edges so that
# they fit the svg canva
global_2d_bounding_box = Bnd_Box2d()
polylines = []
for visible_edge in visible_edges:
visible_svg_line, visible_edge_box2d = edge_to_svg_polyline(visible_edge, 0.1, unit)
polylines.append(visible_svg_line)
global_2d_bounding_box.Add(visible_edge_box2d)
if export_hidden_edges:
for hidden_edge in hidden_edges:
hidden_svg_line, hidden_edge_box2d = edge_to_svg_polyline(hidden_edge, 0.1, unit)
# hidden lines are dashed style
hidden_svg_line.dasharray([5, 5])
polylines.append(hidden_svg_line)
global_2d_bounding_box.Add(hidden_edge_box2d)
# translate and scale polylines
# first compute shape translation and scale according to size/margins
x_min, y_min, x_max, y_max = global_2d_bounding_box.Get()
bb2d_width = x_max - x_min
bb2d_height = y_max - y_min
# build the svg drawing
dwg = svgwrite.Drawing(filename, (width, height), debug=True)
# adjust the view box so that the lines fit then svg canvas
dwg.viewbox(x_min - margin_left, y_min - margin_top,
bb2d_width + 2 * margin_left, bb2d_height + 2 * margin_top)
for polyline in polylines:
# apply color and style
polyline.stroke(color, width=line_width, linecap="round")
# then adds the polyline to the svg canva
dwg.add(polyline)
# export to string or file according to the user choice
if filename is not None:
dwg.save()
if not os.path.isfile(filename):
raise AssertionError("svg export failed")
print("Shape successfully exported to %s" % filename)
return True
return dwg.tostring()
def analyse(assemble_relation_list):
pass
assemble_list=[]
for i in range(len(assemble_relation_list)):
if assemble_relation_list[i]['isassemble'] and not assemble_relation_list[i+1]['isassemble']:
pass
if __name__=="__main__":
pass
shapes_labels_colors,assemble_relation_list= read_step_file_with_names_colors("test.STEP")
display, start_display, add_menu, add_function_to_menu = init_display()
for shpt_lbl_color in shapes_labels_colors:
label, c = shapes_labels_colors[shpt_lbl_color]
#print(label,assemble_relation_list,assemble_relation_list)
display.DisplayColoredShape(shpt_lbl_color, color=Quantity_Color(c.Red(),
c.Green(),
c.Blue(),
Quantity_TOC_RGB))
for i in range(len(assemble_relation_list)):
try:
print(assemble_relation_list[i])
except:
pass
#analyse(assemble_relation_list)
start_display()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/kaohui/occ_example.git
[email protected]:kaohui/occ_example.git
kaohui
occ_example
occ_example
main

搜索帮助