--- /dev/null
-
- std::list<std::pair<GeomShapePtr, ListOfShape> > aSolidsAndSubs;
+ // Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+ //
+ // This library is free software; you can redistribute it and/or
+ // modify it under the terms of the GNU Lesser General Public
+ // License as published by the Free Software Foundation; either
+ // version 2.1 of the License, or (at your option) any later version.
+ //
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ // Lesser General Public License for more details.
+ //
+ // You should have received a copy of the GNU Lesser General Public
+ // License along with this library; if not, write to the Free Software
+ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ //
+ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+ //
+
+ #include "FeaturesPlugin_Chamfer.h"
+ #include "FeaturesPlugin_Tools.h"
+
+ #include <ModelAPI_Data.h>
+ #include <ModelAPI_AttributeDouble.h>
+ #include <ModelAPI_AttributeSelectionList.h>
+ #include <ModelAPI_AttributeString.h>
+ #include <ModelAPI_ResultBody.h>
+ #include <ModelAPI_Session.h>
+ #include <ModelAPI_Tools.h>
+ #include <ModelAPI_Validator.h>
+
+ #include <GeomAlgoAPI_CompoundBuilder.h>
+ #include <GeomAlgoAPI_Chamfer.h>
+ #include <GeomAlgoAPI_MakeShapeList.h>
+ #include <GeomAlgoAPI_Tools.h>
+
+ #include <GeomAPI_DataMapOfShapeMapOfShapes.h>
+ #include <GeomAPI_ShapeExplorer.h>
+ #include <GeomAPI_ShapeIterator.h>
+
+ // Obtain all sub-shapes from the shape and append them to the list
+ static void collectSubs(const GeomShapePtr& theShape,
+ ListOfShape& theSubs,
+ const GeomAPI_Shape::ShapeType theShapeType)
+ {
+ GeomAPI_ShapeExplorer anExp(theShape, theShapeType);
+ for (; anExp.more(); anExp.next()) {
+ GeomShapePtr aShape = anExp.current();
+ // Store all shapes with FORWARD orientation to avoid duplication of shared edges/vertices
+ aShape->setOrientation(GeomAPI_Shape::FORWARD);
+ theSubs.push_back(aShape);
+ }
+ }
+
+ // Extract edges from the list
+ static ListOfShape selectEdges(const ListOfShape& theShapes)
+ {
+ ListOfShape anEdges;
+ for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
+ if ((*anIt)->isEdge())
+ anEdges.push_back(*anIt);
+ return anEdges;
+ }
+
+ // If theShape is a compound of a single sub-shape, return this sub-shape
+ static GeomShapePtr unwrapCompound(const GeomShapePtr& theShape)
+ {
+ GeomShapePtr aShape = theShape;
+ if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+ int aSubResultsNb = 0;
+ GeomAPI_ShapeIterator anIt(aShape);
+ for(; anIt.more(); anIt.next())
+ ++aSubResultsNb;
+
+ if(aSubResultsNb == 1) {
+ anIt.init(aShape);
+ aShape = anIt.current();
+ }
+ }
+ return aShape;
+ }
+
+
+ FeaturesPlugin_Chamfer::FeaturesPlugin_Chamfer()
+ {
+ }
+
+ void FeaturesPlugin_Chamfer::initAttributes()
+ {
+ data()->addAttribute(FeaturesPlugin_Chamfer::CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(FeaturesPlugin_Chamfer::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+ data()->addAttribute(FeaturesPlugin_Chamfer::D1_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Chamfer::D2_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Chamfer::D_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(FeaturesPlugin_Chamfer::ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+ }
+
+
+ void FeaturesPlugin_Chamfer::execute()
+ {
+ AttributeStringPtr aCreationMethod = string(CREATION_METHOD());
+ if (!aCreationMethod)
+ return;
-
++
++ std::list<std::pair<GeomShapePtr, ListOfShape> > aSolidsAndSubs;
+ std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace;
-
++
+ // getting objects and sort them according to parent solids
+ AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
+ for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) {
+ AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+ GeomShapePtr anObject = anObjectAttr->value();
+ if (!anObject)
+ return;
-
++
+ ResultPtr aContext = anObjectAttr->context();
+ GeomShapePtr aParent;
+ if (aContext.get()) {
+ ResultBodyPtr aCtxOwner = ModelAPI_Tools::bodyOwner(aContext);
+ aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
+ } else { // get it from a feature
+ FeaturePtr aFeature = anObjectAttr->contextFeature();
+ if (aFeature.get()) {
+ aParent = aFeature->firstResult()->shape();
+ }
+ }
+ if (!aParent)
+ return;
-
++
+ // searching this parent is already in the list aSolidsAndSubs
+ std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator aSearch = aSolidsAndSubs.begin();
+ ListOfShape* aFound;
+ for(; aSearch != aSolidsAndSubs.end(); aSearch++) {
+ if (aSearch->first->isSame(aParent)) {
+ aFound = &(aSearch->second);
+ break;
+ }
+ }
+ if (aSearch == aSolidsAndSubs.end()) { // not found, so, add a new one
+ aSolidsAndSubs.push_back(std::pair<GeomShapePtr, ListOfShape>(aParent, ListOfShape()));
+ aFound = &(aSolidsAndSubs.back().second);
+ }
+
+ ListOfShape anEdgesAndVertices;
+ collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE);
+ collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX);
+ for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+ aEIt != anEdgesAndVertices.end(); ++aEIt)
+ aFound->push_back(*aEIt);
-
++
+ if (anObject->isFace()) {
+ for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+ aEIt != anEdgesAndVertices.end(); ++aEIt) {
+ if ((*aEIt)->isEdge()) {
+ aMapEdgeFace[(*aEIt)] = anObject;
+ }
+ }
+ }
+ }
-
++
+ //bool isOption1 = true;
+ double aD1 = 0.0, aD2 = 0.0, aD = 0.0, anAngle = 0.0;
+ if (aCreationMethod->value() == CREATION_METHOD_DISTANCE_DISTANCE()) {
+ aD1 = real(FeaturesPlugin_Chamfer::D1_ID())->value();
+ aD2 = real(FeaturesPlugin_Chamfer::D2_ID())->value();
+ } else {
+ aD = real(FeaturesPlugin_Chamfer::D_ID())->value();
+ anAngle = real(FeaturesPlugin_Chamfer::ANGLE_ID())->value();
+ }
-
-
++
+ // Perform chamfer operation
+ GeomAlgoAPI_MakeShapeList aMakeShapeList;
+ std::shared_ptr<GeomAlgoAPI_Chamfer> aChamferBuilder;
+ int aResultIndex = 0;
+ std::string anError;
-
++
++
+ std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+ ListOfShape anOriginalShapesList, aResultShapesList;
-
++
+ std::list<std::pair<GeomShapePtr, ListOfShape> >::iterator anIt = aSolidsAndSubs.begin();
+ for (; anIt != aSolidsAndSubs.end(); ++anIt) {
+ GeomShapePtr aSolid = anIt->first;
+ ListOfShape aFilletEdgesAndVertices = anIt->second;
-
++
+ ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices);
+ if (aCreationMethod->value() == CREATION_METHOD_DISTANCE_DISTANCE()) {
+ aChamferBuilder.reset(new GeomAlgoAPI_Chamfer(aSolid, aFilletEdges, aMapEdgeFace, true, aD1, aD2));
+ } else {
+ aChamferBuilder.reset(new GeomAlgoAPI_Chamfer(aSolid, aFilletEdges, aMapEdgeFace, false, aD, anAngle));
+ }
-
++
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aChamferBuilder, getKind(), anError)) {
+ setError(anError);
+ return;
+ }
++
+ GeomShapePtr aResult = unwrapCompound(aChamferBuilder->shape());
+ std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+ document()->createBody(data(), aResultIndex);
+
+ ListOfShape aBaseShapes;
+ aBaseShapes.push_back(aSolid);
+ FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+ aChamferBuilder, aResult, "Chamfer");
+
+ setResult(aResultBody, aResultIndex);
+ aResultIndex++;
+
+ FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+ aRBA.resultBody = aResultBody;
+ aRBA.baseShape = aSolid;
+ aRBA.makeShape = aChamferBuilder;
+ aResultBaseAlgoList.push_back(aRBA);
+ aResultShapesList.push_back(aResult);
+ anOriginalShapesList.push_back(aSolid);
+
+ const std::string aFilletFaceName = "Chamfer";
+ ListOfShape::iterator aSelectedBase = aFilletEdges.begin();
+ for(; aSelectedBase != aFilletEdges.end(); aSelectedBase++) {
+ GeomShapePtr aBase = *aSelectedBase;
+ // Store new faces generated from edges and vertices
+ aResultBody->loadGeneratedShapes(
+ aChamferBuilder, aBase, GeomAPI_Shape::EDGE, aFilletFaceName, true);
+ }
+ }
+
+ // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+ // result shape has been deleted, but in another it was modified or stayed.
+ GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+ FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
+ anOriginalShapesList, aResultShapesCompound);
+
+ removeResults(aResultIndex);
+ }
--- /dev/null
-
+ // Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+ //
+ // This library is free software; you can redistribute it and/or
+ // modify it under the terms of the GNU Lesser General Public
+ // License as published by the Free Software Foundation; either
+ // version 2.1 of the License, or (at your option) any later version.
+ //
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ // Lesser General Public License for more details.
+ //
+ // You should have received a copy of the GNU Lesser General Public
+ // License along with this library; if not, write to the Free Software
+ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ //
+ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+ //
+
+ #include "GeomAlgoAPI_Chamfer.h"
+
+ #include <BRep_Tool.hxx>
+ #include <BRepFilletAPI_MakeChamfer.hxx>
+ #include <BRepTools.hxx>
+ #include <TopExp.hxx>
+ #include <TopExp_Explorer.hxx>
+ #include <TopoDS.hxx>
+ #include <TopoDS_Face.hxx>
+
+ //=================================================================================================
+ GeomAlgoAPI_Chamfer::GeomAlgoAPI_Chamfer(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theChamferShapes,
+ const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+ const bool performDistances,
+ const double aVal1,
+ const double aVal2)
+ {
+ build(theBaseSolid, theChamferShapes, aMapEdgeFace, performDistances, aVal1, aVal2);
+ }
+
+ //=================================================================================================
+ void GeomAlgoAPI_Chamfer::build(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theChamferShapes,
+ const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+ const bool performDistances,
+ const double aVal1,
+ const double aVal2)
+ {
+ TopoDS_Shape aShapeBase = theBaseSolid->impl<TopoDS_Shape>();
+ TopTools_IndexedDataMapOfShapeListOfShape M;
+ TopExp::MapShapesAndAncestors(aShapeBase, TopAbs_EDGE, TopAbs_FACE, M);
-
++
+ // create chamfer builder
+ BRepFilletAPI_MakeChamfer* aChamferBuilder =
+ new BRepFilletAPI_MakeChamfer(aShapeBase);
+ setImpl(aChamferBuilder);
+ setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
- if (!BRepTools::IsReallyClosed(E,F) && !BRep_Tool::Degenerated(E) &&
++
+ for (ListOfShape::const_iterator anIt = theChamferShapes.begin();
+ anIt != theChamferShapes.end(); ++anIt) {
+ if ((*anIt)->isEdge()) {
+ TopoDS_Edge E = (*anIt)->impl<TopoDS_Edge>();
+ if (aMapEdgeFace.find(*anIt) != aMapEdgeFace.end()) {
+ //TopoDS_Face F = (aMapEdgeFace[*anIt])->impl<TopoDS_Face>();
+ TopoDS_Face F = (aMapEdgeFace.at(*anIt))->impl<TopoDS_Face>();
++ if (!BRepTools::IsReallyClosed(E,F) && !BRep_Tool::Degenerated(E) &&
+ M.FindFromKey(E).Extent() == 2) {
+ if (performDistances) {
+ aChamferBuilder->Add(aVal1, aVal2, E, F);
+ } else {
+ aChamferBuilder->AddDA(aVal1, aVal2 * M_PI / 180., E, F);
+ }
+ }
+ } else {
+ const TopTools_ListOfShape& aFacesList = M.FindFromKey(E);
+ TopoDS_Face F = TopoDS::Face(aFacesList.First());
+ if (performDistances) {
+ aChamferBuilder->Add(aVal1, aVal2, E, F);
+ } else {
+ aChamferBuilder->AddDA(aVal1, aVal2 * M_PI / 180., E, F);
+ }
+ }
+ }
+ }
+
+ // build and get result
+ aChamferBuilder->Build();
+ if (!aChamferBuilder->IsDone())
+ return;
+ const TopoDS_Shape& aResult = aChamferBuilder->Shape();
+
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+ }
--- /dev/null
-
+ // Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+ //
+ // This library is free software; you can redistribute it and/or
+ // modify it under the terms of the GNU Lesser General Public
+ // License as published by the Free Software Foundation; either
+ // version 2.1 of the License, or (at your option) any later version.
+ //
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ // Lesser General Public License for more details.
+ //
+ // You should have received a copy of the GNU Lesser General Public
+ // License along with this library; if not, write to the Free Software
+ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ //
+ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+ //
+
+ #ifndef GeomAlgoAPI_Chamfer_H_
+ #define GeomAlgoAPI_Chamfer_H_
+
+ #include <GeomAlgoAPI.h>
+ #include <GeomAlgoAPI_MakeShape.h>
+
+ #include <GeomAPI_Shape.h>
+ //#include <GeomAPI_Edge.h>
+ //#include <GeomAPI_Face.h>
+
+ /// \class GeomAlgoAPI_Chamfer
+ /// \ingroup DataAlgo
+ /// \brief Perform chamfer
+ class GeomAlgoAPI_Chamfer : public GeomAlgoAPI_MakeShape
+ {
+ public:
+ /// Run chamfer operation with two distances or with a distance and an angle .
+ /// \param theBaseSolid a changing solid
+ /// \param theChamferShapes list of edges the chamfer is performed on
+ /// \param aMapEdgeFace map that associates an edge to a face when the chamfer is applied to a face
+ /// \param performDistances boolean that indicates whether the operation is performed with two distances or not
+ /// \param aVal1 double D1 if performDistances is true or D
+ /// \param aVal2 double D2 if performDistances is true or Angle
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Chamfer(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theChamferShapes,
+ const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+ const bool performDistances,
+ const double aVal1,
+ const double aVal2);
++
+ private:
+ /// Perform chamfer operation.
+ /// \param theBaseSolid a changing solid
+ /// \param theChamferShapes list of edges the chamfer is performed on
+ /// \param aMapEdgeFace map that associates an edge to a face when the chamfer is applied to a face
+ /// \param performDistances boolean that indicates whether the operation is performed with two distances or not
+ /// \param aVal1 double D1 if performDistances is true or D
+ /// \param aVal2 double D2 if performDistances is true or Angle
+ GEOMALGOAPI_EXPORT void build(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theChamferShapes,
+ const std::map<GeomShapePtr, GeomShapePtr> aMapEdgeFace,
+ const bool performDistances,
+ const double aVal1,
+ const double aVal2);
+ };
+
+ #endif