// shared pointers
%shared_ptr(BuildAPI_Edge)
%shared_ptr(BuildAPI_Face)
+%shared_ptr(BuildAPI_Filling)
%shared_ptr(BuildAPI_Shell)
%shared_ptr(BuildAPI_SubShapes)
%shared_ptr(BuildAPI_Vertex)
// all supported interfaces
%include "BuildAPI_Edge.h"
%include "BuildAPI_Face.h"
+%include "BuildAPI_Filling.h"
%include "BuildAPI_Shell.h"
%include "BuildAPI_SubShapes.h"
%include "BuildAPI_Vertex.h"
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildAPI_Filling.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+ : ModelHighAPI_Interface(theFeature)
+{
+ initialize();
+}
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects)
+ : ModelHighAPI_Interface(theFeature)
+{
+ if(initialize())
+ setBase(theBaseObjects);
+}
+
+BuildAPI_Filling::BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::string& theOrientCorrection,
+ const int theMinDegree,
+ const int theMaxDegree,
+ const int theNbIter,
+ const double theTolerance2D,
+ const double theTolerance3D,
+ const bool theApproximate)
+ : ModelHighAPI_Interface(theFeature)
+{
+ if(initialize()) {
+ setOrientationMethod(theOrientCorrection);
+ setMinDegree(theMinDegree);
+ setMaxDegree(theMaxDegree);
+ setNbIterations(theNbIter);
+ setTolerance2d(theTolerance2D);
+ setTolerance3d(theTolerance3D);
+ setApproximation(theApproximate);
+ setAdvancedOptions();
+ setBase(theBaseObjects);
+ }
+}
+
+BuildAPI_Filling::~BuildAPI_Filling()
+{
+}
+
+void BuildAPI_Filling::execIfBaseNotEmpty()
+{
+ if (baseObjects()->size() > 0)
+ execute();
+}
+
+void BuildAPI_Filling::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+ fillAttribute(theBaseObjects, mybaseObjects);
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setOrientationMethod(const std::string& theMethod)
+{
+ fillAttribute(theMethod, myorientationMethod);
+ if (theMethod != BuildPlugin_Filling::METHOD_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setMinDegree(const int theMinDegree)
+{
+ fillAttribute(theMinDegree, myminDegree);
+ if (theMinDegree != BuildPlugin_Filling::MINIMAL_DEGREE_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setMaxDegree(const int theMaxDegree)
+{
+ fillAttribute(theMaxDegree, mymaxDegree);
+ if (theMaxDegree != BuildPlugin_Filling::MAXIMAL_DEGREE_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setNbIterations(const int theNbIter)
+{
+ fillAttribute(theNbIter, mynbIterations);
+ if (theNbIter != BuildPlugin_Filling::NUMBER_OF_ITERATIONS_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setTolerance2d(const double theTol2d)
+{
+ fillAttribute(theTol2d, mytolerance2d);
+ if (theTol2d != BuildPlugin_Filling::TOLERANCE_2D_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setTolerance3d(const double theTol3d)
+{
+ fillAttribute(theTol3d, mytolerance3d);
+ if (theTol3d != BuildPlugin_Filling::TOLERANCE_3D_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setApproximation(const bool theApproximate)
+{
+ fillAttribute(theApproximate, myapproximate);
+ if (theApproximate != BuildPlugin_Filling::APPROXIMATION_DEFAULT())
+ setAdvancedOptions();
+ execIfBaseNotEmpty();
+}
+
+void BuildAPI_Filling::setAdvancedOptions()
+{
+ feature()->string(BuildPlugin_Filling::ADVANCED_OPTIONS_ID())->setValue("true");
+}
+
+void BuildAPI_Filling::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ FeaturePtr aBase = feature();
+ std::string aPartName = theDumper.name(aBase->document());
+
+ theDumper << aBase << " = model.addFilling(" << aPartName << ", " << baseObjects();
+
+ if (!aBase->string(BuildPlugin_Filling::ADVANCED_OPTIONS_ID())->value().empty()) {
+ // dump options too,
+ theDumper << ", " << orientationMethod()
+ << ", " << minDegree() << ", " << maxDegree() << ", " << nbIterations()
+ << ", " << tolerance2d() << ", " << tolerance3d()
+ << ", " << approximate();
+ }
+ theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+
+FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Filling::ID());
+ return FillingPtr(new BuildAPI_Filling(aFeature, theBaseObjects));
+}
+
+FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::string& theOrientCorrection,
+ const int theMinDegree,
+ const int theMaxDegree,
+ const int theNbIter,
+ const double theTolerance2D,
+ const double theTolerance3D,
+ const bool theApproximate)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Filling::ID());
+ return FillingPtr(new BuildAPI_Filling(aFeature, theBaseObjects, theOrientCorrection,
+ theMinDegree, theMaxDegree, theNbIter, theTolerance2D, theTolerance3D, theApproximate));
+}
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildAPI_Filling_H_
+#define BuildAPI_Filling_H_
+
+#include "BuildAPI.h"
+
+#include <BuildPlugin_Filling.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class BuildAPI_Filling
+/// \ingroup CPPHighAPI
+/// \brief Interface for Filling feature.
+class BuildAPI_Filling : public ModelHighAPI_Interface
+{
+public:
+ /// Constructor without values.
+ BUILDAPI_EXPORT explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with base objects.
+ BUILDAPI_EXPORT
+ explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+ /// Constructor with values.
+ BUILDAPI_EXPORT
+ explicit BuildAPI_Filling(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::string& theOrientCorrection,
+ const int theMinDegree,
+ const int theMaxDegree,
+ const int theNbIter,
+ const double theTolerance2D,
+ const double theTolerance3D,
+ const bool theApproximate);
+
+ /// Destructor.
+ BUILDAPI_EXPORT virtual ~BuildAPI_Filling();
+
+ INTERFACE_8(BuildPlugin_Filling::ID(),
+ baseObjects, BuildPlugin_Filling::BASE_OBJECTS_ID(),
+ ModelAPI_AttributeSelectionList,
+ /** Base objects */,
+ orientationMethod, BuildPlugin_Filling::METHOD_ID(),
+ ModelAPI_AttributeString,
+ /** Method to keep edge orientaion */,
+ minDegree, BuildPlugin_Filling::MINIMAL_DEGREE_ID(),
+ ModelAPI_AttributeInteger,
+ /** Minimal degree */,
+ maxDegree, BuildPlugin_Filling::MAXIMAL_DEGREE_ID(),
+ ModelAPI_AttributeInteger,
+ /** Maximal degree */,
+ nbIterations, BuildPlugin_Filling::NUMBER_OF_ITERATIONS_ID(),
+ ModelAPI_AttributeInteger,
+ /** Number of iterations */,
+ tolerance2d, BuildPlugin_Filling::TOLERANCE_2D_ID(),
+ ModelAPI_AttributeDouble,
+ /** 2D tolerance */,
+ tolerance3d, BuildPlugin_Filling::TOLERANCE_3D_ID(),
+ ModelAPI_AttributeDouble,
+ /** 3D tolerance */,
+ approximate, BuildPlugin_Filling::APPROXIMATION_ID(),
+ ModelAPI_AttributeBoolean,
+ /** Approximate original edges */)
+
+ /// Modify base attribute of the feature.
+ BUILDAPI_EXPORT void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+ /// Modify orientation method
+ BUILDAPI_EXPORT void setOrientationMethod(const std::string& theMethod);
+
+ /// Modify minimal degree of result B-spline
+ BUILDAPI_EXPORT void setMinDegree(const int theMinDegree);
+
+ /// Modify maximal degree of result B-spline
+ BUILDAPI_EXPORT void setMaxDegree(const int theMaxDegree);
+
+ /// Modify number of iterations
+ BUILDAPI_EXPORT void setNbIterations(const int theNbIter);
+
+ /// Set 2D tolerance
+ BUILDAPI_EXPORT void setTolerance2d(const double theTol2d);
+
+ /// Set 3D tolerance
+ BUILDAPI_EXPORT void setTolerance3d(const double theTol3d);
+
+ /// Set approximation flag
+ BUILDAPI_EXPORT void setApproximation(const bool theApproximate);
+
+ /// Dump wrapped feature
+ BUILDAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+ void execIfBaseNotEmpty();
+ void setAdvancedOptions();
+};
+
+/// Pointer on Face object.
+typedef std::shared_ptr<BuildAPI_Filling> FillingPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Filling feature.
+BUILDAPI_EXPORT FillingPtr addFilling(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Filling feature.
+BUILDAPI_EXPORT FillingPtr addFilling(
+ const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::string& theOrientCorrection,
+ const int theMinDegree = BuildPlugin_Filling::MINIMAL_DEGREE_DEFAULT(),
+ const int theMaxDegree = BuildPlugin_Filling::MAXIMAL_DEGREE_DEFAULT(),
+ const int theNbIter = BuildPlugin_Filling::NUMBER_OF_ITERATIONS_DEFAULT(),
+ const double theTolerance2D = BuildPlugin_Filling::TOLERANCE_2D_DEFAULT(),
+ const double theTolerance3D = BuildPlugin_Filling::TOLERANCE_3D_DEFAULT(),
+ const bool theApproximate = BuildPlugin_Filling::APPROXIMATION_DEFAULT());
+
+#endif // BuildAPI_Filling_H_
#include "BuildAPI_Edge.h"
#include "BuildAPI_Face.h"
+ #include "BuildAPI_Filling.h"
#include "BuildAPI_Shell.h"
#include "BuildAPI_SubShapes.h"
#include "BuildAPI_Vertex.h"
BuildAPI.h
BuildAPI_Edge.h
BuildAPI_Face.h
+ BuildAPI_Filling.h
BuildAPI_Shell.h
BuildAPI_SubShapes.h
BuildAPI_Vertex.h
SET(PROJECT_SOURCES
BuildAPI_Edge.cpp
BuildAPI_Face.cpp
+ BuildAPI_Filling.cpp
BuildAPI_Shell.cpp
BuildAPI_SubShapes.cpp
BuildAPI_Vertex.cpp
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "BuildPlugin_Filling.h"
+
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <GeomAlgoAPI_Filling.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Wire.h>
+
+#include <cmath>
+
+struct FillingParameters
+{
+ std::string method;
+ int minDegree;
+ int maxDegree;
+ int nbIter;
+ double tol2D;
+ double tol3D;
+ bool isApprox;
+};
+
+
+//=================================================================================================
+BuildPlugin_Filling::BuildPlugin_Filling()
+{
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::initAttributes()
+{
+ data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+ data()->addAttribute(ADVANCED_OPTIONS_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(METHOD_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(MINIMAL_DEGREE_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(MAXIMAL_DEGREE_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(NUMBER_OF_ITERATIONS_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(TOLERANCE_2D_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(TOLERANCE_3D_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(APPROXIMATION_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ restoreDefaultParameters();
+ string(ADVANCED_OPTIONS_ID())->setValue("");
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::execute()
+{
+ // get parameters of algorithm
+ FillingParameters aParameters;
+ aParameters.method = string(METHOD_ID())->value();
+ aParameters.minDegree = integer(MINIMAL_DEGREE_ID())->value();
+ aParameters.maxDegree = integer(MAXIMAL_DEGREE_ID())->value();
+ aParameters.nbIter = integer(NUMBER_OF_ITERATIONS_ID())->value();
+ aParameters.tol2D = real(TOLERANCE_2D_ID())->value();
+ aParameters.tol3D = real(TOLERANCE_3D_ID())->value();
+ aParameters.isApprox = boolean(APPROXIMATION_ID())->value();
+
+ if (aParameters.minDegree > aParameters.maxDegree) {
+ setError("Error: " + getKind() + " algorithm failed (max deg < min deg).");
+ return;
+ }
+
+ std::shared_ptr<GeomAlgoAPI_Filling> aFilling(
+ new GeomAlgoAPI_Filling(aParameters.minDegree, aParameters.maxDegree, aParameters.nbIter,
+ aParameters.tol2D, aParameters.tol3D));
+
+ // get base objects list
+ AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+ if (aSelectionList->size() <= 1)
+ return;
+
+ // collect base shapes
+ for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+ GeomEdgePtr anEdge = toEdge(aSelection->value(), aParameters.method);
+ if (!anEdge) {
+ myLastEdgeStartPoint = GeomPointPtr();
+ myLastEdgeEndPoint = GeomPointPtr();
+ return;
+ }
+ aFilling->add(anEdge);
+ }
+ myLastEdgeStartPoint = GeomPointPtr();
+ myLastEdgeEndPoint = GeomPointPtr();
+
+ // build result
+ aFilling->build(aParameters.isApprox);
+ if (isFailed(aFilling)) {
+ removeResults(0);
+ return;
+ }
+
+ /// store result
+ GeomShapePtr aCreatedFace = aFilling->shape();
+ ResultBodyPtr aResultBody = document()->createBody(data());
+ aResultBody->store(aCreatedFace);
+ // store edges
+ int anEdgeInd = 0;
+ for(GeomAPI_ShapeExplorer anExp(aCreatedFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdge = anExp.current();
+ aResultBody->generated(anEdge, "Edge_" + std::to_string((long long)anEdgeInd), ++anEdgeInd);
+ }
+ setResult(aResultBody, 0);
+}
+
+bool BuildPlugin_Filling::isFailed(
+ const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+ if (!theAlgorithm->isDone()) {
+ static const std::string aFeatureError = "Error: filling algorithm failed.";
+ setError(aFeatureError);
+ return true;
+ }
+ if (theAlgorithm->shape()->isNull()) {
+ static const std::string aShapeError = "Error: Resulting shape of filling is Null.";
+ setError(aShapeError);
+ return true;
+ }
+ if (!theAlgorithm->isValid()) {
+ std::string aFeatureError = "Error: Resulting shape of filling is not valid.";
+ setError(aFeatureError);
+ return true;
+ }
+ return false;
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::attributeChanged(const std::string& theID)
+{
+ if (theID == ADVANCED_OPTIONS_ID() && string(ADVANCED_OPTIONS_ID())->value().empty()) {
+ // Advanced options flag just unchecked => restore default state of all parameters
+ restoreDefaultParameters();
+ }
+}
+
+//=================================================================================================
+GeomEdgePtr BuildPlugin_Filling::toEdge(const GeomShapePtr& theShape, const std::string& theMethod)
+{
+ GeomEdgePtr anEdge;
+ switch (theShape->shapeType()) {
+ case GeomAPI_Shape::EDGE:
+ anEdge = GeomEdgePtr(new GeomAPI_Edge(theShape));
+ break;
+ case GeomAPI_Shape::WIRE:
+ anEdge = GeomAlgoAPI_ShapeTools::wireToEdge(
+ GeomWirePtr(new GeomAPI_Wire(theShape)));
+ break;
+ default:
+ break;
+ }
+
+ if (!anEdge || anEdge->empty()) {
+ static const std::string aFeatureError =
+ "Error: incorrect type of input feature (edges/wire are supported only).";
+ setError(aFeatureError);
+ return anEdge;
+ }
+
+ // correct edge orientation according to filling method
+ if (theMethod == Method::AUTO_CORRECT_ORIENTATION()) {
+ // check the distance to previous edge boundaries, reverse edge if necessary
+ GeomPointPtr aStartPnt = anEdge->firstPoint();
+ GeomPointPtr aEndPnt = anEdge->lastPoint();
+ bool isReverse = false;
+ if (myLastEdgeStartPoint) {
+ double d1 = myLastEdgeStartPoint->distance(aStartPnt)
+ + myLastEdgeEndPoint->distance(aEndPnt);
+ double d2 = myLastEdgeStartPoint->distance(aEndPnt)
+ + myLastEdgeEndPoint->distance(aStartPnt);
+ if (fabs(d1 - d2) < 1.e-7) {
+ // undefined case => check distance to start point only
+ d1 = myLastEdgeStartPoint->distance(aStartPnt);
+ d2 = myLastEdgeStartPoint->distance(aEndPnt);
+ }
+ isReverse = d2 < d1;
+ }
+
+ if (isReverse) {
+ anEdge->reverse();
+ myLastEdgeStartPoint = aEndPnt;
+ myLastEdgeEndPoint = aStartPnt;
+ } else {
+ myLastEdgeStartPoint = aStartPnt;
+ myLastEdgeEndPoint = aEndPnt;
+ }
+ }
+ else if (theMethod == Method::USE_CURVE_INFORMATION()) {
+ // make all edges FORWARD to avoid reversing the curves by GeomAlgoAPI_Filling algorithm
+ anEdge->setOrientation(GeomAPI_Shape::FORWARD);
+ }
+ return anEdge;
+}
+
+//=================================================================================================
+void BuildPlugin_Filling::restoreDefaultParameters()
+{
+ string(METHOD_ID())->setValue(METHOD_DEFAULT());
+ integer(MINIMAL_DEGREE_ID())->setValue(MINIMAL_DEGREE_DEFAULT());
+ integer(MAXIMAL_DEGREE_ID())->setValue(MAXIMAL_DEGREE_DEFAULT());
+ integer(NUMBER_OF_ITERATIONS_ID())->setValue(NUMBER_OF_ITERATIONS_DEFAULT());
+ real(TOLERANCE_2D_ID())->setValue(TOLERANCE_2D_DEFAULT());
+ real(TOLERANCE_3D_ID())->setValue(TOLERANCE_3D_DEFAULT());
+ boolean(APPROXIMATION_ID())->setValue(APPROXIMATION_DEFAULT());
+}
--- /dev/null
+// Copyright (C) 2014-2017 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef BuildPlugin_Filling_H_
+#define BuildPlugin_Filling_H_
+
+#include "BuildPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+#include <memory>
+#include <string>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_Edge;
+class GeomAPI_Pnt;
+class GeomAPI_Shape;
+
+/// \class BuildPlugin_Filling
+/// \ingroup Plugins
+/// \brief Feature for creation of face from list of edges (1D objects).
+class BuildPlugin_Filling: public ModelAPI_Feature
+{
+public:
+ /// Use plugin manager for features creation
+ BuildPlugin_Filling();
+
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Filling");
+ return MY_ID;
+ }
+
+ /// \return the kind of a feature.
+ BUILDPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = BuildPlugin_Filling::ID();
+ return MY_KIND;
+ }
+
+ /// Attribute name of base objects.
+ inline static const std::string& BASE_OBJECTS_ID()
+ {
+ static const std::string MY_BASE_OBJECTS_ID("base_objects");
+ return MY_BASE_OBJECTS_ID;
+ }
+
+ /// Attribute name of advanced options.
+ inline static const std::string& ADVANCED_OPTIONS_ID()
+ {
+ static const std::string MY_ADVANCED_OPTIONS_ID("advanced_options");
+ return MY_ADVANCED_OPTIONS_ID;
+ }
+
+ /// Attribute name of method of edge orientation.
+ inline static const std::string& METHOD_ID()
+ {
+ static const std::string MY_METHOD_ID("orientation");
+ return MY_METHOD_ID;
+ }
+
+ /// Supported methods for edge orientation correction
+ struct Method {
+ inline static const std::string& AUTO_CORRECT_ORIENTATION()
+ {
+ static const std::string MY_AUTO_CORRECT_ORIENTATION("auto_correct");
+ return MY_AUTO_CORRECT_ORIENTATION;
+ }
+ inline static const std::string& USE_CURVE_INFORMATION()
+ {
+ static const std::string MY_USE_CURVE_INFORMATION("curve_info");
+ return MY_USE_CURVE_INFORMATION;
+ }
+ inline static const std::string& USE_EDGES_ORIENTATION()
+ {
+ static const std::string MY_USE_EDGES_ORIENTATION("edge_orient");
+ return MY_USE_EDGES_ORIENTATION;
+ }
+ };
+
+ /// Attribute name of minimal degree.
+ inline static const std::string& MINIMAL_DEGREE_ID()
+ {
+ static const std::string MY_MINIMAL_DEGREE_ID("min_degree");
+ return MY_MINIMAL_DEGREE_ID;
+ }
+
+ /// Attribute name of maximal degree.
+ inline static const std::string& MAXIMAL_DEGREE_ID()
+ {
+ static const std::string MY_MAXIMAL_DEGREE_ID("max_degree");
+ return MY_MAXIMAL_DEGREE_ID;
+ }
+
+ /// Attribute name of number of iterations.
+ inline static const std::string& NUMBER_OF_ITERATIONS_ID()
+ {
+ static const std::string MY_NUMBER_OF_ITERATIONS_ID("nb_iter");
+ return MY_NUMBER_OF_ITERATIONS_ID;
+ }
+
+ /// Attribute name of 2D tolerance.
+ inline static const std::string& TOLERANCE_2D_ID()
+ {
+ static const std::string MY_TOLERANCE_2D_ID("tol_2d");
+ return MY_TOLERANCE_2D_ID;
+ }
+
+ /// Attribute name of 3D tolerance.
+ inline static const std::string& TOLERANCE_3D_ID()
+ {
+ static const std::string MY_TOLERANCE_3D_ID("tol_3d");
+ return MY_TOLERANCE_3D_ID;
+ }
+
+ /// Attribute name of approximation.
+ inline static const std::string& APPROXIMATION_ID()
+ {
+ static const std::string MY_APPROXIMATION_ID("approximation");
+ return MY_APPROXIMATION_ID;
+ }
+
+ /// Default value of the orientation
+ inline static const std::string& METHOD_DEFAULT() { return Method::AUTO_CORRECT_ORIENTATION(); }
+ /// Default value of minimal degree
+ inline static int MINIMAL_DEGREE_DEFAULT() { return 2; }
+ /// Default value of maximal degree
+ inline static int MAXIMAL_DEGREE_DEFAULT() { return 5; }
+ /// Default value of number of iterations
+ inline static int NUMBER_OF_ITERATIONS_DEFAULT() { return 0; }
+ /// Default value of 2D tolerance
+ inline static double TOLERANCE_2D_DEFAULT() { return 1.e-4; }
+ /// Default value of 3D tolerance
+ inline static double TOLERANCE_3D_DEFAULT() { return 1.e-4; }
+ /// Default value of the approximation attribute
+ inline static bool APPROXIMATION_DEFAULT() { return false; }
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ BUILDPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Creates a new part document if needed.
+ BUILDPLUGIN_EXPORT virtual void execute();
+
+ /// Called on change of any argument-attribute of this object.
+ /// \param[in] theID identifier of changed attribute.
+ BUILDPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+private:
+ /// Check the filling algorithm is failed
+ bool isFailed(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+ /// Convert shape to edge according to construction method
+ std::shared_ptr<GeomAPI_Edge> toEdge(const std::shared_ptr<GeomAPI_Shape>& theShape,
+ const std::string& theMethod);
+
+ /// Update values of attributes by their default values
+ void restoreDefaultParameters();
+
+private:
+ std::shared_ptr<GeomAPI_Pnt> myLastEdgeStartPoint;
+ std::shared_ptr<GeomAPI_Pnt> myLastEdgeEndPoint;
+};
+
+#endif
-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2017-20xx 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
#include <BuildPlugin_Face.h>
#include <BuildPlugin_Shell.h>
#include <BuildPlugin_SubShapes.h>
+#include <BuildPlugin_Filling.h>
#include <BuildPlugin_Validators.h>
// the only created instance of this plugin
return FeaturePtr(new BuildPlugin_Shell());
} else if(theFeatureID == BuildPlugin_SubShapes::ID()) {
return FeaturePtr(new BuildPlugin_SubShapes());
+ } else if(theFeatureID == BuildPlugin_Filling::ID()) {
+ return FeaturePtr(new BuildPlugin_Filling());
}
// Feature of such kind is not found.
BuildPlugin_Face.h
BuildPlugin_Shell.h
BuildPlugin_SubShapes.h
+ BuildPlugin_Filling.h
BuildPlugin_Validators.h
)
BuildPlugin_Face.cpp
BuildPlugin_Shell.cpp
BuildPlugin_SubShapes.cpp
+ BuildPlugin_Filling.cpp
BuildPlugin_Validators.cpp
)
face_widget.xml
shell_widget.xml
subshapes_widget.xml
+ filling_widget.xml
)
SET(TEXT_RESOURCES
TestFace.py
TestShell.py
TestSubShapes.py
+ TestFilling_ByEdges.py
+ TestFilling_ByWires.py
+ TestFilling_Mixed.py
Test1920.py)
--- /dev/null
+## Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first edge in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# an arc
+anArc = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+
+# Create second edge in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# a line
+aLine = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aLineStartPoint.setValue(0, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 20)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# an edge
+aSession.startOperation()
+anEdge = aPart.addFeature("Edge")
+aBaseObjectsList = anEdge.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc.lastResult().shape())
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one edge is failed (error is reported)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+assert(aFillingFeature.error() != "")
+
+# =============================================================================
+# Test 2. Add another edge, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(anEdge.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+ for minDeg in range(2, 4):
+ for maxDeg in range(5, 7):
+ for nbIter in range(0, 3, 2):
+ for tol2d in tolerances:
+ for tol3d in tolerances:
+ for approx in [False, True]:
+ aSession.startOperation()
+ aFillingFeature.string("orientation").setValue(ori)
+ aFillingFeature.integer("min_degree").setValue(minDeg)
+ aFillingFeature.integer("max_degree").setValue(maxDeg)
+ aFillingFeature.integer("nb_iter").setValue(nbIter)
+ aFillingFeature.real("tol_2d").setValue(tol2d)
+ aFillingFeature.real("tol_3d").setValue(tol3d)
+ aFillingFeature.boolean("approximation").setValue(approx)
+ aSession.finishOperation()
+ assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n orientation={}\n min deg={}\n max deg={}\n nb iter={}\n tol 2d={}\n tol 3d={}\n approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+# =============================================================================
+# Test 4. Discard parameters to default and add one more edge
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("")
+aSession.finishOperation()
+# new arc
+aSession.startOperation()
+anArc2 = aSketch1.addFeature("SketchArc")
+anArc2Center = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArc2Center.setValue(0, -5)
+anArc2StartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArc2StartPoint.setValue(-20, -5)
+anArc2EndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArc2EndPoint.setValue(20, -5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# update filling
+aSession.startOperation()
+aPart.setCurrentFeature(aFillingFeature, True)
+aBaseObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
--- /dev/null
+## Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first wire in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# arc 1
+anArc1 = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc1.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc1.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc1.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+# arc 2
+anArc2 = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArcCenter.setValue(12.5, 12.5)
+anArcStartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArcStartPoint.setValue(5, 20)
+anArcEndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArcEndPoint.setValue(20, 5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# a wire
+aSession.startOperation()
+aWire1 = aPart.addFeature("Wire")
+aBaseObjectsList = aWire1.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc1.lastResult().shape())
+aBaseObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+
+# Create second wire in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# line 1
+aLine1 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine1.attribute("StartPoint"))
+aLineStartPoint.setValue(30, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine1.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 20)
+# line 2
+aLine2 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLineStartPoint.setValue(20, 20)
+aLineEndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLineEndPoint.setValue(20, 0)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# a wire
+aSession.startOperation()
+aWire2 = aPart.addFeature("Wire")
+aBaseObjectsList = aWire2.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine1.lastResult().shape())
+aBaseObjectsList.append(aSketch2Result, aLine2.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aWire1.lastResult(), None)
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one wire is failed (error is reported)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+assert(aFillingFeature.error() != "")
+
+# =============================================================================
+# Test 2. Add another wire, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(aWire2.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+ for minDeg in range(2, 4):
+ for maxDeg in range(5, 7):
+ for nbIter in range(0, 3, 2):
+ for tol2d in tolerances:
+ for tol3d in tolerances:
+ for approx in [False, True]:
+ aSession.startOperation()
+ aFillingFeature.string("orientation").setValue(ori)
+ aFillingFeature.integer("min_degree").setValue(minDeg)
+ aFillingFeature.integer("max_degree").setValue(maxDeg)
+ aFillingFeature.integer("nb_iter").setValue(nbIter)
+ aFillingFeature.real("tol_2d").setValue(tol2d)
+ aFillingFeature.real("tol_3d").setValue(tol3d)
+ aFillingFeature.boolean("approximation").setValue(approx)
+ aSession.finishOperation()
+ assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n orientation={}\n min deg={}\n max deg={}\n nb iter={}\n tol 2d={}\n tol 3d={}\n approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
--- /dev/null
+## Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+##
+
+# Initialization of the test
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+# Get document
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+
+# Create a part
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPartResult = modelAPI_ResultPart(aPartFeature.firstResult())
+aPart = aPartResult.partDoc()
+
+# Create first edge in a sketch
+aSession.startOperation()
+aSketch1 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch1.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch1.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch1.attribute("Norm"))
+aNorm.setValue(0, 0, 1)
+# an arc
+anArc = aSketch1.addFeature("SketchArc")
+anArcCenter = geomDataAPI_Point2D(anArc.attribute("center_point"))
+anArcCenter.setValue(1, 1)
+anArcStartPoint = geomDataAPI_Point2D(anArc.attribute("start_point"))
+anArcStartPoint.setValue(20, 5)
+anArcEndPoint = geomDataAPI_Point2D(anArc.attribute("end_point"))
+anArcEndPoint.setValue(5, 20)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+
+# Create a wire in another sketch
+aSession.startOperation()
+aSketch2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+anOrigin = geomDataAPI_Point(aSketch2.attribute("Origin"))
+anOrigin.setValue(0, 0, 0)
+aDirX = geomDataAPI_Dir(aSketch2.attribute("DirX"))
+aDirX.setValue(1, 0, 0)
+aNorm = geomDataAPI_Dir(aSketch2.attribute("Norm"))
+aNorm.setValue(0, 0.7071067811865475, 0.7071067811865475)
+# line 1
+aLine1 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine1.attribute("StartPoint"))
+aLineStartPoint.setValue(0, 0)
+aLineEndPoint = geomDataAPI_Point2D(aLine1.attribute("EndPoint"))
+aLineEndPoint.setValue(10, 10)
+# line 2
+aLine2 = aSketch2.addFeature("SketchLine")
+aLineStartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLineStartPoint.setValue(10, 10)
+aLineEndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLineEndPoint.setValue(30, 0)
+aSession.finishOperation()
+aSketch2Result = aSketch2.firstResult()
+# a wire
+aSession.startOperation()
+aWire = aPart.addFeature("Wire")
+aBaseObjectsList = aWire.selectionList("base_objects")
+aBaseObjectsList.append(aSketch2Result, aLine1.lastResult().shape())
+aBaseObjectsList.append(aSketch2Result, aLine2.lastResult().shape())
+aSession.finishOperation()
+
+# Create filling
+aSession.startOperation()
+aFillingFeature = aPart.addFeature("Filling")
+aBaseObjectsList = aFillingFeature.selectionList("base_objects")
+aBaseObjectsList.append(aSketch1Result, anArc.lastResult().shape())
+aSession.finishOperation()
+
+# =============================================================================
+# Test 1. Filling on one edge is failed (error is reported)
+# =============================================================================
+assert(len(aFillingFeature.results()) == 0)
+assert(aFillingFeature.error() != "")
+
+# =============================================================================
+# Test 2. Add a wire, filling should be completed
+# =============================================================================
+aSession.startOperation()
+aBaseObjectsList.append(aWire.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+# =============================================================================
+# Test 3. Change parameters one-by-one and check validity of result
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("true")
+aSession.finishOperation()
+orientations = ["auto_correct", "curve_info", "edge_orient"]
+tolerances = [0.0001, 0.001]
+for ori in orientations:
+ for minDeg in range(2, 4):
+ for maxDeg in range(5, 7):
+ for nbIter in range(0, 3, 2):
+ for tol2d in tolerances:
+ for tol3d in tolerances:
+ for approx in [False, True]:
+ aSession.startOperation()
+ aFillingFeature.string("orientation").setValue(ori)
+ aFillingFeature.integer("min_degree").setValue(minDeg)
+ aFillingFeature.integer("max_degree").setValue(maxDeg)
+ aFillingFeature.integer("nb_iter").setValue(nbIter)
+ aFillingFeature.real("tol_2d").setValue(tol2d)
+ aFillingFeature.real("tol_3d").setValue(tol3d)
+ aFillingFeature.boolean("approximation").setValue(approx)
+ aSession.finishOperation()
+ assert(len(aFillingFeature.results()) > 0), "Filling feature failed with parameters:\n orientation={}\n min deg={}\n max deg={}\n nb iter={}\n tol 2d={}\n tol 3d={}\n approximation={}".format(ori, minDeg, maxDeg, nbIter, tol2d, tol3d, approx)
+
+# =============================================================================
+# Test 4. Discard parameters to default and add one more edge
+# =============================================================================
+aSession.startOperation()
+aFillingFeature.string("advanced_options").setValue("")
+aSession.finishOperation()
+# new arc
+aSession.startOperation()
+anArc2 = aSketch1.addFeature("SketchArc")
+anArc2Center = geomDataAPI_Point2D(anArc2.attribute("center_point"))
+anArc2Center.setValue(0, -5)
+anArc2StartPoint = geomDataAPI_Point2D(anArc2.attribute("start_point"))
+anArc2StartPoint.setValue(-20, -5)
+anArc2EndPoint = geomDataAPI_Point2D(anArc2.attribute("end_point"))
+anArc2EndPoint.setValue(20, -5)
+aSession.finishOperation()
+aSketch1Result = aSketch1.firstResult()
+# an edge
+aSession.startOperation()
+aPart.setCurrentFeature(aWire, True)
+anEdge = aPart.addFeature("Edge")
+anEdgeObjectsList = anEdge.selectionList("base_objects")
+anEdgeObjectsList.append(aSketch1Result, anArc2.lastResult().shape())
+aSession.finishOperation()
+# update filling
+aSession.startOperation()
+aPart.setCurrentFeature(aFillingFeature, True)
+aBaseObjectsList.append(anEdge.lastResult(), None)
+aSession.finishOperation()
+assert(len(aFillingFeature.results()) > 0)
+
+from salome.shaper import model
+assert(model.checkPythonDump())
--- /dev/null
+<!--
+Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+ <multi_selector id="base_objects"
+ label="Segments and wires:"
+ tooltip="Select edges or wires."
+ type_choice="edges wires"
+ concealment="false">
+ <validator id="PartSet_DifferentObjects"/>
+ </multi_selector>
+ <optionalbox id="advanced_options" title="Advanced options">
+ <switch id="orientation" label="Orientation">
+ <case id="auto_correct" title="Auto-correct edges orientation"/>
+ <case id="curve_info" title="Use curve information"/>
+ <case id="edge_orient" title="Use edges orientation"/>
+ </switch>
+ <integervalue id="min_degree" label="Min deg" min="1" default="2">
+ <validator id="GeomValidators_LessOrEqual" parameters="max_degree"/>
+ </integervalue>
+ <integervalue id="max_degree" label="Max deg" min="1" default="5">
+ <validator id="GeomValidators_GreaterOrEqual" parameters="min_degree"/>
+ </integervalue>
+ <integervalue id="nb_iter" label="Nb iter" min="0" default="0"/>
+ <doublevalue id="tol_2d" label="Tol 2D" min="0" default="0.0001" step="0.0001"/>
+ <doublevalue id="tol_3d" label="Tol 3D" min="0" default="0.0001" step="0.0001"/>
+ <boolvalue id="approximation" label="Approximation"/>
+ </optionalbox>
+</source>
<source path="subshapes_widget.xml"/>
</feature>
</group>
- </workbench>
+ <group id="Advanced">
+ <feature id="Filling" title="Filling" tooltip="Create face from list of edges" icon="icons/Build/feature_filling.png">
+ <source path="filling_widget.xml"/>
+ </feature>
+ </group>
+ </workbench>
</plugin>
return !aShape.IsNull() && aShape.ShapeType() == TopAbs_EDGE;
}
+bool GeomAPI_Shape::isWire() const
+{
+ const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
+ return !aShape.IsNull() && aShape.ShapeType() == TopAbs_WIRE;
+}
+
bool GeomAPI_Shape::isFace() const
{
const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
}
}
+void GeomAPI_Shape::reverse()
+{
+ MY_SHAPE->Reverse();
+}
+
bool GeomAPI_Shape::isSubShape(const std::shared_ptr<GeomAPI_Shape> theShape,
const bool theCheckOrientation) const
{
GEOMAPI_EXPORT
virtual bool isEdge() const;
+ /// Returns whether the shape is a wire
+ GEOMAPI_EXPORT
+ virtual bool isWire() const;
+
/// Returns whether the shape is a face
GEOMAPI_EXPORT
virtual bool isFace() const;
/// Sets the shape orientation.
GEOMAPI_EXPORT virtual void setOrientation(const Orientation theOrientation);
+ /// Reverse shape
+ GEOMAPI_EXPORT virtual void reverse();
+
/// \return true if passed shape is a sub-shape of this shape.
/// \param theShape shape to search.
/// \param theCheckOrientation if false, returns true even if orientation of shape differs
this->setImpl(aWire);
}
+
+//==================================================================================================
+GeomAPI_Wire::GeomAPI_Wire(const std::shared_ptr<GeomAPI_Shape>& theShape)
+{
+ if (!theShape->isNull() && theShape->isWire()) {
+ setImpl(new TopoDS_Shape(theShape->impl<TopoDS_Shape>()));
+ }
+}
public:
/// Makes an undefined Wire.
GEOMAPI_EXPORT GeomAPI_Wire();
+
+ /// Creation of wire by the wire-shape
+ GEOMAPI_EXPORT GeomAPI_Wire(const std::shared_ptr<GeomAPI_Shape>& theShape);
};
-#endif
+typedef std::shared_ptr<GeomAPI_Wire> GeomWirePtr;
+#endif
GeomAlgoAPI_UnifySameDomain.h
GeomAlgoAPI_Fillet.h
GeomAlgoAPI_SortListOfShapes.h
+ GeomAlgoAPI_Filling.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_UnifySameDomain.cpp
GeomAlgoAPI_Fillet.cpp
GeomAlgoAPI_SortListOfShapes.cpp
+ GeomAlgoAPI_Filling.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_Filling.h"
+
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAPI_PointsToBSplineSurface.hxx>
+#include <GeomFill_AppSurf.hxx>
+#include <GeomFill_Line.hxx>
+#include <GeomFill_SectionGenerator.hxx>
+#include <Precision.hxx>
+#include <ShapeFix_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+
+static void edgesToCurves(const std::list<GeomEdgePtr>& theEdges,
+ std::list<Handle(Geom_Curve)>& theCurves)
+{
+ for (std::list<GeomEdgePtr>::const_iterator anIt = theEdges.begin();
+ anIt != theEdges.end(); ++anIt) {
+ const TopoDS_Edge& anEdge = (*anIt)->impl<TopoDS_Edge>();
+ if (BRep_Tool::Degenerated(anEdge))
+ continue;
+
+ double aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+
+ aCurve = new Geom_TrimmedCurve(aCurve, aFirst, aLast);
+ if (anEdge.Orientation() == TopAbs_REVERSED)
+ aCurve->Reverse();
+
+ theCurves.push_back(aCurve);
+ }
+}
+
+
+GeomAlgoAPI_Filling::GeomAlgoAPI_Filling(const int theMinDegree,
+ const int theMaxDegree,
+ const int theNbIter,
+ const double theTol2D,
+ const double theTol3D)
+ : myMinDegree(theMinDegree),
+ myMaxDegree(theMaxDegree),
+ myNbIter(theNbIter),
+ myTol2D(theTol2D),
+ myTol3D(theTol3D)
+{
+}
+
+void GeomAlgoAPI_Filling::add(const GeomEdgePtr theEdge)
+{
+ myConstraints.push_back(theEdge);
+}
+
+void GeomAlgoAPI_Filling::build(bool isApproximate)
+{
+ if (myConstraints.size() <= 1) // not enough edges
+ return;
+
+ if (isApproximate)
+ buildByControlPoints();
+ else
+ buildByEdges();
+}
+
+void GeomAlgoAPI_Filling::buildByEdges()
+{
+ GeomFill_SectionGenerator aSection;
+
+ // obtain section curves
+ std::list<Handle(Geom_Curve)> aCurves;
+ edgesToCurves(myConstraints, aCurves);
+ for (std::list<Handle(Geom_Curve)>::iterator anIt = aCurves.begin();
+ anIt != aCurves.end(); ++anIt)
+ aSection.AddCurve(*anIt);
+
+ // a 'tolerance' is used to compare 2 knots
+ aSection.Perform(Precision::PConfusion());
+ Handle(GeomFill_Line) aLine = new GeomFill_Line((int)aCurves.size());
+
+ // perform filling by sections
+ GeomFill_AppSurf anAppSurf(myMinDegree, myMaxDegree, myTol3D, myTol2D, myNbIter);
+ anAppSurf.Perform(aLine, aSection);
+ if (!anAppSurf.IsDone())
+ return;
+
+ // build calculated surface
+ Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots;
+ anAppSurf.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots);
+ Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface(
+ anAppSurf.SurfPoles(), anAppSurf.SurfWeights(), anAppSurf.SurfUKnots(), anAppSurf.SurfVKnots(),
+ anAppSurf.SurfUMults(), anAppSurf.SurfVMults(), anAppSurf.UDegree(), anAppSurf.VDegree());
+
+ if (GBS.IsNull())
+ return;
+
+ // store result
+ TopoDS_Face aFace = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion());
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aFace));
+ setShape(aShape);
+ setDone(true);
+}
+
+static Handle(Geom_Curve) removeTrim(const Handle(Geom_Curve)& theCurve)
+{
+ Handle(Geom_Curve) aCurve = theCurve;
+ Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+ while (!aTC.IsNull()) {
+ aCurve = aTC->BasisCurve();
+ aTC = Handle(Geom_TrimmedCurve)::DownCast(aCurve);
+ }
+ return aCurve;
+}
+
+void GeomAlgoAPI_Filling::buildByControlPoints()
+{
+ // obtain section curves
+ std::list<Handle(Geom_Curve)> aCurves;
+ edgesToCurves(myConstraints, aCurves);
+
+ // compute maximal number of poles in B-spline curves
+ int aMaxPoles = 0;
+ std::list<Handle(Geom_Curve)>::iterator anIt = aCurves.begin();
+ for (; anIt != aCurves.end(); ++anIt) {
+ Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(removeTrim(*anIt));
+ if (!aBC.IsNull())
+ aMaxPoles = Max(aMaxPoles, aBC->NbPoles());
+ }
+
+ // prepare array of points for creation bspline surface
+ // size of this array: by U parameter - number of curves,
+ // by V parameter - determ using MaxNbPoles but it's
+ // value must be between 21(min) and 101(max)
+ int aNbSections = (int) aCurves.size();
+ int aNbPntInSection = Max(21, 2 * aMaxPoles - 1);
+ TColgp_Array2OfPnt aPoints(1, aNbSections, 1, aNbPntInSection);
+ anIt = aCurves.begin();
+ for (int i = 1; anIt != aCurves.end(); ++i, ++anIt) {
+ Handle(Geom_Curve) aC = *anIt;
+ double fp = aC->FirstParameter();
+ double lp = aC->LastParameter();
+ double dp = (lp - fp) / (aNbPntInSection - 1);
+
+ gp_Pnt aPnt;
+ for (int j = 0; j < aNbPntInSection; j++) {
+ aC->D0(fp + dp * j, aPnt);
+ aPoints.SetValue(i, j+1, aPnt);
+ }
+ }
+
+ // convert a grid of points to B-spline surface
+ GeomAPI_PointsToBSplineSurface aPTB(aPoints, myMinDegree, myMaxDegree, GeomAbs_C2, myTol3D);
+ Handle(Geom_BSplineSurface) aBS = aPTB.Surface();
+ if (aBS.IsNull())
+ return;
+
+ // fix face orientation
+ TopoDS_Face aFace = BRepBuilderAPI_MakeFace(aBS, Precision::Confusion());
+ Handle(ShapeFix_Face) aFix = new ShapeFix_Face(aFace);
+ aFix->Perform();
+ aFix->FixOrientation();
+ aFace = aFix->Face();
+
+ // store result
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aFace));
+ setShape(aShape);
+ setDone(true);
+}
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_Filling_H_
+#define GeomAlgoAPI_Filling_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Edge.h>
+
+/// \class GeomAlgoAPI_Filling
+/// \ingroup DataAlgo
+/// \brief Perform building face by the set of edges/wires
+class GeomAlgoAPI_Filling : public GeomAlgoAPI_MakeShape
+{
+public:
+ /// \brief Construct filling operation by the parameters.
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Filling(const int theMinDegree = 2,
+ const int theMaxDegree = 5,
+ const int theNbIter = 0,
+ const double theTol2D = 1.e-4,
+ const double theTol3D = 1.e-4);
+
+ /// \brief Add an edge to constrain filling (the result face should pass through the edge)
+ GEOMALGOAPI_EXPORT void add(const GeomEdgePtr theEdge);
+
+ /// \brief Perform filling operation
+ /// \param isApproximate approximate curves before building a face
+ GEOMALGOAPI_EXPORT void build(bool isApproximate = false);
+
+private:
+ /// \brief Perform filling using the given edges
+ void buildByEdges();
+
+ /// \brief Perform filling by a set of points calculated on each edge
+ void buildByControlPoints();
+
+private:
+ int myMinDegree;
+ int myMaxDegree;
+ int myNbIter;
+ double myTol2D;
+ double myTol3D;
+ std::list<GeomEdgePtr> myConstraints;
+};
+
+#endif
#include <GeomAPI_Face.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Wire.h>
#include <Bnd_Box.hxx>
#include <BOPTools.hxx>
#include <BRep_Builder.hxx>
#include <BRepAdaptor_Curve.hxx>
+#include <BRepAlgo.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
aCentreOfMassPoint.Z()-aPoint.Z()));
return aDir;
}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_ShapeTools::wireToEdge(
+ const std::shared_ptr<GeomAPI_Wire>& theWire)
+{
+ GeomEdgePtr anEdge;
+ if (theWire) {
+ const TopoDS_Wire& aWire = theWire->impl<TopoDS_Wire>();
+ TopoDS_Edge aNewEdge = BRepAlgo::ConcatenateWireC0(aWire);
+ anEdge = GeomEdgePtr(new GeomAPI_Edge);
+ anEdge->setImpl(new TopoDS_Edge(aNewEdge));
+ }
+ return anEdge;
+}
class GeomAPI_PlanarEdges;
class GeomAPI_Pln;
class GeomAPI_Pnt;
+class GeomAPI_Wire;
class GeomDataAPI_Point2D;
class ModelAPI_Object;
GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Dir> buildDirFromAxisAndShape(
const std::shared_ptr<GeomAPI_Shape> theBaseShape,
const std::shared_ptr<GeomAPI_Ax1> theAxis);
+
+ /// \brief Reapproximate a wire to build a single edge
+ GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Edge> wireToEdge(
+ const std::shared_ptr<GeomAPI_Wire>& theWire);
};
#endif
GeomValidators_Different.h
GeomValidators_IntersectionSelection.h
GeomValidators_MinObjectsSelected.h
+ GeomValidators_ValueOrder.h
)
SET(PROJECT_SOURCES
GeomValidators_Different.cpp
GeomValidators_IntersectionSelection.cpp
GeomValidators_MinObjectsSelected.cpp
+ GeomValidators_ValueOrder.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomValidators_ValueOrder.h"
+
+#include <Config_PropManager.h>
+#include <Events_InfoMessage.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+static double attributeValue(AttributePtr theAttr)
+{
+ AttributeIntegerPtr anIntAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theAttr);
+ if (anIntAttr)
+ return (double)anIntAttr->value();
+ AttributeDoublePtr aDoubleAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttr);
+ if (aDoubleAttr)
+ return aDoubleAttr->value();
+ return 0.0;
+}
+
+static bool isGreaterOrEqual(AttributePtr theFirstArg, AttributePtr theSecondArg)
+{
+ if (theFirstArg && theFirstArg->isInitialized() &&
+ theSecondArg && theSecondArg->isInitialized())
+ return attributeValue(theFirstArg) >= attributeValue(theSecondArg);
+ return false;
+}
+
+static bool isLessOrEqual(AttributePtr theFirstArg, AttributePtr theSecondArg)
+{
+ if (theFirstArg && theFirstArg->isInitialized() &&
+ theSecondArg && theSecondArg->isInitialized())
+ return attributeValue(theFirstArg) <= attributeValue(theSecondArg);
+ return false;
+}
+
+// Check the attributes are satisfy theCompare function
+static bool isValidOrder(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError,
+ bool (*theCompare)(AttributePtr, AttributePtr))
+{
+ std::string anAttrType = theAttribute->attributeType();
+ if (anAttrType != ModelAPI_AttributeDouble::typeId() &&
+ anAttrType != ModelAPI_AttributeInteger::typeId()) {
+ theError = "Unsupported attribute type (integer or double applicable)";
+ return false;
+ }
+
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+ if (!anOwner) {
+ theError = "Attribute without owner";
+ return false;
+ }
+
+ for (std::list<std::string>::const_iterator anIt = theArguments.begin();
+ anIt != theArguments.end(); ++anIt) {
+ // check the argument links to the attribute of the current feature
+ AttributePtr aCurAttr = anOwner->attribute(*anIt);
+ if (!aCurAttr) {
+ theError = "Arguments should be names of attributes of current feature";
+ return false;
+ }
+
+ // compare values
+ if (!(*theCompare)(theAttribute, aCurAttr)) {
+ theError = "Attributes have incorrect order";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+/// Global instance for validators factory
+GeomValidators_GreaterOrEqual MY_GEQ_INSTANCE;
+GeomValidators_LessOrEqual MY_LEQ_INSTANCE;
+
+GeomValidators_GreaterOrEqual::GeomValidators_GreaterOrEqual()
+{
+ // this validator is registered in the factory on this library loading
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+ aFactory->registerValidator("GeomValidators_GreaterOrEqual", this);
+}
+
+bool GeomValidators_GreaterOrEqual::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ return isValidOrder(theAttribute, theArguments, theError, &isGreaterOrEqual);
+}
+
+
+
+GeomValidators_LessOrEqual::GeomValidators_LessOrEqual()
+{
+ // this validator is registered in the factory on this library loading
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+ aFactory->registerValidator("GeomValidators_LessOrEqual", this);
+}
+
+bool GeomValidators_LessOrEqual::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ return isValidOrder(theAttribute, theArguments, theError, &isLessOrEqual);
+}
--- /dev/null
+// Copyright (C) 2017-20xx 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomValidators_ValueOrder_H
+#define GeomValidators_ValueOrder_H
+
+#include <GeomValidators.h>
+#include <ModelAPI_AttributeValidator.h>
+
+/**
+ * Validates that the integer/double attribute is greater or equal to another attribute values
+ */
+class GeomValidators_GreaterOrEqual : public ModelAPI_AttributeValidator
+{
+public:
+ //! Constructor for only one instance per application: will register the validator
+ GeomValidators_GreaterOrEqual();
+ //! returns true if attribute is valid
+ //! \param[in] theAttribute the checked attribute
+ //! \param[in] theArguments arguments of the attribute
+ //! \param[out] theError error message.
+ GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+
+};
+
+/**
+ * Validates that the integer/double attribute is less or equal to another attribute values
+ */
+class GeomValidators_LessOrEqual : public ModelAPI_AttributeValidator
+{
+public:
+ //! Constructor for only one instance per application: will register the validator
+ GeomValidators_LessOrEqual();
+ //! returns true if attribute is valid
+ //! \param[in] theAttribute the checked attribute
+ //! \param[in] theArguments arguments of the attribute
+ //! \param[out] theError error message.
+ GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+
+};
+
+#endif
ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
{
- myDumpBuffer << "[";
+ static const int aThreshold = 2;
+ // if number of elements in the list if greater than a threshold,
+ // dump it in a separate line with specific name
+ std::string aDumped = myDumpBuffer.str();
- GeomShapePtr aShape;
- std::string aShapeTypeStr;
+ if (aDumped.empty() || theAttrSelList->size() <= aThreshold) {
+ myDumpBuffer << "[";
- bool isAdded = false;
+ GeomShapePtr aShape;
+ std::string aShapeTypeStr;
- for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
- AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
- aShape = anAttribute->value();
- if(!aShape.get()) {
- ResultPtr aContext = anAttribute->context();
- if (aContext.get())
- aShape = aContext->shape();
- }
+ bool isAdded = false;
- if(!aShape.get()) {
- continue;
- }
+ for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
+ aShape = anAttribute->value();
+ if(!aShape.get()) {
+ ResultPtr aContext = anAttribute->context();
+ if (aContext.get())
+ aShape = aContext->shape();
+ }
- if(isAdded) {
- myDumpBuffer << ", ";
- } else {
- isAdded = true;
+ if(!aShape.get()) {
+ continue;
+ }
+
+ if(isAdded) {
+ myDumpBuffer << ", ";
+ } else {
+ isAdded = true;
+ }
+ myDumpBuffer << "model.selection(\"" <<
+ aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
}
- myDumpBuffer << "model.selection(\"" <<
- aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
- }
- myDumpBuffer << "]";
+ myDumpBuffer << "]";
+ } else {
+ // clear buffer and store list "as is"
+ myDumpBuffer.str("");
+ *this << theAttrSelList;
+ // save buffer and clear it again
+ std::string aDumpedList = myDumpBuffer.str();
+ myDumpBuffer.str("");
+ // obtain name of list
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelList->owner());
+ std::string aListName = name(anOwner) + "_objects";
+ // store all previous data
+ myDumpBuffer << aListName << " = " << aDumpedList << std::endl
+ << aDumped << aListName;
+ }
return *this;
}
from BuildAPI import addVertex, addEdge, addWire, addFace, addShell
from BuildAPI import addSubShapes
+from BuildAPI import addFilling