[PD] Revert 316506f, back to shell algo for some helix cases (#15678)
* [PD] Revert 316506f, back to shell algo for some helix cases * fix test accuracy
This commit is contained in:
committed by
GitHub
parent
1f67a96a66
commit
84e25ed38d
@@ -232,12 +232,78 @@ App::DocumentObjectExecReturn* Helix::execute()
|
||||
|
||||
// generate the helix path
|
||||
TopoDS_Shape path = generateHelixPath();
|
||||
TopoDS_Shape auxpath = generateHelixPath(1.0);
|
||||
|
||||
TopoDS_Shape face = Part::FaceMakerCheese::makeFace(wires);
|
||||
face.Move(invObjLoc);
|
||||
BRepOffsetAPI_MakePipe mkPS(TopoDS::Wire(path), face, GeomFill_Trihedron::GeomFill_IsFrenet, Standard_False);
|
||||
mkPS.Build();
|
||||
result = mkPS.Shape();
|
||||
// Use MakePipe for frenet ( Angle is 0 ) calculations, faster than MakePipeShell
|
||||
if ( Angle.getValue() == 0 ) {
|
||||
TopoDS_Shape face = Part::FaceMakerCheese::makeFace(wires);
|
||||
face.Move(invObjLoc);
|
||||
BRepOffsetAPI_MakePipe mkPS(TopoDS::Wire(path), face, GeomFill_Trihedron::GeomFill_IsFrenet, Standard_False);
|
||||
result = mkPS.Shape();
|
||||
} else {
|
||||
std::vector<std::vector<TopoDS_Wire>> wiresections;
|
||||
for (TopoDS_Wire& wire : wires)
|
||||
wiresections.emplace_back(1, wire);
|
||||
|
||||
//build all shells
|
||||
std::vector<TopoDS_Shape> shells;
|
||||
std::vector<TopoDS_Wire> frontwires, backwires;
|
||||
for (std::vector<TopoDS_Wire>& wires : wiresections) {
|
||||
|
||||
BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));
|
||||
|
||||
// Frenet mode doesn't place the face quite right on an angled helix, so
|
||||
// use the auxiliary spine to force that.
|
||||
mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxiliary
|
||||
|
||||
for (TopoDS_Wire& wire : wires) {
|
||||
wire.Move(invObjLoc);
|
||||
mkPS.Add(wire);
|
||||
}
|
||||
|
||||
if (!mkPS.IsReady())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Could not build"));
|
||||
mkPS.Build();
|
||||
|
||||
shells.push_back(mkPS.Shape());
|
||||
|
||||
if (!mkPS.Shape().Closed()) {
|
||||
// // shell is not closed - use simulate to get the end wires
|
||||
TopTools_ListOfShape sim;
|
||||
mkPS.Simulate(2, sim);
|
||||
|
||||
frontwires.push_back(TopoDS::Wire(sim.First()));
|
||||
backwires.push_back(TopoDS::Wire(sim.Last()));
|
||||
}
|
||||
BRepBuilderAPI_MakeSolid mkSolid;
|
||||
|
||||
if (!frontwires.empty()) {
|
||||
// build the end faces, sew the shell and build the final solid
|
||||
TopoDS_Shape front = Part::FaceMakerCheese::makeFace(frontwires);
|
||||
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
|
||||
|
||||
BRepBuilderAPI_Sewing sewer;
|
||||
sewer.SetTolerance(Precision::Confusion());
|
||||
sewer.Add(front);
|
||||
sewer.Add(back);
|
||||
|
||||
for (TopoDS_Shape& s : shells)
|
||||
sewer.Add(s);
|
||||
sewer.Perform();
|
||||
mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
|
||||
}
|
||||
else {
|
||||
// shells are already closed - add them directly
|
||||
for (TopoDS_Shape& s : shells) {
|
||||
mkSolid.Add(TopoDS::Shell(s));
|
||||
}
|
||||
}
|
||||
if (!mkSolid.IsDone())
|
||||
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Result is not a solid"));
|
||||
|
||||
result = mkSolid.Shape();
|
||||
}
|
||||
}
|
||||
|
||||
BRepClass3d_SolidClassifier SC(result);
|
||||
SC.PerformInfinitePoint(Precision::Confusion());
|
||||
@@ -335,7 +401,7 @@ void Helix::updateAxis()
|
||||
Axis.setValue(dir.x, dir.y, dir.z);
|
||||
}
|
||||
|
||||
TopoDS_Shape Helix::generateHelixPath()
|
||||
TopoDS_Shape Helix::generateHelixPath(double startOffset0)
|
||||
{
|
||||
double turns = Turns.getValue();
|
||||
double height = Height.getValue();
|
||||
@@ -381,7 +447,7 @@ TopoDS_Shape Helix::generateHelixPath()
|
||||
bool turned = axisOffset < 0;
|
||||
// since the factor does not only change the radius but also the path position, we must shift its offset back
|
||||
// using the square of the factor
|
||||
double startOffset = 10000.0 * std::fabs(baseVector * axisVector);
|
||||
double startOffset = 10000.0 * std::fabs(startOffset0 + profileCenter * axisVector - baseVector * axisVector);
|
||||
|
||||
if (radius < Precision::Confusion()) {
|
||||
// in this case ensure that axis is not in the sketch plane
|
||||
@@ -398,7 +464,8 @@ TopoDS_Shape Helix::generateHelixPath()
|
||||
radiusTop = radius + height * tan(Base::toRadians(angle));
|
||||
|
||||
//build the helix path
|
||||
TopoDS_Shape path = TopoShape().makeSpiralHelix(radius, radiusTop, height, turns, 1000, leftHanded);
|
||||
//TopoShape helix = TopoShape().makeLongHelix(pitch, height, radius, angle, leftHanded);
|
||||
TopoDS_Shape path = TopoShape().makeSpiralHelix(radius, radiusTop, height, turns, 1, leftHanded);
|
||||
|
||||
/*
|
||||
* The helix wire is created with the axis coinciding with z-axis and the start point at (radius, 0, 0)
|
||||
|
||||
@@ -80,7 +80,7 @@ protected:
|
||||
void updateAxis();
|
||||
|
||||
/// generate helix and move it to the right location.
|
||||
TopoDS_Shape generateHelixPath();
|
||||
TopoDS_Shape generateHelixPath(double startOffset0 = 0.0);
|
||||
|
||||
// project shape on plane. Used for detecting self intersection.
|
||||
TopoDS_Shape projectShape(const TopoDS_Shape& input, const gp_Ax2& plane);
|
||||
|
||||
@@ -95,7 +95,7 @@ class TestHelix(unittest.TestCase):
|
||||
|
||||
profileSketch.addGeometry(Part.Circle(FreeCAD.Vector(2, 0, 0), FreeCAD.Vector(0,0,1), 0.5) )
|
||||
self.Doc.recompute()
|
||||
self.assertAlmostEqual(helix.Shape.Volume, 100.63,places=2)
|
||||
self.assertAlmostEqual(helix.Shape.Volume, 100.63, places=2)
|
||||
|
||||
|
||||
def testRectangle(self):
|
||||
@@ -174,7 +174,7 @@ class TestHelix(unittest.TestCase):
|
||||
helix.Mode = 0
|
||||
helix.Reversed = True
|
||||
self.Doc.recompute()
|
||||
self.assertAlmostEqual(helix.Shape.Volume/1e5, 3.8828,places=4)
|
||||
self.assertAlmostEqual(helix.Shape.Volume/1e5, 3.8828, places=3)
|
||||
|
||||
def tearDown(self):
|
||||
FreeCAD.closeDocument("PartDesignTestHelix")
|
||||
|
||||
Reference in New Issue
Block a user