diff --git a/src/Mod/PartDesign/App/FeatureMirrored.cpp b/src/Mod/PartDesign/App/FeatureMirrored.cpp index 90ace67654..d582677fb0 100644 --- a/src/Mod/PartDesign/App/FeatureMirrored.cpp +++ b/src/Mod/PartDesign/App/FeatureMirrored.cpp @@ -52,75 +52,140 @@ Mirrored::Mirrored() short Mirrored::mustExecute() const { - if (MirrorPlane.isTouched()) + if (MirrorPlane.isTouched()) { return 1; + } return Transformed::mustExecute(); } const std::list Mirrored::getTransformations(const std::vector) { + using getMirrorAxis = std::function; + + // 2D part object + getMirrorAxis axisOfSketch = [this](gp_Pnt& axbase, gp_Dir& axdir) { + App::DocumentObject* refObject = MirrorPlane.getValue(); + std::vector subStrings = MirrorPlane.getSubValues(); + + if (auto refSketch = dynamic_cast(refObject)) { + Base::Axis axis; + if (subStrings[0] == "H_Axis") { + axis = refSketch->getAxis(Part::Part2DObject::V_Axis); + } + else if (subStrings[0] == "V_Axis") { + axis = refSketch->getAxis(Part::Part2DObject::H_Axis); + } + else if (subStrings[0].empty()) { + axis = refSketch->getAxis(Part::Part2DObject::N_Axis); + } + else if (subStrings[0].compare(0, 4, "Axis") == 0) { + int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); + if (AxId >= 0 && AxId < refSketch->getAxisCount()) { + axis = refSketch->getAxis(AxId); + axis.setBase(axis.getBase() + 0.5 * axis.getDirection()); + axis.setDirection(Base::Vector3d(-axis.getDirection().y, axis.getDirection().x, axis.getDirection().z)); + } + } + axis *= refSketch->Placement.getValue(); + axbase = gp_Pnt(axis.getBase().x, axis.getBase().y, axis.getBase().z); + axdir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); + return true; + } + + return false; + }; + + // Datum plane + getMirrorAxis axisOfDatumPlane = [this](gp_Pnt& axbase, gp_Dir& axdir) { + App::DocumentObject* refObject = MirrorPlane.getValue(); + if (auto plane = dynamic_cast(refObject)) { + Base::Vector3d base = plane->getBasePoint(); + axbase = gp_Pnt(base.x, base.y, base.z); + Base::Vector3d dir = plane->getNormal(); + axdir = gp_Dir(dir.x, dir.y, dir.z); + return true; + } + + return false; + }; + + // Normal plane + getMirrorAxis axisOfPlane = [this](gp_Pnt& axbase, gp_Dir& axdir) { + App::DocumentObject* refObject = MirrorPlane.getValue(); + if (auto plane = dynamic_cast(refObject)) { + Base::Vector3d base = plane->Placement.getValue().getPosition(); + axbase = gp_Pnt(base.x, base.y, base.z); + Base::Rotation rot = plane->Placement.getValue().getRotation(); + Base::Vector3d dir(0,0,1); + rot.multVec(dir, dir); + axdir = gp_Dir(dir.x, dir.y, dir.z); + return true; + } + + return false; + }; + + // Planar shape + getMirrorAxis axisOfPlanarShape = [this](gp_Pnt& axbase, gp_Dir& axdir) { + App::DocumentObject* refObject = MirrorPlane.getValue(); + std::vector subStrings = MirrorPlane.getSubValues(); + + if (auto feature = dynamic_cast(refObject)) { + if (subStrings[0].empty()) { + throw Base::ValueError("No direction reference specified"); + } + + Part::TopoShape baseShape = feature->Shape.getShape(); + // TODO: Check for multiple mirror planes? + TopoDS_Shape shape = baseShape.getSubShape(subStrings[0].c_str()); + TopoDS_Face face = TopoDS::Face(shape); + if (face.IsNull()) { + throw Base::ValueError("Failed to extract mirror plane"); + } + + BRepAdaptor_Surface adapt(face); + if (adapt.GetType() != GeomAbs_Plane) { + throw Base::TypeError("Mirror face must be planar"); + } + + axbase = getPointFromFace(face); + axdir = adapt.Plane().Axis().Direction(); + return true; + } + + return false; + }; + + // ------------------------------------------------------------------------ + App::DocumentObject* refObject = MirrorPlane.getValue(); - if (!refObject) + if (!refObject) { throw Base::ValueError("No mirror plane reference specified"); + } std::vector subStrings = MirrorPlane.getSubValues(); - if (subStrings.empty()) + if (subStrings.empty()) { throw Base::ValueError("No mirror plane reference specified"); + } gp_Pnt axbase; gp_Dir axdir; - if (refObject->isDerivedFrom()) { - Part::Part2DObject* refSketch = static_cast(refObject); - Base::Axis axis; - if (subStrings[0] == "H_Axis") - axis = refSketch->getAxis(Part::Part2DObject::V_Axis); - else if (subStrings[0] == "V_Axis") - axis = refSketch->getAxis(Part::Part2DObject::H_Axis); - else if (subStrings[0].empty()) - axis = refSketch->getAxis(Part::Part2DObject::N_Axis); - else if (subStrings[0].compare(0, 4, "Axis") == 0) { - int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); - if (AxId >= 0 && AxId < refSketch->getAxisCount()) { - axis = refSketch->getAxis(AxId); - axis.setBase(axis.getBase() + 0.5 * axis.getDirection()); - axis.setDirection(Base::Vector3d(-axis.getDirection().y, axis.getDirection().x, axis.getDirection().z)); - } - } - axis *= refSketch->Placement.getValue(); - axbase = gp_Pnt(axis.getBase().x, axis.getBase().y, axis.getBase().z); - axdir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); - } else if (refObject->isDerivedFrom()) { - PartDesign::Plane* plane = static_cast(refObject); - Base::Vector3d base = plane->getBasePoint(); - axbase = gp_Pnt(base.x, base.y, base.z); - Base::Vector3d dir = plane->getNormal(); - axdir = gp_Dir(dir.x, dir.y, dir.z); - } else if (refObject->isDerivedFrom()) { - App::Plane* plane = static_cast(refObject); - Base::Vector3d base = plane->Placement.getValue().getPosition(); - axbase = gp_Pnt(base.x, base.y, base.z); - Base::Rotation rot = plane->Placement.getValue().getRotation(); - Base::Vector3d dir(0,0,1); - rot.multVec(dir, dir); - axdir = gp_Dir(dir.x, dir.y, dir.z); - } else if (refObject->isDerivedFrom()) { - if (subStrings[0].empty()) - throw Base::ValueError("No direction reference specified"); - Part::TopoShape baseShape = static_cast(refObject)->Shape.getShape(); - // TODO: Check for multiple mirror planes? - TopoDS_Shape shape = baseShape.getSubShape(subStrings[0].c_str()); - TopoDS_Face face = TopoDS::Face(shape); - if (face.IsNull()) - throw Base::ValueError("Failed to extract mirror plane"); - BRepAdaptor_Surface adapt(face); - if (adapt.GetType() != GeomAbs_Plane) - throw Base::TypeError("Mirror face must be planar"); + std::vector axisCheckers; + axisCheckers.push_back(axisOfSketch); + axisCheckers.push_back(axisOfDatumPlane); + axisCheckers.push_back(axisOfPlane); + axisCheckers.push_back(axisOfPlanarShape); - axbase = getPointFromFace(face); - axdir = adapt.Plane().Axis().Direction(); - } else { - throw Base::ValueError("Mirror plane reference must be a sketch axis, a face of a feature or a datum plane"); + for (const auto& getAxis : axisCheckers) { + if (getAxis(axbase, axdir)) { + return createTransformations(axbase, axdir); + } } + throw Base::ValueError("Mirror plane reference must be a sketch axis, a face of a feature or a datum plane"); +} + +std::list Mirrored::createTransformations(gp_Pnt& axbase, gp_Dir& axdir) const +{ TopLoc_Location invObjLoc = this->getLocation().Inverted(); axbase.Transform(invObjLoc.Transformation()); axdir.Transform(invObjLoc.Transformation()); diff --git a/src/Mod/PartDesign/App/FeatureMirrored.h b/src/Mod/PartDesign/App/FeatureMirrored.h index 597845a84c..fce4565085 100644 --- a/src/Mod/PartDesign/App/FeatureMirrored.h +++ b/src/Mod/PartDesign/App/FeatureMirrored.h @@ -56,6 +56,9 @@ public: * the given face, which must be planar */ const std::list getTransformations(const std::vector) override; + +private: + std::list createTransformations(gp_Pnt& axbase, gp_Dir& axdir) const; }; } //namespace PartDesign