Merge branch 'master' into adam-urbanczyk-brepfeat-prism

This commit is contained in:
Adam Urbańczyk
2019-02-28 21:55:08 +01:00
committed by GitHub
3 changed files with 71 additions and 24 deletions

View File

@ -2278,7 +2278,8 @@ class Workplane(CQ):
newS = newS.clean()
return newS
def sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False, combine=True, clean=True):
def sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False,
combine=True, clean=True, transition='right'):
"""
Use all un-extruded wires in the parent chain to create a swept solid.
@ -2288,10 +2289,14 @@ class Workplane(CQ):
True to create only one solid swept along path with shape following the list of wires on the chain
:param boolean combine: True to combine the resulting solid with parent solids if found.
:param boolean clean: call :py:meth:`clean` afterwards to have a clean shape
:param transition:
handling of profile orientation at C1 path discontinuities.
Possible values are {'transformed','round', 'right'} (default: 'right').
:return: a CQ object with the resulting solid selected.
"""
r = self._sweep(path.wire(), sweepAlongWires, makeSolid, isFrenet) # returns a Solid (or a compound if there were multiple)
r = self._sweep(path.wire(), sweepAlongWires, makeSolid, isFrenet,
transition) # returns a Solid (or a compound if there were multiple)
if combine:
newS = self._combineWithBase(r)
else:
@ -2644,7 +2649,8 @@ class Workplane(CQ):
return Compound.makeCompound(toFuse)
def _sweep(self, path, sweepAlongWires=False, makeSolid=True, isFrenet=False):
def _sweep(self, path, sweepAlongWires=False, makeSolid=True,
isFrenet=False, transition='right'):
"""
Makes a swept solid from an existing set of pending wires.
@ -2652,7 +2658,7 @@ class Workplane(CQ):
:param boolean sweepAlongWires:
False to create multiple swept from wires on the chain along path
True to create only one solid swept along path with shape following the list of wires on the chain
:return:a FreeCAD solid, suitable for boolean operations
:return:a solid, suitable for boolean operations
"""
# group wires together into faces based on which ones are inside the others
@ -2665,7 +2671,8 @@ class Workplane(CQ):
toFuse = []
if not sweepAlongWires:
for ws in wireSets:
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid, isFrenet)
thisObj = Solid.sweep(ws[0], ws[1:], path.val(), makeSolid,
isFrenet, transition)
toFuse.append(thisObj)
else:
section = []

View File

@ -16,7 +16,10 @@ from OCC.Core.BRepBuilderAPI import (BRepBuilderAPI_MakeVertex,
BRepBuilderAPI_MakeWire,
BRepBuilderAPI_Copy,
BRepBuilderAPI_GTransform,
BRepBuilderAPI_Transform)
BRepBuilderAPI_Transform,
BRepBuilderAPI_Transformed,
BRepBuilderAPI_RightCorner,
BRepBuilderAPI_RoundCorner)
# properties used to store mass calculation result
from OCC.Core.GProp import GProp_GProps
from OCC.Core.BRepGProp import BRepGProp_Face, \
@ -114,6 +117,7 @@ from OCC.Core.Addons import (text_to_brep,
from OCC.Core.BRepFeat import BRepFeat_MakePrism, BRepFeat_MakeDPrism
from math import pi, sqrt
from functools import reduce
TOLERANCE = 1e-6
DEG2RAD = 2 * pi / 360.
@ -194,7 +198,7 @@ class Shape(object):
"""Experimental clean using ShapeUpgrade"""
upgrader = ShapeUpgrade_UnifySameDomain(
self.wrapped, True, True, False)
self.wrapped, True, True, True)
upgrader.Build()
return self.cast(upgrader.Shape())
@ -1070,7 +1074,6 @@ class Mixin3D(object):
# make a edge --> faces mapping
edge_face_map = TopTools_IndexedDataMapOfShapeListOfShape()
topexp_MapShapesAndAncestors(self.wrapped,
ta.TopAbs_EDGE,
ta.TopAbs_FACE,
@ -1383,32 +1386,47 @@ class Solid(Shape, Mixin3D):
return cls(revol_builder.Shape())
_transModeDict = {'transformed' : BRepBuilderAPI_Transformed,
'round' : BRepBuilderAPI_RoundCorner,
'right' : BRepBuilderAPI_RightCorner}
@classmethod
def sweep(cls, outerWire, innerWires, path, makeSolid=True, isFrenet=False):
def sweep(cls, outerWire, innerWires, path, makeSolid=True, isFrenet=False,
transitionMode='transformed'):
"""
Attempt to sweep the list of wires into a prismatic solid along the provided path
:param outerWire: the outermost wire
:param innerWires: a list of inner wires
:param path: The wire to sweep the face resulting from the wires over
:param boolean makeSolid: return Solid or Shell (defualt True)
:param boolean isFrenet: Frenet mode (default False)
:param transitionMode:
handling of profile orientation at C1 path discontinuities.
Possible values are {'transformed','round', 'right'} (default: 'right').
:return: a Solid object
"""
if path.ShapeType() == 'Edge':
path = Wire.assembleEdges([path, ])
if makeSolid:
face = Face.makeFromWires(outerWire, innerWires)
builder = BRepOffsetAPI_MakePipe(path.wrapped, face.wrapped)
rv = cls(builder.Shape())
else:
shapes = []
for w in [outerWire]+innerWires:
builder = BRepOffsetAPI_MakePipeShell(path.wrapped)
builder.SetMode(isFrenet)
builder.SetTransitionMode(cls._transModeDict[transitionMode])
builder.Add(w.wrapped)
builder.Build()
if makeSolid:
builder.MakeSolid()
shapes.append(cls(builder.Shape()))
rv = Compound.makeCompound(shapes)
rv,inner_shapes = shapes[0],shapes[1:]
if inner_shapes:
inner_shapes = reduce(lambda a,b: a.fuse(b),inner_shapes)
rv = rv.cut(inner_shapes)
return rv
@ -1435,8 +1453,6 @@ class Solid(Shape, Mixin3D):
if makeSolid:
builder.MakeSolid()
return cls(builder.Shape())
def dprism(self, basis, profiles, depth=None, taper=0, thruAll=True,

View File

@ -438,10 +438,34 @@ class TestCadQuery(BaseTest):
path = Workplane("XZ").polyline(pts)
# Test defaults
result = Workplane("XY").circle(0.1).sweep(path)
result = Workplane("XY").circle(0.1).sweep(path,transition='transformed')
self.assertEqual(5, result.faces().size())
self.assertEqual(7, result.edges().size())
# Polyline path and one inner profiles
path = Workplane("XZ").polyline(pts)
# Test defaults
result = Workplane("XY").circle(0.2).circle(0.1).sweep(path,transition='transformed')
self.assertEqual(8, result.faces().size())
self.assertEqual(14, result.edges().size())
# Polyline path and different transition settings
for t in ('transformed','right','round'):
path = Workplane("XZ").polyline(pts)
result = Workplane("XY").circle(0.2).rect(0.2,0.1).rect(0.1,0.2)\
.sweep(path,transition=t)
self.assertTrue(result.solids().val().isValid())
# Polyline path and multiple inner profiles
path = Workplane("XZ").polyline(pts)
# Test defaults
result = Workplane("XY").circle(0.2).rect(0.2,0.1).rect(0.1,0.2)\
.circle(0.1).sweep(path)
self.assertTrue(result.solids().val().isValid())
# Arc path
path = Workplane("XZ").threePointArc((1.0, 1.5), (0.0, 1.0))