#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""STEP reader.
:Date: 2020-01-03
.. module:: data_step
:platform: *nix, Windows
:synopsis: STEP reader.
.. moduleauthor:: Daniel Weschke <daniel.weschke@directbox.de>
"""
from .data import read, find_last, str_between, str_to_list
from .data_step_std import (
CARTESIAN_POINT, VERTEX_POINT, DIRECTION, VECTOR, LINE,
AXIS2_PLACEMENT_2D, AXIS2_PLACEMENT_3D, CIRCLE, SURFACE_CURVE,
SEAM_CURVE, EDGE_CURVE, B_SPLINE_CURVE_WITH_KNOTS,
ORIENTED_EDGE, EDGE_LOOP, ELLIPSE
)
from .mathematics import vector
from .geometry import (
World, Line, Point, Circle, CS, ArcCircle, ArcEllipse, Direction,
Polyline, Ellipse, B_spline_curve_with_knots, ArcBSplineCurveWithKnots
)
[docs]class step:
r"""STEP reader class.
1st read a STEP file.
2nd convert header and data section string to list of commands.
The STEP file string can have commands distributed over several
lines, the commands are seperated by ``;\n``. This class un-wraps
each command into one line (remove ``\n``) and removes empty lines.
:Example:
::
header part of a step file (between HEADER; and ENDSEC;):
FILE_DESCRIPTION(('Open CASCADE Model'),'2;1');
FILE_NAME('Open CASCADE Shape Model','2019-10-14T14:32:20',('Author'),(
'Open CASCADE'),'Open CASCADE STEP processor 7.1','Open CASCADE 7.1'
,'Unknown');
FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'));
will result in (but as a list):
FILE_DESCRIPTION(('Open CASCADE Model'),'2;1')
FILE_NAME('Open CASCADE Shape Model','2019-10-14T14:32:20',('Author'),('Open CASCADE'),'Open CASCADE STEP processor 7.1','Open CASCADE 7.1','Unknown')
FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }'))
"""
def __init__(self, file_name):
self.file_str = read(file_name)
step_str = str_between(self.file_str, 'ISO-10303-21;',
'END-ISO-10303-21;')
if not step_str:
raise ValueError('File is not a step file')
header_str = str_between(step_str, 'HEADER;', 'ENDSEC;')
self.header = str_to_list(string=header_str, delimiter=';\n',
newline_replacement='')
data_str = str_between(step_str, 'DATA;', 'ENDSEC;')
self.data = str_to_list(string=data_str, delimiter=';\n',
newline_replacement='')
[docs]def str_to_cmd_args(cmd_str):
"""
Using negative lookahead to match all the commas which are not
inside a parenthesis and then split the string at the commas.
:Example:
::
CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000))
will become
command = 'CARTESIAN_POINT'
arguments = ['', '(0.E+000,0.E+000,0.E+000)']
"""
import re
command = cmd_str[0:cmd_str.find('(')]
inside_parenthesis = cmd_str[(cmd_str.find('(')+1):find_last(cmd_str, ')')]
arguments = re.split(r',\s*(?![^()]*\))', inside_parenthesis)
# arguments = [i.strip() for i in inside_parenthesis.split(',')] # does not work for arguments with commas inside the parenthsis
return command, arguments
[docs]def data_cmds_to_data_dict(data_cmds, verbose=False):
"""Create dict with step objects
1st it creats keys equal to the number id string and values with
the command string.
2nd it creats keys for different step object types to dict all
commands as new created objects of that type.
:Example:
::
from:
["#12 = CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000))",
"#22 = VERTEX_POINT('',#23)"]
to:
{'#12': 'CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000))',
'#22': 'VERTEX_POINT('',#23)'}
additional
{
'cartesian_points': {
'#12': pointer_to_new_created_point_object,
...
},
'vertex_points': {
'#22': pointer_to_new_created_vertex_object,
...
},
...
}
"""
data_dict = {}
data_dict['cmds'] = {}
data_dict['cartesian_point'] = {}
data_dict['vertex_point'] = {}
data_dict['direction'] = {}
data_dict['vector'] = {}
data_dict['line'] = {}
data_dict['circle'] = {}
data_dict['ellipse'] = {}
data_dict['axis2_placement_2d'] = {}
data_dict['axis2_placement_3d'] = {}
data_dict['surface_curve'] = {}
data_dict['seam_curve'] = {}
data_dict['b_spline_curve_with_knots'] = {}
data_dict['edge_curve'] = {}
data_dict['oriented_edge'] = {}
data_dict['edge_loop'] = {}
processed_cmds = 0
ignored_cmds = 0
for data_cmd in data_cmds:
#print(data_cmd)
key, value = data_cmd.split('=')
key, value = key.strip(), value.strip()
command, arguments = str_to_cmd_args(value)
data_dict['cmds'][key] = (command, arguments)
# command can be empty (empty string: '')
# #2052 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') )
try: # do if command.lower() is in data_dict else do nothing
data_dict[command.lower()][key] = None
processed_cmds += 1
except:
ignored_cmds += 1
print('processed_cmds', processed_cmds)
print('ignored_cmds', ignored_cmds)
#
# Order is important!
#
#
# POINT objects
#
# create point objects, these will be referenced by vertex_points
# #12 = CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000));
for key in data_dict['cartesian_point']:
command, arguments = data_dict['cmds'][key]
data_dict['cartesian_point'][key] = CARTESIAN_POINT(
arguments[0],
eval(arguments[1])) # tuple of floats # TODO: not use eval!
# vertex_points references to cartesian_points
# #22 = VERTEX_POINT('',#23);
# #23 = CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000));
for key in data_dict['vertex_point']:
command, arguments = data_dict['cmds'][key]
data_dict['vertex_point'][key] = VERTEX_POINT(
arguments[0],
data_dict['cartesian_point'][arguments[1]])
#
# EDGE objects
#
# DIRECTIONs
# #30 = DIRECTION('',(0.E+000,0.E+000,1.));
for key in data_dict['direction']:
command, arguments = data_dict['cmds'][key]
data_dict['direction'][key] = DIRECTION(
arguments[0],
eval(arguments[1])) # tuple of floats # TODO: not use eval!
# VECTORs references to DIRECTIONs
# #29 = VECTOR('',#30,1.);
# #30 = DIRECTION('',(0.E+000,0.E+000,1.));
for key in data_dict['vector']:
command, arguments = data_dict['cmds'][key]
data_dict['vector'][key] = VECTOR(
arguments[0],
data_dict['direction'][arguments[1]],
eval(arguments[2])) # TODO: not use eval!
# LINEs references to cartesian_point and vector
# #27 = LINE('',#28,#29);
# #28 = CARTESIAN_POINT('',(0.E+000,0.E+000,0.E+000));
# #29 = VECTOR('',#30,1.);
for key in data_dict['line']:
command, arguments = data_dict['cmds'][key]
data_dict['line'][key] = LINE(
arguments[0],
data_dict['cartesian_point'][arguments[1]],
data_dict['vector'][arguments[2]])
# AXIS2_PLACEMENT_2Ds references to location (CARTESIAN_POINT) and ref_direction (DIRECTION)
# #50 = AXIS2_PLACEMENT_2D('',#51,#52);
# #51 = CARTESIAN_POINT('',(0.,0.));
# #52 = DIRECTION('',(1.,0.));
for key in data_dict['axis2_placement_2d']:
command, arguments = data_dict['cmds'][key]
data_dict['axis2_placement_2d'][key] = AXIS2_PLACEMENT_2D(
arguments[0],
data_dict['cartesian_point'][arguments[1]],
data_dict['direction'][arguments[2]])
# AXIS2_PLACEMENT_3Ds references to location (CARTESIAN_POINT), axis (DIRECTION) and ref_direction (DIRECTION)
# #26 = AXIS2_PLACEMENT_3D('',#27,#28,#29);
# #27 = CARTESIAN_POINT('',(0.,0.,10.));
# #28 = DIRECTION('',(0.,0.,1.));
# #29 = DIRECTION('',(1.,0.,-0.));
for key in data_dict['axis2_placement_3d']:
command, arguments = data_dict['cmds'][key]
data_dict['axis2_placement_3d'][key] = AXIS2_PLACEMENT_3D(
arguments[0],
data_dict['cartesian_point'][arguments[1]],
data_dict['direction'][arguments[2]],
data_dict['direction'][arguments[3]])
# CIRCLE references to AXIS2_PLACEMENT_3D and radius
# #25 = CIRCLE('',#26,5.);
# #26 = AXIS2_PLACEMENT_3D('',#27,#28,#29);
for key in data_dict['circle']:
command, arguments = data_dict['cmds'][key]
axis2_placement_cmd, axis2_placement_args = data_dict['cmds'][arguments[1]]
if axis2_placement_cmd == 'AXIS2_PLACEMENT_3D':
axis2_placement = data_dict['axis2_placement_3d'][arguments[1]]
elif axis2_placement_cmd == 'AXIS2_PLACEMENT_2D':
axis2_placement = data_dict['axis2_placement_2d'][arguments[1]]
data_dict['circle'][key] = CIRCLE(
arguments[0],
axis2_placement,
eval(arguments[2])) # TODO: not use eval!
# ELLIPSE references to AXIS2_PLACEMENT_3D and both semi axes
# #1049 = ELLIPSE('',#1050,176.13914953808,100.);
# #1050 = AXIS2_PLACEMENT_3D('',#1051,#1052,#1053);
for key in data_dict['ellipse']:
command, arguments = data_dict['cmds'][key]
axis2_placement_cmd, axis2_placement_args = data_dict['cmds'][arguments[1]]
if axis2_placement_cmd == 'AXIS2_PLACEMENT_3D':
axis2_placement = data_dict['axis2_placement_3d'][arguments[1]]
elif axis2_placement_cmd == 'AXIS2_PLACEMENT_2D':
axis2_placement = data_dict['axis2_placement_2d'][arguments[1]]
data_dict['ellipse'][key] = ELLIPSE(
arguments[0],
axis2_placement,
eval(arguments[2]), # TODO: not use eval!
eval(arguments[3])) # TODO: not use eval!
# B_SPLINE_CURVE_WITH_KNOTS references to list of CARTESIAN_POINTs
# #2195=B_SPLINE_CURVE_WITH_KNOTS('',3,(#43614,#43615,#43616,#43617,#43618,
# #43619,#43620,#43621,#43622,#43623,#43624,#43625,#43626,#43627,#43628,#43629,
# #43630,#43631,#43632,#43633),.UNSPECIFIED.,.F.,.F.,(4,2,2,2,2,2,2,2,2,4),
# (-0.540362356556626,-0.521155983847334,-0.45632355837375,-0.391167894616668,
# -0.32606569132423,-0.260898117378603,-0.19567917747905,-0.130414239126491,
# -0.0649893846296135,-0.0228378692889149),.UNSPECIFIED.);
# #43614=CARTESIAN_POINT('Ctrl Pts',(-0.852590969048745,68.3094592905054,1.00613961606655E-15));
# #43615=CARTESIAN_POINT('Ctrl Pts',(-0.879956199816603,68.2515804555212,8.67420237522527E-16));
# ...
for key in data_dict['b_spline_curve_with_knots']:
command, arguments = data_dict['cmds'][key]
data_dict['b_spline_curve_with_knots'][key] = B_SPLINE_CURVE_WITH_KNOTS(
arguments[0],
int(arguments[1]),
tuple(data_dict['cartesian_point'][i] for
i in str_to_cmd_args(arguments[2])[1]),
arguments[3],
arguments[4],
arguments[5],
eval(arguments[6]), # TODO: not use eval!
eval(arguments[7]), # TODO: not use eval!
arguments[8]
)
# SURFACE_CURVE references to a LINE and a list of (two) PCURVEs and a ?
# #26 = SURFACE_CURVE('',#27,(#31,#43),.PCURVE_S1.);
# #27 = LINE('',#28,#29);
# #31 = PCURVE('',#32,#37);
# #32 = PLANE('',#33);
# #33 = AXIS2_PLACEMENT_3D('',#34,#35,#36);
# #37 = DEFINITIONAL_REPRESENTATION('',(#38),#42);
# #38 = LINE('',#39,#40);
# #42 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
# #43 = PCURVE('',#44,#49);
# #44 = PLANE('',#45);
# #45 = AXIS2_PLACEMENT_3D('',#46,#47,#48);
# #49 = DEFINITIONAL_REPRESENTATION('',(#50),#54);
# #50 = LINE('',#51,#52);
# #54 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
# #24 = SURFACE_CURVE('',#25,(#30,#42),.PCURVE_S1.);
# #25 = CIRCLE('',#26,5.);
# #30 = PCURVE('',#31,#36);
# #31 = CONICAL_SURFACE('',#32,10.,0.463647609001);
# #32 = AXIS2_PLACEMENT_3D('',#33,#34,#35);
# #36 = DEFINITIONAL_REPRESENTATION('',(#37),#41);
# #37 = LINE('',#38,#39);
# #41 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
# #42 = PCURVE('',#43,#48);
# #43 = PLANE('',#44);
# #44 = AXIS2_PLACEMENT_3D('',#45,#46,#47);
# #48 = DEFINITIONAL_REPRESENTATION('',(#49),#53);
# #49 = CIRCLE('',#50,5.);
# #50 = AXIS2_PLACEMENT_2D('',#51,#52);
# #51 = CARTESIAN_POINT('',(0.,0.));
# #52 = DIRECTION('',(1.,0.));
# #53 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
# #243 = SURFACE_CURVE('',#244,(#319,#415),.PCURVE_S1.);
# #244 = B_SPLINE_CURVE_WITH_KNOTS();
for key in data_dict['surface_curve']:
command, arguments = data_dict['cmds'][key]
curve_3d_cmd, curve3d_args = data_dict['cmds'][arguments[1]]
if curve_3d_cmd == 'LINE':
curve_3d = data_dict['line'][arguments[1]]
elif curve_3d_cmd == 'CIRCLE':
curve_3d = data_dict['circle'][arguments[1]]
elif curve_3d_cmd == 'ELLIPSE':
curve_3d = data_dict['ellipse'][arguments[1]]
elif curve_3d_cmd == 'B_SPLINE_CURVE_WITH_KNOTS':
curve_3d = data_dict['b_spline_curve_with_knots'][arguments[1]]
else:
curve_3d = arguments[1]
if verbose:
print('surface_curve', key, 'unknown curve_3d', curve_3d)
data_dict['surface_curve'][key] = SURFACE_CURVE(
arguments[0],
curve_3d,
arguments[2],
arguments[3])
# SEAM_CURVE references to a Line and a list of (two) PCURVEs and a ?
# #58 = SEAM_CURVE('',#59,(#63,#70),.PCURVE_S1.);
# #59 = LINE('',#60,#61);
# #63 = PCURVE('',#31,#64);
# #31 = CONICAL_SURFACE('',#32,10.,0.463647609001);
# #32 = AXIS2_PLACEMENT_3D('',#33,#34,#35);
# #33 = CARTESIAN_POINT('',(0.,0.,0.));
# #34 = DIRECTION('',(-0.,-0.,-1.));
# #35 = DIRECTION('',(1.,0.,-0.));
# #64 = DEFINITIONAL_REPRESENTATION('',(#65),#69);
# #65 = LINE('',#66,#67);
# #69 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
# #70 = PCURVE('',#31,#71);
# #31 = CONICAL_SURFACE('',#32,10.,0.463647609001);
# #32 = AXIS2_PLACEMENT_3D('',#33,#34,#35);
# #33 = CARTESIAN_POINT('',(0.,0.,0.));
# #34 = DIRECTION('',(-0.,-0.,-1.));
# #35 = DIRECTION('',(1.,0.,-0.));
# #71 = DEFINITIONAL_REPRESENTATION('',(#72),#76);
# #72 = LINE('',#73,#74);
# #76 = ( GEOMETRIC_REPRESENTATION_CONTEXT(2) PARAMETRIC_REPRESENTATION_CONTEXT() REPRESENTATION_CONTEXT('2D SPACE','') );
for key in data_dict['seam_curve']:
command, arguments = data_dict['cmds'][key]
curve_3d_cmd, curve3d_args = data_dict['cmds'][arguments[1]]
if curve_3d_cmd == 'LINE':
curve_3d = data_dict['line'][arguments[1]]
elif curve_3d_cmd == 'CIRCLE':
curve_3d = data_dict['circle'][arguments[1]]
else:
curve_3d = arguments[1]
if verbose:
print('seam_curve', key, 'unknown curve_3d', curve_3d)
data_dict['seam_curve'][key] = SEAM_CURVE(
arguments[0],
curve_3d,
arguments[2],
arguments[3])
# EDGE_CURVE references to two VERTEX_POINTs, a CURVE and a BOOLEAN
# #21 = EDGE_CURVE('',#22,#24,#26,.T.);
# #22 = VERTEX_POINT('',#23);
# #24 = VERTEX_POINT('',#25);
# #26 = SURFACE_CURVE('',#27,(#31,#43),.PCURVE_S1.);
# #55 = EDGE_CURVE('',#56,#22,#58,.T.);
# #56 = VERTEX_POINT('',#57);
# #22 = VERTEX_POINT('',#23);
# #58 = SEAM_CURVE('',#59,(#63,#70),.PCURVE_S1.);
# #21187=EDGE_CURVE('',#15685,#15685,#12509,.T.);
# #15685=VERTEX_POINT('',#230114);
# #15685=VERTEX_POINT('',#230114);
# #12509=CIRCLE('',#37712,11.1464466094067);
# #15689=EDGE_CURVE('',#12514,#12512,#2195,.T.);
# #12514=VERTEX_POINT('',#43613);
# #12512=VERTEX_POINT('',#43610);
# #2195=B_SPLINE_CURVE_WITH_KNOTS(...)
for key in data_dict['edge_curve']:
command, arguments = data_dict['cmds'][key]
geometry_cmd, geometry_args = data_dict['cmds'][arguments[3]]
if geometry_cmd == 'SURFACE_CURVE':
edge_geometry = data_dict['surface_curve'][arguments[3]]
elif geometry_cmd == 'SEAM_CURVE':
edge_geometry = data_dict['seam_curve'][arguments[3]]
elif geometry_cmd == 'LINE':
edge_geometry = data_dict['line'][arguments[3]]
elif geometry_cmd == 'CIRCLE':
edge_geometry = data_dict['circle'][arguments[3]]
elif geometry_cmd == 'B_SPLINE_CURVE_WITH_KNOTS':
edge_geometry = data_dict['b_spline_curve_with_knots'][arguments[3]]
else:
edge_geometry = arguments[3]
if verbose:
print('edge_curve', key, 'unknown edge_geometry', geometry_cmd)
data_dict['edge_curve'][key] = EDGE_CURVE(
arguments[0],
data_dict['vertex_point'][arguments[1]],
data_dict['vertex_point'][arguments[2]],
edge_geometry,
arguments[4]
)
#
# poly-curve objects
# to speed things up use EDGE_LOOP to create wireframes instead
# of plotting every single EDGE_CURVE in it's own plot cmd
#
# ORIENTED_EDGE references to two re-declared attributes from a CURVE, a CURVE and a BOOLEAN
# 83 = ORIENTED_EDGE('',*,*,#84,.F.);
# #84 = EDGE_CURVE('',#85,#87,#89,.T.);
# ORIENTED_EDGE will have multiple same edges, because connected faces
# use the same curve (about double as EDGE_CURVE)
# BUT combined with EDGE_LOOP the number of concatenated curves decrease.
# (about half to 2/3 of EDGE_CURVE)
for key in data_dict['oriented_edge']:
command, arguments = data_dict['cmds'][key]
edge_element_cmd, edge_element_args = data_dict['cmds'][arguments[3]]
if edge_element_cmd == 'EDGE_CURVE':
edge_element = data_dict['edge_curve'][arguments[3]]
else:
edge_element = arguments[3]
if verbose:
print('oriented_edge', key, 'unknown edge_element', edge_element_cmd)
data_dict['oriented_edge'][key] = ORIENTED_EDGE(
arguments[0],
arguments[1],
arguments[2],
edge_element,
arguments[4]
)
# EDGE_LOOP
# #82 = EDGE_LOOP('',(#83,#118,#146,#174));
# #83 = ORIENTED_EDGE('',*,*,#84,.F.);
# #118 = ORIENTED_EDGE('',*,*,#119,.T.);
# #146 = ORIENTED_EDGE('',*,*,#147,.T.);
# #174 = ORIENTED_EDGE('',*,*,#175,.F.);
for key in data_dict['edge_loop']:
command, arguments = data_dict['cmds'][key]
data_dict['edge_loop'][key] = EDGE_LOOP(
arguments[0],
tuple(data_dict['oriented_edge'][i] for
i in str_to_cmd_args(arguments[1])[1]),
)
return data_dict
[docs]def data_section_dict(step, verbose=False):
return data_cmds_to_data_dict(step.data, verbose)
[docs]def line_geometry(p1, p2):
# (normally)
# edge_curve.edge_geometry.curve_3d.pnt.coordinates is
# equal to p1 (see above) this is
# edge_curve.edge_start.vertex_geometry.coordinates
# p2 could be calculated from
# edge_curve.edge_geometry.curve_3d.dir.orientation.direction_ratios
# and edge_curve.edge_geometry.curve_3d.dir.magnitude
# vector = [i*edge_curve.edge_geometry.curve_3d.dir.magnitude for
# i in edge_curve.edge_geometry.curve_3d.dir.orientation.direction_ratios]
return Line(point1=p1, point2=p2)
import math
[docs]def arc_circle_geometry(conic, p1, p2, ellipse=False):
z = Direction(*conic.position.axis.direction_ratios)
x = Direction(*conic.position.ref_direction.direction_ratios)
y = Direction.cross(z, x)
cs_gl = CS(x, y, z) # transform from global to local
cs_lg = CS.transposed(cs_gl) # transform from local to global
location = vector(conic.position.location.coordinates)
if p1 == p2: # Full Circle or Ellipse
if ellipse:
a = conic.semi_axis_1
b = conic.semi_axis_2
return Ellipse(a, b).ch_cs(cs_lg).translate(*location)
# else Circle
radius = conic.radius
return Circle(radius).ch_cs(cs_lg).translate(*location)
# else Arc
# points relative to the location
v1, v2 = p1 - location, p2 - location
#ang1, ang2 = vector.ang(x, v1), vector.ang(x, v2)
# relative points transformed into circle coordinate system
# relative point lay in local xy-plane
vl1, vl2 = vector(v1).ch_cs(cs_gl), vector(v2).ch_cs(cs_gl)
ang1, ang2 = math.atan2(*vl1[:2][::-1]), math.atan2(*vl2[:2][::-1])
if ellipse:
a = conic.semi_axis_1
b = conic.semi_axis_2
return ArcEllipse(a, b, ang1, ang2).ch_cs(cs_lg).translate(*location)
radius = conic.radius
return ArcCircle(radius, ang1, ang2).ch_cs(cs_lg).translate(*location)
import copy
[docs]def b_spline_curve_with_knots_geometry(b_spline, p1, p2):
"""
Currently only clamped b_spline curves and assumed, i. e. closed
= False.
"""
control_points = [i.coordinates for i in b_spline.control_points]
# es_near = [vector.isclose(p1, i.coordinates, abs_tol=2.1) for i in b_spline.control_points].index(True)
es_near = len(b_spline.control_points) - 1 - [vector.isclose(p1, i.coordinates, abs_tol=2.1) for i in b_spline.control_points[::-1]].index(True)
# ee_near = len(b_spline.control_points) - 1 - [vector.isclose(p2, i.coordinates, abs_tol=2.1) for i in b_spline.control_points[::-1]].index(True)
ee_near = [vector.isclose(p2, i.coordinates, abs_tol=2.1) for i in b_spline.control_points].index(True)
knots = [b_spline.knots[i] for i in range(len(b_spline.knots)) for
j in range(b_spline.knot_multiplicities[i])]
# print('bs es, ee in:', es_near, ee_near,
# knots[es_near], knots[ee_near+b_spline.degree])
# print(' knots, knote:', knots[0], knots[-1], len(knots))
if es_near is not None and ee_near is not None:
#print('yes')
bs = ArcBSplineCurveWithKnots(
b_spline.degree, control_points, b_spline.knot_multiplicities,
b_spline.knots, knots[es_near+1], knots[ee_near+b_spline.degree-1])
bs._points = [copy.copy(p1)] + bs._points + [copy.copy(p2)]
return bs
# +1 so not the last near point but the following, also -1
print('error')
return B_spline_curve_with_knots(
b_spline.degree, control_points, b_spline.knot_multiplicities,
b_spline.knots)
# TODO: backup solution to draw each edge_curve,
# new is to put edge_curves to edge_loops and draw these loops
# see data_dict_to_geometry_world
[docs]def data_dict_to_geometry_world_edge_curve(data_dict):
w = World()
data_dict_edge_curve_to_geometry(data_dict)
edges = data_dict['geometry_edge_curves']
for i in edges.values():
w.add(i)
return w
[docs]def data_dict_edge_curve_to_geometry(data_dict):
edges = {}
for key, edge_curve in data_dict['edge_curve'].items():
p1 = Point(*edge_curve.edge_start.vertex_geometry.coordinates)
p2 = Point(*edge_curve.edge_end.vertex_geometry.coordinates)
idn = edge_curve.idn
# if SURFACE_CURVE or SEAM_CURVE, b/c SEAM_CURVE(SURFACE_CURVE)
if isinstance(edge_curve.edge_geometry, SURFACE_CURVE):
if isinstance(edge_curve.edge_geometry.curve_3d, LINE):
edges[idn] = line_geometry(p1, p2)
elif isinstance(edge_curve.edge_geometry.curve_3d, CIRCLE):
circle = edge_curve.edge_geometry.curve_3d
edges[idn] = arc_circle_geometry(circle, p1, p2)
elif isinstance(edge_curve.edge_geometry.curve_3d, ELLIPSE):
ellipse = edge_curve.edge_geometry.curve_3d
edges[idn] = arc_circle_geometry(ellipse, p1, p2, True)
elif isinstance(edge_curve.edge_geometry.curve_3d, B_SPLINE_CURVE_WITH_KNOTS):
b_spline = edge_curve.edge_geometry.curve_3d
edges[idn] = b_spline_curve_with_knots_geometry(b_spline, p1, p2)
else:
print('edge_curve', key, 'unknown SURFACE_CURVE',
type(edge_curve.edge_geometry.curve_3d))
elif isinstance(edge_curve.edge_geometry, LINE):
edges[idn] = line_geometry(p1, p2)
elif isinstance(edge_curve.edge_geometry, CIRCLE):
circle = edge_curve.edge_geometry
edges[idn] = arc_circle_geometry(circle, p1, p2)
elif isinstance(edge_curve.edge_geometry, B_SPLINE_CURVE_WITH_KNOTS):
b_spline = edge_curve.edge_geometry
edges[idn] = b_spline_curve_with_knots_geometry(b_spline, p1, p2)
else: # fallback to straight line
edges[idn] = line_geometry(p1, p2)
print('edge_curve', key, 'unknown type', type(edge_curve))
data_dict['geometry_edge_curves'] = edges
[docs]def data_dict_to_geometry_world(data_dict):
w = World()
data_dict_edge_curve_to_geometry(data_dict)
edges = data_dict['geometry_edge_curves']
# add all but the last point, it is a path.
import math
iter = 0
for key, edge_loop in data_dict['edge_loop'].items():
points = []
last_end_point = None
for oriented_edge in edge_loop.edge_list:
edge_curve = oriented_edge.edge_element
idn = edge_curve.idn
if idn in edges:
pts = edges[idn].points()
if oriented_edge.orientation:
#[points.append(i) for i in pts[:-1]]
[points.append(i) for i in pts]
start_point = pts[0]
end_point = pts[-1]
else:
#[points.append(i) for i in pts[:0:-1]]
[points.append(i) for i in pts[::-1]]
start_point = pts[-1]
end_point = pts[0]
if last_end_point is not None:
# TODO: some points are only near because of the current
# b-spline cut in b_spline_curve_with_knots_geometry
isclose = all([math.isclose(i, j, abs_tol=1e-3) for i, j in zip(start_point, last_end_point)])
if isclose:
pass
else:
pass
print(isclose, start_point, last_end_point)
else:
pass
#print('start of loop')
last_end_point = end_point
else:
pass
print('error')
if points:
# add last end point of path
# if oriented_edge.orientation:
# points.append(Point(*edge_curve.edge_end.vertex_geometry.coordinates))
# else:
# points.append(Point(*edge_curve.edge_start.vertex_geometry.coordinates))
#points.append(Point(*oriented_edge.edge_end.vertex_geometry.coordinates))
w.add(Polyline(*points))
# if iter == 4:
# print()
# print(key)
# break
# iter += 1
return w
# TODO: delete this testing def
[docs]def print_edge_loop(data_dict, instance_name):
from pylib.mathematics import vector
from pylib.data_step_std import LINE, B_SPLINE_CURVE_WITH_KNOTS
print('edge_loop:', instance_name, data_dict['edge_loop'][instance_name].idn)
for oriented_edge in data_dict['edge_loop'][instance_name].edge_list:
print(' orientation: ', oriented_edge.orientation)
print(' edge_start: ', oriented_edge.edge_start.vertex_geometry.coordinates)
print(' edge_end: ', oriented_edge.edge_end.vertex_geometry.coordinates)
edge_element = oriented_edge.edge_element
print(' edge_element')
print(' same_sense: ', edge_element.same_sense)
print(' edge_start: ', edge_element.edge_start.vertex_geometry.coordinates)
print(' edge_end: ', edge_element.edge_end.vertex_geometry.coordinates)
curve_3d = edge_element.edge_geometry.curve_3d
print(' edge_geometry.curve_3d')
print(' type: ', type(curve_3d))
if isinstance(curve_3d, LINE):
print(' es in: ',
vector.isclose(edge_element.edge_start.vertex_geometry.coordinates, curve_3d.pnt.coordinates))
print(' ee in: ',
vector.isclose(edge_element.edge_end.vertex_geometry.coordinates, curve_3d.pnt.coordinates))
print(' pnt: ', curve_3d.pnt.coordinates)
print(' pnt2: ', [curve_3d.dir.magnitude*i+j for i,j in zip(curve_3d.dir.orientation.direction_ratios, curve_3d.pnt.coordinates)])
if isinstance(curve_3d, B_SPLINE_CURVE_WITH_KNOTS):
print(' es in: ',
any([vector.isclose(edge_element.edge_start.vertex_geometry.coordinates, i.coordinates, abs_tol=2.1) for i in curve_3d.control_points]))
print(' ee in: ',
any([vector.isclose(edge_element.edge_end.vertex_geometry.coordinates, i.coordinates, abs_tol=2.1) for i in curve_3d.control_points]))
print(' control_points')
print(' ', curve_3d.control_points[0].coordinates, '...')
print(' ', curve_3d.control_points[-1].coordinates)
# print()
# print_edge_loop(data_dict, '#1306')