From e6b4778d4149817207f15d843af58acaa53ebf9b Mon Sep 17 00:00:00 2001 From: tnakaicode Date: Fri, 16 Sep 2022 18:36:39 +0900 Subject: [PATCH 1/2] remve BRepAdaptor_HCompCurve,BRepAdaptor_HCurve --- .gitignore | 3 +++ OCCUtils/Common.py | 10 +++++----- OCCUtils/Construct.py | 4 ++-- OCCUtils/edge.py | 2 +- examples/occutils_geomplate.py | 12 ++++++------ 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index ba74660..7f67d86 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ docs/_build/ # PyBuilder target/ + +# VScode +.vscode/launch.json diff --git a/OCCUtils/Common.py b/OCCUtils/Common.py index f390571..66c4064 100644 --- a/OCCUtils/Common.py +++ b/OCCUtils/Common.py @@ -26,8 +26,8 @@ TColgp_Array1OfPnt2d, TColgp_Array1OfVec) from OCC.Core.TColStd import TColStd_HArray1OfBoolean -from OCC.Core.BRepAdaptor import (BRepAdaptor_Curve, BRepAdaptor_HCurve, - BRepAdaptor_CompCurve, BRepAdaptor_HCompCurve) +from OCC.Core.BRepAdaptor import (BRepAdaptor_Curve, BRepAdaptor_Curve, + BRepAdaptor_CompCurve, BRepAdaptor_CompCurve) from OCC.Core.GeomAPI import (GeomAPI_Interpolate, GeomAPI_PointsToBSpline, GeomAPI_ProjectPointOnCurve) from OCC.Core.gp import gp_Pnt, gp_Vec, gp_Trsf @@ -525,7 +525,7 @@ def adapt_edge_to_curve(edg): def adapt_edge_to_hcurve(edg): - c = BRepAdaptor_HCurve() + c = BRepAdaptor_Curve() c.ChangeCurve().Initialize(edg) return c @@ -579,7 +579,7 @@ def wire_to_curve(wire, tolerance=TOLERANCE, order=GeomAbs_C2, max_segment=200, @param wire: ''' adap = BRepAdaptor_CompCurve(wire) - hadap = BRepAdaptor_HCompCurve(adap) + hadap = BRepAdaptor_CompCurve(adap) from OCC.Core.Approx import Approx_Curve3d approx = Approx_Curve3d(hadap, tolerance, order, max_segment, max_order) with assert_isdone(approx, 'not able to compute approximation from wire'): @@ -595,6 +595,6 @@ def adapt_edge_to_curve(edg): def adapt_edge_to_hcurve(edg): - c = BRepAdaptor_HCurve() + c = BRepAdaptor_Curve() c.ChangeCurve().Initialize(edg) return c diff --git a/OCCUtils/Construct.py b/OCCUtils/Construct.py index 6759fd6..7364db1 100644 --- a/OCCUtils/Construct.py +++ b/OCCUtils/Construct.py @@ -28,7 +28,7 @@ import math from OCC.Core.BRep import BRep_Tool -from OCC.Core.BRepAdaptor import BRepAdaptor_HCurve +from OCC.Core.BRepAdaptor import BRepAdaptor_Curve from OCC.Core.BRepOffset import BRepOffset_Skin from OCC.Core.Geom import Geom_TrimmedCurve from OCC.Core.GeomConvert import GeomConvert_ApproxCurve @@ -546,7 +546,7 @@ def make_constrained_surface_from_edges(edges): from OCC.Core.BRepFill import BRepFill_CurveConstraint bpSrf = GeomPlate_BuildPlateSurface(3, 15, 2) for edg in edges: - c = BRepAdaptor_HCurve() + c = BRepAdaptor_Curve() c.ChangeCurve().Initialize(edg) constraint = BRepFill_CurveConstraint(c, 0) bpSrf.Add(constraint) diff --git a/OCCUtils/edge.py b/OCCUtils/edge.py index 0ec2faf..e3e10fc 100644 --- a/OCCUtils/edge.py +++ b/OCCUtils/edge.py @@ -15,7 +15,7 @@ ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see -from OCC.Core.BRepAdaptor import BRepAdaptor_Curve, BRepAdaptor_HCurve +from OCC.Core.BRepAdaptor import BRepAdaptor_Curve, BRepAdaptor_Curve from OCC.Core.GCPnts import GCPnts_UniformAbscissa from OCC.Core.Geom import Geom_OffsetCurve, Geom_TrimmedCurve from OCC.Core.TopExp import topexp diff --git a/examples/occutils_geomplate.py b/examples/occutils_geomplate.py index d2966a0..16795ff 100644 --- a/examples/occutils_geomplate.py +++ b/examples/occutils_geomplate.py @@ -29,16 +29,16 @@ import time from OCC.Core.gp import gp_Pnt -from OCC.Core.BRepAdaptor import BRepAdaptor_HCurve +from OCC.Core.BRepAdaptor import BRepAdaptor_Curve from OCC.Core.BRep import BRep_Tool from OCC.Core.ShapeAnalysis import ShapeAnalysis_Surface from OCC.Core.GeomLProp import GeomLProp_SLProps from OCC.Core.BRepFill import BRepFill_CurveConstraint -from OCC.GeomPlate import (GeomPlate_MakeApprox, +from OCC.Core.GeomPlate import (GeomPlate_MakeApprox, GeomPlate_BuildPlateSurface, GeomPlate_PointConstraint) -from OCC.IGESControl import IGESControl_Reader -from OCC.IFSelect import (IFSelect_RetDone, +from OCC.Core.IGESControl import IGESControl_Reader +from OCC.Core.IFSelect import (IFSelect_RetDone, IFSelect_ItemsByEntity) from OCC.Display.SimpleGui import init_display from OCC.Core.TopoDS import TopoDS_Compound @@ -154,7 +154,7 @@ def build_plate(polygon, points): # add curve constraints for poly in polygon: for edg in WireExplorer(poly).ordered_edges(): - c = BRepAdaptor_HCurve() + c = BRepAdaptor_Curve() c.ChangeCurve().Initialize(edg) constraint = BRepFill_CurveConstraint(c.GetHandle(), 0) bpSrf.Add(constraint.GetHandle()) @@ -270,7 +270,7 @@ def build_geom_plate(edges): # add curve constraints for edg in edges: - c = BRepAdaptor_HCurve() + c = BRepAdaptor_Curve() print('edge:', edg) c.ChangeCurve().Initialize(edg) constraint = BRepFill_CurveConstraint(c.GetHandle(), 0) From 68da72e6fb9d6967438f3fecafb266e169bb331f Mon Sep 17 00:00:00 2001 From: tpaviot Date: Sat, 17 Sep 2022 06:27:24 +0200 Subject: [PATCH 2/2] Fixed, blackify --- OCCUtils/Common.py | 316 ++++++++++++++++++++-------------- OCCUtils/Construct.py | 386 ++++++++++++++++++++++++++---------------- OCCUtils/Image.py | 14 +- OCCUtils/Iteration.py | 18 +- OCCUtils/Topology.py | 148 +++++++++------- OCCUtils/base.py | 93 ++++++---- OCCUtils/edge.py | 169 +++++++++--------- OCCUtils/face.py | 112 ++++++------ OCCUtils/shell.py | 6 +- OCCUtils/solid.py | 6 +- OCCUtils/types_lut.py | 241 +++++++++++++++++--------- OCCUtils/vertex.py | 15 +- OCCUtils/wire.py | 9 +- test/occutils_test.py | 1 + 14 files changed, 931 insertions(+), 603 deletions(-) diff --git a/OCCUtils/Common.py b/OCCUtils/Common.py index 66c4064..f0aa418 100644 --- a/OCCUtils/Common.py +++ b/OCCUtils/Common.py @@ -21,44 +21,58 @@ from OCC.Core.Bnd import Bnd_Box from OCC.Core.BRepBndLib import brepbndlib_Add -from OCC.Core.TColgp import (TColgp_HArray1OfPnt, - TColgp_Array1OfPnt, - TColgp_Array1OfPnt2d, - TColgp_Array1OfVec) +from OCC.Core.TColgp import ( + TColgp_HArray1OfPnt, + TColgp_Array1OfPnt, + TColgp_Array1OfPnt2d, + TColgp_Array1OfVec, +) from OCC.Core.TColStd import TColStd_HArray1OfBoolean -from OCC.Core.BRepAdaptor import (BRepAdaptor_Curve, BRepAdaptor_Curve, - BRepAdaptor_CompCurve, BRepAdaptor_CompCurve) -from OCC.Core.GeomAPI import (GeomAPI_Interpolate, GeomAPI_PointsToBSpline, - GeomAPI_ProjectPointOnCurve) +from OCC.Core.BRepAdaptor import ( + BRepAdaptor_Curve, + BRepAdaptor_Curve, + BRepAdaptor_CompCurve, + BRepAdaptor_CompCurve, +) +from OCC.Core.GeomAPI import ( + GeomAPI_Interpolate, + GeomAPI_PointsToBSpline, + GeomAPI_ProjectPointOnCurve, +) from OCC.Core.gp import gp_Pnt, gp_Vec, gp_Trsf from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Transform from OCC.Core.TopoDS import TopoDS_Edge, TopoDS_Shape, TopoDS_Wire, TopoDS_Vertex from OCC.Core.Quantity import Quantity_Color, Quantity_TOC_RGB from OCC.Core.GProp import GProp_GProps from OCC.Core.GeomAbs import GeomAbs_C1, GeomAbs_C2, GeomAbs_C3 -from OCC.Core.BRepGProp import (brepgprop_LinearProperties, - brepgprop_SurfaceProperties, - brepgprop_VolumeProperties) +from OCC.Core.BRepGProp import ( + brepgprop_LinearProperties, + brepgprop_SurfaceProperties, + brepgprop_VolumeProperties, +) from OCC.Core.GeomAdaptor import GeomAdaptor_Curve from OCC.Core.Geom import Geom_Curve from OCC.Core import Graphic3d -#=========================================================================== +# =========================================================================== # No PythonOCC dependencies... -#=========================================================================== +# =========================================================================== class assert_isdone(object): - ''' + """ raises an assertion error when IsDone() returns false, with the error specified in error_statement - ''' + """ + def __init__(self, to_check, error_statement): self.to_check = to_check self.error_statement = error_statement - def __enter__(self, ): + def __enter__( + self, + ): if self.to_check.IsDone(): pass else: @@ -71,19 +85,20 @@ def __exit__(self, assertion_type, value, traceback): def roundlist(li, n_decimals=3): return [round(i, n_decimals) for i in li] -#=========================================================================== + +# =========================================================================== # CONSTANTS -#=========================================================================== +# =========================================================================== TOLERANCE = 1e-6 def get_boundingbox(shape, tol=TOLERANCE): - ''' + """ :param shape: TopoDS_Shape such as TopoDS_Face :param tol: tolerance :return: xmin, ymin, zmin, xmax, ymax, zmax - ''' + """ bbox = Bnd_Box() bbox.SetGap(tol) brepbndlib_Add(shape, bbox) @@ -93,18 +108,19 @@ def get_boundingbox(shape, tol=TOLERANCE): def smooth_pnts(pnts): smooth = [pnts[0]] - for i in range(1, len(pnts)-1): - prev = pnts[i-1] + for i in range(1, len(pnts) - 1): + prev = pnts[i - 1] this = pnts[i] - next_pnt = pnts[i+1] - pt = (prev+this+next_pnt) / 3.0 + next_pnt = pnts[i + 1] + pt = (prev + this + next_pnt) / 3.0 smooth.append(pt) smooth.append(pnts[-1]) return smooth -#=========================================================================== + +# =========================================================================== # Data type utilities -#=========================================================================== +# =========================================================================== def color(r, g, b): @@ -113,19 +129,20 @@ def color(r, g, b): def to_string(_string): from OCC.Core.TCollection import TCollection_ExtendedString + return TCollection_ExtendedString(_string) def to_tcol_(_list, collection_type): - array = collection_type(1, len(_list)+1) + array = collection_type(1, len(_list) + 1) for n, i in enumerate(_list): - array.SetValue(n+1, i) + array.SetValue(n + 1, i) return array def _Tcol_dim_1(li, _type): - '''function factory for 1-dimensional TCol* types''' - pts = _type(0, len(li)-1) + """function factory for 1-dimensional TCol* types""" + pts = _type(0, len(li) - 1) for n, i in enumerate(li): pts.SetValue(n, i) pts.thisown = False @@ -133,7 +150,7 @@ def _Tcol_dim_1(li, _type): def point_list_to_TColgp_Array1OfPnt(li): - pts = TColgp_Array1OfPnt(0, len(li)-1) + pts = TColgp_Array1OfPnt(0, len(li) - 1) for n, i in enumerate(li): pts.SetValue(n, i) return pts @@ -142,16 +159,17 @@ def point_list_to_TColgp_Array1OfPnt(li): def point2d_list_to_TColgp_Array1OfPnt2d(li): return _Tcol_dim_1(li, TColgp_Array1OfPnt2d) -#=========================================================================== + +# =========================================================================== # --- INTERPOLATION --- -#=========================================================================== +# =========================================================================== def filter_points_by_distance(list_of_point, distance=0.1): - ''' + """ get rid of those point that lie within tolerance of a consequtive series of points - ''' + """ tmp = [list_of_point[0]] for a in list_of_point[1:]: if any([a.IsEqual(i, distance) for i in tmp]): @@ -162,24 +180,27 @@ def filter_points_by_distance(list_of_point, distance=0.1): def points_to_bspline(pnts): - ''' + """ Points to bspline - ''' + """ pnts = point_list_to_TColgp_Array1OfPnt(pnts) crv = GeomAPI_PointsToBSpline(pnts) return crv.Curve() -def interpolate_points_to_spline(list_of_points, start_tangent, end_tangent, filter_pts=True, tolerance=TOLERANCE): - ''' +def interpolate_points_to_spline( + list_of_points, start_tangent, end_tangent, filter_pts=True, tolerance=TOLERANCE +): + """ GeomAPI_Interpolate is buggy: need to use `fix` in order to get the right points in... - ''' + """ + def fix(li, _type): - '''function factory for 1-dimensional TCol* types''' + """function factory for 1-dimensional TCol* types""" pts = _type(1, len(li)) for n, i in enumerate(li): - pts.SetValue(n+1, i) + pts.SetValue(n + 1, i) pts.thisown = False return pts @@ -197,25 +218,31 @@ def fix(li, _type): print("Failed to interpolate the shown points") -def interpolate_points_vectors_to_spline(list_of_points, list_of_vectors, vector_mask=None, tolerance=TOLERANCE): - ''' +def interpolate_points_vectors_to_spline( + list_of_points, list_of_vectors, vector_mask=None, tolerance=TOLERANCE +): + """ build a curve from a set of points and vectors the vectors describe the tangent vector at the corresponding point - ''' + """ # GeomAPI_Interpolate is buggy: need to use `fix` in order to # get the right points in... - assert len(list_of_points) == len(list_of_vectors), 'vector and point list not of same length' + assert len(list_of_points) == len( + list_of_vectors + ), "vector and point list not of same length" def fix(li, _type): - '''function factory for 1-dimensional TCol* types''' + """function factory for 1-dimensional TCol* types""" pts = _type(1, len(li)) for n, i in enumerate(li): - pts.SetValue(n+1, i) + pts.SetValue(n + 1, i) pts.thisown = False return pts if vector_mask is not None: - assert len(vector_mask) == len(list_of_points), 'length vector mask is not of length points list nor []' + assert len(vector_mask) == len( + list_of_points + ), "length vector mask is not of length points list nor []" else: vector_mask = [True for i in range(len(list_of_points))] @@ -231,19 +258,22 @@ def fix(li, _type): return interp.Curve() except RuntimeError: # the exception was unclear - raise RuntimeError('FAILED TO INTERPOLATE THE POINTS') + raise RuntimeError("FAILED TO INTERPOLATE THE POINTS") -def interpolate_points_to_spline_no_tangency(list_of_points, filter_pts=True, closed=False, tolerance=TOLERANCE): - ''' +def interpolate_points_to_spline_no_tangency( + list_of_points, filter_pts=True, closed=False, tolerance=TOLERANCE +): + """ GeomAPI_Interpolate is buggy: need to use `fix` in order to get the right points in... - ''' + """ + def fix(li, _type): - '''function factory for 1-dimensional TCol* types''' + """function factory for 1-dimensional TCol* types""" pts = _type(1, len(li)) for n, i in enumerate(li): - pts.SetValue(n+1, i) + pts.SetValue(n + 1, i) pts.thisown = False return pts @@ -259,11 +289,13 @@ def fix(li, _type): except RuntimeError: # the exception was unclear - raise RuntimeError('FAILED TO INTERPOLATE THE POINTS') + raise RuntimeError("FAILED TO INTERPOLATE THE POINTS") + -#=========================================================================== +# =========================================================================== # --- RANDOMNESS --- -#=========================================================================== +# =========================================================================== + def random_vec(): x, y, z = [random.uniform(-1, 1) for i in range(3)] @@ -271,7 +303,7 @@ def random_vec(): def random_colored_material_aspect(): - clrs = [i for i in dir(Graphic3d) if i.startswith('Graphic3d_NOM_')] + clrs = [i for i in dir(Graphic3d) if i.startswith("Graphic3d_NOM_")] color = random.sample(clrs, 1)[0] print("color", color) return Graphic3d.Graphic3d_MaterialAspect(getattr(Graphic3d, color)) @@ -280,38 +312,40 @@ def random_colored_material_aspect(): def random_color(): return color(random.random(), random.random(), random.random()) -#=========================================================================== + +# =========================================================================== # --- BUILD PATCHES --- -#=========================================================================== +# =========================================================================== def common_vertex(edg1, edg2): from OCC.Core.TopExp import topexp_CommonVertex + vert = TopoDS_Vertex() if topexp_CommonVertex(edg1, edg2, vert): return vert else: - raise ValueError('no common vertex found') + raise ValueError("no common vertex found") def midpoint(pntA, pntB): - ''' + """ computes the point that lies in the middle between pntA and pntB @param pntA: gp_Pnt @param pntB: gp_Pnt - ''' + """ vec1 = gp_Vec(pntA.XYZ()) vec2 = gp_Vec(pntB.XYZ()) - veccie = (vec1+vec2)/2. + veccie = (vec1 + vec2) / 2.0 return gp_Pnt(veccie.XYZ()) def center_boundingbox(shape): - ''' + """ compute the center point of a TopoDS_Shape, based on its bounding box @param shape: TopoDS_* instance returns a gp_Pnt instance - ''' + """ xmin, ymin, zmin, xmax, ymax, zmax = get_boundingbox(shape, 1e-6) return midpoint(gp_Pnt(xmin, ymin, zmin), gp_Pnt(xmax, ymax, zmax)) @@ -341,37 +375,40 @@ def point_in_solid(solid, pnt, tolerance=1e-5): """ from OCC.Core.BRepClass3d import BRepClass3d_SolidClassifier from OCC.Core.TopAbs import TopAbs_ON, TopAbs_OUT, TopAbs_IN + _in_solid = BRepClass3d_SolidClassifier(solid, pnt, tolerance) print("State", _in_solid.State()) if _in_solid.State() == TopAbs_ON: - return None, 'on' + return None, "on" if _in_solid.State() == TopAbs_OUT: - return False, 'out' + return False, "out" if _in_solid.State() == TopAbs_IN: - return True, 'in' + return True, "in" def intersection_from_three_planes(planeA, planeB, planeC): - ''' + """ intersection from 3 planes accepts both Geom_Plane and gp_Pln @param planeA: @param planeB: @param planeC: @param show: - ''' + """ from OCC.Core.IntAna import IntAna_Int3Pln - planeA = planeA if not hasattr(planeA, 'Pln') else planeA.Pln() - planeB = planeB if not hasattr(planeB, 'Pln') else planeB.Pln() - planeC = planeC if not hasattr(planeC, 'Pln') else planeC.Pln() + planeA = planeA if not hasattr(planeA, "Pln") else planeA.Pln() + planeB = planeB if not hasattr(planeB, "Pln") else planeB.Pln() + planeC = planeC if not hasattr(planeC, "Pln") else planeC.Pln() intersection_planes = IntAna_Int3Pln(planeA, planeB, planeC) pnt = intersection_planes.Value() return pnt -def intersect_shape_by_line(topods_shape, line, low_parameter=0.0, hi_parameter=float("+inf")): +def intersect_shape_by_line( + topods_shape, line, low_parameter=0.0, hi_parameter=float("+inf") +): """ finds the intersection of a shape and a line @@ -388,63 +425,84 @@ def intersect_shape_by_line(topods_shape, line, low_parameter=0.0, hi_parameter= :raise: """ from OCC.Core.IntCurvesFace import IntCurvesFace_ShapeIntersector + shape_inter = IntCurvesFace_ShapeIntersector() shape_inter.Load(topods_shape, TOLERANCE) shape_inter.PerformNearest(line, low_parameter, hi_parameter) with assert_isdone(shape_inter, "failed to computer shape / line intersection"): - return (shape_inter.Pnt(1), - shape_inter.Face(1), - shape_inter.UParameter(1), - shape_inter.VParameter(1), - shape_inter.WParameter(1)) + return ( + shape_inter.Pnt(1), + shape_inter.Face(1), + shape_inter.UParameter(1), + shape_inter.VParameter(1), + shape_inter.WParameter(1), + ) -def normal_vector_from_plane(plane, vec_length=1.): - ''' +def normal_vector_from_plane(plane, vec_length=1.0): + """ returns a vector normal to the plane of length vec_length @param plane: - ''' + """ trns = gp_Vec(plane.Axis().Direction()) return trns.Normalized() * vec_length -#=========================================================================== + +# =========================================================================== # FIX -#=========================================================================== +# =========================================================================== def fix_tolerance(shape, tolerance=TOLERANCE): from OCC.Core.ShapeFix import ShapeFix_ShapeTolerance + ShapeFix_ShapeTolerance().SetTolerance(shape, tolerance) def fix_continuity(edge, continuity=1): from OCC.Core.ShapeUpgrade import ShapeUpgrade_ShapeDivideContinuity + su = ShapeUpgrade_ShapeDivideContinuity(edge) - su.SetBoundaryCriterion(eval('GeomAbs_C'+str(continuity))) + su.SetBoundaryCriterion(eval("GeomAbs_C" + str(continuity))) su.Perform() te = st(su.Result()) return te -def resample_curve_with_uniform_deflection(curve, deflection=0.5, degreeMin=3, degreeMax=8, continuity=GeomAbs_C2, tolerance=1e-4): - ''' +def resample_curve_with_uniform_deflection( + curve, + deflection=0.5, + degreeMin=3, + degreeMax=8, + continuity=GeomAbs_C2, + tolerance=1e-4, +): + """ fits a bspline through the samples on `curve` @param curve: TopoDS_Wire, TopoDS_Edge, curve @param n_samples: - ''' + """ from OCC.Core.GCPnts import GCPnts_UniformDeflection + crv = to_adaptor_3d(curve) defl = GCPnts_UniformDeflection(crv, deflection) - with assert_isdone(defl, 'failed to compute UniformDeflection'): + with assert_isdone(defl, "failed to compute UniformDeflection"): print("Number of points:", defl.NbPoints()) sampled_pnts = [defl.Value(i) for i in range(1, defl.NbPoints())] - resampled_curve = GeomAPI_PointsToBSpline(point_list_to_TColgp_Array1OfPnt(sampled_pnts), degreeMin, degreeMax, continuity, tolerance) + resampled_curve = GeomAPI_PointsToBSpline( + point_list_to_TColgp_Array1OfPnt(sampled_pnts), + degreeMin, + degreeMax, + continuity, + tolerance, + ) return resampled_curve.Curve().GetObject() -#=========================================================================== + +# =========================================================================== # global properties -#=========================================================================== +# =========================================================================== class GpropsFromShape(object): @@ -453,42 +511,40 @@ def __init__(self, shape, tolerance=1e-5): self.tolerance = tolerance def volume(self): - '''returns the volume of a solid - ''' + """returns the volume of a solid""" prop = GProp_GProps() brepgprop_VolumeProperties(self.shape, prop, self.tolerance) return prop def surface(self): - '''returns the area of a surface - ''' + """returns the area of a surface""" prop = GProp_GProps() brepgprop_SurfaceProperties(self.shape, prop, self.tolerance) return prop def linear(self): - '''returns the length of a wire or edge - ''' + """returns the length of a wire or edge""" prop = GProp_GProps() brepgprop_LinearProperties(self.shape, prop) return prop def curve_length(crv): - ''' + """ get the length from a TopoDS_Edge or TopoDS_Wire - ''' - assert isinstance(crv, (TopoDS_Wire, TopoDS_Edge)), 'either a wire or edge...' + """ + assert isinstance(crv, (TopoDS_Wire, TopoDS_Edge)), "either a wire or edge..." gprop = GpropsFromShape(crv) return gprop.linear().Mass() -#======================================================================= +# ======================================================================= # Distance -#======================================================================= +# ======================================================================= + def minimum_distance(shp1, shp2): - ''' + """ compute minimum distance between 2 BREP's @param shp1: any TopoDS_* @param shp2: any TopoDS_* @@ -496,31 +552,32 @@ def minimum_distance(shp1, shp2): @return: minimum distance, minimum distance points on shp1 minimum distance points on shp2 - ''' + """ from OCC.Core.BRepExtrema import BRepExtrema_DistShapeShape + bdss = BRepExtrema_DistShapeShape(shp1, shp2) bdss.Perform() - with assert_isdone(bdss, 'failed computing minimum distances'): + with assert_isdone(bdss, "failed computing minimum distances"): min_dist = bdss.Value() min_dist_shp1, min_dist_shp2 = [], [] - for i in range(1, bdss.NbSolution()+1): + for i in range(1, bdss.NbSolution() + 1): min_dist_shp1.append(bdss.PointOnShape1(i)) min_dist_shp2.append(bdss.PointOnShape2(i)) return min_dist, min_dist_shp1, min_dist_shp2 def vertex2pnt(vertex): - '''returns a gp_Pnt from a TopoDS_Vertex - ''' + """returns a gp_Pnt from a TopoDS_Vertex""" from OCC.Core.Core.BRep import BRep_Tool + return BRep_Tool.Pnt(vertex) def adapt_edge_to_curve(edg): - ''' + """ returns a curve adaptor from an edge @param edg: TopoDS_Edge - ''' + """ return BRepAdaptor_Curve(edg) @@ -531,22 +588,25 @@ def adapt_edge_to_hcurve(edg): def to_adaptor_3d(curveType): - ''' + """ abstract curve like type into an adaptor3d @param curveType: - ''' + """ if isinstance(curveType, TopoDS_Wire): return BRepAdaptor_CompCurve(curveType) elif isinstance(curveType, TopoDS_Edge): return BRepAdaptor_Curve(curveType) elif issubclass(curveType.__class__, Geom_Curve): return GeomAdaptor_Curve(curveType) - elif hasattr(curveType, 'GetObject'): + elif hasattr(curveType, "GetObject"): _crv = curveType.GetObject() if issubclass(_crv.__class__, Geom_Curve): return GeomAdaptor_Curve(curveType) else: - raise TypeError('allowed types are Wire, Edge or a subclass of Geom_Curve\nGot a %s' % (curveType.__class__)) + raise TypeError( + "allowed types are Wire, Edge or a subclass of Geom_Curve\nGot a %s" + % (curveType.__class__) + ) def project_point_on_curve(crv, pnt): @@ -554,43 +614,47 @@ def project_point_on_curve(crv, pnt): # get the curve crv = adapt_edge_to_curve(crv).Curve().Curve() else: - raise NotImplementedError('expected a TopoDS_Edge...') + raise NotImplementedError("expected a TopoDS_Edge...") rrr = GeomAPI_ProjectPointOnCurve(pnt, crv) return rrr.LowerDistanceParameter(), rrr.NearestPoint() def project_point_on_plane(plane, point): - ''' + """ project point on plane @param plane: Geom_Plane @param point: gp_Pnt - ''' + """ from OCC.Core.ProjLib import projlib_Project + pl = plane.Pln() aa, bb = projlib_Project(pl, point).Coord() point = plane.Value(aa, bb) return point -def wire_to_curve(wire, tolerance=TOLERANCE, order=GeomAbs_C2, max_segment=200, max_order=12): - ''' +def wire_to_curve( + wire, tolerance=TOLERANCE, order=GeomAbs_C2, max_segment=200, max_order=12 +): + """ a wire can consist of many edges. these edges are merged given a tolerance and a curve @param wire: - ''' + """ adap = BRepAdaptor_CompCurve(wire) hadap = BRepAdaptor_CompCurve(adap) from OCC.Core.Approx import Approx_Curve3d + approx = Approx_Curve3d(hadap, tolerance, order, max_segment, max_order) - with assert_isdone(approx, 'not able to compute approximation from wire'): + with assert_isdone(approx, "not able to compute approximation from wire"): return approx.Curve().GetObject() def adapt_edge_to_curve(edg): - ''' + """ returns a curve adaptor from an edge @param edg: TopoDS_Edge - ''' + """ return BRepAdaptor_Curve(edg) diff --git a/OCCUtils/Construct.py b/OCCUtils/Construct.py index 7364db1..4e9587b 100644 --- a/OCCUtils/Construct.py +++ b/OCCUtils/Construct.py @@ -17,9 +17,9 @@ ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see . -''' +""" This modules makes the construction of geometry a little easier -''' +""" from __future__ import with_statement from functools import wraps @@ -33,32 +33,62 @@ from OCC.Core.Geom import Geom_TrimmedCurve from OCC.Core.GeomConvert import GeomConvert_ApproxCurve from OCC.Core.GeomLProp import GeomLProp_SLProps -from OCC.Core.BRepBuilderAPI import (BRepBuilderAPI_MakeFace, - BRepBuilderAPI_Transform, - BRepBuilderAPI_Sewing, - BRepBuilderAPI_MakePolygon, - BRepBuilderAPI_MakeWire, - BRepBuilderAPI_MakeSolid, - BRepBuilderAPI_MakeShell, - BRepBuilderAPI_MakeEdge2d, - BRepBuilderAPI_MakeEdge, - BRepBuilderAPI_MakeVertex, - BRepBuilderAPI_FindPlane) -from OCC.Core.BRepPrimAPI import (BRepPrimAPI_MakeBox, BRepPrimAPI_MakePrism) +from OCC.Core.BRepBuilderAPI import ( + BRepBuilderAPI_MakeFace, + BRepBuilderAPI_Transform, + BRepBuilderAPI_Sewing, + BRepBuilderAPI_MakePolygon, + BRepBuilderAPI_MakeWire, + BRepBuilderAPI_MakeSolid, + BRepBuilderAPI_MakeShell, + BRepBuilderAPI_MakeEdge2d, + BRepBuilderAPI_MakeEdge, + BRepBuilderAPI_MakeVertex, + BRepBuilderAPI_FindPlane, +) +from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakePrism from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakeEvolved -from OCC.Core.GeomAbs import (GeomAbs_Arc, GeomAbs_C2, GeomAbs_C0, GeomAbs_Tangent, - GeomAbs_Intersection, GeomAbs_G1, GeomAbs_G2, - GeomAbs_C1) +from OCC.Core.GeomAbs import ( + GeomAbs_Arc, + GeomAbs_C2, + GeomAbs_C0, + GeomAbs_Tangent, + GeomAbs_Intersection, + GeomAbs_G1, + GeomAbs_G2, + GeomAbs_C1, +) from OCC.Core.TopAbs import TopAbs_REVERSED -from OCC.Core.TopoDS import (TopoDS_Wire, TopoDS_Solid, TopoDS_Vertex, TopoDS_Shape, - TopoDS_Builder, TopoDS_Compound) +from OCC.Core.TopoDS import ( + TopoDS_Wire, + TopoDS_Solid, + TopoDS_Vertex, + TopoDS_Shape, + TopoDS_Builder, + TopoDS_Compound, +) from OCC.Core.TColgp import TColgp_SequenceOfVec, TColgp_HArray1OfPnt -from OCC.Core.gp import (gp_Vec, gp_Pnt, gp_Dir, gp_Trsf, gp_Ax1, gp_Quaternion, - gp_Circ, gp_Pln) - -from OCCUtils.Common import (TOLERANCE, assert_isdone, to_tcol_, to_adaptor_3d, - vertex2pnt, smooth_pnts, points_to_bspline, - project_point_on_curve) +from OCC.Core.gp import ( + gp_Vec, + gp_Pnt, + gp_Dir, + gp_Trsf, + gp_Ax1, + gp_Quaternion, + gp_Circ, + gp_Pln, +) + +from OCCUtils.Common import ( + TOLERANCE, + assert_isdone, + to_tcol_, + to_adaptor_3d, + vertex2pnt, + smooth_pnts, + points_to_bspline, + project_point_on_curve, +) from OCCUtils.types_lut import ShapeToTopology from OCCUtils.Topology import Topo @@ -88,18 +118,18 @@ def add_vector_to_point(self, vec): def gp_Pnt_get_state(self): - '''pack as a tuple + """pack as a tuple used for copying / serializing the instance - ''' + """ return self.XYZ().Coord() def gp_Pnt_set_state(self, state): - '''unpack tuple and return instance... + """unpack tuple and return instance... used for copying / serializing the instance - ''' + """ self.__init__(*state) @@ -111,7 +141,7 @@ def gp_pnt_print(self): x = self.X() y = self.Y() z = self.Z() - return '< gp_Pnt: {0}, {1}, {2} >'.format(x, y, z) + return "< gp_Pnt: {0}, {1}, {2} >".format(x, y, z) def gp_vec_print(self): @@ -119,13 +149,15 @@ def gp_vec_print(self): y = self.Y() z = self.Z() magn = self.Magnitude() - return '< gp_Vec: {0}, {1}, {2}, magnitude: {3} >'.format(x, y, z, magn) + return "< gp_Vec: {0}, {1}, {2}, magnitude: {3} >".format(x, y, z, magn) def gp_ax1_print(self): pX, pY, pZ = self.Location().Coord() dX, dY, dZ = self.Direction().Coord() - return "< gp_Ax1: location: {pX}, {pY}, {pZ}, direction: {dX}, {dY}, {dZ} >".format(**vars()) + return "< gp_Ax1: location: {pX}, {pY}, {pZ}, direction: {dX}, {dY}, {dZ} >".format( + **vars() + ) def gp_trsf_print(self): @@ -133,14 +165,18 @@ def gp_trsf_print(self): a, b, c, d = _f(1) e, f, g, h = _f(2) i, j, k, l = _f(3) - return "< gp_Trsf:\n {a:.3f}, {b:.3f}, {c:.3f}, {d:.3f}\n {e:.3f}, {f:.3f}, {g:.3f}, {h:.3f}\n {i:.3f}, {j:.3f}, {k:.3f}, {l:.3f} >".format(**vars()) + return "< gp_Trsf:\n {a:.3f}, {b:.3f}, {c:.3f}, {d:.3f}\n {e:.3f}, {f:.3f}, {g:.3f}, {h:.3f}\n {i:.3f}, {j:.3f}, {k:.3f}, {l:.3f} >".format( + **vars() + ) def gp_quat_print(self): w, x, y, z = self.W(), self.X(), self.Y(), self.Z() vec = gp_Vec() angle = math.degrees(self.GetVectorAndAngle(vec)) - return "< gp_Quaternion: w:{w}, x:{x}, y:{y}, z:{z} >\nvector:{vec} angle:{angle}".format(**vars()) + return "< gp_Quaternion: w:{w}, x:{x}, y:{y}, z:{z} >\nvector:{vec} angle:{angle}".format( + **vars() + ) def _apply(pnt, other, _operator): @@ -190,21 +226,21 @@ def gp_pnt_div(self, other): gp_Trsf.__str__ = gp_trsf_print gp_Quaternion.__repr__ = gp_quat_print gp_Quaternion.__str__ = gp_quat_print -#gp_Pnt.__eq__ = gp_equal +# gp_Pnt.__eq__ = gp_equal gp_Pnt.__add__ = gp_pnt_add gp_Pnt.__sub__ = gp_pnt_sub gp_Pnt.__mul__ = gp_pnt_mul gp_Pnt.__div__ = gp_pnt_div -#=========================================================================== +# =========================================================================== # ---TOPOLOGY--- -#=========================================================================== +# =========================================================================== @wraps(BRepBuilderAPI_MakeSolid) def make_solid(*args): sld = BRepBuilderAPI_MakeSolid(*args) - with assert_isdone(sld, 'failed to produce solid'): + with assert_isdone(sld, "failed to produce solid"): result = sld.Solid() return result @@ -213,7 +249,7 @@ def make_solid(*args): def make_shell(*args): shell = BRepBuilderAPI_MakeShell(*args) st = ShapeToTopology() - with assert_isdone(shell, 'failed to produce shell'): + with assert_isdone(shell, "failed to produce shell"): result = shell.Shell() return st(result) @@ -221,7 +257,7 @@ def make_shell(*args): @wraps(BRepBuilderAPI_MakeFace) def make_face(*args): face = BRepBuilderAPI_MakeFace(*args) - with assert_isdone(face, 'failed to produce face'): + with assert_isdone(face, "failed to produce face"): result = face.Face() return result @@ -229,7 +265,7 @@ def make_face(*args): @wraps(BRepBuilderAPI_MakeEdge2d) def make_edge2d(*args): edge = BRepBuilderAPI_MakeEdge2d(*args) - with assert_isdone(edge, 'failed to produce edge'): + with assert_isdone(edge, "failed to produce edge"): result = edge.Edge() return result @@ -237,7 +273,7 @@ def make_edge2d(*args): @wraps(BRepBuilderAPI_MakeEdge) def make_edge(*args): edge = BRepBuilderAPI_MakeEdge(*args) - with assert_isdone(edge, 'failed to produce edge'): + with assert_isdone(edge, "failed to produce edge"): result = edge.Edge() return result @@ -245,10 +281,11 @@ def make_edge(*args): @wraps(BRepBuilderAPI_MakeVertex) def make_vertex(*args): vert = BRepBuilderAPI_MakeVertex(*args) - with assert_isdone(vert, 'failed to produce vertex'): + with assert_isdone(vert, "failed to produce vertex"): result = vert.Vertex() return result + @wraps(BRepBuilderAPI_MakeWire) def make_wire(*args): # if we get an iterable, than add all edges to wire builder @@ -261,7 +298,7 @@ def make_wire(*args): wire = BRepBuilderAPI_MakeWire(*args) wire.Build() - with assert_isdone(wire, 'failed to produce wire'): + with assert_isdone(wire, "failed to produce wire"): result = wire.Wire() return result @@ -280,7 +317,7 @@ def make_polygon(args, closed=False): poly.Close() poly.Build() - with assert_isdone(poly, 'failed to produce wire'): + with assert_isdone(poly, "failed to produce wire"): result = poly.Wire() return result @@ -296,21 +333,22 @@ def make_closed_polygon(*args): poly.Add(pt) poly.Build() poly.Close() - with assert_isdone(poly, 'failed to produce wire'): + with assert_isdone(poly, "failed to produce wire"): result = poly.Wire() return result -#=========================================================================== + +# =========================================================================== # PRIMITIVES -#=========================================================================== +# =========================================================================== def make_circle(pnt, radius): - ''' + """ returns an edge @param pnt: @param radius: - ''' + """ circ = gp_Circ() circ.SetLocation(pnt) circ.SetRadius(radius) @@ -323,55 +361,65 @@ def make_line(pnt1, pnt2): def make_evolved(spine, profile): evol = BRepOffsetAPI_MakeEvolved(spine, profile) - with assert_isdone(evol, 'failed buillding evolved'): + with assert_isdone(evol, "failed buillding evolved"): evol.Build() return evol.Evolved() def make_pipe(spine, profile): from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakePipe + pipe = BRepOffsetAPI_MakePipe(spine, profile) - with assert_isdone(pipe, 'failed building pipe'): + with assert_isdone(pipe, "failed building pipe"): pipe.Build() return pipe.Shape() def make_prism(profile, vec): - ''' + """ makes a finite prism - ''' + """ pri = BRepPrimAPI_MakePrism(profile, vec, True) - with assert_isdone(pri, 'failed building prism'): + with assert_isdone(pri, "failed building prism"): pri.Build() return pri.Shape() -def make_offset_shape(shapeToOffset, offsetDistance, tolerance=TOLERANCE, - offsetMode=BRepOffset_Skin, intersection=False, - selfintersection=False, joinType=GeomAbs_Arc): - ''' +def make_offset_shape( + shapeToOffset, + offsetDistance, + tolerance=TOLERANCE, + offsetMode=BRepOffset_Skin, + intersection=False, + selfintersection=False, + joinType=GeomAbs_Arc, +): + """ builds an offsetted shell from a shape construct an offsetted version of the shape - ''' + """ from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakeOffsetShape + try: - offset = BRepOffsetAPI_MakeOffsetShape(shapeToOffset, - offsetDistance, - tolerance, - offsetMode, - intersection, - selfintersection, - joinType) + offset = BRepOffsetAPI_MakeOffsetShape( + shapeToOffset, + offsetDistance, + tolerance, + offsetMode, + intersection, + selfintersection, + joinType, + ) if offset.IsDone(): return offset.Shape() else: return None - except RuntimeError('failed to offset shape'): + except RuntimeError("failed to offset shape"): return None def make_offset(wire_or_face, offsetDistance, altitude=0, joinType=GeomAbs_Arc): - ''' + """ builds a offsetted wire or face from a wire or face construct an offsetted version of the shape @@ -384,10 +432,11 @@ def make_offset(wire_or_face, offsetDistance, altitude=0, joinType=GeomAbs_Arc): note: a shape that has a negative offsetDistance will return a sharp corner - ''' + """ from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakeOffset + _joints = [GeomAbs_Arc, GeomAbs_Tangent, GeomAbs_Intersection] - assert joinType in _joints, '%s is not one of %s' % (joinType, _joints) + assert joinType in _joints, "%s is not one of %s" % (joinType, _joints) try: offset = BRepOffsetAPI_MakeOffset(wire_or_face, joinType) offset.Perform(offsetDistance, altitude) @@ -395,12 +444,19 @@ def make_offset(wire_or_face, offsetDistance, altitude=0, joinType=GeomAbs_Arc): return ST(offset.Shape()) else: return None - except RuntimeError('failed to offset shape'): + except RuntimeError("failed to offset shape"): return None -def make_loft(elements, ruled=False, tolerance=TOLERANCE, continuity=GeomAbs_C2, check_compatibility=True): +def make_loft( + elements, + ruled=False, + tolerance=TOLERANCE, + continuity=GeomAbs_C2, + check_compatibility=True, +): from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_ThruSections + sections = BRepOffsetAPI_ThruSections(False, ruled, tolerance) for i in elements: if isinstance(i, TopoDS_Wire): @@ -408,12 +464,15 @@ def make_loft(elements, ruled=False, tolerance=TOLERANCE, continuity=GeomAbs_C2, elif isinstance(i, TopoDS_Vertex): sections.AddVertex(i) else: - raise TypeError('elements is a list of TopoDS_Wire or TopoDS_Vertex, found a %s fool' % i.__class__) + raise TypeError( + "elements is a list of TopoDS_Wire or TopoDS_Vertex, found a %s fool" + % i.__class__ + ) sections.CheckCompatibility(check_compatibility) sections.SetContinuity(continuity) sections.Build() - with assert_isdone(sections, 'failed lofting'): + with assert_isdone(sections, "failed lofting"): te = ShapeToTopology() loft = te(sections.Shape()) return loft @@ -421,24 +480,23 @@ def make_loft(elements, ruled=False, tolerance=TOLERANCE, continuity=GeomAbs_C2, def make_ruled(edgeA, edgeB): from OCC.Core.BRepFill import brepfill_Face + return brepfill_Face(edgeA, edgeB) -def make_plane(center=gp_Pnt(0, 0, 0), - vec_normal=gp_Vec(0, 0, 1), - extent_x_min=-100., - extent_x_max=100., - extent_y_min=-100., - extent_y_max=100., - depth=0.): +def make_plane( + center=gp_Pnt(0, 0, 0), + vec_normal=gp_Vec(0, 0, 1), + extent_x_min=-100.0, + extent_x_max=100.0, + extent_y_min=-100.0, + extent_y_max=100.0, + depth=0.0, +): if depth != 0: center = center.add_vec(gp_Vec(0, 0, depth)) PL = gp_Pln(center, vec_normal.as_dir()) - face = make_face(PL, - extent_x_min, - extent_x_max, - extent_y_min, - extent_y_max) + face = make_face(PL, extent_x_min, extent_x_max, extent_y_min, extent_y_max) return face @@ -455,9 +513,13 @@ def make_oriented_box(v_corner, v_x, v_y, v_z): :return: TopoDS_Solid """ from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakePipe - verts = map(lambda x: x.as_pnt(), [v_corner, v_corner+v_x, v_corner+v_x+v_y, v_corner+v_y]) + + verts = map( + lambda x: x.as_pnt(), + [v_corner, v_corner + v_x, v_corner + v_x + v_y, v_corner + v_y], + ) p = make_polygon(verts, closed=True) - li = make_line(v_corner.as_pnt(), (v_corner+v_z).as_pnt()) + li = make_line(v_corner.as_pnt(), (v_corner + v_z).as_pnt()) bmp = BRepOffsetAPI_MakePipe(p, li) bmp.Build() shp = bmp.Shape() @@ -472,7 +534,7 @@ def make_oriented_box(v_corner, v_x, v_y, v_z): def make_box(*args): box = BRepPrimAPI_MakeBox(*args) box.Build() - with assert_isdone(box, 'failed to built a cube...'): + with assert_isdone(box, "failed to built a cube..."): return box.Shape() @@ -502,6 +564,7 @@ def make_n_sided(edges, points, continuity=GeomAbs_C0): :return: TopoDS_Face """ from OCC.Core.BRepFill import BRepFill_Filling + n_sided = BRepFill_Filling() for edg in edges: n_sided.Add(edg, continuity) @@ -515,6 +578,7 @@ def make_n_sided(edges, points, continuity=GeomAbs_C0): def make_n_sections(edges): from OCC.Core.TopTools import TopTools_SequenceOfShape from OCC.Core.BRepFill import BRepFill_NSections + seq = TopTools_SequenceOfShape() for i in edges: seq.Append(i) @@ -524,6 +588,7 @@ def make_n_sections(edges): def make_coons(edges): from OCC.GeomFill import GeomFill_BSplineCurves, GeomFill_StretchStyle + if len(edges) == 4: spl1, spl2, spl3, spl4 = edges srf = GeomFill_BSplineCurves(spl1, spl2, spl3, spl4, GeomFill_StretchStyle) @@ -534,16 +599,17 @@ def make_coons(edges): spl1, spl2 = edges srf = GeomFill_BSplineCurves(spl1, spl2, GeomFill_StretchStyle) else: - raise ValueError('give 2,3 or 4 curves') + raise ValueError("give 2,3 or 4 curves") return srf.Surface() def make_constrained_surface_from_edges(edges): - ''' + """ DOESNT RESPECT BOUNDARIES - ''' + """ from OCC.GeomPlate import GeomPlate_MakeApprox, GeomPlate_BuildPlateSurface from OCC.Core.BRepFill import BRepFill_CurveConstraint + bpSrf = GeomPlate_BuildPlateSurface(3, 15, 2) for edg in edges: c = BRepAdaptor_Curve() @@ -561,13 +627,13 @@ def make_constrained_surface_from_edges(edges): def add_wire_to_face(face, wire, reverse=False): - ''' + """ apply a wire to a face use reverse to set the orientation of the wire to opposite @param face: @param wire: @param reverse: - ''' + """ face = BRepBuilderAPI_MakeFace(face) if reverse: wire.Reverse() @@ -592,25 +658,28 @@ def sew_shapes(shapes, tolerance=0.001): result = ShapeToTopology()(sew.SewedShape()) return result -#=========================================================================== + +# =========================================================================== # ---BOOL--- -#=========================================================================== +# =========================================================================== def boolean_cut(shapeToCutFrom, cuttingShape): from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut + try: cut = BRepAlgoAPI_Cut(shapeToCutFrom, cuttingShape) print("Can work?", cut.BuilderCanWork()) - _error = {0: '- Ok', - 1: '- The Object is created but Nothing is Done', - 2: '- Null source shapes is not allowed', - 3: '- Check types of the arguments', - 4: '- Can not allocate memory for the DSFiller', - 5: '- The Builder can not work with such types of arguments', - 6: '- Unknown operation is not allowed', - 7: '- Can not allocate memory for the Builder', - } + _error = { + 0: "- Ok", + 1: "- The Object is created but Nothing is Done", + 2: "- Null source shapes is not allowed", + 3: "- Check types of the arguments", + 4: "- Can not allocate memory for the DSFiller", + 5: "- The Builder can not work with such types of arguments", + 6: "- Unknown operation is not allowed", + 7: "- Can not allocate memory for the Builder", + } print("Error status:", _error[cut.ErrorStatus()]) cut.RefineEdges() cut.FuseEdges() @@ -624,6 +693,7 @@ def boolean_cut(shapeToCutFrom, cuttingShape): def boolean_fuse(shapeToCutFrom, joiningShape): from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse + join = BRepAlgoAPI_Fuse(shapeToCutFrom, joiningShape) join.RefineEdges() join.FuseEdges() @@ -633,30 +703,34 @@ def boolean_fuse(shapeToCutFrom, joiningShape): def trim_wire(wire, shapeLimit1, shapeLimit2, periodic=False): - '''return the trimmed wire that lies between `shapeLimit1` + """return the trimmed wire that lies between `shapeLimit1` and `shapeLimit2` returns TopoDS_Edge - ''' + """ adap = to_adaptor_3d(wire) bspl = adap.BSpline() if periodic: if bspl.IsClosed(): bspl.SetPeriodic() else: - warnings.warn('the wire to be trimmed is not closed, hence cannot be made periodic') + warnings.warn( + "the wire to be trimmed is not closed, hence cannot be made periodic" + ) p1 = project_point_on_curve(bspl, shapeLimit1)[0] p2 = project_point_on_curve(bspl, shapeLimit2)[0] a, b = sorted([p1, p2]) tr = Geom_TrimmedCurve(bspl, a, b) return make_edge(tr) -#=========================================================================== + +# =========================================================================== # ---FIXES--- -#=========================================================================== +# =========================================================================== def fix_shape(shp, tolerance=1e-3): from OCC.ShapeFix import ShapeFix_Shape + fix = ShapeFix_Shape(shp) fix.SetFixFreeShellMode(True) sf = fix.FixShellTool() @@ -668,23 +742,25 @@ def fix_shape(shp, tolerance=1e-3): def fix_face(shp, tolerance=1e-3): from OCC.ShapeFix import ShapeFix_Face + fix = ShapeFix_Face(shp) fix.SetMaxTolerance(tolerance) fix.Perform() return fix.Face() -#=========================================================================== + +# =========================================================================== # --- TRANSFORM --- -#=========================================================================== +# =========================================================================== def translate_topods_from_vector(brep_or_iterable, vec, copy=False): - ''' + """ translate a brep over a vector @param brep: the Topo_DS to translate @param vec: the vector defining the translation @param copy: copies to brep if True - ''' + """ st = ShapeToTopology() trns = gp_Trsf() trns.SetTranslation(vec) @@ -693,17 +769,20 @@ def translate_topods_from_vector(brep_or_iterable, vec, copy=False): brep_trns.Build() return st(brep_trns.Shape()) else: - return [translate_topods_from_vector(brep_or_iterable, vec, copy) for i in brep_or_iterable] + return [ + translate_topods_from_vector(brep_or_iterable, vec, copy) + for i in brep_or_iterable + ] def scale_uniformal(brep, pnt, factor, copy=False): - ''' + """ translate a brep over a vector @param brep: the Topo_DS to translate @param pnt: a gp_Pnt @param triple: scaling factor @param copy: copies to brep if True - ''' + """ trns = gp_Trsf() trns.SetScale(pnt, factor) brep_trns = BRepBuilderAPI_Transform(brep, trns, copy) @@ -712,55 +791,60 @@ def scale_uniformal(brep, pnt, factor, copy=False): def mirror_pnt_dir(brep, pnt, direction, copy=False): - ''' + """ @param brep: @param line: - ''' + """ trns = gp_Trsf() trns.SetMirror(gp_Ax1(pnt, direction)) brep_trns = BRepBuilderAPI_Transform(brep, trns, copy) - with assert_isdone(brep_trns, 'could not produce mirror'): + with assert_isdone(brep_trns, "could not produce mirror"): brep_trns.Build() return brep_trns.Shape() def mirror_axe2(brep, axe2, copy=False): - ''' + """ @param brep: @param line: - ''' + """ trns = gp_Trsf() trns.SetMirror(axe2) brep_trns = BRepBuilderAPI_Transform(brep, trns, copy) - with assert_isdone(brep_trns, 'could not produce mirror'): + with assert_isdone(brep_trns, "could not produce mirror"): brep_trns.Build() return brep_trns.Shape() def rotate(brep, axe, degree, copy=False): - ''' + """ @param brep: @param axe: @param degree: - ''' + """ from math import radians + trns = gp_Trsf() trns.SetRotation(axe, radians(degree)) brep_trns = BRepBuilderAPI_Transform(brep, trns, copy) - with assert_isdone(brep_trns, 'could not produce rotation'): + with assert_isdone(brep_trns, "could not produce rotation"): brep_trns.Build() return ST(brep_trns.Shape()) -#============================================================================= + +# ============================================================================= # Not so sure where this should be located -#============================================================================= +# ============================================================================= def face_normal(face): from OCC.Core.BRepTools import breptools_UVBounds + umin, umax, vmin, vmax = breptools_UVBounds(face) surf = BRep_Tool().Surface(face) - props = GeomLProp_SLProps(surf, (umin+umax)/2., (vmin+vmax)/2., 1, TOLERANCE) + props = GeomLProp_SLProps( + surf, (umin + umax) / 2.0, (vmin + vmax) / 2.0, 1, TOLERANCE + ) norm = props.Normal() if face.Orientation() == TopAbs_REVERSED: norm.Reverse() @@ -769,7 +853,12 @@ def face_normal(face): def face_from_plane(_geom_plane, lowerLimit=-1000, upperLimit=1000): from OCC.Geom import Geom_RectangularTrimmedSurface - _trim_plane = make_face(Geom_RectangularTrimmedSurface(_geom_plane, lowerLimit, upperLimit, lowerLimit, upperLimit)) + + _trim_plane = make_face( + Geom_RectangularTrimmedSurface( + _geom_plane, lowerLimit, upperLimit, lowerLimit, upperLimit + ) + ) return _trim_plane @@ -781,7 +870,7 @@ def find_plane_from_shape(shape, tolerance=-1): else: return None except: - raise AssertionError('couldnt find plane in %s' % (shape)) + raise AssertionError("couldnt find plane in %s" % (shape)) def fit_plane_through_face_vertices(_face): @@ -791,7 +880,9 @@ def fit_plane_through_face_vertices(_face): """ from OCC.GeomPlate import GeomPlate_BuildAveragePlane - uvs_from_vertices = [_face.project_vertex(vertex2pnt(i)) for i in Topo(_face).vertices()] + uvs_from_vertices = [ + _face.project_vertex(vertex2pnt(i)) for i in Topo(_face).vertices() + ] normals = [gp_Vec(_face.DiffGeom.normal(*uv[0])) for uv in uvs_from_vertices] points = [i[1] for i in uvs_from_vertices] @@ -813,21 +904,26 @@ def project_edge_onto_plane(edg, plane): :return: TopoDS_Edge projected on the plane """ from OCC.GeomProjLib import geomprojlib_ProjectOnPlane - proj = geomprojlib_ProjectOnPlane(edg.adaptor.Curve().Curve(), plane, plane.Axis().Direction(), 1) + + proj = geomprojlib_ProjectOnPlane( + edg.adaptor.Curve().Curve(), plane, plane.Axis().Direction(), 1 + ) return make_edge(proj) -def curve_to_bspline(crv, tolerance=TOLERANCE, continuity=GeomAbs_C1, sections=300, degree=12): +def curve_to_bspline( + crv, tolerance=TOLERANCE, continuity=GeomAbs_C1, sections=300, degree=12 +): approx_curve = GeomConvert_ApproxCurve(crv, tolerance, continuity, sections, degree) - with assert_isdone(approx_curve, 'could not compute bspline from curve'): + with assert_isdone(approx_curve, "could not compute bspline from curve"): return approx_curve.Curve() def compound(topo): - ''' + """ accumulate a bunch of TopoDS_* in list `topo` to a TopoDS_Compound @param topo: list of TopoDS_* instances - ''' + """ bd = TopoDS_Builder() comp = TopoDS_Compound() bd.MakeCompound(comp) @@ -836,7 +932,9 @@ def compound(topo): return comp -def geodesic_path(pntA, pntB, edgA, edgB, kbe_face, n_segments=20, _tolerance=0.1, n_iter=20): +def geodesic_path( + pntA, pntB, edgA, edgB, kbe_face, n_segments=20, _tolerance=0.1, n_iter=20 +): """ :param pntA: point to start from :param pntB: point to move towards @@ -854,12 +952,14 @@ def geodesic_path(pntA, pntB, edgA, edgB, kbe_face, n_segments=20, _tolerance=0. path = [] for i in range(n_segments): t = i / float(n_segments) - u = uvA[0] + t*(uvB[0] - uvA[0]) - v = uvA[1] + t*(uvB[1] - uvA[1]) + u = uvA[0] + t * (uvB[0] - uvA[0]) + v = uvA[1] + t * (uvB[1] - uvA[1]) path.append(kbe_face.parameter_to_point(u, v)) project_pnts = lambda x: [kbe_face.project_vertex(i)[1] for i in x] - poly_length = lambda x: sum([x[i].Distance(x[i+1]) for i in range(len(x)-1)]) / len(x) + poly_length = lambda x: sum( + [x[i].Distance(x[i + 1]) for i in range(len(x) - 1)] + ) / len(x) length = poly_length(path) @@ -868,7 +968,7 @@ def geodesic_path(pntA, pntB, edgA, edgB, kbe_face, n_segments=20, _tolerance=0. path = smooth_pnts(path) path = project_pnts(path) newlength = poly_length(path) - if abs(newlength-length) < _tolerance or n == n_iter: + if abs(newlength - length) < _tolerance or n == n_iter: crv = points_to_bspline(path) return make_edge(crv) n += 1 diff --git a/OCCUtils/Image.py b/OCCUtils/Image.py index 898014e..2ad4f82 100644 --- a/OCCUtils/Image.py +++ b/OCCUtils/Image.py @@ -26,6 +26,7 @@ class Texture(object): This class encapsulates the necessary texture properties: Filename, toScaleU, etc. """ + def __init__(self, filename): if not os.path.isfile(filename): raise IOError("File %s not found.\n" % filename) @@ -50,7 +51,12 @@ def TextureOrigin(self, originU, originV): self._originV = originV def GetProperties(self): - return (self._filename, - self._toScaleU, self._toScaleV, - self._toRepeatU, self._toRepeatV, - self._originU, self._originV) + return ( + self._filename, + self._toScaleU, + self._toScaleV, + self._toRepeatU, + self._toRepeatV, + self._originU, + self._originV, + ) diff --git a/OCCUtils/Iteration.py b/OCCUtils/Iteration.py index 9d4486a..be81b17 100644 --- a/OCCUtils/Iteration.py +++ b/OCCUtils/Iteration.py @@ -15,9 +15,9 @@ ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see . -''' +""" This module helps looping through topology -''' +""" from OCC.Core.BRep import BRep_Tool from OCCUtils.Topology import WireExplorer, Topo @@ -25,9 +25,10 @@ class EdgePairsFromWire(object): - ''' + """ helper class to loop through a wire and return ordered pairs of edges - ''' + """ + def __init__(self, wire): self.wire = wire self.edge_pairs = [] @@ -44,10 +45,10 @@ def next(self): # first edge, need to set self.previous_edge self.previous_edge = next(self.we) self.current_edge = next(self.we) - self.first_edge = self.previous_edge # for the last iteration + self.first_edge = self.previous_edge # for the last iteration self.index += 1 return [self.previous_edge, self.current_edge] - elif self.index == self.number_of_edges-1: + elif self.index == self.number_of_edges - 1: # no next edge self.index += 1 return [self.current_edge, self.first_edge] @@ -62,10 +63,11 @@ def __iter__(self): class LoopWirePairs(object): - ''' + """ for looping through consequtive wires assures that the returned edge pairs are ordered - ''' + """ + def __init__(self, wireA, wireB): self.wireA = wireA self.wireB = wireB diff --git a/OCCUtils/Topology.py b/OCCUtils/Topology.py index 52ad4f1..adcb679 100644 --- a/OCCUtils/Topology.py +++ b/OCCUtils/Topology.py @@ -19,30 +19,50 @@ from __future__ import print_function -__all__ = ['Topo', 'WireExplorer', 'dumpTopology'] +__all__ = ["Topo", "WireExplorer", "dumpTopology"] from OCC.Core.BRep import BRep_Tool from OCC.Core.BRepTools import BRepTools_WireExplorer -from OCC.Core.TopAbs import (TopAbs_VERTEX, TopAbs_EDGE, TopAbs_FACE, TopAbs_WIRE, - TopAbs_SHELL, TopAbs_SOLID, TopAbs_COMPOUND, - TopAbs_COMPSOLID) +from OCC.Core.TopAbs import ( + TopAbs_VERTEX, + TopAbs_EDGE, + TopAbs_FACE, + TopAbs_WIRE, + TopAbs_SHELL, + TopAbs_SOLID, + TopAbs_COMPOUND, + TopAbs_COMPSOLID, +) from OCC.Core.TopExp import TopExp_Explorer, topexp_MapShapesAndAncestors -from OCC.Core.TopTools import (TopTools_ListOfShape, - TopTools_ListIteratorOfListOfShape, - TopTools_IndexedDataMapOfShapeListOfShape) -from OCC.Core.TopoDS import (topods, TopoDS_Wire, TopoDS_Vertex, TopoDS_Edge, - TopoDS_Face, TopoDS_Shell, TopoDS_Solid, - TopoDS_Compound, TopoDS_CompSolid, topods_Edge, - topods_Vertex, TopoDS_Iterator) +from OCC.Core.TopTools import ( + TopTools_ListOfShape, + TopTools_ListIteratorOfListOfShape, + TopTools_IndexedDataMapOfShapeListOfShape, +) +from OCC.Core.TopoDS import ( + topods, + TopoDS_Wire, + TopoDS_Vertex, + TopoDS_Edge, + TopoDS_Face, + TopoDS_Shell, + TopoDS_Solid, + TopoDS_Compound, + TopoDS_CompSolid, + topods_Edge, + topods_Vertex, + TopoDS_Iterator, +) class WireExplorer(object): - ''' + """ Wire traversal - ''' + """ + def __init__(self, wire): - assert isinstance(wire, TopoDS_Wire), 'not a TopoDS_Wire' + assert isinstance(wire, TopoDS_Wire), "not a TopoDS_Wire" self.wire = wire self.wire_explorer = BRepTools_WireExplorer(self.wire) self.done = False @@ -88,9 +108,9 @@ def ordered_vertices(self): class Topo(object): - ''' + """ Topology traversal - ''' + """ def __init__(self, myShape, ignore_orientation=False): """ @@ -133,26 +153,33 @@ def __init__(self, myShape, ignore_orientation=False): TopAbs_SHELL: topods.Shell, TopAbs_SOLID: topods.Solid, TopAbs_COMPOUND: topods.Compound, - TopAbs_COMPSOLID: topods.CompSolid + TopAbs_COMPSOLID: topods.CompSolid, } - def _loop_topo(self, topologyType, topologicalEntity=None, topologyTypeToAvoid=None): - ''' + def _loop_topo( + self, topologyType, topologicalEntity=None, topologyTypeToAvoid=None + ): + """ this could be a faces generator for a python TopoShape class that way you can just do: for face in srf.faces: processFace(face) - ''' - topoTypes = {TopAbs_VERTEX: TopoDS_Vertex, - TopAbs_EDGE: TopoDS_Edge, - TopAbs_FACE: TopoDS_Face, - TopAbs_WIRE: TopoDS_Wire, - TopAbs_SHELL: TopoDS_Shell, - TopAbs_SOLID: TopoDS_Solid, - TopAbs_COMPOUND: TopoDS_Compound, - TopAbs_COMPSOLID: TopoDS_CompSolid} - - assert topologyType in topoTypes.keys(), '%s not one of %s' % (topologyType, topoTypes.keys()) + """ + topoTypes = { + TopAbs_VERTEX: TopoDS_Vertex, + TopAbs_EDGE: TopoDS_Edge, + TopAbs_FACE: TopoDS_Face, + TopAbs_WIRE: TopoDS_Wire, + TopAbs_SHELL: TopoDS_Shell, + TopAbs_SOLID: TopoDS_Solid, + TopAbs_COMPOUND: TopoDS_Compound, + TopAbs_COMPSOLID: TopoDS_CompSolid, + } + + assert topologyType in topoTypes.keys(), "%s not one of %s" % ( + topologyType, + topoTypes.keys(), + ) self.topExp = TopExp_Explorer() # use self.myShape if nothing is specified if topologicalEntity is None and topologyTypeToAvoid is None: @@ -162,9 +189,7 @@ def _loop_topo(self, topologyType, topologicalEntity=None, topologyTypeToAvoid=N elif topologyTypeToAvoid is None: self.topExp.Init(topologicalEntity, topologyType) elif topologyTypeToAvoid: - self.topExp.Init(topologicalEntity, - topologyType, - topologyTypeToAvoid) + self.topExp.Init(topologicalEntity, topologyType, topologyTypeToAvoid) seq = [] hashes = [] # list that stores hashes to avoid redundancy occ_seq = TopTools_ListOfShape() @@ -201,9 +226,9 @@ def _loop_topo(self, topologyType, topologicalEntity=None, topologyTypeToAvoid=N return iter(seq) def faces(self): - ''' + """ loops over all faces - ''' + """ return self._loop_topo(TopAbs_FACE) def _number_of_topo(self, iterable): @@ -216,72 +241,72 @@ def number_of_faces(self): return self._number_of_topo(self.faces()) def vertices(self): - ''' + """ loops over all vertices - ''' + """ return self._loop_topo(TopAbs_VERTEX) def number_of_vertices(self): return self._number_of_topo(self.vertices()) def edges(self): - ''' + """ loops over all edges - ''' + """ return self._loop_topo(TopAbs_EDGE) def number_of_edges(self): return self._number_of_topo(self.edges()) def wires(self): - ''' + """ loops over all wires - ''' + """ return self._loop_topo(TopAbs_WIRE) def number_of_wires(self): return self._number_of_topo(self.wires()) def shells(self): - ''' + """ loops over all shells - ''' + """ return self._loop_topo(TopAbs_SHELL, None) def number_of_shells(self): return self._number_of_topo(self.shells()) def solids(self): - ''' + """ loops over all solids - ''' + """ return self._loop_topo(TopAbs_SOLID, None) def number_of_solids(self): return self._number_of_topo(self.solids()) def comp_solids(self): - ''' + """ loops over all compound solids - ''' + """ return self._loop_topo(TopAbs_COMPSOLID) def number_of_comp_solids(self): return self._number_of_topo(self.comp_solids()) def compounds(self): - ''' + """ loops over all compounds - ''' + """ return self._loop_topo(TopAbs_COMPOUND) def number_of_compounds(self): return self._number_of_topo(self.compounds()) def ordered_vertices_from_wire(self, wire): - ''' + """ @param wire: TopoDS_Wire - ''' + """ we = WireExplorer(wire) return we.ordered_vertices() @@ -289,9 +314,9 @@ def number_of_ordered_vertices_from_wire(self, wire): return self._number_of_topo(self.ordered_vertices_from_wire(wire)) def ordered_edges_from_wire(self, wire): - ''' + """ @param wire: TopoDS_Wire - ''' + """ we = WireExplorer(wire) return we.ordered_edges() @@ -299,12 +324,12 @@ def number_of_ordered_edges_from_wire(self, wire): return self._number_of_topo(self.ordered_edges_from_wire(wire)) def _map_shapes_and_ancestors(self, topoTypeA, topoTypeB, topologicalEntity): - ''' + """ using the same method @param topoTypeA: @param topoTypeB: @param topologicalEntity: - ''' + """ topo_set = set() _map = TopTools_IndexedDataMapOfShapeListOfShape() topexp_MapShapesAndAncestors(self.myShape, topoTypeA, topoTypeB, _map) @@ -335,14 +360,14 @@ def _map_shapes_and_ancestors(self, topoTypeA, topoTypeB, topologicalEntity): topology_iterator.Next() def _number_shapes_ancestors(self, topoTypeA, topoTypeB, topologicalEntity): - '''returns the number of shape ancestors + """returns the number of shape ancestors If you want to know how many edges a faces has: _number_shapes_ancestors(self, TopAbs_EDGE, TopAbs_FACE, edg) - will return the number of edges a faces has + will return the number of edges a faces has @param topoTypeA: @param topoTypeB: @param topologicalEntity: - ''' + """ topo_set = set() _map = TopTools_IndexedDataMapOfShapeListOfShape() topexp_MapShapesAndAncestors(self.myShape, topoTypeA, topoTypeB, _map) @@ -484,13 +509,16 @@ def number_of_faces_from_solids(self, solid): def dumpTopology(shape, level=0): """ - Print the details of an object from the top down + Print the details of an object from the top down """ brt = BRep_Tool() s = shape.ShapeType() if s == TopAbs_VERTEX: pnt = brt.Pnt(topods_Vertex(shape)) - print(".." * level + "" % (hash(shape), pnt.X(), pnt.Y(), pnt.Z())) + print( + ".." * level + + "" % (hash(shape), pnt.X(), pnt.Y(), pnt.Z()) + ) else: print(".." * level, end="") print(shapeTypeString(shape)) diff --git a/OCCUtils/base.py b/OCCUtils/base.py index 8a6dfc6..1e85077 100644 --- a/OCCUtils/base.py +++ b/OCCUtils/base.py @@ -15,7 +15,7 @@ ##You should have received a copy of the GNU Lesser General Public License ##along with pythonOCC. If not, see -''' +""" Please note the following; @readonly means that the decorated method is a readonly descriptor @@ -33,26 +33,34 @@ Can be a module, class or namespace. -''' +""" import functools from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Copy -from OCC.Core.BRepGProp import (brepgprop_VolumeProperties, - brepgprop_LinearProperties, - brepgprop_SurfaceProperties) -from OCC.Core.BRepCheck import (BRepCheck_Vertex, BRepCheck_Edge, BRepCheck_Wire, - BRepCheck_Face, BRepCheck_Shell, BRepCheck_Analyzer) +from OCC.Core.BRepGProp import ( + brepgprop_VolumeProperties, + brepgprop_LinearProperties, + brepgprop_SurfaceProperties, +) +from OCC.Core.BRepCheck import ( + BRepCheck_Vertex, + BRepCheck_Edge, + BRepCheck_Wire, + BRepCheck_Face, + BRepCheck_Shell, + BRepCheck_Analyzer, +) from OCC.Core.GProp import GProp_GProps from OCC.Display.SimpleGui import init_display from OCCUtils.Common import get_boundingbox -from OCCUtils.Construct import (make_vertex, TOLERANCE) +from OCCUtils.Construct import make_vertex, TOLERANCE from OCCUtils.types_lut import shape_lut, topo_lut, curve_lut, surface_lut -#=========================================================================== +# =========================================================================== # DISPLAY -#=========================================================================== +# =========================================================================== global display @@ -71,18 +79,25 @@ def __call__(self, *args, **kwargs): @singleton class Display(object): def __init__(self): - self.display, self.start_display, self.add_menu, self.add_function_to_menu = init_display() + ( + self.display, + self.start_display, + self.add_menu, + self.add_function_to_menu, + ) = init_display() def __call__(self, *args, **kwargs): return self.display.DisplayShape(*args, **kwargs) -#============ + +# ============ # base class -#============ +# ============ class BaseObject(object): """base class for all objects""" + def __init__(self, name=None, tolerance=TOLERANCE): self.GlobalProperties = GlobalProperties(self) self.name = name @@ -92,8 +107,8 @@ def __init__(self, name=None, tolerance=TOLERANCE): @property def is_dirty(self): - '''when an object is dirty, its topology will be - rebuild when update is called''' + """when an object is dirty, its topology will be + rebuild when update is called""" return self._dirty @is_dirty.setter @@ -106,26 +121,29 @@ def topo_type(self): @property def geom_type(self): - if self.topo_type == 'edge': + if self.topo_type == "edge": return curve_lut[self.ShapeType()] - if self.topo_type == 'face': + if self.topo_type == "face": return surface_lut[self.adaptor.GetType()] else: - raise ValueError('geom_type works only for edges and faces...') + raise ValueError("geom_type works only for edges and faces...") def set_display(self, display): - if hasattr(display, 'DisplayShape'): + if hasattr(display, "DisplayShape"): self.display_set = True self.display = display else: - raise ValueError('not a display') + raise ValueError("not a display") def check(self): - """ - """ - _check = dict(vertex=BRepCheck_Vertex, edge=BRepCheck_Edge, - wire=BRepCheck_Wire, face=BRepCheck_Face, - shell=BRepCheck_Shell) + """ """ + _check = dict( + vertex=BRepCheck_Vertex, + edge=BRepCheck_Edge, + wire=BRepCheck_Wire, + face=BRepCheck_Face, + shell=BRepCheck_Shell, + ) _check[self.topo_type] # TODO: BRepCheck will be able to inform *what* actually is the matter, # though implementing this still is a bit of work... @@ -152,13 +170,13 @@ def copy(self): return _copy def distance(self, other): - ''' + """ return the minimum distance :return: minimum distance, minimum distance points on shp1 minimum distance points on shp2 - ''' + """ return minimum_distance(self, other) def show(self, *args, **kwargs): @@ -173,7 +191,7 @@ def show(self, *args, **kwargs): self.disp.DisplayShape(*args, **kwargs) def build(self): - if self.name.startswith('Vertex'): + if self.name.startswith("Vertex"): self = make_vertex(self) def __eq__(self, other): @@ -184,9 +202,10 @@ def __ne__(self, other): class GlobalProperties(object): - ''' + """ global properties for all topologies - ''' + """ + def __init__(self, instance): self.instance = instance @@ -195,11 +214,11 @@ def system(self): self._system = GProp_GProps() # todo, type should be abstracted with TopoDS... _topo_type = self.instance.topo_type - if _topo_type == 'face' or _topo_type == 'shell': + if _topo_type == "face" or _topo_type == "shell": brepgprop_SurfaceProperties(self.instance, self._system) - elif _topo_type == 'edge': + elif _topo_type == "edge": brepgprop_LinearProperties(self.instance, self._system) - elif _topo_type == 'solid': + elif _topo_type == "solid": brepgprop_VolumeProperties(self.instance, self._system) return self._system @@ -210,15 +229,15 @@ def centre(self): return self.system.CentreOfMass() def inertia(self): - '''returns the inertia matrix''' + """returns the inertia matrix""" return self.system.MatrixOfInertia(), self.system.MomentOfInertia() def area(self): - '''returns the area of the surface''' + """returns the area of the surface""" return self.system.Mass() def bbox(self): - ''' + """ returns the bounding box of the face - ''' + """ return get_boundingbox(self.instance) diff --git a/OCCUtils/edge.py b/OCCUtils/edge.py index e3e10fc..c85a651 100644 --- a/OCCUtils/edge.py +++ b/OCCUtils/edge.py @@ -42,9 +42,9 @@ def __init__(self, instance): self.instance = instance def intersect(self, other, tolerance=1e-2): - '''Intersect self with a point, curve, edge, face, solid + """Intersect self with a point, curve, edge, face, solid method wraps dealing with the various topologies - ''' + """ if isinstance(other, TopoDS_Face): face_curve_intersect = BRepIntCurveSurface_Inter() face_curve_intersect.Init(other, self.instance.adaptor.Curve(), tolerance) @@ -58,15 +58,16 @@ def intersect(self, other, tolerance=1e-2): class DiffGeomCurve(object): def __init__(self, instance): self.instance = instance - self._local_props = BRepLProp_CLProps(self.instance.adaptor, 2, self.instance.tolerance) + self._local_props = BRepLProp_CLProps( + self.instance.adaptor, 2, self.instance.tolerance + ) @property def _curvature(self): return self._local_props def radius(self, u): - '''returns the radius at u - ''' + """returns the radius at u""" # NOT SO SURE IF THIS IS THE SAME THING!!! self._curvature.SetParameter(u) pnt = gp_Pnt() @@ -79,74 +80,78 @@ def curvature(self, u): return self._curvature.Curvature() def tangent(self, u): - '''sets or gets ( iff vector ) the tangency at the u parameter + """sets or gets ( iff vector ) the tangency at the u parameter tangency can be constrained so when setting the tangency, you're constrainting it in fact - ''' + """ self._curvature.SetParameter(u) if self._curvature.IsTangentDefined(): ddd = gp_Dir() self._curvature.Tangent(ddd) return ddd else: - raise ValueError('no tangent defined') + raise ValueError("no tangent defined") def normal(self, u): - '''returns the normal at u + """returns the normal at u computes the main normal if no normal is found see: www.opencascade.org/org/forum/thread_645+&cd=10&hl=nl&ct=clnk&gl=nl - ''' + """ try: self._curvature.SetParameter(u) a_dir = gp_Dir() self._curvature.Normal(a_dir) return a_dir except: - raise ValueError('no normal was found') + raise ValueError("no normal was found") def derivative(self, u, n): - ''' + """ returns n derivatives at parameter b - ''' + """ self._curvature.SetParameter(u) - deriv = {1: self._curvature.D1, - 2: self._curvature.D2, - 3: self._curvature.D3, - } + deriv = { + 1: self._curvature.D1, + 2: self._curvature.D2, + 3: self._curvature.D3, + } try: return deriv[n] except KeyError: - raise AssertionError('n of derivative is one of [1,2,3]') + raise AssertionError("n of derivative is one of [1,2,3]") def points_from_tangential_deflection(self): pass -#=========================================================================== + +# =========================================================================== # Curve.Construct -#=========================================================================== +# =========================================================================== -class ConstructFromCurve(): +class ConstructFromCurve: def __init__(self, instance): self.instance = instance def make_offset(self, offset, vec): - ''' + """ returns an offsetted curve @param offset: the distance between self.crv and the curve to offset @param vec: offset direction - ''' + """ return Geom_OffsetCurve(self.instance.h_crv, offset, vec) class Edge(TopoDS_Edge, BaseObject): def __init__(self, edge): - assert isinstance(edge, TopoDS_Edge), 'need a TopoDS_Edge, got a %s' % edge.__class__ + assert isinstance(edge, TopoDS_Edge), ( + "need a TopoDS_Edge, got a %s" % edge.__class__ + ) assert not edge.IsNull() super(Edge, self).__init__() - BaseObject.__init__(self, 'edge') + BaseObject.__init__(self, "edge") # we need to copy the base shape using the following three # lines assert self.IsNull() @@ -185,9 +190,9 @@ def continuity(self): return self.adaptor.Continuity def degree(self): - if 'line' in self.type: + if "line" in self.type: return 1 - elif 'curve' in self.type: + elif "curve" in self.type: return self.adaptor.Degree() else: # hyperbola, parabola, circle @@ -204,7 +209,7 @@ def curve(self): if self._curve is not None and not self.is_dirty: pass else: - self._curve = BRep_Tool().Curve(self)[0] + self._curve = BRep_Tool().Curve(self)[0] return self._curve @property @@ -215,7 +220,6 @@ def adaptor(self): self._adaptor = BRepAdaptor_Curve(self) return self._adaptor - @property def type(self): return geom_lut[self.adaptor.Curve().GetType()] @@ -233,63 +237,70 @@ def _local_properties(self): self._local_properties_init = True def domain(self): - '''returns the u,v domain of the curve''' + """returns the u,v domain of the curve""" return self.adaptor.FirstParameter(), self.adaptor.LastParameter() -#=========================================================================== -# Curve.GlobalProperties -#=========================================================================== + # =========================================================================== + # Curve.GlobalProperties + # =========================================================================== def length(self, lbound=None, ubound=None, tolerance=1e-5): - '''returns the curve length + """returns the curve length if either lbound | ubound | both are given, than the length of the curve will be measured over that interval - ''' + """ _min, _max = self.domain() if _min < self.adaptor.FirstParameter(): - raise ValueError('the lbound argument is lower than the first parameter of the curve: %s ' % (self.adaptor.FirstParameter())) + raise ValueError( + "the lbound argument is lower than the first parameter of the curve: %s " + % (self.adaptor.FirstParameter()) + ) if _max > self.adaptor.LastParameter(): - raise ValueError('the ubound argument is greater than the last parameter of the curve: %s ' % (self.adaptor.LastParameter())) + raise ValueError( + "the ubound argument is greater than the last parameter of the curve: %s " + % (self.adaptor.LastParameter()) + ) lbound = _min if lbound is None else lbound ubound = _max if ubound is None else ubound return GCPnts_AbscissaPoint().Length(self.adaptor, lbound, ubound, tolerance) -#=========================================================================== -# Curve.modify -#=========================================================================== + # =========================================================================== + # Curve.modify + # =========================================================================== def trim(self, lbound, ubound): - ''' + """ trim the curve @param lbound: @param ubound: - ''' + """ a, b = sorted([lbound, ubound]) tr = Geom_TrimmedCurve(self.adaptor.Curve().Curve(), a, b) return Edge(make_edge(tr)) def extend_by_point(self, pnt, degree=3, beginning=True): - '''extends the curve to point + """extends the curve to point does not extend if the degree of self.curve > 3 @param pnt: @param degree: @param beginning: - ''' + """ if self.degree > 3: - raise ValueError('to extend you self.curve should be <= 3, is %s' % (self.degree)) + raise ValueError( + "to extend you self.curve should be <= 3, is %s" % (self.degree) + ) return geomlib.ExtendCurveToPoint(self.curve, pnt, degree, beginning) -#=========================================================================== -# Curve. -#=========================================================================== + # =========================================================================== + # Curve. + # =========================================================================== def closest(self, other): return minimum_distance(self, other) def project_vertex(self, pnt_or_vertex): - ''' returns the closest orthogonal project on `pnt` on edge - ''' + """returns the closest orthogonal project on `pnt` on edge""" if isinstance(pnt_or_vertex, TopoDS_Vertex): pnt_or_vertex = vertex2pnt(pnt_or_vertex) @@ -297,12 +308,14 @@ def project_vertex(self, pnt_or_vertex): return poc.LowerDistanceParameter(), poc.NearestPoint() def distance_on_curve(self, distance, close_parameter, estimate_parameter): - '''returns the parameter if there is a parameter + """returns the parameter if there is a parameter on the curve with a distance length from u raises OutOfBoundary if no such parameter exists - ''' - gcpa = GCPnts_AbscissaPoint(self.adaptor, distance, close_parameter, estimate_parameter, 1e-5) - with assert_isdone(gcpa, 'couldnt compute distance on curve'): + """ + gcpa = GCPnts_AbscissaPoint( + self.adaptor, distance, close_parameter, estimate_parameter, 1e-5 + ) + with assert_isdone(gcpa, "couldnt compute distance on curve"): return gcpa.Parameter() def mid_point(self): @@ -311,13 +324,13 @@ def mid_point(self): its corresponding gp_Pnt """ _min, _max = self.domain() - _mid = (_min+_max) / 2. + _mid = (_min + _max) / 2.0 return _mid, self.adaptor.Value(_mid) def divide_by_number_of_points(self, n_pts, lbound=None, ubound=None): - '''returns a nested list of parameters and points on the edge + """returns a nested list of parameters and points on the edge at the requested interval [(param, gp_Pnt),...] - ''' + """ _lbound, _ubound = self.domain() if lbound: _lbound = lbound @@ -334,7 +347,7 @@ def divide_by_number_of_points(self, n_pts, lbound=None, ubound=None): print("Warning : GCPnts_UniformAbscissa failed") if npts.IsDone(): tmp = [] - for i in xrange(1, npts.NbPoints()+1): + for i in xrange(1, npts.NbPoints() + 1): param = npts.Parameter(i) pnt = self.adaptor.Value(param) tmp.append((param, pnt)) @@ -343,7 +356,7 @@ def divide_by_number_of_points(self, n_pts, lbound=None, ubound=None): return None def __eq__(self, other): - if hasattr(other, 'topo'): + if hasattr(other, "topo"): return self.IsEqual(other) else: return self.IsEqual(other) @@ -369,15 +382,16 @@ def as_vec(self): first, last = map(vertex2pnt, [self.first_vertex(), self.last_vertex()]) return gp_Vec(first, last) else: - raise ValueError("edge is not a line, hence no meaningful vector can be returned") + raise ValueError( + "edge is not a line, hence no meaningful vector can be returned" + ) -#=========================================================================== -# Curve. -#=========================================================================== + # =========================================================================== + # Curve. + # =========================================================================== def parameter_to_point(self, u): - '''returns the coordinate at parameter u - ''' + """returns the coordinate at parameter u""" return self.adaptor.Value(u) def fix_continuity(self, continuity): @@ -390,13 +404,12 @@ def fix_continuity(self, continuity): def continuity_from_faces(self, f1, f2): return BRep_Tool_Continuity(self, f1, f2) -#=========================================================================== -# Curve. -#=========================================================================== + # =========================================================================== + # Curve. + # =========================================================================== def is_line(self): - '''checks if the curve is planar - ''' + """checks if the curve is planar""" if self.nb_knots() == 2 and self.nb_poles() == 2: return True else: @@ -411,26 +424,26 @@ def is_seam(self, face): return sae.IsSeam(self, face) def is_edge_on_face(self, face): - '''checks whether curve lies on a surface or a face - ''' + """checks whether curve lies on a surface or a face""" return ShapeAnalysis_Edge().HasPCurve(self, face) -#=========================================================================== -# Curve.graphic -#=========================================================================== + # =========================================================================== + # Curve.graphic + # =========================================================================== def show(self): - ''' + """ poles, knots, should render all slightly different. here's how... http://www.opencascade.org/org/forum/thread_1125/ - ''' + """ super(Edge, self).show() -if __name__ == '__main__': +if __name__ == "__main__": from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox from OCCUtils.Topology import Topo + b = BRepPrimAPI_MakeBox(10, 20, 30).Shape() t = Topo(b) ed = next(t.edges()) diff --git a/OCCUtils/face.py b/OCCUtils/face.py index 34e3352..0154196 100644 --- a/OCCUtils/face.py +++ b/OCCUtils/face.py @@ -25,7 +25,7 @@ from OCC.Core.TopoDS import TopoDS_Vertex, TopoDS_Face, TopoDS_Edge from OCC.Core.GeomLProp import GeomLProp_SLProps from OCC.Core.BRepTools import breptools_UVBounds -from OCC.Core.BRepAdaptor import BRepAdaptor_Surface, BRepAdaptor_HSurface +from OCC.Core.BRepAdaptor import BRepAdaptor_Surface from OCC.Core.ShapeAnalysis import ShapeAnalysis_Surface from OCC.Core.GeomProjLib import geomprojlib from OCC.Core.Adaptor3d import Adaptor3d_IsoCurve @@ -44,7 +44,7 @@ def __init__(self, instance): self._curvature_initiated = False def curvature(self, u, v): - '''returns the curvature at the u parameter + """returns the curvature at the u parameter the curvature object can be returned too using curvatureType == curvatureType curvatureTypes are: @@ -53,25 +53,27 @@ def curvature(self, u, v): maximum mean curvatureType - ''' + """ if not self._curvature_initiated: self._curvature = GeomLProp_SLProps(self.instance.surface, u, v, 2, 1e-7) _domain = self.instance.domain() if u in _domain or v in _domain: - print('<<>>') + print("<<>>") div = 1000 - delta_u, delta_v = (_domain[0] - _domain[1])/div, (_domain[2] - _domain[3])/div + delta_u, delta_v = (_domain[0] - _domain[1]) / div, ( + _domain[2] - _domain[3] + ) / div if u in _domain: - low, hi = u-_domain[0], u-_domain[1] + low, hi = u - _domain[0], u - _domain[1] if low < hi: u = u - delta_u else: u = u + delta_u if v in _domain: - low, hi = v-_domain[2], v-_domain[3] + low, hi = v - _domain[2], v - _domain[3] if low < hi: v = v - delta_v else: @@ -100,7 +102,7 @@ def normal(self, u, v): if curv.IsNormalDefined(): return curv.Normal() else: - raise ValueError('normal is not defined at u,v: {0}, {1}'.format(u, v)) + raise ValueError("normal is not defined at u,v: {0}, {1}".format(u, v)) def tangent(self, u, v): dU, dV = gp_Dir(), gp_Dir() @@ -112,19 +114,18 @@ def tangent(self, u, v): return None, None def radius(self, u, v): - '''returns the radius at u - ''' + """returns the radius at u""" # TODO: SHOULD WE RETURN A SIGNED RADIUS? ( get rid of abs() )? try: - _crv_min = 1./self.min_curvature(u, v) + _crv_min = 1.0 / self.min_curvature(u, v) except ZeroDivisionError: - _crv_min = 0. + _crv_min = 0.0 try: - _crv_max = 1./self.max_curvature(u, v) + _crv_max = 1.0 / self.max_curvature(u, v) except ZeroDivisionError: - _crv_max = 0. - return abs((_crv_min+_crv_max)/2.) + _crv_max = 0.0 + return abs((_crv_min + _crv_max) / 2.0) class Face(TopoDS_Face, BaseObject): @@ -132,13 +133,15 @@ class Face(TopoDS_Face, BaseObject): object is a Face if part of a Solid otherwise the same methods do apply, apart from the topology obviously """ + def __init__(self, face): - ''' - ''' - assert isinstance(face, TopoDS_Face), 'need a TopoDS_Face, got a %s' % face.__class__ + """ """ + assert isinstance(face, TopoDS_Face), ( + "need a TopoDS_Face, got a %s" % face.__class__ + ) assert not face.IsNull() super(Face, self).__init__() - BaseObject.__init__(self, 'face') + BaseObject.__init__(self, "face") # we need to copy the base shape using the following three # lines assert self.IsNull() @@ -154,13 +157,15 @@ def __init__(self, face): self._curvature_initiated = False self._geometry_lookup_init = False - #=================================================================== + # =================================================================== # properties - #=================================================================== + # =================================================================== self._h_srf = None self._srf = None self._adaptor = None - self._classify_uv = None # cache the u,v classifier, no need to rebuild for every sample + self._classify_uv = ( + None # cache the u,v classifier, no need to rebuild for every sample + ) self._topo = None # aliasing of useful methods @@ -195,9 +200,9 @@ def v_continuity(self): return self.adaptor.VContinuity() def domain(self): - '''the u,v domain of the curve + """the u,v domain of the curve :return: UMin, UMax, VMin, VMax - ''' + """ return breptools_UVBounds(self) def mid_point(self): @@ -206,8 +211,8 @@ def mid_point(self): and its corresponding gp_Pnt """ u_min, u_max, v_min, v_max = self.domain() - u_mid = (u_min + u_max) / 2. - v_mid = (v_min + v_max) / 2. + u_mid = (u_min + u_max) / 2.0 + v_mid = (v_min + v_max) / 2.0 return ((u_mid, v_mid), self.adaptor.Value(u_mid, v_mid)) @property @@ -232,15 +237,14 @@ def adaptor(self): self._adaptor = BRepAdaptor_Surface(self) return self._adaptor - def is_closed(self): sa = ShapeAnalysis_Surface(self.surface) return sa.IsUClosed(), sa.IsVClosed() def is_planar(self, tol=TOLERANCE): - '''checks if the surface is planar within a tolerance + """checks if the surface is planar within a tolerance :return: bool, gp_Pln - ''' + """ is_planar_surface = GeomLib_IsPlanarSurface(self.surface, tol) return is_planar_surface.IsPlanar() @@ -256,13 +260,12 @@ def is_trimmed(self): a = map(_round, breptools_UVBounds(self)) b = map(_round, self.adaptor.Surface().Surface().Bounds()) if a != b: - print('a,b', a, b) + print("a,b", a, b) return True return False def on_trimmed(self, u, v): - '''tests whether the surface at the u,v parameter has been trimmed - ''' + """tests whether the surface at the u,v parameter has been trimmed""" if self._classify_uv is None: self._classify_uv = BRepTopAdaptor_FClass2d(self, 1e-9) uv = gp_Pnt2d(u, v) @@ -272,15 +275,14 @@ def on_trimmed(self, u, v): return False def parameter_to_point(self, u, v): - '''returns the coordinate at u,v - ''' + """returns the coordinate at u,v""" return self.surface.Value(u, v) def point_to_parameter(self, pt): - ''' + """ returns the uv value of a point on a surface @param pt: - ''' + """ sas = ShapeAnalysis_Surface(self.surface) uv = sas.ValueOfUV(pt, self.tolerance) return uv.Coord() @@ -301,19 +303,19 @@ def continuity_edge_face(self, edge, face): else: return False, None -#=========================================================================== -# Surface.project -# project curve, point on face -#=========================================================================== + # =========================================================================== + # Surface.project + # project curve, point on face + # =========================================================================== def project_vertex(self, pnt, tol=TOLERANCE): - '''projects self with a point, curve, edge, face, solid + """projects self with a point, curve, edge, face, solid method wraps dealing with the various topologies if other is a point: returns uv, point - ''' + """ if isinstance(pnt, TopoDS_Vertex): pnt = BRep_Tool.Pnt(pnt) @@ -325,17 +327,21 @@ def project_vertex(self, pnt, tol=TOLERANCE): def project_curve(self, other): # this way Geom_Circle and alike are valid too - if (isinstance(other, TopoDS_Edge) or - isinstance(other, Geom_Curve) or - issubclass(other, Geom_Curve)): - # convert edge to curve - first, last = topexp.FirstVertex(other), topexp.LastVertex(other) - lbound, ubound = BRep_Tool().Parameter(first, other), BRep_Tool().Parameter(last, other) - other = BRep_Tool.Curve(other, lbound, ubound) - return geomprojlib.Project(other, self.surface) + if ( + isinstance(other, TopoDS_Edge) + or isinstance(other, Geom_Curve) + or issubclass(other, Geom_Curve) + ): + # convert edge to curve + first, last = topexp.FirstVertex(other), topexp.LastVertex(other) + lbound, ubound = BRep_Tool().Parameter(first, other), BRep_Tool().Parameter( + last, other + ) + other = BRep_Tool.Curve(other, lbound, ubound) + return geomprojlib.Project(other, self.surface) def project_edge(self, edg): - if hasattr(edg, 'adaptor'): + if hasattr(edg, "adaptor"): return self.project_curve(self, self.adaptor) return self.project_curve(self, to_adaptor_3d(edg)) @@ -346,7 +352,7 @@ def iso_curve(self, u_or_v, param): :param param: :return: """ - uv = 0 if u_or_v == 'u' else 1 + uv = 0 if u_or_v == "u" else 1 iso = Adaptor3d_IsoCurve(self.adaptor, uv, param) return iso @@ -359,8 +365,10 @@ def __repr__(self): def __str__(self): return self.__repr__() + if __name__ == "__main__": from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeSphere + sph = BRepPrimAPI_MakeSphere(1, 1).Face() fc = Face(sph) print(fc.is_trimmed()) diff --git a/OCCUtils/shell.py b/OCCUtils/shell.py index 744bdc0..1104503 100644 --- a/OCCUtils/shell.py +++ b/OCCUtils/shell.py @@ -26,10 +26,12 @@ class Shell(TopoDS_Shell, BaseObject): _n = 0 def __init__(self, shell): - assert isinstance(shell, TopoDS_Shell), 'need a TopoDS_Shell, got a %s' % shell.__class__ + assert isinstance(shell, TopoDS_Shell), ( + "need a TopoDS_Shell, got a %s" % shell.__class__ + ) assert not shell.IsNull() super(Shell, self).__init__() - BaseObject.__init__(self, 'shell') + BaseObject.__init__(self, "shell") # we need to copy the base shape using the following three # lines assert self.IsNull() diff --git a/OCCUtils/solid.py b/OCCUtils/solid.py index d80df0a..2f28803 100644 --- a/OCCUtils/solid.py +++ b/OCCUtils/solid.py @@ -24,10 +24,12 @@ class Solid(TopoDS_Solid, BaseObject): def __init__(self, solid): - assert isinstance(solid, TopoDS_Solid), 'need a TopoDS_Solid, got a %s' % solid.__class__ + assert isinstance(solid, TopoDS_Solid), ( + "need a TopoDS_Solid, got a %s" % solid.__class__ + ) assert not solid.IsNull() super(Solid, self).__init__() - BaseObject.__init__(self, 'solid') + BaseObject.__init__(self, "solid") # we need to copy the base shape using the following three # lines assert self.IsNull() diff --git a/OCCUtils/types_lut.py b/OCCUtils/types_lut.py index 4f4cd28..dd08f4e 100644 --- a/OCCUtils/types_lut.py +++ b/OCCUtils/types_lut.py @@ -24,25 +24,27 @@ class ShapeToTopology(object): - ''' + """ looks up the topology type and returns the corresponding topological entity - ''' + """ + def __init__(self): - self.topoTypes = {TopAbs_VERTEX: topods.Vertex, - TopAbs_EDGE: topods.Edge, - TopAbs_FACE: topods.Face, - TopAbs_WIRE: topods.Wire, - TopAbs_SHELL: topods.Shell, - TopAbs_SOLID: topods.Solid, - TopAbs_COMPOUND: topods.Compound, - TopAbs_COMPSOLID: topods.CompSolid, - } + self.topoTypes = { + TopAbs_VERTEX: topods.Vertex, + TopAbs_EDGE: topods.Edge, + TopAbs_FACE: topods.Face, + TopAbs_WIRE: topods.Wire, + TopAbs_SHELL: topods.Shell, + TopAbs_SOLID: topods.Solid, + TopAbs_COMPOUND: topods.Compound, + TopAbs_COMPSOLID: topods.CompSolid, + } def __call__(self, shape): if isinstance(shape, TopoDS_Shape): return self.topoTypes[shape.ShapeType()](shape) else: - raise AttributeError('shape has not method `ShapeType`') + raise AttributeError("shape has not method `ShapeType`") def __getitem__(self, item): return self(item) @@ -52,6 +54,7 @@ class EnumLookup(object): """ perform bi-directional lookup of Enums'... """ + def __init__(self, li_in, li_out): self.d = {} for a, b in zip(li_in, li_out): @@ -62,51 +65,118 @@ def __getitem__(self, item): return self.d[item] -_curve_typesA = (GeomAbs_Line, GeomAbs_Circle, GeomAbs_Ellipse, - GeomAbs_Hyperbola, GeomAbs_Parabola, - GeomAbs_BezierCurve, GeomAbs_BSplineCurve, GeomAbs_OtherCurve) -_curve_typesB = ('line', 'circle', 'ellipse', 'hyperbola', 'parabola', - 'bezier', 'spline', 'other') -_surface_typesA = (GeomAbs_Plane, GeomAbs_Cylinder, GeomAbs_Cone, - GeomAbs_Sphere, GeomAbs_Torus, GeomAbs_BezierSurface, - GeomAbs_BSplineSurface, GeomAbs_SurfaceOfRevolution, - GeomAbs_SurfaceOfExtrusion, - GeomAbs_OffsetSurface, GeomAbs_OtherSurface) -_surface_typesB = ('plane', 'cylinder', 'cone', 'sphere', 'torus', 'bezier', - 'spline', 'revolution', 'extrusion', 'offset', 'other') - - -_stateA = ('in', 'out', 'on', 'unknown') +_curve_typesA = ( + GeomAbs_Line, + GeomAbs_Circle, + GeomAbs_Ellipse, + GeomAbs_Hyperbola, + GeomAbs_Parabola, + GeomAbs_BezierCurve, + GeomAbs_BSplineCurve, + GeomAbs_OtherCurve, +) +_curve_typesB = ( + "line", + "circle", + "ellipse", + "hyperbola", + "parabola", + "bezier", + "spline", + "other", +) +_surface_typesA = ( + GeomAbs_Plane, + GeomAbs_Cylinder, + GeomAbs_Cone, + GeomAbs_Sphere, + GeomAbs_Torus, + GeomAbs_BezierSurface, + GeomAbs_BSplineSurface, + GeomAbs_SurfaceOfRevolution, + GeomAbs_SurfaceOfExtrusion, + GeomAbs_OffsetSurface, + GeomAbs_OtherSurface, +) +_surface_typesB = ( + "plane", + "cylinder", + "cone", + "sphere", + "torus", + "bezier", + "spline", + "revolution", + "extrusion", + "offset", + "other", +) + + +_stateA = ("in", "out", "on", "unknown") _stateB = (TopAbs_IN, TopAbs_OUT, TopAbs_ON, TopAbs_UNKNOWN) -_orientA = ['TopAbs_FORWARD', 'TopAbs_REVERSED', 'TopAbs_INTERNAL', - 'TopAbs_EXTERNAL'] -_orientB = [TopAbs_FORWARD, TopAbs_REVERSED, TopAbs_INTERNAL, - TopAbs_EXTERNAL] - - -_topoTypesA = ['vertex', 'edge', 'wire', 'face', 'shell', - 'solid', 'compsolid', 'compound', 'shape'] -_topoTypesB = [TopAbs_VERTEX, TopAbs_EDGE, TopAbs_WIRE, TopAbs_FACE, - TopAbs_SHELL, TopAbs_SOLID, - TopAbs_COMPSOLID, TopAbs_COMPOUND, TopAbs_SHAPE] - - -_geom_types_a = ['line', 'circle', 'ellipse', 'hyperbola', 'parabola', - 'beziercurve', 'bsplinecurve', 'othercurve'] -_geom_types_b = [GeomAbs_Line, GeomAbs_Circle, GeomAbs_Ellipse, - GeomAbs_Hyperbola, GeomAbs_Parabola, GeomAbs_BezierCurve, - GeomAbs_BSplineCurve, GeomAbs_OtherCurve] +_orientA = ["TopAbs_FORWARD", "TopAbs_REVERSED", "TopAbs_INTERNAL", "TopAbs_EXTERNAL"] +_orientB = [TopAbs_FORWARD, TopAbs_REVERSED, TopAbs_INTERNAL, TopAbs_EXTERNAL] + + +_topoTypesA = [ + "vertex", + "edge", + "wire", + "face", + "shell", + "solid", + "compsolid", + "compound", + "shape", +] +_topoTypesB = [ + TopAbs_VERTEX, + TopAbs_EDGE, + TopAbs_WIRE, + TopAbs_FACE, + TopAbs_SHELL, + TopAbs_SOLID, + TopAbs_COMPSOLID, + TopAbs_COMPOUND, + TopAbs_SHAPE, +] + + +_geom_types_a = [ + "line", + "circle", + "ellipse", + "hyperbola", + "parabola", + "beziercurve", + "bsplinecurve", + "othercurve", +] +_geom_types_b = [ + GeomAbs_Line, + GeomAbs_Circle, + GeomAbs_Ellipse, + GeomAbs_Hyperbola, + GeomAbs_Parabola, + GeomAbs_BezierCurve, + GeomAbs_BSplineCurve, + GeomAbs_OtherCurve, +] # TODO: make a function that generalizes this, there is absolutely # no need for 2 lists to define an EnumLookup + def fix_formatting(_str): - return [i.strip() for i in _str.split(',')] + return [i.strip() for i in _str.split(",")] + -_brep_check_a = fix_formatting("NoError, InvalidPointOnCurve,\ +_brep_check_a = fix_formatting( + "NoError, InvalidPointOnCurve,\ InvalidPointOnCurveOnSurface, InvalidPointOnSurface,\ No3DCurve, Multiple3DCurve, Invalid3DCurve, NoCurveOnSurface,\ InvalidCurveOnSurface, InvalidCurveOnClosedSurface, InvalidSameRangeFlag,\ @@ -116,29 +186,45 @@ def fix_formatting(_str): InvalidWire, RedundantWire, IntersectingWires, InvalidImbricationOfWires,\ EmptyShell, RedundantFace, UnorientableShape, NotClosed,\ NotConnected, SubshapeNotInShape, BadOrientation, BadOrientationOfSubshape,\ -InvalidToleranceValue, CheckFail") - -_brep_check_b = [BRepCheck_NoError, BRepCheck_InvalidPointOnCurve, - BRepCheck_InvalidPointOnCurveOnSurface, - BRepCheck_InvalidPointOnSurface, - BRepCheck_No3DCurve, BRepCheck_Multiple3DCurve, - BRepCheck_Invalid3DCurve, BRepCheck_NoCurveOnSurface, - BRepCheck_InvalidCurveOnSurface, - BRepCheck_InvalidCurveOnClosedSurface, - BRepCheck_InvalidSameRangeFlag, - BRepCheck_InvalidSameParameterFlag, - BRepCheck_InvalidDegeneratedFlag, BRepCheck_FreeEdge, - BRepCheck_InvalidMultiConnexity, BRepCheck_InvalidRange, - BRepCheck_EmptyWire, BRepCheck_RedundantEdge, - BRepCheck_SelfIntersectingWire, BRepCheck_NoSurface, - BRepCheck_InvalidWire, BRepCheck_RedundantWire, - BRepCheck_IntersectingWires, - BRepCheck_InvalidImbricationOfWires, - BRepCheck_EmptyShell, BRepCheck_RedundantFace, - BRepCheck_UnorientableShape, BRepCheck_NotClosed, - BRepCheck_NotConnected, BRepCheck_SubshapeNotInShape, - BRepCheck_BadOrientation, BRepCheck_BadOrientationOfSubshape, - BRepCheck_InvalidToleranceValue, BRepCheck_CheckFail] +InvalidToleranceValue, CheckFail" +) + +_brep_check_b = [ + BRepCheck_NoError, + BRepCheck_InvalidPointOnCurve, + BRepCheck_InvalidPointOnCurveOnSurface, + BRepCheck_InvalidPointOnSurface, + BRepCheck_No3DCurve, + BRepCheck_Multiple3DCurve, + BRepCheck_Invalid3DCurve, + BRepCheck_NoCurveOnSurface, + BRepCheck_InvalidCurveOnSurface, + BRepCheck_InvalidCurveOnClosedSurface, + BRepCheck_InvalidSameRangeFlag, + BRepCheck_InvalidSameParameterFlag, + BRepCheck_InvalidDegeneratedFlag, + BRepCheck_FreeEdge, + BRepCheck_InvalidMultiConnexity, + BRepCheck_InvalidRange, + BRepCheck_EmptyWire, + BRepCheck_RedundantEdge, + BRepCheck_SelfIntersectingWire, + BRepCheck_NoSurface, + BRepCheck_InvalidWire, + BRepCheck_RedundantWire, + BRepCheck_IntersectingWires, + BRepCheck_InvalidImbricationOfWires, + BRepCheck_EmptyShell, + BRepCheck_RedundantFace, + BRepCheck_UnorientableShape, + BRepCheck_NotClosed, + BRepCheck_NotConnected, + BRepCheck_SubshapeNotInShape, + BRepCheck_BadOrientation, + BRepCheck_BadOrientationOfSubshape, + BRepCheck_InvalidToleranceValue, + BRepCheck_CheckFail, +] brepcheck_lut = EnumLookup(_brep_check_a, _brep_check_b) curve_lut = EnumLookup(_curve_typesA, _curve_typesB) @@ -159,21 +245,20 @@ def fix_formatting(_str): classes = dir() geom_classes = [] for elem in classes: - if elem.startswith('Geom') and not 'swig' in elem: + if elem.startswith("Geom") and not "swig" in elem: geom_classes.append(elem) def what_is_face(face): - ''' Returns all class names for which this class can be downcasted - ''' + """Returns all class names for which this class can be downcasted""" if not face.ShapeType() == TopAbs_FACE: - print('%s is not a TopAbs_FACE. Conversion impossible') + print("%s is not a TopAbs_FACE. Conversion impossible") return None hs = BRep_Tool_Surface(face) obj = hs.GetObject() result = [] for elem in classes: - if (elem.startswith('Geom') and not 'swig' in elem): + if elem.startswith("Geom") and not "swig" in elem: geom_classes.append(elem) # Run the test for each class for geom_class in geom_classes: @@ -183,8 +268,7 @@ def what_is_face(face): def face_is_plane(face): - ''' Returns True if the TopoDS_Shape is a plane, False otherwise - ''' + """Returns True if the TopoDS_Shape is a plane, False otherwise""" hs = BRep_Tool_Surface(face) downcast_result = Geom_Plane().DownCast(hs) # the handle is null if downcast failed or is not possible, @@ -196,8 +280,7 @@ def face_is_plane(face): def shape_is_cylinder(face): - ''' Returns True is the TopoDS_Shape is a cylinder, False otherwise - ''' + """Returns True is the TopoDS_Shape is a cylinder, False otherwise""" hs = BRep_Tool_Surface(face) downcast_result = Geom_CylindricalSurface().DownCast(hs) if downcast_result.IsNull(): diff --git a/OCCUtils/vertex.py b/OCCUtils/vertex.py index f561cf6..353326e 100644 --- a/OCCUtils/vertex.py +++ b/OCCUtils/vertex.py @@ -27,12 +27,13 @@ class Vertex(TopoDS_Vertex, BaseObject): """ wraps gp_Pnt """ + _n = 0 def __init__(self, x, y, z): super(Vertex, self).__init__() """Constructor for KbeVertex""" - BaseObject.__init__(self, name='Vertex #{0}'.format(self._n)) + BaseObject.__init__(self, name="Vertex #{0}".format(self._n)) self._n += 1 # should be a property of KbeObject self._pnt = gp_Pnt(x, y, z) @@ -40,9 +41,7 @@ def __init__(self, x, y, z): TopoDS_Vertex.__init__(self, self._vertex) def _update(self): - """ - - """ + """ """ # TODO: perhaps should take an argument until which topological level # topological entities bound to the vertex should be updated too... reshape = ShapeBuild_ReShape() @@ -94,17 +93,17 @@ def __repr__(self): @property def as_vec(self): - '''returns a gp_Vec version of self''' + """returns a gp_Vec version of self""" return gp_Vec(*self._pnt.Coord()) @property def as_dir(self): - '''returns a gp_Dir version of self''' + """returns a gp_Dir version of self""" return gp_Dir(*self._pnt.Coord()) @property def as_xyz(self): - '''returns a gp_XYZ version of self''' + """returns a gp_XYZ version of self""" return gp_XYZ(*self._pnt.Coord()) @property @@ -113,5 +112,5 @@ def as_pnt(self): @property def as_2d(self): - '''returns a gp_Pnt2d version of self''' + """returns a gp_Pnt2d version of self""" return gp_Pnt2d(*self._pnt.Coord()[:2]) diff --git a/OCCUtils/wire.py b/OCCUtils/wire.py index 20ed5ca..97ca4c2 100644 --- a/OCCUtils/wire.py +++ b/OCCUtils/wire.py @@ -24,12 +24,13 @@ class Wire(TopoDS_Wire, BaseObject): def __init__(self, wire): - ''' - ''' - assert isinstance(wire, TopoDS_Wire), 'need a TopoDS_Wire, got a %s' % wire.__class__ + """ """ + assert isinstance(wire, TopoDS_Wire), ( + "need a TopoDS_Wire, got a %s" % wire.__class__ + ) assert not wire.IsNull() super(Wire, self).__init__() - BaseObject.__init__(self, 'wire') + BaseObject.__init__(self, "wire") # we need to copy the base shape using the following three # lines assert self.IsNull() diff --git a/test/occutils_test.py b/test/occutils_test.py index 3280965..451a9ba 100644 --- a/test/occutils_test.py +++ b/test/occutils_test.py @@ -20,6 +20,7 @@ import unittest import sys +sys.path.append('../') sys.path.append('../OCCUtils') from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeSphere