@@ -4222,7 +4222,7 @@ def _get_edges(s: Shape) -> Iterable[Shape]:
42224222
42234223def _get_wire_lists (s : Sequence [Shape ]) -> List [List [Wire ]]:
42244224 """
4225- Get lists or wires for sweeping or lofting.
4225+ Get lists of wires for sweeping or lofting.
42264226 """
42274227
42284228 wire_lists : List [List [Wire ]] = []
@@ -4237,6 +4237,23 @@ def _get_wire_lists(s: Sequence[Shape]) -> List[List[Wire]]:
42374237 return wire_lists
42384238
42394239
4240+ def _get_face_lists (s : Sequence [Shape ]) -> List [List [Face ]]:
4241+ """
4242+ Get lists of faces for sweeping or lofting.
4243+ """
4244+
4245+ face_lists : List [List [Face ]] = []
4246+
4247+ for el in s :
4248+ if not face_lists :
4249+ face_lists = [[f ] for f in el .Faces ()]
4250+ else :
4251+ for face_list , f in zip (face_lists , el .Faces ()):
4252+ face_list .append (f )
4253+
4254+ return face_lists
4255+
4256+
42404257def _normalize (s : Shape ) -> Shape :
42414258 """
42424259 Apply some normalizations:
@@ -4482,7 +4499,7 @@ def rect(w: float, h: float) -> Shape:
44824499@multimethod
44834500def spline (* pts : VectorLike , tol : float = 1e-6 , periodic : bool = False ) -> Shape :
44844501 """
4485- Construct a polygon (closed polyline) from points.
4502+ Construct a spline from points.
44864503 """
44874504
44884505 data = _pts_to_harray (pts )
@@ -4910,74 +4927,165 @@ def offset(s: Shape, t: float, cap=True, tol: float = 1e-6) -> Shape:
49104927@multimethod
49114928def sweep (s : Shape , path : Shape , cap : bool = False ) -> Shape :
49124929 """
4913- Sweep edge or wire along a path.
4930+ Sweep edge, wire or face along a path. For faces cap has no effect.
4931+ Do not mix faces with other types.
49144932 """
49154933
49164934 spine = _get_one_wire (path )
49174935
49184936 results = []
49194937
4920- for w in _get_wires (s ):
4921- builder = BRepOffsetAPI_MakePipeShell (spine .wrapped )
4922- builder .Add (w .wrapped , False , False )
4923- builder .Build ()
4938+ # try to get faces
4939+ faces = s .Faces ()
49244940
4925- if cap :
4926- builder .MakeSolid ()
4941+ # if faces were supplied
4942+ if faces :
4943+ for f in faces :
4944+ tmp = sweep (f .outerWire (), path , True )
49274945
4928- results .append (builder .Shape ())
4946+ # if needed subtract two sweeps
4947+ inner_wires = f .innerWires ()
4948+ if inner_wires :
4949+ tmp -= sweep (compound (inner_wires ), path , True )
4950+
4951+ results .append (tmp .wrapped )
4952+
4953+ # otherwise sweep wires
4954+ else :
4955+ for w in _get_wires (s ):
4956+ builder = BRepOffsetAPI_MakePipeShell (spine .wrapped )
4957+ builder .Add (w .wrapped , False , False )
4958+ builder .Build ()
4959+
4960+ if cap :
4961+ builder .MakeSolid ()
4962+
4963+ results .append (builder .Shape ())
49294964
49304965 return _compound_or_shape (results )
49314966
49324967
49334968@sweep .register
49344969def sweep (s : Sequence [Shape ], path : Shape , cap : bool = False ) -> Shape :
49354970 """
4936- Sweep edges or wires along a path, chaining sections are supported.
4971+ Sweep edges, wires or faces along a path, multiple sections are supported.
4972+ For faces cap has no effect. Do not mix faces with other types.
49374973 """
49384974
49394975 spine = _get_one_wire (path )
49404976
49414977 results = []
49424978
4943- # construct sweeps
4944- for el in _get_wire_lists (s ):
4979+ # try to construct sweeps using faces
4980+ for el in _get_face_lists (s ):
4981+ # build outer part
49454982 builder = BRepOffsetAPI_MakePipeShell (spine .wrapped )
49464983
4947- for w in el :
4948- builder .Add (w .wrapped , False , False )
4984+ for f in el :
4985+ builder .Add (f . outerWire () .wrapped , False , False )
49494986
49504987 builder .Build ()
4988+ builder .MakeSolid ()
49514989
4952- if cap :
4953- builder . MakeSolid ()
4990+ # build inner parts
4991+ builders_inner = []
49544992
4955- results .append (builder .Shape ())
4993+ # initialize builders
4994+ for w in el [0 ].innerWires ():
4995+ builder_inner = BRepOffsetAPI_MakePipeShell (spine .wrapped )
4996+ builder_inner .Add (w .wrapped , False , False )
4997+ builders_inner .append (builder_inner )
4998+
4999+ # add remaining sections
5000+ for f in el [1 :]:
5001+ for builder_inner , w in zip (builders_inner , f .innerWires ()):
5002+ builder_inner .Add (w .wrapped , False , False )
5003+
5004+ # actually build
5005+ inner_parts = []
5006+
5007+ for builder_inner in builders_inner :
5008+ builder_inner .Build ()
5009+ builder_inner .MakeSolid ()
5010+ inner_parts .append (Shape (builder_inner .Shape ()))
5011+
5012+ results .append ((Shape (builder .Shape ()) - compound (inner_parts )).wrapped )
5013+
5014+ # if no faces were provided try with wires
5015+ if not results :
5016+ # construct sweeps
5017+ for el in _get_wire_lists (s ):
5018+ builder = BRepOffsetAPI_MakePipeShell (spine .wrapped )
5019+
5020+ for w in el :
5021+ builder .Add (w .wrapped , False , False )
5022+
5023+ builder .Build ()
5024+
5025+ if cap :
5026+ builder .MakeSolid ()
5027+
5028+ results .append (builder .Shape ())
49565029
49575030 return _compound_or_shape (results )
49585031
49595032
49605033@multimethod
49615034def loft (s : Sequence [Shape ], cap : bool = False , ruled : bool = False ) -> Shape :
49625035 """
4963- Loft edges or wires .
5036+ Loft edges, wires or faces. For faces cap has no effect. Do not mix faces with other types .
49645037 """
49655038
49665039 results = []
4967-
4968- # construct lofts
49695040 builder = BRepOffsetAPI_ThruSections ()
49705041
4971- for el in _get_wire_lists (s ):
4972- builder .Init (cap , ruled )
5042+ # try to construct lofts using faces
5043+ for el in _get_face_lists (s ):
5044+ # build outer part
5045+ builder .Init (True , ruled )
49735046
4974- for w in el :
4975- builder .AddWire (w .wrapped )
5047+ for f in el :
5048+ builder .AddWire (f . outerWire () .wrapped )
49765049
49775050 builder .Build ()
49785051 builder .Check ()
49795052
4980- results .append (builder .Shape ())
5053+ builders_inner = []
5054+
5055+ # initialize builders
5056+ for w in el [0 ].innerWires ():
5057+ builder_inner = BRepOffsetAPI_ThruSections ()
5058+ builder_inner .Init (True , ruled )
5059+ builder_inner .AddWire (w .wrapped )
5060+ builders_inner .append (builder_inner )
5061+
5062+ # add remaining sections
5063+ for f in el [1 :]:
5064+ for builder_inner , w in zip (builders_inner , f .innerWires ()):
5065+ builder_inner .AddWire (w .wrapped )
5066+
5067+ # actually build
5068+ inner_parts = []
5069+
5070+ for builder_inner in builders_inner :
5071+ builder_inner .Build ()
5072+ builder_inner .Check ()
5073+ inner_parts .append (Shape (builder_inner .Shape ()))
5074+
5075+ results .append ((Shape (builder .Shape ()) - compound (inner_parts )).wrapped )
5076+
5077+ # otherwise construct using wires
5078+ if not results :
5079+ for el in _get_wire_lists (s ):
5080+ builder .Init (cap , ruled )
5081+
5082+ for w in el :
5083+ builder .AddWire (w .wrapped )
5084+
5085+ builder .Build ()
5086+ builder .Check ()
5087+
5088+ results .append (builder .Shape ())
49815089
49825090 return _compound_or_shape (results )
49835091
0 commit comments