Toponaming: Remove all FC_USE_TNP_FIX protected old code

This commit is contained in:
bgbsww
2024-05-20 21:57:39 -04:00
committed by Chris Hennes
parent 60640fa441
commit ecf7e51ab3
52 changed files with 22 additions and 4760 deletions

View File

@@ -62,9 +62,6 @@ Feature::Feature()
BaseFeature.setStatus(App::Property::Hidden, true);
App::SuppressibleExtension::initExtension(this);
#ifndef FC_USE_TNP_FIX
Suppressed.setStatus(App::Property::Status::Hidden, true);
#endif
}
App::DocumentObjectExecReturn* Feature::recompute()

View File

@@ -114,7 +114,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
return new App::DocumentObjectExecReturn(e.what());
}
#ifdef FC_USE_TNP_FIX
TopShape.setTransform(Base::Matrix4D());
auto edges = UseAllEdges.getValue() ? TopShape.getSubTopoShapes(TopAbs_EDGE)
@@ -124,24 +123,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "No edges specified"));
}
#else
std::vector<std::string> SubNames = std::vector<std::string>(Base.getSubValues());
if (UseAllEdges.getValue()){
SubNames.clear();
std::string edgeTypeName = Part::TopoShape::shapeName(TopAbs_EDGE); //"Edge"
int count = TopShape.countSubElements(edgeTypeName.c_str());
for (int ii = 0; ii < count; ii++){
std::ostringstream edgeName;
edgeName << edgeTypeName << ii+1;
SubNames.push_back(edgeName.str());
}
}
std::vector<std::string> FaceNames;
getContinuousEdges(TopShape, SubNames, FaceNames);
#endif
const int chamferType = ChamferType.getValue();
const double size = Size.getValue();
double size2 = Size2.getValue();
@@ -155,22 +136,10 @@ App::DocumentObjectExecReturn *Chamfer::execute()
this->positionByBaseFeature();
#ifdef FC_USE_TNP_FIX
if ( static_cast<Part::ChamferType>(chamferType) == Part::ChamferType::distanceAngle ) {
size2 = angle;
}
#else
//If no element is selected, then we use a copy of previous feature.
if (SubNames.empty()) {
this->Shape.setValue(TopShape);
return App::DocumentObject::StdReturn;
}
// create an untransformed copy of the basefeature shape
Part::TopoShape baseShape(TopShape);
baseShape.setTransform(Base::Matrix4D());
#endif
try {
#ifdef FC_USE_TNP_FIX
TopoShape shape(0);
shape.makeElementChamfer(TopShape,
edges,
@@ -207,81 +176,6 @@ App::DocumentObjectExecReturn *Chamfer::execute()
QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
return App::DocumentObject::StdReturn;
#else
BRepFilletAPI_MakeChamfer mkChamfer(baseShape.getShape());
TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
TopExp::MapShapesAndAncestors(baseShape.getShape(), TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
for (const auto &itSN : SubNames) {
TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(itSN.c_str()));
const TopoDS_Shape& faceLast = mapEdgeFace.FindFromKey(edge).Last();
const TopoDS_Shape& faceFirst = mapEdgeFace.FindFromKey(edge).First();
// Set the face based on flipDirection for all edges by default. Note for chamferType==0 it does not matter which face is used.
TopoDS_Face face = TopoDS::Face( flipDirection ? faceLast : faceFirst );
// for chamfer types otherthan Equal (type = 0) check if one of the faces associated with the edge
// is one of the originally selected faces. If so use the other face by default or the selected face if "flipDirection" is set
if (chamferType != 0) {
// for each selected face
for (const auto &itFN : FaceNames) {
const TopoDS_Shape selFace = baseShape.getSubShape(itFN.c_str());
if ( faceLast.IsEqual(selFace) )
face = TopoDS::Face( flipDirection ? faceFirst : faceLast );
else if ( faceFirst.IsEqual(selFace) )
face = TopoDS::Face( flipDirection ? faceLast : faceFirst );
}
}
switch (chamferType) {
case 0: // Equal distance
mkChamfer.Add(size, size, edge, face);
break;
case 1: // Two distances
mkChamfer.Add(size, size2, edge, face);
break;
case 2: // Distance and angle
mkChamfer.AddDA(size, Base::toRadians(angle), edge, face);
break;
}
}
mkChamfer.Build();
if (!mkChamfer.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Failed to create chamfer"));
TopoDS_Shape shape = mkChamfer.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is null"));
TopTools_ListOfShape aLarg;
aLarg.Append(baseShape.getShape());
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
ShapeFix_ShapeTolerance aSFT;
aSFT.LimitTolerance(shape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(shape);
aSfs->Perform();
shape = aSfs->Shape();
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
}
if (!isSingleSolidRuleSatisfied(shape)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
shape = refineShapeIfActive(shape);
this->Shape.setValue(getSolid(shape));
return App::DocumentObject::StdReturn;
#endif
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());

View File

@@ -325,11 +325,7 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
baseShape.move(base->getLocation().Inverted());
if (base->getAddSubType() == Additive) {
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
#endif
else
shapes.push_back(shape);
} else {
@@ -339,35 +335,22 @@ void DressUp::getAddSubShape(Part::TopoShape &addShape, Part::TopoShape &subShap
// push an empty compound to indicate null additive shape
shapes.emplace_back(comp);
if(!baseShape.isNull() && baseShape.hasSubShape(TopAbs_SOLID))
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
else
shapes.push_back(shape);
}
} else {
baseShape = getBaseTopoShape();
baseShape.move(getLocation().Inverted());
#ifdef FC_USE_TNP_FIX
shapes.emplace_back(shape.makeElementCut(baseShape.getShape()));
shapes.emplace_back(baseShape.makeElementCut(shape.getShape()));
#else
shapes.emplace_back(shape.cut(baseShape.getShape()));
shapes.emplace_back(baseShape.cut(shape.getShape()));
#endif
}
// Make a compound to contain both additive and subtractive shape,
// bceause a dressing (e.g. a fillet) can either be additive or
// subtractive. And the dressup feature can contain mixture of both.
#ifdef FC_USE_TNP_FIX
AddSubShape.setValue(Part::TopoShape().makeElementCompound(shapes));
#else
AddSubShape.setValue(Part::TopoShape().makeCompound(shapes));
#endif
} catch (Standard_Failure &e) {
FC_THROWM(Base::CADKernelError, "Failed to calculate AddSub shape: "
<< e.GetMessageString());

View File

@@ -65,7 +65,6 @@ short Fillet::mustExecute() const
App::DocumentObjectExecReturn *Fillet::execute()
{
#ifdef FC_USE_TNP_FIX
Part::TopoShape baseShape;
try {
baseShape = getBaseTopoShape();
@@ -127,87 +126,6 @@ App::DocumentObjectExecReturn *Fillet::execute()
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
#else
Part::TopoShape TopShape;
try {
TopShape = getBaseTopoShape();
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
std::vector<std::string> SubNames = std::vector<std::string>(Base.getSubValues());
if (UseAllEdges.getValue()){
SubNames.clear();
std::string edgeTypeName = Part::TopoShape::shapeName(TopAbs_EDGE); //"Edge"
int count = TopShape.countSubElements(edgeTypeName.c_str());
for (int ii = 0; ii < count; ii++){
std::ostringstream edgeName;
edgeName << edgeTypeName << ii+1;
SubNames.push_back(edgeName.str());
}
}
getContinuousEdges(TopShape, SubNames);
double radius = Radius.getValue();
if(radius <= 0)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Fillet radius must be greater than zero"));
this->positionByBaseFeature();
//If no element is selected, then we use a copy of previous feature.
if (SubNames.empty()) {
this->Shape.setValue(TopShape);
return App::DocumentObject::StdReturn;
}
// create an untransformed copy of the base shape
Part::TopoShape baseShape(TopShape);
baseShape.setTransform(Base::Matrix4D());
try {
BRepFilletAPI_MakeFillet mkFillet(baseShape.getShape());
for (const auto & it : SubNames) {
TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it.c_str()));
mkFillet.Add(radius, edge);
}
mkFillet.Build();
if (!mkFillet.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Failed to create fillet"));
TopoDS_Shape shape = mkFillet.Shape();
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is null"));
TopTools_ListOfShape aLarg;
aLarg.Append(baseShape.getShape());
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
ShapeFix_ShapeTolerance aSFT;
aSFT.LimitTolerance(shape, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(shape);
aSfs->Perform();
shape = aSfs->Shape();
if (!BRepAlgo::IsValid(aLarg, shape, Standard_False, Standard_False)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is invalid"));
}
}
if (!isSingleSolidRuleSatisfied(shape)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
shape = refineShapeIfActive(shape);
this->Shape.setValue(getSolid(shape));
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
#endif
}
void Fillet::Restore(Base::XMLReader &reader)

View File

@@ -79,170 +79,6 @@ short Groove::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Groove::execute()
{
// Validate parameters
// All angles are in radians unless explicitly stated
double angleDeg = Angle.getValue();
if (angleDeg > 360.0)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Angle of groove too large"));
double angle = Base::toRadians<double>(angleDeg);
if (angle < Precision::Angular())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Angle of groove too small"));
double angle2 = Base::toRadians(Angle2.getValue());
TopoDS_Shape sketchshape;
try {
sketchshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoDS_Shape base;
try {
base = getBaseShape();
}
catch (const Base::Exception&) {
std::string text(QT_TRANSLATE_NOOP("Exception", "The requested feature cannot be created. The reason may be that:\n"
" - the active Body does not contain a base shape, so there is no\n"
" material to be removed;\n"
" - the selected sketch does not belong to the active Body."));
return new App::DocumentObjectExecReturn(text);
}
// update Axis from ReferenceAxis
try {
updateAxis();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// get revolve axis
Base::Vector3d b = Base.getValue();
gp_Pnt pnt(b.x,b.y,b.z);
Base::Vector3d v = Axis.getValue();
gp_Dir dir(v.x,v.y,v.z);
try {
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Creating a face from sketch failed"));
RevolMethod method = methodFromString(Type.getValueAsString());
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
pnt.Transform(invObjLoc.Transformation());
dir.Transform(invObjLoc.Transformation());
base.Move(invObjLoc);
sketchshape.Move(invObjLoc);
// Check distance between sketchshape and axis - to avoid failures and crashes
TopExp_Explorer xp;
xp.Init(sketchshape, TopAbs_FACE);
for (;xp.More(); xp.Next()) {
if (checkLineCrossesFace(gp_Lin(pnt, dir), TopoDS::Face(xp.Current())))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Revolve axis intersects the sketch"));
}
// Create a fresh support even when base exists so that it can be used for patterns
TopoDS_Shape result;
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (method == RevolMethod::ToFace || method == RevolMethod::ToFirst) {
TopoDS_Face upToFace;
if (method == RevolMethod::ToFace) {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
else
throw Base::RuntimeError("ProfileBased: Groove up to first is not yet supported");
// TODO: This method is designed for extrusions. needs to be adapted for grooves.
// getUpToFace(upToFace, base, supportface, sketchshape, method, dir);
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
RevolMode mode = RevolMode::CutFromBase;
generateRevolution(result, base, sketchshape, supportface, upToFace, gp_Ax1(pnt, dir), method, mode, Standard_True);
result = refineShapeIfActive(result);
// the result we get here is the shape _after_ the operation is done
// And the really expensive way to get the SubShape...
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn("Groove: Up to face: Could not get SubShape!");
// FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!!
TopoDS_Shape subshape = refineShapeIfActive(mkCut.Shape());
this->AddSubShape.setValue(subshape);
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn("Groove: Result has multiple solids. This is not supported at this time.");
}
this->Shape.setValue(getSolid(result));
}
else {
bool midplane = Midplane.getValue();
bool reversed = Reversed.getValue();
generateRevolution(result, sketchshape, gp_Ax1(pnt, dir), angle, angle2, midplane, reversed, method);
if (result.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not revolve the sketch!"));
// set the subtractive shape property for later usage in e.g. pattern
result = refineShapeIfActive(result);
this->AddSubShape.setValue(result);
// cut out groove to get one result object
BRepAlgoAPI_Cut mkCut(base, result);
// Let's check if the fusion has been successful
if (!mkCut.IsDone())
throw Base::CADKernelError(QT_TRANSLATE_NOOP("Exception", "Cut out of base feature failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(mkCut.Shape());
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
solRes = refineShapeIfActive(solRes);
this->Shape.setValue(getSolid(solRes));
if (!isSingleSolidRuleSatisfied(solRes)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face")
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities in a sketch are not allowed."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
}
#else
App::DocumentObjectExecReturn *Groove::execute()
{
// Validate parameters
@@ -372,8 +208,6 @@ App::DocumentObjectExecReturn *Groove::execute()
}
}
#endif
bool Groove::suggestReversed()
{
updateAxis();

View File

@@ -65,273 +65,6 @@ short Loft::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Loft::execute()
{
auto getSectionShape =
[](App::DocumentObject* feature, const std::vector<std::string> &subs) -> TopoDS_Shape {
if (!feature ||
!feature->isDerivedFrom(Part::Feature::getClassTypeId()))
throw Base::TypeError("Loft: Invalid profile/section");
auto subName = subs.empty() ? "" : subs.front();
// only take the entire shape when we have a sketch selected, but
// not a point of the sketch
if (feature->isDerivedFrom(Part::Part2DObject::getClassTypeId()) &&
subName.compare(0, 6, "Vertex") != 0)
return static_cast<Part::Part2DObject*>(feature)->Shape.getValue();
else {
if(subName.empty())
throw Base::ValueError("No valid subelement linked in Part::Feature");
return static_cast<Part::Feature*>(feature)->Shape.getShape().getSubShape(subName.c_str());
}
};
auto addWiresToWireSections =
[](TopoDS_Shape& section,
std::vector<std::vector<TopoDS_Shape>>& wiresections) -> size_t {
TopExp_Explorer ex;
size_t i=0;
bool initialWireSectionsEmpty = wiresections.empty();
for (ex.Init(section, TopAbs_WIRE); ex.More(); ex.Next(), ++i) {
// if profile was just a point then this is where we can first set our list
if (i>=wiresections.size()) {
if (initialWireSectionsEmpty)
wiresections.emplace_back(1, ex.Current());
else
throw Base::ValueError("Loft: Sections need to have the same amount of inner wires (except profile and last section, which can be points)");
}
else
wiresections[i].push_back(TopoDS::Wire(ex.Current()));
}
return i;
};
std::vector<TopoDS_Wire> wires;
TopoDS_Shape profilePoint;
// if the Base property has a valid shape, fuse the pipe into it
TopoDS_Shape base;
try {
base = getBaseShape();
} catch (const Base::Exception&) {
base = TopoDS_Shape();
}
try {
// setup the location
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
if (!base.IsNull())
base.Move(invObjLoc);
// build up multisections
auto multisections = Sections.getSubListValues();
if (multisections.empty())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: At least one section is needed"));
TopoDS_Shape profileShape = getSectionShape(Profile.getValue(),
Profile.getSubValues());
if (profileShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Could not obtain profile shape"));
std::vector<std::vector<TopoDS_Shape>> wiresections;
size_t numWires = addWiresToWireSections(profileShape, wiresections);
if (numWires == 0) {
// profileShape had no wires so only other valid option is point section
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(profileShape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i) {
profilePoint = ex.Current();
}
if (i > 1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: When using points for profile/sections, the sketch should have a single point"));
}
bool isLastSectionVertex = false;
size_t subSetCnt=0;
for (const auto & subSet : multisections) {
if (!subSet.first->isDerivedFrom(Part::Feature::getClassTypeId()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: All sections need to be part features"));
// if the selected subvalue is a point, pick that even if we have a sketch
TopoDS_Shape shape = getSectionShape(subSet.first, subSet.second);
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Could not obtain section shape"));
size_t numWiresAdded = addWiresToWireSections(shape, wiresections);
if (numWiresAdded == 0) {
// The shape of the given object doesn't contain any wires, though it still might be valid if it is a vertex (or a COMPOUND consisting a single vertex)
TopoDS_Shape vertexShape;
TopExp_Explorer ex{shape, TopAbs_VERTEX};
if (ex.More()) {
vertexShape = ex.Current();
ex.Next();
if (ex.More()) { // some additional vertexes in the shape, we shouldn't use it
vertexShape.Nullify();
}
}
if (vertexShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: A section doesn't contain any wires nor is a single vertex"));
if (subSetCnt != multisections.size()-1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Only the profile and the last section can be vertices"));
if (Closed.getValue())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: For closed lofts only the profile can be a vertex"));
// all good; push vertex to all wiresection list
for (auto &wires : wiresections)
wires.push_back(vertexShape);
isLastSectionVertex = true;
} else if (numWiresAdded != wiresections.size())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: all loft sections need to have the same amount of inner wires"));
subSetCnt++;
}
if (Closed.getValue()) {
// For a closed loft add starting sketch again at the end
if (profilePoint.IsNull()) {
size_t numWiresAdded = addWiresToWireSections(profileShape, wiresections);
assert (numWiresAdded == wiresections.size());
boost::ignore_unused(numWiresAdded);
} else { // !profilePoint.IsNull()
for (auto &wires : wiresections)
wires.push_back(profilePoint);
}
}
// build all shells
std::vector<TopoDS_Shape> shells;
TopoDS_Shape copyProfilePoint(profilePoint);
if (!profilePoint.IsNull())
copyProfilePoint.Move(invObjLoc);
for (auto& wires : wiresections) {
BRepOffsetAPI_ThruSections mkTS(false, Ruled.getValue(), Precision::Confusion());
if (!profilePoint.IsNull())
mkTS.AddVertex(TopoDS::Vertex(copyProfilePoint));
for (auto& shape : wires) {
shape.Move(invObjLoc);
if (shape.ShapeType() == TopAbs_VERTEX)
mkTS.AddVertex(TopoDS::Vertex(shape));
else
mkTS.AddWire(TopoDS::Wire(shape));
}
mkTS.Build();
if (!mkTS.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft could not be built"));
// build the shell use simulate to get the top and bottom wires in an easy way
shells.push_back(mkTS.Shape());
}
// build the top and bottom faces (where possible), sew the shell,
// and build the final solid
BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
if (!Closed.getValue()) {
if (profilePoint.IsNull()) {
TopoDS_Shape front = getVerifiedFace();
front.Move(invObjLoc);
sewer.Add(front);
}
if (!isLastSectionVertex) {
std::vector<TopoDS_Wire> backwires;
for (auto& wires : wiresections)
backwires.push_back(TopoDS::Wire(wires.back()));
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
sewer.Add(back);
}
}
for (TopoDS_Shape& s : shells)
sewer.Add(s);
sewer.Perform();
// build the solid
BRepBuilderAPI_MakeSolid mkSolid;
mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
if (!mkSolid.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Result is not a solid"));
TopoDS_Shape result = mkSolid.Shape();
BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
if ( SC.State() == TopAbs_IN) {
result.Reverse();
}
AddSubShape.setValue(result);
if (base.IsNull()) {
if (getAddSubType() == FeatureAddSub::Subtractive)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: There is nothing to subtract from"));
Shape.setValue(getSolid(result));
return App::DocumentObject::StdReturn;
}
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, result);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Adding the loft failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: Subtracting the loft failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
catch (...) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Loft: A fatal error occurred when making the loft"));
}
}
#else
std::vector<Part::TopoShape>
Loft::getSectionShape(const char *name,
App::DocumentObject *obj,
@@ -533,8 +266,6 @@ App::DocumentObjectExecReturn *Loft::execute()
}
}
#endif
PROPERTY_SOURCE(PartDesign::AdditiveLoft, PartDesign::Loft)
AdditiveLoft::AdditiveLoft() {
addSubType = Additive;

View File

@@ -68,204 +68,8 @@ Pad::Pad()
Length2.setConstraints(nullptr);
}
#ifdef FC_USE_TNP_FIX
App::DocumentObjectExecReturn* Pad::execute()
{
return buildExtrusion(ExtrudeOption::MakeFace | ExtrudeOption::MakeFuse);
}
#else
App::DocumentObjectExecReturn *Pad::execute()
{
double L = Length.getValue();
double L2 = Length2.getValue();
// if midplane is true, disable reversed and vice versa
bool hasMidplane = Midplane.getValue();
bool hasReversed = Reversed.getValue();
Midplane.setReadOnly(hasReversed);
Reversed.setReadOnly(hasMidplane);
std::string method(Type.getValueAsString());
TopoDS_Shape sketchshape;
try {
sketchshape = getVerifiedFace();
}
catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoDS_Shape base;
try {
base = getBaseShape();
}
catch (const Base::Exception&) {
if (method == "UpToShape") {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Can't pad up to shape without base shape."));
}
base = TopoDS_Shape();
}
// get the normal vector of the sketch
Base::Vector3d SketchVector = getProfileNormal();
try {
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
base.Move(invObjLoc);
Base::Vector3d paddingDirection = computeDirection(SketchVector, false);
// create vector in padding direction with length 1
gp_Dir dir(paddingDirection.x, paddingDirection.y, paddingDirection.z);
// The length of a gp_Dir is 1 so the resulting pad would have
// the length L in the direction of dir. But we want to have its height in the
// direction of the normal vector.
// Therefore we must multiply L by the factor that is necessary
// to make dir as long that its projection to the SketchVector
// equals the SketchVector.
// This is the scalar product of both vectors.
// Since the pad length cannot be negative, the factor must not be negative.
double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z));
// factor would be zero if vectors are orthogonal
if (factor < Precision::Confusion())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Creation failed because direction is orthogonal to sketch's normal vector"));
// perform the length correction if not along custom vector
if (AlongSketchNormal.getValue()) {
L = L / factor;
L2 = L2 / factor;
}
dir.Transform(invObjLoc.Transformation());
if (sketchshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Creating a face from sketch failed"));
sketchshape.Move(invObjLoc);
TopoDS_Shape prism;
if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace" || method == "UpToShape") {
// Note: This will return an unlimited planar face if support is a datum plane
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
TopoDS_Face upToFace;
if (method != "UpToShape") {
// Find a valid face or datum plane to extrude up to
if (method == "UpToFace") {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
getUpToFace(upToFace, base, sketchshape, method, dir);
addOffsetToFace(upToFace, dir, Offset.getValue());
}
// TODO: Write our own PrismMaker which does not depend on a solid base shape
if (base.IsNull()) {
//generatePrism(prism, sketchshape, "Length", dir, length, 0.0, false, false);
base = sketchshape;
supportface = TopoDS::Face(sketchshape);
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
PrismMode mode = PrismMode::None;
if (method == "UpToShape")
generatePrism(prism, "UpToFace", base, sketchshape, supportface, base, dir, mode, Standard_True);
else
generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, mode, Standard_True);
base.Nullify();
}
else {
// A support object is always required and we need to use BRepFeat_MakePrism
// Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid
// because the feature does not add any material. This only happens with the "2" option, though
// Note: It might be possible to pass a shell or a compound containing multiple faces
// as the Until parameter of Perform()
// Note: Multiple independent wires are not supported, we should check for that and
// warn the user
// FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results
// Check supportface for limits, otherwise Perform() throws an exception
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
PrismMode mode = PrismMode::None;
if (method == "UpToShape")
generatePrism(prism, "UpToFace", base, sketchshape, supportface, base, dir, mode, Standard_True);
else
generatePrism(prism, method, base, sketchshape, supportface, upToFace, dir, mode, Standard_True);
}
}
else {
if (hasTaperedAngle()) {
if (hasReversed)
dir.Reverse();
generateTaperedPrism(prism, sketchshape, method, dir, L, L2, TaperAngle.getValue(), TaperAngle2.getValue(), hasMidplane);
}
else {
generatePrism(prism, sketchshape, method, dir, L, L2, hasMidplane, hasReversed);
}
}
if (prism.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Resulting shape is empty"));
// set the additive shape property for later usage in e.g. pattern
prism = refineShapeIfActive(prism);
this->AddSubShape.setValue(prism);
if (!base.IsNull()) {
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Fuse mkFuse(base, prism);
// Let's check if the fusion has been successful
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pad: Fusion with base feature failed"));
TopoDS_Shape result = mkFuse.Shape();
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(result);
// lets check if the result is a solid
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
solRes = refineShapeIfActive(solRes);
this->Shape.setValue(getSolid(solRes));
}
else {
if (!isSingleSolidRuleSatisfied(prism)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
this->Shape.setValue(getSolid(prism));
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face")
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities or multiple faces in a sketch are not allowed."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
}
#endif

View File

@@ -102,341 +102,6 @@ short Pipe::mustExecute() const
return ProfileBased::mustExecute();
}
#ifndef FC_USE_TNP_FIX
App::DocumentObjectExecReturn *Pipe::execute()
{
auto getSectionShape = [](App::DocumentObject* feature,
const std::vector<std::string>& subs) -> TopoDS_Shape {
if (!feature || !feature->isDerivedFrom(Part::Feature::getClassTypeId()))
throw Base::TypeError("Pipe: Invalid profile/section");
auto subName = subs.empty() ? "" : subs.front();
// only take the entire shape when we have a sketch selected, but
// not a point of the sketch
if (feature->isDerivedFrom(Part::Part2DObject::getClassTypeId())
&& subName.compare(0, 6, "Vertex") != 0)
return static_cast<Part::Part2DObject*>(feature)->Shape.getValue();
else {
if (subName.empty())
throw Base::ValueError("Pipe: No valid subelement linked in Part::Feature");
return static_cast<Part::Feature*>(feature)->Shape.getShape().getSubShape(
subName.c_str());
}
};
auto addWiresToWireSections =
[](TopoDS_Shape& section, std::vector<std::vector<TopoDS_Shape>>& wiresections) -> size_t {
TopExp_Explorer ex;
size_t i = 0;
bool initialWireSectionsEmpty = wiresections.empty();
for (ex.Init(section, TopAbs_WIRE); ex.More(); ex.Next(), ++i) {
// if profile was just a point then this is where we can first set our list
if (i >= wiresections.size()) {
if (initialWireSectionsEmpty)
wiresections.emplace_back(1, ex.Current());
else
throw Base::ValueError(
"Pipe: Sections need to have the same amount of inner wires (except "
"profile and last section, which can be points)");
}
else
wiresections[i].push_back(TopoDS::Wire(ex.Current()));
}
return i;
};
// TODO: currently we can only allow planar faces, so add that check.
// The reason for this is that with other faces in front, we could not use the
// current simulate approach and build the start and end face from the wires.
// As the shell begins always at the spine and not the profile, the sketchshape
// cannot be used directly as front face. We would need a method to translate
// the front shape to match the shell starting position somehow...
std::vector<TopoDS_Wire> wires;
TopoDS_Shape profilePoint;
// if the Base property has a valid shape, fuse the pipe into it
TopoDS_Shape base;
try {
base = getBaseShape();
} catch (const Base::Exception&) {
base = TopoDS_Shape();
}
try {
// setup the location
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
if (!base.IsNull())
base.Move(invObjLoc);
// setup the profile section
TopoDS_Shape profileShape = getSectionShape(Profile.getValue(),
Profile.getSubValues());
if (profileShape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pipe: Could not obtain profile shape"));
// build the paths
App::DocumentObject* spine = Spine.getValue();
if (!(spine && spine->isDerivedFrom<Part::Feature>()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No spine linked"));
std::vector<std::string> subedge = Spine.getSubValues();
TopoDS_Shape path;
const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue();
buildPipePath(shape, subedge, path);
path.Move(invObjLoc);
// auxiliary
TopoDS_Shape auxpath;
if (Mode.getValue() == 3) {
App::DocumentObject* auxspine = AuxillerySpine.getValue();
if (!(auxspine && auxspine->isDerivedFrom<Part::Feature>()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "No auxiliary spine linked."));
std::vector<std::string> auxsubedge = AuxillerySpine.getSubValues();
const Part::TopoShape& auxshape =
static_cast<Part::Feature*>(auxspine)->Shape.getValue();
buildPipePath(auxshape, auxsubedge, auxpath);
auxpath.Move(invObjLoc);
}
// build up multisections
auto multisections = Sections.getSubListValues();
std::vector<std::vector<TopoDS_Shape>> wiresections;
size_t numWires = addWiresToWireSections(profileShape, wiresections);
if (numWires == 0) {
// profileShape had no wires so only other valid option is single point section
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(profileShape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i)
profilePoint = ex.Current();
if (i > 1)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Only one isolated point is needed if using a sketch with isolated "
"points for section"));
}
if (!profilePoint.IsNull() && (Transformation.getValue() != 1 || multisections.empty()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: At least one section is needed when using a single point for profile"));
// maybe we need a scaling law
Handle(Law_Function) scalinglaw;
bool isLastSectionVertex = false;
// see if we shall use multiple sections
if (Transformation.getValue() == 1) {
// TODO: we need to order the sections to prevent occ from crashing,
// as makepipeshell connects the sections in the order of adding
for (auto& subSet : multisections) {
if (!subSet.first->isDerivedFrom(Part::Feature::getClassTypeId()))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: All sections need to be part features"));
// if the section is an object's face then take just the face
TopoDS_Shape shape = getSectionShape(subSet.first, subSet.second);
if (shape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Could not obtain section shape"));
size_t nWiresAdded = addWiresToWireSections(shape, wiresections);
if (nWiresAdded == 0) {
TopExp_Explorer ex;
size_t i = 0;
for (ex.Init(shape, TopAbs_VERTEX); ex.More(); ex.Next(), ++i) {
if (isLastSectionVertex)
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Pipe: Only the profile and last section can be vertices"));
isLastSectionVertex = true;
for (auto& wires : wiresections)
wires.push_back(ex.Current());
}
}
if (!isLastSectionVertex && nWiresAdded < wiresections.size())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Multisections need to have the same amount of inner wires as the base "
"section"));
}
}
/*//build the law functions instead
else if (Transformation.getValue() == 2) {
if (ScalingData.getValues().size()<1)
return new App::DocumentObjectExecReturn("No valid data given for linear scaling mode");
Handle(Law_Linear) lin = new Law_Linear();
lin->Set(0, 1, 1, ScalingData[0].x);
scalinglaw = lin;
}
else if (Transformation.getValue() == 3) {
if (ScalingData.getValues().size()<1)
return new App::DocumentObjectExecReturn("No valid data given for S-shape scaling mode");
Handle(Law_S) s = new Law_S();
s->Set(0, 1, ScalingData[0].y, 1, ScalingData[0].x, ScalingData[0].z);
scalinglaw = s;
}*/
// Verify that path is not a null shape
if (path.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP(
"Exception", "Path must not be a null shape"));
// build all shells
std::vector<TopoDS_Shape> shells;
TopoDS_Shape copyProfilePoint(profilePoint);
if (!profilePoint.IsNull())
copyProfilePoint.Move(invObjLoc);
std::vector<TopoDS_Wire> frontwires, backwires;
for (auto& wires : wiresections) {
BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));
setupAlgorithm(mkPS, auxpath);
if (!scalinglaw) {
if (!profilePoint.IsNull())
mkPS.Add(copyProfilePoint);
for (auto& wire : wires) {
wire.Move(invObjLoc);
mkPS.Add(wire);
}
}
else {
if (!profilePoint.IsNull())
mkPS.SetLaw(copyProfilePoint, scalinglaw);
for (auto& wire : wires) {
wire.Move(invObjLoc);
mkPS.SetLaw(wire, scalinglaw);
}
}
if (!mkPS.IsReady())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pipe could not be built"));
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);
// Note that while we call them front and back, these sections
// appear to correspond to the front or back of the path. When one
// or both ends of the pipe are points, one or both of these wires
// (and eventually faces) will be null.
frontwires.push_back(TopoDS::Wire(sim.First()));
backwires.push_back(TopoDS::Wire(sim.Last()));
}
}
BRepBuilderAPI_MakeSolid mkSolid;
if (!frontwires.empty() || !backwires.empty()) {
BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
// build the end faces, sew the shell and build the final solid
if (!frontwires.empty()) {
TopoDS_Shape front = Part::FaceMakerCheese::makeFace(frontwires);
sewer.Add(front);
}
if (!backwires.empty()) {
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
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", "Result is not a solid"));
TopoDS_Shape result = mkSolid.Shape();
BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
if (SC.State() == TopAbs_IN) {
result.Reverse();
}
//result.Move(invObjLoc);
AddSubShape.setValue(result);
if (base.IsNull()) {
if (getAddSubType() == FeatureAddSub::Subtractive)
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Pipe: There is nothing to subtract from"));
result = refineShapeIfActive(result);
Shape.setValue(getSolid(result));
return App::DocumentObject::StdReturn;
}
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, result);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Adding the pipe failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, result);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Subtracting the pipe failed"));
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception",
"Result has multiple solids: that is not currently supported."));
}
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
}
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (...) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "A fatal error occurred when making the pipe"));
}
}
#else
App::DocumentObjectExecReturn *Pipe::execute()
{
auto getSectionShape = [](App::DocumentObject* feature,
@@ -772,7 +437,6 @@ App::DocumentObjectExecReturn *Pipe::execute()
}
}
#endif
void Pipe::setupAlgorithm(BRepOffsetAPI_MakePipeShell& mkPipeShell, const TopoDS_Shape& auxshape) {
mkPipeShell.SetTolerance(Precision::Confusion());

View File

@@ -71,200 +71,17 @@ Pocket::Pocket()
App::DocumentObjectExecReturn *Pocket::execute()
{
#ifdef FC_USE_TNP_FIX
// MakeFace|MakeFuse: because we want a solid.
// InverseDirection: to inverse the auto detected extrusion direction for
// backward compatibility to upstream
ExtrudeOptions options(ExtrudeOption::MakeFace | ExtrudeOption::MakeFuse
| ExtrudeOption::InverseDirection);
return buildExtrusion(options);
#else
// Handle legacy features, these typically have Type set to 3 (previously NULL, now UpToFace),
// empty FaceName (because it didn't exist) and a value for Length
if (std::string(Type.getValueAsString()) == "UpToFace" &&
(!UpToFace.getValue() && Length.getValue() > Precision::Confusion()))
Type.setValue("Length");
double L = Length.getValue();
double L2 = Length2.getValue();
TopoDS_Shape profileshape;
try {
profileshape = getVerifiedFace();
} catch (const Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
// if the Base property has a valid shape, fuse the prism into it
TopoShape base;
try {
base = getBaseTopoShape();
}
catch (const Base::Exception&) {
std::string text(QT_TRANSLATE_NOOP("Exception", ("The requested feature cannot be created. The reason may be that:\n"
" - the active Body does not contain a base shape, so there is no\n"
" material to be removed;\n"
" - the selected sketch does not belong to the active Body.")));
return new App::DocumentObjectExecReturn(text);
}
// get the normal vector of the sketch
Base::Vector3d SketchVector = getProfileNormal();
// turn around for pockets
SketchVector *= -1;
try {
this->positionByPrevious();
TopLoc_Location invObjLoc = this->getLocation().Inverted();
base.move(invObjLoc);
Base::Vector3d pocketDirection = computeDirection(SketchVector, false);
// create vector in pocketing direction with length 1
gp_Dir dir(pocketDirection.x, pocketDirection.y, pocketDirection.z);
// The length of a gp_Dir is 1 so the resulting pocket would have
// the length L in the direction of dir. But we want to have its height in the
// direction of the normal vector.
// Therefore we must multiply L by the factor that is necessary
// to make dir as long that its projection to the SketchVector
// equals the SketchVector.
// This is the scalar product of both vectors.
// Since the pocket length cannot be negative, the factor must not be negative.
double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z));
// factor would be zero if vectors are orthogonal
if (factor < Precision::Confusion())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Creation failed because direction is orthogonal to sketch's normal vector"));
// perform the length correction if not along custom vector
if (AlongSketchNormal.getValue()) {
L = L / factor;
L2 = L2 / factor;
}
dir.Transform(invObjLoc.Transformation());
if (profileshape.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Creating a face from sketch failed"));
profileshape.Move(invObjLoc);
std::string method(Type.getValueAsString());
if (method == "UpToFirst" || method == "UpToFace") {
if (base.isNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Extruding up to a face is only possible if the sketch is located on a face"));
// Note: This will return an unlimited planar face if support is a datum plane
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
if (Reversed.getValue())
dir.Reverse();
// Find a valid face or datum plane to extrude up to
TopoDS_Face upToFace;
if (method == "UpToFace") {
getFaceFromLinkSub(upToFace, UpToFace);
upToFace.Move(invObjLoc);
}
getUpToFace(upToFace, base.getShape(), profileshape, method, dir);
addOffsetToFace(upToFace, dir, Offset.getValue());
// BRepFeat_MakePrism(..., 2, 1) in combination with PerForm(upToFace) is buggy when the
// prism that is being created is contained completely inside the base solid
// In this case the resulting shape is empty. This is not a problem for the Pad or Pocket itself
// but it leads to an invalid SubShape
// The bug only occurs when the upToFace is limited (by a wire), not for unlimited upToFace. But
// other problems occur with unlimited concave upToFace so it is not an option to always unlimit upToFace
// Check supportface for limits, otherwise Perform() throws an exception
TopExp_Explorer Ex(supportface,TopAbs_WIRE);
if (!Ex.More())
supportface = TopoDS_Face();
TopoDS_Shape prism;
PrismMode mode = PrismMode::CutFromBase;
generatePrism(prism, method, base.getShape(), profileshape, supportface, upToFace, dir, mode, Standard_True);
// And the really expensive way to get the SubShape...
BRepAlgoAPI_Cut mkCut(base.getShape(), prism);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Up to face: Could not get SubShape!"));
// FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!!
TopoDS_Shape result = refineShapeIfActive(mkCut.Shape());
this->AddSubShape.setValue(result);
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
this->Shape.setValue(getSolid(prism));
}
else {
TopoDS_Shape prism;
if (hasTaperedAngle()) {
if (Reversed.getValue())
dir.Reverse();
generateTaperedPrism(prism, profileshape, method, dir, L, L2, TaperAngle.getValue(), TaperAngle2.getValue(), Midplane.getValue());
}
else {
generatePrism(prism, profileshape, method, dir, L, L2, Midplane.getValue(), Reversed.getValue());
}
if (prism.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Resulting shape is empty"));
// set the subtractive shape property for later usage in e.g. pattern
prism = refineShapeIfActive(prism);
this->AddSubShape.setValue(prism);
// Cut the SubShape out of the base feature
BRepAlgoAPI_Cut mkCut(base.getShape(), prism);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Pocket: Cut out of base feature failed"));
TopoDS_Shape result = mkCut.Shape();
// we have to get the solids (fuse sometimes creates compounds)
TopoDS_Shape solRes = this->getSolid(result);
if (solRes.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(result)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
solRes = refineShapeIfActive(solRes);
remapSupportShape(solRes);
this->Shape.setValue(getSolid(solRes));
}
// eventually disable some settings that are not valid for the current method
updateProperties(method);
return App::DocumentObject::StdReturn;
}
catch (Standard_Failure& e) {
if (std::string(e.GetMessageString()) == "TopoDS::Face" &&
(std::string(Type.getValueAsString()) == "UpToFirst" || std::string(Type.getValueAsString()) == "UpToFace"))
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Could not create face from sketch.\n"
"Intersecting sketch entities or multiple faces in a sketch are not allowed "
"for making a pocket up to a face."));
else
return new App::DocumentObjectExecReturn(e.GetMessageString());
}
catch (Base::Exception& e) {
return new App::DocumentObjectExecReturn(e.what());
}
#endif
}
Base::Vector3d Pocket::getProfileNormal() const
{
auto res = FeatureExtrude::getProfileNormal();
// turn around for pockets
#ifdef FC_USE_TNP_FIX
return res * -1;
#else
return res;
#endif
}

View File

@@ -73,7 +73,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
FeatureAddSub::execute();
//if we have no base we just add the standard primitive shape
#ifdef FC_USE_TNP_FIX
TopoShape primitiveShape;
primitiveShape.setShape(primitive);
@@ -85,15 +84,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
primitiveShape.Tag = -this->getID();
}
#else
auto primitiveShape = primitive;
TopoDS_Shape base;
try {
//if we have a base shape we need to make sure that it does not get our transformation to
BRepBuilderAPI_Transform trsf(getBaseShape(), getLocation().Transformation().Inverted(), true);
base = trsf.Shape();
}
#endif
catch (const Base::Exception&) {
//as we use this for preview we can add it even if useless for subtractive
@@ -106,7 +96,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
return App::DocumentObject::StdReturn;
}
#ifdef FC_USE_TNP_FIX
AddSubShape.setValue(primitiveShape);
TopoShape boolOp(0);
@@ -136,40 +125,6 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri
return new App::DocumentObjectExecReturn(
QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
}
#else
TopoDS_Shape boolOp;
if (getAddSubType() == FeatureAddSub::Additive) {
BRepAlgoAPI_Fuse mkFuse(base, primitiveShape);
if (!mkFuse.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Adding the primitive failed"));
// we have to get the solids (fuse sometimes creates compounds)
boolOp = this->getSolid(mkFuse.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
else if (getAddSubType() == FeatureAddSub::Subtractive) {
BRepAlgoAPI_Cut mkCut(base, primitiveShape);
if (!mkCut.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Subtracting the primitive failed"));
// we have to get the solids (fuse sometimes creates compounds)
boolOp = this->getSolid(mkCut.Shape());
// lets check if the result is a solid
if (boolOp.IsNull())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Resulting shape is not a solid"));
if (!isSingleSolidRuleSatisfied(boolOp)) {
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Result has multiple solids: that is not currently supported."));
}
}
#endif
boolOp = refineShapeIfActive(boolOp);
Shape.setValue(getSolid(boolOp));
AddSubShape.setValue(primitiveShape);

View File

@@ -160,11 +160,7 @@ App::DocumentObjectExecReturn* Revolution::execute()
}
// Create a fresh support even when base exists so that it can be used for patterns
#ifdef FC_USE_TNP_FIX
TopoShape result(0);
#else
TopoDS_Shape result;
#endif
TopoDS_Face supportface = getSupportFace();
supportface.Move(invObjLoc);
@@ -194,27 +190,15 @@ App::DocumentObjectExecReturn* Revolution::execute()
if (!Ex.More()) {
supportface = TopoDS_Face();
}
#ifdef FC_USE_TNP_FIX
RevolMode mode = RevolMode::None;
// revolve the face to a solid
// TopoShape result(0);
try {
result = base.makeElementRevolution(gp_Ax1(pnt, dir), supportface, upToFace);
result = base.makeElementRevolution(gp_Ax1(pnt, dir), supportface, upToFace);
}
catch (Standard_Failure&) {
return new App::DocumentObjectExecReturn("Could not revolve the sketch!");
}
#else
RevolMode mode = RevolMode::None;
generateRevolution(result,
base.getShape(),
sketchshape.getShape(),
supportface,
upToFace,
gp_Ax1(pnt, dir),
method,
mode,
Standard_True);
#endif
}
else {
bool midplane = Midplane.getValue();
@@ -229,7 +213,6 @@ App::DocumentObjectExecReturn* Revolution::execute()
method);
}
#ifdef FC_USE_TNP_FIX
if (!result.isNull()) {
result = refineShapeIfActive(result);
// set the additive shape property for later usage in e.g. pattern
@@ -239,25 +222,6 @@ App::DocumentObjectExecReturn* Revolution::execute()
result = result.makeElementFuse(base);
result = refineShapeIfActive(result);
}
#else
if (!result.IsNull()) {
result = refineShapeIfActive(result);
// set the additive shape property for later usage in e.g. pattern
this->AddSubShape.setValue(result);
if (!base.isNull()) {
// Let's call algorithm computing a fuse operation:
BRepAlgoAPI_Fuse mkFuse(base.getShape(), result);
// Let's check if the fusion has been successful
if (!mkFuse.IsDone()) {
throw Part::BooleanException(
QT_TRANSLATE_NOOP("Exception", "Fusion with base feature failed"));
}
result = mkFuse.Shape();
result = refineShapeIfActive(result);
}
#endif
this->Shape.setValue(getSolid(result));
}
else {
@@ -329,12 +293,7 @@ Revolution::RevolMethod Revolution::methodFromString(const std::string& methodSt
return RevolMethod::Dimension;
}
#ifdef FC_USE_TNP_FIX
void Revolution::generateRevolution(TopoShape& revol,
#else
void Revolution::generateRevolution(TopoDS_Shape& revol,
#endif
const TopoDS_Shape& sketchshape,
const gp_Ax1& axis,
const double angle,
@@ -373,22 +332,8 @@ void Revolution::generateRevolution(TopoDS_Shape& revol,
from.Move(loc);
}
#ifdef FC_USE_TNP_FIX
revol = TopoShape(from);
// revol.Tag = getID();
revol = revol.makeElementRevolve(revolAx,angleTotal);
revol = TopoShape(from).makeElementRevolve(revolAx,angleTotal);
revol.Tag = -getID();
#else
// revolve the face to a solid
// BRepPrimAPI is the only option that allows use of this shape for patterns.
// See https://forum.freecadweb.org/viewtopic.php?f=8&t=70185&p=611673#p611673.
BRepPrimAPI_MakeRevol RevolMaker(from, revolAx, angleTotal);
if (!RevolMaker.IsDone())
throw Base::RuntimeError("ProfileBased: RevolMaker failed! Could not revolve the sketch!");
else
revol = RevolMaker.Shape();
#endif
} else {
std::stringstream str;
str << "ProfileBased: Internal error: Unknown method for generateRevolution()";

View File

@@ -95,11 +95,7 @@ protected:
/**
* Generates a revolution of the input sketchshape and stores it in the given \a revol.
*/
#ifdef FC_USE_TNP_FIX
void generateRevolution(TopoShape& revol,
#else
void generateRevolution(TopoDS_Shape& revol,
#endif
const TopoDS_Shape& sketchshape,
const gp_Ax1& ax1,
const double angle,

View File

@@ -1134,105 +1134,11 @@ bool ProfileBased::checkLineCrossesFace(const gp_Lin& line, const TopoDS_Face& f
void ProfileBased::remapSupportShape(const TopoDS_Shape & newShape)
{
#if FC_USE_TNP_FIX
(void)newShape;
// Realthunder: with the new topological naming, I don't think this function
// is necessary. A missing element will cause an explicitly error, and the
// user will be force to manually select the element. Various editors, such
// as dress up editors, can perform element guessing when activated.
#else
TopTools_IndexedMapOfShape faceMap;
TopExp::MapShapes(newShape, TopAbs_FACE, faceMap);
// here we must reset the placement otherwise the geometric matching doesn't work
Part::TopoShape shape = this->Shape.getValue();
TopoDS_Shape sh = shape.getShape();
sh.Location(TopLoc_Location());
shape.setShape(sh);
std::vector<App::DocumentObject*> refs = this->getInList();
for (auto ref : refs) {
std::vector<App::Property*> props;
ref->getPropertyList(props);
for (auto prop : props) {
if (!prop->isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
continue;
App::PropertyLinkSub* link = static_cast<App::PropertyLinkSub*>(prop);
if (link->getValue() != this)
continue;
std::vector<std::string> subValues = link->getSubValues();
std::vector<std::string> newSubValues;
for (auto & subValue : subValues) {
std::string shapetype;
if (subValue.compare(0, 4, "Face") == 0) {
shapetype = "Face";
}
else if (subValue.compare(0, 4, "Edge") == 0) {
shapetype = "Edge";
}
else if (subValue.compare(0, 6, "Vertex") == 0) {
shapetype = "Vertex";
}
else {
newSubValues.push_back(subValue);
continue;
}
bool success = false;
TopoDS_Shape element;
try {
element = shape.getSubShape(subValue.c_str());
}
catch (Standard_Failure&) {
// This shape doesn't even exist, so no chance to do some tests
newSubValues.push_back(subValue);
continue;
}
try {
// as very first test check if old face and new face are parallel planes
TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(subValue.c_str());
if (isParallelPlane(element, newElement)) {
newSubValues.push_back(subValue);
success = true;
}
}
catch (Standard_Failure&) {
}
// try an exact matching
if (!success) {
for (int i = 1; i < faceMap.Extent(); i++) {
if (isQuasiEqual(element, faceMap.FindKey(i))) {
std::stringstream str;
str << shapetype << i;
newSubValues.push_back(str.str());
success = true;
break;
}
}
}
// if an exact matching fails then try to compare only the geometries
if (!success) {
for (int i = 1; i < faceMap.Extent(); i++) {
if (isEqualGeometry(element, faceMap.FindKey(i))) {
std::stringstream str;
str << shapetype << i;
newSubValues.push_back(str.str());
success = true;
break;
}
}
}
// the new shape couldn't be found so keep the old sub-name
if (!success)
newSubValues.push_back(subValue);
}
link->setValue(this, newSubValues);
}
}
#endif
}
namespace PartDesign {
@@ -1514,7 +1420,6 @@ Base::Vector3d ProfileBased::getProfileNormal() const {
Base::Placement SketchPos = obj->Placement.getValue();
Base::Rotation SketchOrientation = SketchPos.getRotation();
SketchOrientation.multVec(SketchVector, SketchVector);
#ifdef FC_USE_TNP_FIX
return SketchVector;
}
@@ -1592,31 +1497,6 @@ Base::Vector3d ProfileBased::getProfileNormal() const {
}
return dir.Normalize();
}
#else
}
else {
TopoDS_Shape shape = getVerifiedFace(true);
if (shape.IsNull())
return SketchVector;
// the shape can be a single face or a compound of faces, only consider the first face
TopExp_Explorer ex(shape, TopAbs_FACE);
if (ex.More()) {
TopoDS_Face face = TopoDS::Face(ex.Current());
BRepAdaptor_Surface adapt(face);
double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter()) / 2.;
double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter()) / 2.;
BRepLProp_SLProps prop(adapt, u, v, 2, Precision::Confusion());
if (prop.IsNormalDefined()) {
gp_Pnt pnt; gp_Vec vec;
// handles the orientation state of the shape
BRepGProp_Face(face).Normal(u, v, pnt, vec);
SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z());
}
}
}
#endif
return SketchVector;
}

View File

@@ -324,22 +324,12 @@ App::DocumentObjectExecReturn* Transformed::execute()
"Shape of additive/subtractive feature is empty"));
}
gp_Trsf trsf = feature->getLocation().Transformation().Multiplied(trsfInv);
#ifdef FC_USE_TNP_FIX
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeElementTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeElementTransform(trsf);
}
#else
if (!fuseShape.isNull()) {
fuseShape = fuseShape.makeTransform(trsf);
}
if (!cutShape.isNull()) {
cutShape = cutShape.makeTransform(trsf);
}
#endif
if (!fuseShape.isNull()) {
supportShape.makeElementFuse(getTransformedCompShape(supportShape, fuseShape));
}

View File

@@ -731,11 +731,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
else {
for (size_t i = 0; i < shapes.size(); ++i) {
auto& shape = shapes[i];
#ifdef FC_USE_TNP_FIX
shape = shape.makeElementTransform(*shapeMats[i]);
#else
shape = shape.makeTransform(*shapeMats[i]);
#endif
// if(shape.Hasher
// && shape.getElementMapSize()
// && shape.Hasher != getDocument()->getStringHasher())
@@ -750,11 +746,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
// Shape.resetElementMapVersion();
return;
}
#ifdef FC_USE_TNP_FIX
result.makeElementCompound(shapes);
#else
result.makeCompound(shapes);
#endif
bool fused = false;
if (Fuse.getValue()) {
// If the compound has solid, fuse them together, and ignore other type of
@@ -773,11 +765,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
else if (!solid.isNull()) {
// wrap the single solid in compound to keep its placement
#ifdef FC_USE_TNP_FIX
result.makeElementCompound({ solid });
#else
result.makeCompound({ solid });
#endif
fused = true;
}
}
@@ -786,7 +774,6 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
&& !result.hasSubShape(TopAbs_FACE)
&& result.hasSubShape(TopAbs_EDGE))
{
#ifdef FC_USE_TNP_FIX
result = result.makeElementWires();
if (MakeFace.getValue()) {
try {
@@ -794,33 +781,16 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
catch (...) {}
}
#else
result = result.makeWires();
if (MakeFace.getValue()) {
try {
result = result.makeFace(nullptr);
}
catch (...) {}
}
#endif
}
if (!fused && result.hasSubShape(TopAbs_WIRE)
&& Offset.getValue() != 0.0) {
try {
#ifdef FC_USE_TNP_FIX
result = result.makeElementOffset2D(Offset.getValue(),
(Part::JoinType) OffsetJoinType.getValue() ,
OffsetFill.getValue() ? Part::FillType::fill : Part::FillType::noFill,
OffsetOpenResult.getValue() ? Part::OpenResult::allowOpenResult : Part::OpenResult::noOpenResult,
OffsetIntersection.getValue());
#else
result = result.makeOffset2D(Offset.getValue(),
OffsetJoinType.getValue(),
OffsetFill.getValue(),
OffsetOpenResult.getValue(),
OffsetIntersection.getValue());
#endif
}
catch (...) {
std::ostringstream msg;
@@ -830,11 +800,7 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
}
if (Refine.getValue())
#ifdef FC_USE_TNP_FIX
result = result.makeElementRefine();
#else
result = result.makeRefine();
#endif
result.setPlacement(Placement.getValue());
Shape.setValue(result);
}