def what_is_face(face): ''' 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') return None hs = BRep_Tool_Surface(face) obj = hs.GetObject() result = [] for elem in classes: 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: if obj.IsKind(geom_class) and not geom_class in result: result.append(geom_class) return result
def testRemovedByRefFeature(self): ''' test that arguments returned by ref transormation is ok ''' from OCC.BRepPrimAPI import BRepPrimAPI_MakeSphere from OCC.BRep import BRep_Tool_Surface from OCC.GeomLProp import GeomLProp_SLProps from OCC.gp import gp_Pnt sphere_shape = BRepPrimAPI_MakeSphere(40.).Shape() # build a surface from this sphere from OCC.Utils.Topology import Topo t = Topo(sphere_shape) for f in t.faces(): face = f surf = BRep_Tool_Surface(face) lprop = GeomLProp_SLProps(0, 1e-12) lprop.SetSurface(surf) # evaluate_uv_coordinates coords = [] p = 0.0 # first point u, v = [0, 0] lprop.SetParameters(u, v) pnt = lprop.Value() print 'First point coords : ', pnt.Coord() print surf.GetObject().Value(u, v).Coord() # This one is [40.0,0.,0.] self.assertEqual(str(pnt.Coord()), '(40.0, 0.0, 0.0)') coords.append(pnt) #second point u, v = [0.5, 0.5] lprop.SetParameters(u, v) pnt2 = lprop.Value() # check then that the value has not changed (it does if returned by ref) self.assertEqual(str(pnt.Coord()), '(40.0, 0.0, 0.0)')
class Face(TopoDS_Face, BaseObject): """high level surface API 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 not face.IsNull() super(Face, self).__init__() BaseObject.__init__(self, 'face') # we need to copy the base shape using the following three # lines assert self.IsNull() self.TShape(face.TShape()) self.Location(face.Location()) self.Orientation(face.Orientation()) assert not self.IsNull() # cooperative classes self.DiffGeom = DiffGeomSurface(self) # STATE; whether cooperative classes are yet initialized self._curvature_initiated = False self._geometry_lookup_init = False #=================================================================== # properties #=================================================================== self._h_srf = None self._srf = None self._adaptor = None self._adaptor_handle = None self._classify_uv = None # cache the u,v classifier, no need to rebuild for every sample self._topo = None # aliasing of useful methods def is_u_periodic(self): return self.adaptor.IsUPeriodic() def is_v_periodic(self): return self.adaptor.IsVPeriodic() def is_u_closed(self): return self.adaptor.IsUClosed() def is_v_closed(self): return self.adaptor.IsVClosed() def is_u_rational(self): return self.adaptor.IsURational() def is_v_rational(self): return self.adaptor.IsVRational() def u_degree(self): return self.adaptor.UDegree() def v_degree(self): return self.adaptor.VDegree() def u_continuity(self): return self.adaptor.UContinuity() def v_continuity(self): return self.adaptor.VContinuity() def domain(self): '''the u,v domain of the curve :return: UMin, UMax, VMin, VMax ''' return breptools_UVBounds(self) def mid_point(self): """ :return: the parameter at the mid point of the face, 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. return ((u_mid, v_mid), self.adaptor.Value(u_mid, v_mid)) @property def topo(self): if self._topo is not None: return self._topo else: self._topo = Topo(self) return self._topo @property def surface(self): if self._srf is None or self.is_dirty: self._h_srf = BRep_Tool_Surface(self) self._srf = self._h_srf.GetObject() return self._srf @property def surface_handle(self): if self._h_srf is None or self.is_dirty: self.surface # force building handle return self._h_srf @property def adaptor(self): if self._adaptor is not None and not self.is_dirty: pass else: self._adaptor = BRepAdaptor_Surface(self) self._adaptor_handle = BRepAdaptor_HSurface() self._adaptor_handle.Set(self._adaptor) return self._adaptor @property def adaptor_handle(self): if self._adaptor_handle is not None and not self.is_dirty: pass else: self.adaptor return self._adaptor_handle def is_closed(self): sa = ShapeAnalysis_Surface(self.surface_handle) # sa.GetBoxUF() return sa.IsUClosed(), sa.IsVClosed() def is_planar(self, tol=TOLERANCE): '''checks if the surface is planar within a tolerance :return: bool, gp_Pln ''' print(self.surface_handle) is_planar_surface = GeomLib_IsPlanarSurface(self.surface_handle, tol) return is_planar_surface.IsPlanar() def is_trimmed(self): """ :return: True if the Wire delimiting the Face lies on the bounds of the surface if this is not the case, the wire represents a contour that delimits the face [ think cookie cutter ] and implies that the surface is trimmed """ _round = lambda x: round(x, 3) a = map(_round, breptools_UVBounds(self)) b = map(_round, self.adaptor.Surface().Surface().GetObject().Bounds()) if 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 ''' if self._classify_uv is None: self._classify_uv = BRepTopAdaptor_FClass2d(self, 1e-9) ##1e-9 uv = gp_Pnt2d(u, v) if self._classify_uv.Perform(uv) == TopAbs_IN: #IN return True else: return False def parameter_to_point(self, 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_handle) uv = sas.ValueOfUV(pt, self.tolerance) return uv.Coord() def continuity_edge_face(self, edge, face): """ compute the continuity between two faces at :edge: :param edge: an Edge or TopoDS_Edge from :face: :param face: a Face or TopoDS_Face :return: bool, GeomAbs_Shape if it has continuity, otherwise False, None """ bt = BRep_Tool() if bt.HasContinuity(edge, self, face): continuity = bt.Continuity(edge, self, face) return True, continuity else: return False, None #=========================================================================== # Surface.project # project curve, point on face #=========================================================================== def project_vertex(self, pnt, tol=TOLERANCE): '''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) proj = GeomAPI_ProjectPointOnSurf(pnt, self.surface_handle, tol) uv = proj.LowerDistanceParameters() proj_pnt = proj.NearestPoint() return uv, proj_pnt 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).GetObject() return geomprojlib.Project(other, self.surface_handle) def project_edge(self, edg): if hasattr(edg, 'adaptor'): return self.project_curve(self, self.adaptor) return self.project_curve(self, to_adaptor_3d(edg)) def iso_curve(self, u_or_v, param): """ get the iso curve from a u,v + parameter :param u_or_v: :param param: :return: """ uv = 0 if u_or_v == 'u' else 1 iso = Adaptor3d_IsoCurve(self.adaptor_handle.GetHandle(), uv, param) return iso def edges(self): return [ Edge(i) for i in WireExplorer(next(self.topo.wires())).ordered_edges() ] def __repr__(self): return self.name def __str__(self): return self.__repr__()
class Face(KbeObject): """high level surface API object is a Face iff part of a Solid otherwise the same methods do apply, apart from the topology obviously """ def __init__(self, face): ''' ''' from OCC.TopoDS import TopoDS_Face KbeObject.__init__(self, name='face') self._topo_type = TopoDS_Face self.topo = face # cooperative classes self.GlobalProperties = GlobalProperties(self) self.DiffGeom = DiffGeomSurface(self) # STATE; whether cooperative classes are yet initialized self._curvature_initiated = False self._geometry_lookup_init = False self._h_srf = None self._srf = None self._adaptor = None self._adaptor_handle = None self._classify_uv = None # cache the u,v classifier, no need to rebuild for every sample # aliasing of useful methods self.is_u_periodic = self.adaptor.IsUPeriodic self.is_v_periodic = self.adaptor.IsVPeriodic self.is_u_closed = self.adaptor.IsUClosed self.is_v_closed = self.adaptor.IsVClosed self.is_u_rational = self.adaptor.IsURational self.is_u_rational = self.adaptor.IsVRational self.u_degree = self.adaptor.UDegree self.v_degree = self.adaptor.VDegree self.u_continuity = self.adaptor.UContinuity self.v_continuity = self.adaptor.VContinuity # meh, RuntimeError... self.nb_u_knots = self.adaptor.NbUKnots self.nb_v_knots = self.adaptor.NbVKnots self.nb_u_poles = self.adaptor.NbUPoles self.nb_v_poles = self.adaptor.NbVPoles def show(self, *args, **kwargs): # TODO: factor out once inheriting from KbeObject Display()(self.topo, *args, **kwargs) def check(self): ''' interesting for valdating the state of self ''' from OCC.BRepCheck import BRepCheck_Face bcf = BRepCheck_Face(self.topo) return bcf def domain(self): '''returns the u,v domain of the curve''' from OCC.BRepTools import BRepTools return BRepTools.UVBounds(self.topo) @property def surface(self): if self._srf is not None and not self.is_dirty: pass else: self._h_srf = BRep_Tool_Surface(self.topo) self._srf = self._h_srf.GetObject() return self._srf @property def surface_handle(self): if self._h_srf is not None and not self.is_dirty: pass else: self.surface return self._h_srf @property def adaptor(self): if self._adaptor is not None and not self.is_dirty: pass else: from OCC.BRepAdaptor import BRepAdaptor_Surface, BRepAdaptor_HSurface self._adaptor = BRepAdaptor_Surface(self.topo) self._adaptor_handle = BRepAdaptor_HSurface() self._adaptor_handle.Set(self._adaptor) return self._adaptor @property def adaptor_handle(self): if self._adaptor_handle is not None and not self.is_dirty: pass else: self.adaptor return self._adaptor_handle def weight(self, indx): '''sets or gets the weight of a control point at the index ''' # TODO: somehow its hard to get a Geom_SplineSurface object from a face # nessecary to get control points and weights raise NotImplementedError def close(self): '''if possible, close self''' raise NotImplementedError @property def type(self): return 'face' def kind(self): if not self._geometry_lookup_init: self._geometry_lookup = GeometryTypeLookup() self._geometry_lookup_init = True return self._geometry_lookup[self.topo] def is_closed(self): from OCC.ShapeAnalysis import ShapeAnalysis_Surface sa = ShapeAnalysis_Surface(self.surface_handle) sa.GetBoxUF() return sa.IsUClosed(), sa.IsVClosed() def is_planar(self): '''checks if the surface is planar within a tolerance :return: bool, gp_Pln ''' aaa = GeomLib_IsPlanarSurface(self.surface_handle, self.tolerance) if aaa.IsPlanar(): return aaa.IsPlanar(), aaa.Plan() else: return aaa.IsPlanar(), None def on_trimmed(self, u, v): '''tests whether the surface at the u,v parameter has been trimmed ''' if self._classify_uv is None: self._classify_uv = BRepTopAdaptor_FClass2d(self.topo, 1e-9) uv = gp_Pnt2d(u,v) if self._classify_uv.Perform(uv) == TopAbs_IN: return True else: return False def parameter_to_point(self, 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: ''' from OCC.ShapeAnalysis import ShapeAnalysis_Surface sas = ShapeAnalysis_Surface(self.surface_handle) uv = sas.ValueOfUV(pt, self.tolerance) return uv.Coord() def transform(self, transform): '''affine transform ''' raise NotImplementedError def continuity_edge_face(self, edge, face): """ compute the continuity between two faces at :edge: :param edge: an Edge or TopoDS_Edge from :face: :param face: a Face or TopoDS_Face :return: bool, GeomAbs_Shape if it has continuity, otherwise False, None """ edge = edge if not isinstance(edge,KbeObject) else edge.topo face = face if not isinstance(face, KbeObject) else face.topo bt = BRep_Tool() if bt.HasContinuity(edge, self.topo, face): continuity = bt.Continuity(edge, self.topo, face) return True, continuity else: return False, None #=============================================================================== # Surface.project # project curve, point on face #=============================================================================== def project_vertex( self, other ): '''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(other, TopoDS_Face): raise AssertionError, 'Cannot project a face on another face' elif isinstance(other, TopoDS_Vertex): pt = BRep_Tool.Pnt(other) proj = GeomAPI_ProjectPointOnSurf(pt, self.surface_handle) # SHOULD USE THIS!!! #proj.LowerDistanceParameters() ext = proj.Extrema() for i in range(ext.NbExt()): if proj.Point().Coord() == ext.Point(i).Value().Coord(): result = ext.Point(i) uv = result.Parameter() pt = result.Value() return uv, pt 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): if isinstance(other, TopoDS_Edge): # convert edge to curve first, last = TopExp.FirstVertex(other), TopExp.LastVertex(other) lbound, ubound = BRep_Tool().Parameter(first, other), BRep_Tool().Parameter(first, other) other = BRep_Tool.Curve(other, lbound, ubound).GetObject() from OCC.GeomProjLib import GeomProjLib return GeomProjLib().Project(other, self.surface_handle) def project_edge(self, edg): return self.project_cur def iso_curve(self, u_or_v, param): """ :return: an iso curve at parameter `param` :param u_or_v: "u" or "v" :param param: the parameter where the iso curve lies """ pass def Edges(self): return [Edge(i) for i in Topo(self.topo).edges()]
class Face(TopoDS_Face, BaseObject): """high level surface API object is a Face if part of a Solid otherwise the same methods do apply, apart from the topology obviously """ def __init__(self, face:TopoDS_Face, **kwargs): """ """ 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', **kwargs) # we need to copy the base shape using the following three # lines assert self.IsNull() self.TShape(face.TShape()) self.Location(face.Location()) self.Orientation(face.Orientation()) assert not self.IsNull() # cooperative classes self.DiffGeom = DiffGeomSurface(self) # STATE; whether cooperative classes are yet initialized self._curvature_initiated = False self._geometry_lookup_init = False # =================================================================== # properties # =================================================================== self._h_srf = None self._srf = None self._adaptor = None self._adaptor_handle = None self._classify_uv = None # cache the u,v classifier, no need to rebuild for every sample self._topo = None # aliasing of useful methods def is_u_periodic(self): return self.adaptor.IsUPeriodic() def is_v_periodic(self): return self.adaptor.IsVPeriodic() def is_u_closed(self): return self.adaptor.IsUClosed() def is_v_closed(self): return self.adaptor.IsVClosed() def is_u_rational(self): return self.adaptor.IsURational() def is_v_rational(self): return self.adaptor.IsVRational() def u_degree(self): return self.adaptor.UDegree() def v_degree(self): return self.adaptor.VDegree() def u_continuity(self): return self.adaptor.UContinuity() def v_continuity(self): return self.adaptor.VContinuity() def domain(self) -> Tuple[float, float, float, float]: """the u,v domain of the curve :return: UMin, UMax, VMin, VMax """ return breptools_UVBounds(self) @property def area(self, tolerance=1e-5): prop = GProp_GProps() brepgprop.SurfaceProperties(self, prop, tolerance) return prop.Mass() def mid_point(self) -> Tuple[Tuple[float, float], gp_Pnt]: """ :return: the parameter at the mid point of the face, 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. return (u_mid, v_mid), self.adaptor.Value(u_mid, v_mid) @property def centroid(self): _, m = self.mid_point() return m @property def normal(self) -> gp_Dir: return face_normal(self.Shape()) @property def topo(self): if self._topo is not None: return self._topo else: self._topo = Topo(self) return self._topo def Shape(self) -> TopoDS_Face: return self.topo.Shape() @property def surface(self): if self._srf is None or self.is_dirty: self._h_srf = BRep_Tool_Surface(self) self._srf = self._h_srf.GetObject() return self._srf @property def surface_handle(self): if self._h_srf is None or self.is_dirty: self.surface # force building handle return self._h_srf # ------------------------------------------------------ @property def adaptor(self): if self._adaptor is not None and not self.is_dirty: pass else: self._adaptor = BRepAdaptor_Surface(self) self._adaptor_handle = BRepAdaptor_HSurface() self._adaptor_handle.Set(self._adaptor) return self._adaptor @property def adaptor_handle(self): if self._adaptor_handle is not None and not self.is_dirty: pass else: self.adaptor return self._adaptor_handle def is_closed(self) -> Tuple[bool, bool]: sa = ShapeAnalysis_Surface(self.surface_handle) # sa.GetBoxUF() return sa.IsUClosed(), sa.IsVClosed() def is_planar(self, tol=TOLERANCE): """checks if the surface is planar within a tolerance :return: bool, gp_Pln """ # print(self.surface_handle) is_planar_surface = GeomLib_IsPlanarSurface(self.surface_handle, tol) return is_planar_surface.IsPlanar() def is_trimmed(self): """ :return: True if the Wire delimiting the Face lies on the bounds of the surface if this is not the case, the wire represents a contour that delimits the face [ think cookie cutter ] and implies that the surface is trimmed """ _round = lambda x: round(x, 3) a = map(_round, breptools_UVBounds(self)) b = map(_round, self.adaptor.Surface().Surface().GetObject().Bounds()) if 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 """ if self._classify_uv is None: self._classify_uv = BRepTopAdaptor_FClass2d(self, 1e-9) uv = gp_Pnt2d(u, v) if self._classify_uv.Perform(uv) == TopAbs_IN: return True else: return False def parameter_to_point(self, 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_handle) uv = sas.ValueOfUV(pt, self.tolerance) return uv.Coord() def continuity_edge_face(self, edge, face): """ compute the continuity between two faces at :edge: :param edge: an Edge or TopoDS_Edge from :face: :param face: a Face or TopoDS_Face :return: bool, GeomAbs_Shape if it has continuity, otherwise False, None """ bt = BRep_Tool() if bt.HasContinuity(edge, self, face): continuity = bt.Continuity(edge, self, face) return True, continuity else: return False, None # =========================================================================== # Surface.project # project curve, point on face # =========================================================================== def project_vertex(self, pnt, tol=TOLERANCE) -> gp_Pnt: """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) proj = GeomAPI_ProjectPointOnSurf(pnt, self.surface_handle, tol) # uv = proj.LowerDistanceParameters() proj_pnt = proj.NearestPoint() return proj_pnt 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).GetObject() return geomprojlib.Project(other, self.surface_handle) def project_edge(self, edg): if hasattr(edg, 'adaptor'): return self.project_curve(self, self.adaptor) return self.project_curve(self, to_adaptor_3d(edg)) @classmethod def create(cls, args): """ * Not done. :type F: TopoDS_Face & :type P: gp_Pln :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float :type C: gp_Cylinder :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float :type C: gp_Cone :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float :type S: gp_Sphere :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float :type C: gp_Torus :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float * Make a face from a Surface. Accepts tolerance value (TolDegen) for resolution of degenerated edges. :type S: Handle_Geom_Surface & :type TolDegen: float * Make a face from a Surface. Accepts tolerance value (TolDegen) for resolution of degenerated edges. :type S: Handle_Geom_Surface & :type UMin: (Optional) float :type UMax: (Optional) float :type VMin: (Optional) float :type VMax: (Optional) float :type TolDegen: float * Find a surface from the wire and make a face. if <OnlyPlane> is true, the computed surface will be a plane. If it is not possible to find a plane, the flag NotDone will be set. :type W: TopoDS_Wire & :param OnlyPlane: bool - default value is Standard_False * Make a face from a plane and a wire. :type P: gp_Pln :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Make a face from a cylinder and a wire. :type C: gp_Cylinder :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Make a face from a cone and a wire. :type C: gp_Cone :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Make a face from a sphere and a wire. :type S: gp_Sphere :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Make a face from a torus and a wire. :type C: gp_Torus :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Make a face from a Surface and a wire. :type S: Handle_Geom_Surface & :type W: TopoDS_Wire & :param Inside: default value is Standard_True :type Inside: bool * Adds the wire <W> in the face <F> A general method to create a face is to give - a surface S as the support (the geometric domain) of the face, - and a wire W to bound it. The bounds of the face can also be defined by four parameter values umin, umax, vmin, vmax which determine isoparametric limitations on the parametric space of the surface. In this way, a patch is defined. The parameter values are optional. If they are omitted, the natural bounds of the surface are used. A wire is automatically built using the defined bounds. Up to four edges and four vertices are created with this wire (no edge is created when the corresponding parameter value is infinite). Wires can then be added using the function Add to define other restrictions on the face. These restrictions represent holes. More than one wire may be added by this way, provided that the wires do not cross each other and that they define only one area on the surface. (Be careful, however, as this is not checked). Forbidden addition of wires Note that in this schema, the third case is valid if edges of the wire W are declared internal to the face. As a result, these edges are no longer bounds of the face. A default tolerance (Precision::Confusion()) is given to the face, this tolerance may be increased during construction of the face using various algorithms. Rules applied to the arguments For the surface: - The surface must not be a 'null handle'. - If the surface is a trimmed surface, the basis surface is used. - For the wire: the wire is composed of connected edges, each edge having a parametric curve description in the parametric domain of the surface; in other words, as a pcurve. For the parameters: - The parameter values must be in the parametric range of the surface (or the basis surface, if the surface is trimmed). If this condition is not satisfied, the face is not built, and the Error function will return BRepBuilderAPI_ParametersOutOfRange. - The bounding parameters p1 and p2 are adjusted on a periodic surface in a given parametric direction by adding or subtracting the period to obtain p1 in the parametric range of the surface and such p2, that p2 - p1 <= Period, where Period is the period of the surface in this parametric direction. - A parameter value may be infinite. There will be no edge and no vertex in the corresponding direction. :type F: TopoDS_Face & :type W: TopoDS_Wire & """ # BRepBuilderAPI_MakeFace # if isinstance(args, Topo): return @classmethod def from_wire(cls, topo: Union[Topo, TopoDS_Shape], plane: Optional[gp_Pln] = None) -> TopoDS_Face: """ create face from compound of edges """ # if topo.number_of_wires() == 0: from .Construct import assert_isdone wire_builder = BRepBuilderAPI_MakeWire() if isinstance(topo, TopoDS_Shape): top = Topo(topo) else: top = topo for edge in top.edges(): wire_builder.Add(edge) with assert_isdone(wire_builder, 'wire'): wire_builder.Build() w = wire_builder.Wire() if plane is not None: bface = BRepBuilderAPI_MakeFace(plane) else: # todo - this doesnt work ---- _face = TopoDS_Face() bface = BRepBuilderAPI_MakeFace(_face) bface.Add(w) with assert_isdone(bface, 'face'): bface.Build() face = bface.Shape() return face @classmethod def from_wires(cls, topo: List[TopoDS_Wire], plane: Optional[gp_Pln] = None) -> TopoDS_Face: """ create face from compound of edges """ # if topo.number_of_wires() == 0: wire = BRepBuilderAPI_MakeFace() for edge in topo: wire.Add(edge) wire.Build() w = wire.Face() return w @classmethod def from_topo_edges(cls, topo: Topo, plane: Optional[gp_Pln]=None) -> TopoDS_Face: """ create face from compound of edges """ # if topo.number_of_wires() == 0: wire = BRepBuilderAPI_MakeWire() for edge in topo.edges(): wire.Add(edge) wire.Build() w = wire.Wire() if plane is not None: bface = BRepBuilderAPI_MakeFace(plane) else: # todo - this doesnt work ---- _face = TopoDS_Face() bface = BRepBuilderAPI_MakeFace(_face) bface.Add(w) bface.Build() face = bface.Shape() return face def project_onto_plane(self, plane: gp_Pln): return @property def outter_wire(self): return breptools_OuterWire(self) @property def inner_wires(self): ow = breptools_OuterWire(self) inner = [] topo = Topo(self) for wire in topo.wires(): if wire.IsSame(ow): continue inner.append(wire) return inner def iso_curve(self, u_or_v, param): """ get the iso curve from a u,v + parameter :param u_or_v: :param param: :return: """ uv = 0 if u_or_v == 'u' else 1 iso = Adaptor3d_IsoCurve(self.adaptor_handle.GetHandle(), uv, param) return iso def edges(self): return [Edge(i) for i in WireExplorer(next(self.topo.wires())).ordered_edges()] def wires(self): topo = Topo(self) return [w for w in topo.wires()] def __repr__(self): return self.name def __str__(self): return self.__repr__() def plane(self): from OCC.Geom import Handle_Geom_Plane_DownCast _, center = self.mid_point() surf = BRep_Tool.Surface(self) obj = surf.GetObject() # Get resulting shapes if obj.DynamicType().GetObject().Name() != "Geom_Plane": # todo handle projection of cylindrical surfaces # 'expeced Geom_Plane, got {}'.format(obj.DynamicType().GetObject().Name()) return plane = Handle_Geom_Plane_DownCast(surf).GetObject() return plane.Pln()